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

feat(datastore): implement ModelIndex #1366

Merged
merged 4 commits into from
Mar 3, 2022
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions packages/amplify_core/lib/amplify_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export 'src/types/models/model_association.dart';
export 'src/types/models/model_field.dart';
export 'src/types/models/model_field_definition.dart';
export 'src/types/models/model_field_type.dart';
export 'src/types/models/model_index.dart';
export 'src/types/models/model_provider.dart';
export 'src/types/models/model_schema.dart';
export 'src/types/models/model_schema_definition.dart';
Expand Down
89 changes: 89 additions & 0 deletions packages/amplify_core/lib/src/types/models/model_index.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

import 'dart:convert';

import 'package:amplify_core/amplify_core.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';

/// Describe an index that is created by `@primaryKey` or `@index` directive,
HuiSF marked this conversation as resolved.
Show resolved Hide resolved
/// and is listed in [ModelSchemaDefinition.indexes].
@immutable
class ModelIndex {
/// Index name that is defined by the name parameter of `@index` directive in
/// a model schema. [name] will always be null when the index is representing
/// `@primaryKey` directive.
final String? name;

/// An array of field names. The first field is always the field that is
/// annotated by` @primaryKey` or `@index` directive, and the remaining
/// fields are the fields specified by `sortKeyFields` parameter of
/// `@primaryKey` or `@index` directive.
final List<String> fields;

/// Constructor
HuiSF marked this conversation as resolved.
Show resolved Hide resolved
const ModelIndex({
required this.fields,
this.name,
});

/// Make a copy of an existing [ModelIndex] instance.
ModelIndex copyWith({
List<String>? fields,
String? name,
}) =>
ModelIndex(fields: fields ?? this.fields, name: name ?? this.name);

/// Generate a [Map] that represents [ModelIndex].
Map<String, dynamic> toMap() {
final map = {
'name': name,
'fields': fields,
};

return map;
}

/// Create an instance of [ModelIndex] from a [Map].
factory ModelIndex.fromMap(Map<String, dynamic> map) =>
ModelIndex(fields: map['fields'], name: map['name']);

/// Create an instance of [ModelIndex] from a json
factory ModelIndex.fromJson(String source) =>
ModelIndex.fromMap(jsonDecode(source));

/// Generate a json string that represents [ModelIndex]
String toJson() => jsonEncode(toMap());

@override
String toString() => 'ModelIndex(name: $name, fields: $fields)';

@override
bool operator ==(Object other) {
Copy link
Member

Choose a reason for hiding this comment

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

Should we start using the AWSEquatable mixin instead of implementing these everywhere? It is currently in amplify_flutter, so you would have to move it if you want to use it. I don't think you have to use it for this PR, but I want to discuss if we want to start using it moving forward.

@dnys1 I think you added AWSEquatable. Any reason we can't move that to amplify_core and start using it throughout all packages?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, wasn't aware of this mixin. Can we also use it with generated models? @dnys1

if (identical(this, other)) {
return true;
}

final listEquals = const DeepCollectionEquality().equals;

return other is ModelIndex &&
name == other.name &&
listEquals(fields, other.fields);
}

@override
int get hashCode => name.hashCode ^ fields.hashCode;
}
209 changes: 109 additions & 100 deletions packages/amplify_core/lib/src/types/models/model_schema.dart
Original file line number Diff line number Diff line change
@@ -1,100 +1,109 @@
/*
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

library model_schema;

import 'dart:convert';

import 'package:collection/collection.dart';

import 'auth_rule.dart';
import 'model_field.dart';

class ModelSchema {
final String name;
final String? pluralName; //opt
final List<AuthRule>? authRules; //opt
final Map<String, ModelField>? fields;

const ModelSchema({
required this.name,
this.pluralName,
this.authRules,
this.fields,
});

ModelSchema copyWith(
{String? name,
String? pluralName,
List<AuthRule>? authRules,
Map<String, ModelField>? fields}) {
return ModelSchema(
name: name ?? this.name,
pluralName: pluralName ?? this.pluralName,
authRules: authRules ?? this.authRules,
fields: fields ?? this.fields);
}

Map<String, dynamic> toMap() {
final map = {
'name': name,
'pluralName': pluralName,
'authRules': authRules?.map((x) => x.toMap()).toList(),
'fields': fields?.map((key, value) => MapEntry('$key', value.toMap())),
};
return Map<String, dynamic>.from(map)
..removeWhere((k, dynamic v) => v == null);
}

factory ModelSchema.fromMap(Map<String, dynamic> map) {
return ModelSchema(
name: map['name'],
pluralName: map['pluralName'],
authRules: List<AuthRule>.from(
map['authRules']?.map((dynamic x) => AuthRule.fromMap(x))),
fields: Map<String, ModelField>.from(map['fields']),
);
}

String toJson() => json.encode(toMap());

factory ModelSchema.fromJson(String source) =>
ModelSchema.fromMap(json.decode(source));

@override
String toString() {
return 'ModelSchema(name: $name, pluralName: $pluralName, authRules: $authRules, fields: $fields)';
}

@override
bool operator ==(Object o) {
if (identical(this, o)) return true;
final collectionEquals = const DeepCollectionEquality().equals;

return o is ModelSchema &&
o.name == name &&
o.pluralName == pluralName &&
collectionEquals(o.authRules, authRules) &&
collectionEquals(o.fields, fields);
}

@override
int get hashCode {
return name.hashCode ^
pluralName.hashCode ^
authRules.hashCode ^
fields.hashCode;
}
}
/*
* Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Copy link
Member

Choose a reason for hiding this comment

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

Not sure why this is registering as a change?

Copy link
Member Author

Choose a reason for hiding this comment

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

As this PR converts this file from CRLF to LF mode (The first commit of this PR).
If you view the second commit it shows the actual changes on this file.

*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

library model_schema;

import 'dart:convert';

import 'package:collection/collection.dart';

import 'auth_rule.dart';
import 'model_field.dart';
import 'model_index.dart';

class ModelSchema {
final String name;
final String? pluralName; //opt
final List<AuthRule>? authRules; //opt
final Map<String, ModelField>? fields;
final List<ModelIndex>? indexes;

const ModelSchema({
required this.name,
this.pluralName,
this.authRules,
this.fields,
this.indexes,
});

ModelSchema copyWith(
{String? name,
String? pluralName,
List<AuthRule>? authRules,
Map<String, ModelField>? fields}) {
return ModelSchema(
name: name ?? this.name,
pluralName: pluralName ?? this.pluralName,
authRules: authRules ?? this.authRules,
fields: fields ?? this.fields,
indexes: indexes ?? this.indexes,
);
}

Map<String, dynamic> toMap() {
final map = {
'name': name,
'pluralName': pluralName,
'authRules': authRules?.map((x) => x.toMap()).toList(),
'fields': fields?.map((key, value) => MapEntry('$key', value.toMap())),
'indexes': indexes?.map((value) => value.toMap()).toList(),
};
return Map<String, dynamic>.from(map)
..removeWhere((k, dynamic v) => v == null);
}

factory ModelSchema.fromMap(Map<String, dynamic> map) {
return ModelSchema(
name: map['name'],
pluralName: map['pluralName'],
authRules: List<AuthRule>.from(
map['authRules']?.map((dynamic x) => AuthRule.fromMap(x))),
fields: Map<String, ModelField>.from(map['fields']),
indexes: List<ModelIndex>.from(map['indexes']),
);
}

String toJson() => json.encode(toMap());

factory ModelSchema.fromJson(String source) =>
ModelSchema.fromMap(json.decode(source));

@override
String toString() {
return 'ModelSchema(name: $name, pluralName: $pluralName, authRules: $authRules, fields: $fields, indexes: $indexes)';
}

@override
bool operator ==(Object o) {
if (identical(this, o)) return true;
final collectionEquals = const DeepCollectionEquality().equals;

return o is ModelSchema &&
o.name == name &&
o.pluralName == pluralName &&
collectionEquals(o.authRules, authRules) &&
collectionEquals(o.fields, fields) &&
collectionEquals(o.indexes, indexes);
}

@override
int get hashCode {
return name.hashCode ^
pluralName.hashCode ^
authRules.hashCode ^
fields.hashCode ^
indexes.hashCode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
import 'auth_rule.dart';
import 'model_field.dart';
import 'model_field_definition.dart';
import 'model_index.dart';
import 'model_schema.dart';

class ModelSchemaDefinition {
late String name;
String? pluralName;
List<AuthRule>? authRules;
List<ModelIndex>? indexes;
late Map<String, ModelField> fields;

ModelSchemaDefinition() {
Expand All @@ -38,6 +40,7 @@ class ModelSchemaDefinition {
pluralName: pluralName,
authRules: authRules,
fields: fields,
indexes: indexes,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export 'package:amplify_core/src/types/models/model.dart';
export 'package:amplify_core/src/types/models/model_field.dart';
export 'package:amplify_core/src/types/models/model_field_definition.dart';
export 'package:amplify_core/src/types/models/model_field_type.dart';
export 'package:amplify_core/src/types/models/model_index.dart';
export 'package:amplify_core/src/types/models/model_provider.dart';
export 'package:amplify_core/src/types/models/model_schema.dart';
export 'package:amplify_core/src/types/models/model_schema_definition.dart';
Expand Down
Loading