Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Amplify.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@
B4A19DAD24101F7100DE2E55 /* AuthSignUpOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4A19DAC24101F7100DE2E55 /* AuthSignUpOperation.swift */; };
B4ADE8F4241063820007E86C /* AuthCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4ADE8F3241063820007E86C /* AuthCategory.swift */; };
B4B1E0E524733687007F3261 /* AuthEventName.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4B1E0E424733687007F3261 /* AuthEventName.swift */; };
B4B34C55255B725F00033033 /* ModelFieldAssociationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4B34C54255B725F00033033 /* ModelFieldAssociationTests.swift */; };
B4B5CC812457B0690019C783 /* AuthFetchUserAttributesRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4B5CC802457B0690019C783 /* AuthFetchUserAttributesRequest.swift */; };
B4B5CC872457B2470019C783 /* AuthUpdateUserAttributeRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4B5CC862457B2470019C783 /* AuthUpdateUserAttributeRequest.swift */; };
B4B5CC8B2457B32D0019C783 /* AuthConfirmUserAttributeRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4B5CC8A2457B32D0019C783 /* AuthConfirmUserAttributeRequest.swift */; };
Expand Down Expand Up @@ -1112,6 +1113,7 @@
B4A19DAC24101F7100DE2E55 /* AuthSignUpOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthSignUpOperation.swift; sourceTree = "<group>"; };
B4ADE8F3241063820007E86C /* AuthCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthCategory.swift; sourceTree = "<group>"; };
B4B1E0E424733687007F3261 /* AuthEventName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthEventName.swift; sourceTree = "<group>"; };
B4B34C54255B725F00033033 /* ModelFieldAssociationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelFieldAssociationTests.swift; sourceTree = "<group>"; };
B4B5CC802457B0690019C783 /* AuthFetchUserAttributesRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthFetchUserAttributesRequest.swift; sourceTree = "<group>"; };
B4B5CC862457B2470019C783 /* AuthUpdateUserAttributeRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthUpdateUserAttributeRequest.swift; sourceTree = "<group>"; };
B4B5CC8A2457B32D0019C783 /* AuthConfirmUserAttributeRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthConfirmUserAttributeRequest.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3396,11 +3398,12 @@
children = (
FAD3937923820CDB00463F5E /* DataStoreCategoryClientAPITests.swift */,
FAD3937C23820D0200463F5E /* DataStoreCategoryConfigurationTests.swift */,
B4944D51251C141200BF0BFE /* JSONValueHolderTest.swift */,
B4B34C54255B725F00033033 /* ModelFieldAssociationTests.swift */,
FAE414602399A6A500CE94C2 /* ModelRegistryTests.swift */,
B99EF4B423DB020C00D821BC /* TemporalComparableTests.swift */,
B9AF547D23F37DF20059E6C4 /* TemporalOperationTests.swift */,
B91A87A323D64B0F0049A12F /* TemporalTests.swift */,
B4944D51251C141200BF0BFE /* JSONValueHolderTest.swift */,
);
path = DataStore;
sourceTree = "<group>";
Expand Down Expand Up @@ -4796,6 +4799,7 @@
FACD264D2386E8F10068FBE6 /* JSONValue+KeyPathTests.swift in Sources */,
FA9FB782232AA26500C04D32 /* DefaultHubPluginCustomChannelTests.swift in Sources */,
FAC23567227A056600424678 /* APICategoryClientRESTTests.swift in Sources */,
B4B34C55255B725F00033033 /* ModelFieldAssociationTests.swift in Sources */,
219A88EF23F3358F00BBC5F2 /* TreeTests.swift in Sources */,
FACA35EB2326B217000E74F6 /* AmplifyConfigurationInitializationTests.swift in Sources */,
FAD3937A23820CDB00463F5E /* DataStoreCategoryClientAPITests.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ extension Model {
/// - attributes: model attributes (aka "directives" or "annotations")
/// - define: the closure used to define the model attributes and fields
/// - Returns: a valid `ModelSchema` instance
/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public static func defineSchema(name: String? = nil,
attributes: ModelAttribute...,
Expand All @@ -51,7 +51,7 @@ extension Model {
return definition.build()
}

/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public static func rule(allow: AuthStrategy,
ownerField: String? = nil,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,29 @@ import Foundation
/// }
/// ```
///
/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public enum ModelAssociation {
case hasMany(associatedWith: String?)
case hasOne(associatedWith: String?)
case belongsTo(associatedWith: String?, targetName: String?)
case hasMany(associatedFieldName: String?)
case hasOne(associatedFieldName: String?)
case belongsTo(associatedFieldName: String?, targetName: String?)

public static let belongsTo: ModelAssociation = .belongsTo(associatedWith: nil, targetName: nil)
public static let belongsTo: ModelAssociation = .belongsTo(associatedFieldName: nil, targetName: nil)

public static func belongsTo(targetName: String? = nil) -> ModelAssociation {
return .belongsTo(associatedWith: nil, targetName: nil)
return .belongsTo(associatedFieldName: nil, targetName: nil)
}

public static func hasMany(associatedWith: CodingKey?) -> ModelAssociation {
return .hasMany(associatedFieldName: associatedWith?.stringValue)
}

public static func hasOne(associatedWith: CodingKey?) -> ModelAssociation {
return .hasOne(associatedFieldName: associatedWith?.stringValue)
}

public static func belongsTo(associatedWith: CodingKey?, targetName: String?) -> ModelAssociation {
return .belongsTo(associatedFieldName: associatedWith?.stringValue, targetName: targetName)
}

}
Expand All @@ -107,6 +119,23 @@ extension ModelField {
return association != nil
}

/// If the field represents an association returns the `Model.Type`.
/// - seealso: `ModelFieldType`
/// - seealso: `ModelFieldAssociation`
/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// by host applications. The behavior of this may change without warning.
@available(*, deprecated, message: """
Use of associated model type is deprecated, use `associatedModelName` instead.
""")
public var associatedModel: Model.Type? {
switch type {
case .model(let modelName), .collection(let modelName):
return ModelRegistry.modelType(from: modelName)
default:
return nil
}
}

/// If the field represents an association returns the `ModelName`.
/// - seealso: `ModelFieldType`
/// - seealso: `ModelFieldAssociation`
Expand All @@ -130,7 +159,30 @@ extension ModelField {
/// allows (i.e. the field is a valid relationship, such as foreign keys).
/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public var requiredAssociatedModel: ModelName {
@available(*, deprecated, message: """
Use of requiredAssociatedModel with Model.Type is deprecated, use `requiredAssociatedModelName`
that return ModelName instead.
""")
public var requiredAssociatedModel: Model.Type {
guard let modelType = associatedModel else {
preconditionFailure("""
Model fields that are foreign keys must be connected to another Model.
Check the `ModelSchema` section of your "\(name)+Schema.swift" file.
""")
}
return modelType
}

/// This calls `associatedModelName` but enforces that the field must represent an association.
/// In case the field type is not a `Model` it calls `preconditionFailure`. Consumers
/// should fix their models in order to recover from it, since associations are only
/// possible between two `Model`.
///
/// - Note: as a maintainer, make sure you use this computed property only when context
/// allows (i.e. the field is a valid relationship, such as foreign keys).
/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public var requiredAssociatedModelName: ModelName {
guard let modelName = associatedModelName else {
preconditionFailure("""
Model fields that are foreign keys must be connected to another Model.
Expand All @@ -153,7 +205,7 @@ extension ModelField {
/// by host applications. The behavior of this may change without warning.
public var associatedField: ModelField? {
if hasAssociation {
let associatedModel = requiredAssociatedModel
let associatedModel = requiredAssociatedModelName
switch association {
case .belongsTo(let associatedKey, _):
// TODO handle modelName casing (convert to camelCase)
Expand Down Expand Up @@ -203,6 +255,23 @@ extension ModelField {
return false
}

/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// by host applications. The behavior of this may change without warning.
@available(*, deprecated, message: """
Use `embeddedType` is deprecated, use `embeddedTypeSchema` instead.
""")
public var embeddedType: Embeddable.Type? {
switch type {
case .embedded(let type, _), .embeddedCollection(let type, _):
if let embeddedType = type as? Embeddable.Type {
return embeddedType
}
return nil
default:
return nil
}
}

/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public var embeddedTypeSchema: ModelSchema? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

/// Defines the type of a `Model` field.
/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public enum ModelFieldType {

Expand All @@ -21,11 +21,33 @@ public enum ModelFieldType {
case timestamp
case bool
case `enum`(type: EnumPersistable.Type)
case embedded(type: Codable.Type, schema: ModelSchema? = nil)
case embeddedCollection(of: Codable.Type, schema: ModelSchema? = nil)
case embedded(type: Codable.Type, schema: ModelSchema?)
case embeddedCollection(of: Codable.Type, schema: ModelSchema?)
case model(name: ModelName)
case collection(of: ModelName)

public static func model(type: Model.Type) -> ModelFieldType {
.model(name: type.modelName)
}

public static func collection(of type: Model.Type) -> ModelFieldType {
.collection(of: type.modelName)
}

public static func embedded(type: Codable.Type) -> ModelFieldType {
guard let embeddedType = type as? Embeddable.Type else {
return .embedded(type: type, schema: nil)
}
return .embedded(type: type, schema: embeddedType.schema)
}

public static func embeddedCollection(of type: Codable.Type) -> ModelFieldType {
guard let embeddedType = type as? Embeddable.Type else {
return .embedded(type: type, schema: nil)
}
return .embeddedCollection(of: type, schema: embeddedType.schema)
}

public var isArray: Bool {
switch self {
case .collection, .embeddedCollection:
Expand Down Expand Up @@ -72,16 +94,16 @@ public enum ModelFieldType {
return .enum(type: enumType)
}
if let modelType = type as? Model.Type {
return .model(name: modelType.modelName)
return .model(type: modelType)
}
if let embeddedType = type as? Codable.Type {
return .embedded(type: embeddedType, schema: nil)
return .embedded(type: embeddedType)
}
preconditionFailure("Could not create a ModelFieldType from \(String(describing: type)) MetaType")
}
}

/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public enum ModelFieldNullability {
case optional
Expand All @@ -97,7 +119,7 @@ public enum ModelFieldNullability {
}
}

/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public struct ModelSchemaDefinition {

Expand Down Expand Up @@ -138,7 +160,7 @@ public struct ModelSchemaDefinition {
}
}

/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public enum ModelFieldDefinition {

Expand All @@ -155,21 +177,8 @@ public enum ModelFieldDefinition {
attributes: [ModelFieldAttribute] = [],
association: ModelAssociation? = nil,
authRules: AuthRules = []) -> ModelFieldDefinition {
var modifiedType: ModelFieldType = type
switch type {
case .embedded(let codable, let schema):
if schema == nil, let embeddedType = codable as? Embeddable.Type {
modifiedType = .embedded(type: codable, schema: embeddedType.schema)
}
case .embeddedCollection(let codable, let schema):
if schema == nil, let embeddedType = codable as? Embeddable.Type {
modifiedType = .embeddedCollection(of: codable, schema: embeddedType.schema)
}
default:
modifiedType = type
}
return .field(name: key.stringValue,
type: modifiedType,
type: type,
nullability: nullability,
association: association,
attributes: attributes,
Expand All @@ -195,8 +204,8 @@ public enum ModelFieldDefinition {
associatedWith associatedKey: CodingKey) -> ModelFieldDefinition {
return .field(key,
is: nullability,
ofType: .collection(of: type.modelName),
association: .hasMany(associatedWith: associatedKey.stringValue))
ofType: .collection(of: type),
association: .hasMany(associatedWith: associatedKey))
}

public static func hasOne(_ key: CodingKey,
Expand All @@ -205,8 +214,8 @@ public enum ModelFieldDefinition {
associatedWith associatedKey: CodingKey) -> ModelFieldDefinition {
return .field(key,
is: nullability,
ofType: .model(name: type.modelName),
association: .hasOne(associatedWith: associatedKey.stringValue))
ofType: .model(type: type),
association: .hasOne(associatedWith: associatedKey))
}

public static func belongsTo(_ key: CodingKey,
Expand All @@ -216,8 +225,8 @@ public enum ModelFieldDefinition {
targetName: String? = nil) -> ModelFieldDefinition {
return .field(key,
is: nullability,
ofType: .model(name: type.modelName),
association: .belongsTo(associatedWith: associatedKey?.stringValue, targetName: targetName))
ofType: .model(type: type),
association: .belongsTo(associatedWith: associatedKey, targetName: targetName))
}

public var modelField: ModelField {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// SPDX-License-Identifier: Apache-2.0
//

/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public enum ModelAttribute {

Expand All @@ -16,13 +16,13 @@ public enum ModelAttribute {
case isSystem
}

/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public enum ModelFieldAttribute {
case primaryKey
}

/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public struct ModelField {

Expand Down Expand Up @@ -55,15 +55,15 @@ public struct ModelField {
}
}

/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public typealias ModelFields = [String: ModelField]

/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public typealias ModelName = String

/// - Warning: Although this has `public` access, it is intended for internal use and should not be used directly
/// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used directly
/// by host applications. The behavior of this may change without warning.
public struct ModelSchema {

Expand Down
Loading