Skip to content

Commit

Permalink
fix(api): GraphQL Model Helpers support lowercase model names #4143 (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Equartey authored Dec 4, 2023
1 parent 864adb4 commit 3e23919
Show file tree
Hide file tree
Showing 18 changed files with 967 additions and 474 deletions.
8 changes: 8 additions & 0 deletions packages/api/amplify_api/example/amplify/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Getting Started with Amplify CLI
This directory was generated by [Amplify CLI](https://docs.amplify.aws/cli).

Helpful resources:
- Amplify documentation: https://docs.amplify.aws
- Amplify CLI documentation: https://docs.amplify.aws/cli
- More details on this folder & generated files: https://docs.amplify.aws/cli/reference/files
- Join Amplify's community: https://amplify.aws/community/
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,18 @@ type OwnerOnly @model @auth(rules: [{allow: owner}]) {
id: ID!
name: String!
}

type lowerCase
@model
@auth(
rules: [
{ allow: public, operations: [read], provider: apiKey },
{ allow: public, operations: [read], provider: iam },
{ allow: private, operations: [read], provider: iam },
{ allow: private, operations: [read], provider: userPools },
{ allow: owner, operations: [create, read, update, delete] }
]
) {
id: ID!
name: String!
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"9.2.1\",\"stackType\":\"function-Lambda\",\"metadata\":{}}",
"Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"12.8.2\",\"stackType\":\"function-Lambda\",\"metadata\":{}}",
"Parameters": {
"CloudWatchRule": {
"Type": "String",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"9.2.1\",\"stackType\":\"function-Lambda\",\"metadata\":{}}",
"Description": "{\"createdOn\":\"Mac\",\"createdBy\":\"Amplify\",\"createdWith\":\"12.8.2\",\"stackType\":\"function-Lambda\",\"metadata\":{}}",
"Parameters": {
"DOMAINBLACKLIST": {
"Type": "String",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,24 @@ void main({bool useExistingTestUser = false}) {
expect(data.rating, equals(rating));
});

testWidgets('should CREATE a lower case model name with Model helper',
(WidgetTester tester) async {
final name = 'Integration Test lowercase - ${uuid()}';
final model = lowerCase(name: name);

final req = ModelMutations.create(
model,
authorizationMode: APIAuthorizationType.userPools,
);
final res = await Amplify.API.mutate(request: req).response;
expect(res, hasNoGraphQLErrors);
final data = res.data;
if (data != null) lowerCaseCache.add(data);

expect(data?.name, equals(model.name));
expect(data?.id, equals(model.id));
});

testWidgets('should UPDATE a blog with Model helper',
(WidgetTester tester) async {
const oldName = 'Integration Test Blog to update';
Expand Down
14 changes: 14 additions & 0 deletions packages/api/amplify_api/example/integration_test/util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ TestUser? testUser;
final blogCache = <Blog>[];
final postCache = <Post>[];
final ownerOnlyCache = <OwnerOnly>[];
final lowerCaseCache = <lowerCase>[];
final cpkParentCache = <CpkOneToOneBidirectionalParentCD>[];
final cpkExplicitChildCache = <CpkOneToOneBidirectionalChildExplicitCD>[];
final cpkImplicitChildCache = <CpkOneToOneBidirectionalChildImplicitCD>[];
Expand Down Expand Up @@ -297,12 +298,25 @@ Future<OwnerOnly?> deleteOwnerOnly(OwnerOnly model) async {
return res.data;
}

Future<lowerCase?> deleteLowerCase(lowerCase model) async {
final request = ModelMutations.deleteById(
lowerCase.classType,
model.modelIdentifier,
authorizationMode: APIAuthorizationType.userPools,
);
final res = await Amplify.API.mutate(request: request).response;
expect(res, hasNoGraphQLErrors);
lowerCaseCache.removeWhere((modelFromCache) => modelFromCache.id == model.id);
return res.data;
}

Future<void> deleteTestModels() async {
await Future.wait(blogCache.map(deleteBlog));
await Future.wait(postCache.map(deletePost));
await Future.wait(cpkExplicitChildCache.map(deleteCpkExplicitChild));
await Future.wait(cpkImplicitChildCache.map(deleteCpkImplicitChild));
await Future.wait(ownerOnlyCache.map(deleteOwnerOnly));
await Future.wait(lowerCaseCache.map(deleteLowerCase));
}

/// Wait for subscription established for given request.
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

157 changes: 86 additions & 71 deletions packages/api/amplify_api/example/lib/models/Blog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,17 @@
// ignore_for_file: public_member_api_docs, annotate_overrides, dead_code, dead_codepublic_member_api_docs, depend_on_referenced_packages, file_names, library_private_types_in_public_api, no_leading_underscores_for_library_prefixes, no_leading_underscores_for_local_identifiers, non_constant_identifier_names, null_check_on_nullable_type_parameter, prefer_adjacent_string_concatenation, prefer_const_constructors, prefer_if_null_operators, prefer_interpolation_to_compose_strings, slash_for_doc_comments, sort_child_properties_last, unnecessary_const, unnecessary_constructor_name, unnecessary_late, unnecessary_new, unnecessary_null_aware_assignments, unnecessary_nullable_for_final_variable_declarations, unnecessary_string_interpolations, use_build_context_synchronously

import 'ModelProvider.dart';
import 'package:amplify_core/amplify_core.dart';
import 'package:amplify_core/amplify_core.dart' as amplify_core;
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';

/// This is an auto generated class representing the Blog type in your schema.
@immutable
class Blog extends Model {
static const classType = _BlogModelType();
/** This is an auto generated class representing the Blog type in your schema. */
class Blog extends amplify_core.Model {
static const classType = const _BlogModelType();
final String id;
final String? _name;
final List<Post>? _posts;
final TemporalDateTime? _createdAt;
final TemporalDateTime? _updatedAt;
final amplify_core.TemporalDateTime? _createdAt;
final amplify_core.TemporalDateTime? _updatedAt;

@override
getInstanceType() => classType;
Expand All @@ -50,10 +48,10 @@ class Blog extends Model {
try {
return _name!;
} catch (e) {
throw AmplifyCodeGenModelException(
AmplifyExceptionMessages
throw amplify_core.AmplifyCodeGenModelException(
amplify_core.AmplifyExceptionMessages
.codeGenRequiredFieldForceCastExceptionMessage,
recoverySuggestion: AmplifyExceptionMessages
recoverySuggestion: amplify_core.AmplifyExceptionMessages
.codeGenRequiredFieldForceCastRecoverySuggestion,
underlyingException: e.toString());
}
Expand All @@ -63,11 +61,11 @@ class Blog extends Model {
return _posts;
}

TemporalDateTime? get createdAt {
amplify_core.TemporalDateTime? get createdAt {
return _createdAt;
}

TemporalDateTime? get updatedAt {
amplify_core.TemporalDateTime? get updatedAt {
return _updatedAt;
}

Expand All @@ -80,7 +78,7 @@ class Blog extends Model {

factory Blog({String? id, required String name, List<Post>? posts}) {
return Blog._internal(
id: id == null ? UUID.getUUID() : id,
id: id == null ? amplify_core.UUID.getUUID() : id,
name: name,
posts: posts != null ? List<Post>.unmodifiable(posts) : posts);
}
Expand All @@ -103,7 +101,7 @@ class Blog extends Model {

@override
String toString() {
var buffer = StringBuffer();
var buffer = new StringBuffer();

buffer.write("Blog {");
buffer.write("id=" + "$id" + ", ");
Expand All @@ -123,21 +121,29 @@ class Blog extends Model {
id: id, name: name ?? this.name, posts: posts ?? this.posts);
}

Blog copyWithModelFieldValues(
{ModelFieldValue<String>? name, ModelFieldValue<List<Post>?>? posts}) {
return Blog._internal(
id: id,
name: name == null ? this.name : name.value,
posts: posts == null ? this.posts : posts.value);
}

Blog.fromJson(Map<String, dynamic> json)
: id = json['id'],
_name = json['name'],
_posts = json['posts'] is List
? (json['posts'] as List)
.where((e) => e?['serializedData'] != null)
.map((e) => Post.fromJson(
Map<String, dynamic>.from(e['serializedData'])))
new Map<String, dynamic>.from(e['serializedData'])))
.toList()
: null,
_createdAt = json['createdAt'] != null
? TemporalDateTime.fromString(json['createdAt'])
? amplify_core.TemporalDateTime.fromString(json['createdAt'])
: null,
_updatedAt = json['updatedAt'] != null
? TemporalDateTime.fromString(json['updatedAt'])
? amplify_core.TemporalDateTime.fromString(json['updatedAt'])
: null;

Map<String, dynamic> toJson() => {
Expand All @@ -156,76 +162,84 @@ class Blog extends Model {
'updatedAt': _updatedAt
};

static final QueryModelIdentifier<BlogModelIdentifier> MODEL_IDENTIFIER =
QueryModelIdentifier<BlogModelIdentifier>();
static final QueryField ID = QueryField(fieldName: "id");
static final QueryField NAME = QueryField(fieldName: "name");
static final QueryField POSTS = QueryField(
static final amplify_core.QueryModelIdentifier<BlogModelIdentifier>
MODEL_IDENTIFIER =
amplify_core.QueryModelIdentifier<BlogModelIdentifier>();
static final ID = amplify_core.QueryField(fieldName: "id");
static final NAME = amplify_core.QueryField(fieldName: "name");
static final POSTS = amplify_core.QueryField(
fieldName: "posts",
fieldType: ModelFieldType(ModelFieldTypeEnum.model, ofModelName: 'Post'));
static var schema =
Model.defineSchema(define: (ModelSchemaDefinition modelSchemaDefinition) {
fieldType: amplify_core.ModelFieldType(
amplify_core.ModelFieldTypeEnum.model,
ofModelName: 'Post'));
static var schema = amplify_core.Model.defineSchema(
define: (amplify_core.ModelSchemaDefinition modelSchemaDefinition) {
modelSchemaDefinition.name = "Blog";
modelSchemaDefinition.pluralName = "Blogs";

modelSchemaDefinition.authRules = [
AuthRule(
authStrategy: AuthStrategy.PUBLIC,
provider: AuthRuleProvider.APIKEY,
operations: [ModelOperation.READ]),
AuthRule(
authStrategy: AuthStrategy.PUBLIC,
provider: AuthRuleProvider.IAM,
operations: [ModelOperation.READ]),
AuthRule(
authStrategy: AuthStrategy.PRIVATE,
provider: AuthRuleProvider.IAM,
operations: [ModelOperation.READ]),
AuthRule(
authStrategy: AuthStrategy.PRIVATE,
provider: AuthRuleProvider.USERPOOLS,
operations: [ModelOperation.READ]),
AuthRule(
authStrategy: AuthStrategy.OWNER,
amplify_core.AuthRule(
authStrategy: amplify_core.AuthStrategy.PUBLIC,
provider: amplify_core.AuthRuleProvider.APIKEY,
operations: const [amplify_core.ModelOperation.READ]),
amplify_core.AuthRule(
authStrategy: amplify_core.AuthStrategy.PUBLIC,
provider: amplify_core.AuthRuleProvider.IAM,
operations: const [amplify_core.ModelOperation.READ]),
amplify_core.AuthRule(
authStrategy: amplify_core.AuthStrategy.PRIVATE,
provider: amplify_core.AuthRuleProvider.IAM,
operations: const [amplify_core.ModelOperation.READ]),
amplify_core.AuthRule(
authStrategy: amplify_core.AuthStrategy.PRIVATE,
provider: amplify_core.AuthRuleProvider.USERPOOLS,
operations: const [amplify_core.ModelOperation.READ]),
amplify_core.AuthRule(
authStrategy: amplify_core.AuthStrategy.OWNER,
ownerField: "owner",
identityClaim: "cognito:username",
provider: AuthRuleProvider.USERPOOLS,
operations: [
ModelOperation.CREATE,
ModelOperation.READ,
ModelOperation.UPDATE,
ModelOperation.DELETE
provider: amplify_core.AuthRuleProvider.USERPOOLS,
operations: const [
amplify_core.ModelOperation.CREATE,
amplify_core.ModelOperation.READ,
amplify_core.ModelOperation.UPDATE,
amplify_core.ModelOperation.DELETE
])
];

modelSchemaDefinition.addField(ModelFieldDefinition.id());
modelSchemaDefinition.addField(amplify_core.ModelFieldDefinition.id());

modelSchemaDefinition.addField(ModelFieldDefinition.field(
modelSchemaDefinition.addField(amplify_core.ModelFieldDefinition.field(
key: Blog.NAME,
isRequired: true,
ofType: ModelFieldType(ModelFieldTypeEnum.string)));
ofType: amplify_core.ModelFieldType(
amplify_core.ModelFieldTypeEnum.string)));

modelSchemaDefinition.addField(ModelFieldDefinition.hasMany(
modelSchemaDefinition.addField(amplify_core.ModelFieldDefinition.hasMany(
key: Blog.POSTS,
isRequired: false,
ofModelName: 'Post',
associatedKey: Post.BLOG));

modelSchemaDefinition.addField(ModelFieldDefinition.nonQueryField(
fieldName: 'createdAt',
isRequired: false,
isReadOnly: true,
ofType: ModelFieldType(ModelFieldTypeEnum.dateTime)));

modelSchemaDefinition.addField(ModelFieldDefinition.nonQueryField(
fieldName: 'updatedAt',
isRequired: false,
isReadOnly: true,
ofType: ModelFieldType(ModelFieldTypeEnum.dateTime)));
modelSchemaDefinition.addField(
amplify_core.ModelFieldDefinition.nonQueryField(
fieldName: 'createdAt',
isRequired: false,
isReadOnly: true,
ofType: amplify_core.ModelFieldType(
amplify_core.ModelFieldTypeEnum.dateTime)));

modelSchemaDefinition.addField(
amplify_core.ModelFieldDefinition.nonQueryField(
fieldName: 'updatedAt',
isRequired: false,
isReadOnly: true,
ofType: amplify_core.ModelFieldType(
amplify_core.ModelFieldTypeEnum.dateTime)));
});
}

class _BlogModelType extends ModelType<Blog> {
class _BlogModelType extends amplify_core.ModelType<Blog> {
const _BlogModelType();

@override
Expand All @@ -239,13 +253,14 @@ class _BlogModelType extends ModelType<Blog> {
}
}

/// This is an auto generated class representing the model identifier
/// of [Blog] in your schema.
@immutable
class BlogModelIdentifier implements ModelIdentifier<Blog> {
/**
* This is an auto generated class representing the model identifier
* of [Blog] in your schema.
*/
class BlogModelIdentifier implements amplify_core.ModelIdentifier<Blog> {
final String id;

/// Create an instance of BlogModelIdentifier using [id] the primary key.
/** Create an instance of BlogModelIdentifier using [id] the primary key. */
const BlogModelIdentifier({required this.id});

@override
Expand Down
Loading

0 comments on commit 3e23919

Please sign in to comment.