amplify-codegen
amplify-codegen copied to clipboard
[iOS & Swift] UUID strings are in All caps/uppercase, causing issues on DynamoDB
Before opening, please confirm:
- [X] I have installed the latest version of the Amplify CLI (see above), and confirmed that the issue still persists.
- [X] I have searched for duplicate or closed issues.
- [X] I have read the guide for submitting bug reports.
- [X] I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
- [X] I have removed any sensitive information from my code snippets and submission.
How did you install the Amplify CLI?
npm
If applicable, what version of Node.js are you using?
17.4.0
Amplify CLI Version
9.1.0
What operating system are you using?
Mac
Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes made.
No manual changes made
Amplify Categories
auth, storage, api
Amplify Commands
codegen, pull
Describe the bug
On iOS (Swift), amplify codegen models generates models in swift. The issue (only on iOS, Swift) is as follows:
- The generated models use
UUID().uuidStringfor fields defined asIDin the schema, and stores them asStringtype because DynamoDB expects aStringtype as key. In Swift,UUID().uuidStringresults in an all caps/uppercase string to be generated, which is an Apple standard. - The issue is that having the same UUID in uppercase vs lowercase causes two different keys to be identified by DynamoDB. This is especially a problem for us because we have multiple scripts (for media processing and storage) running in background that expect all lowercase strings. Since DynamoDB stores UUID strings instead of actual UUIDs for keys, we cannot rely on the case-insensitivity of UUIDs.
- What we want is to have the IDs of every record generated on Swift (iOS) to be strictly in lowercase. Maybe using
UUID().uuidString.lowercased()to generateStringfor theIDfield of each model.
The Swift struct for Post model
public struct Post: Model {
public let id: String
public var name: String
public var random_id: String?
public var blog: Blog?
public var createdAt: Temporal.DateTime?
public var updatedAt: Temporal.DateTime?
public init(id: String = UUID().uuidString,
name: String,
random_id: String? = nil,
blog: Blog? = nil) {
self.init(id: id,
name: name,
random_id: random_id,
blog: blog,
createdAt: nil,
updatedAt: nil)
}
internal init(id: String = UUID().uuidString,
name: String,
random_id: String? = nil,
blog: Blog? = nil,
createdAt: Temporal.DateTime? = nil,
updatedAt: Temporal.DateTime? = nil) {
self.id = id
self.name = name
self.random_id = random_id
self.blog = blog
self.createdAt = createdAt
self.updatedAt = updatedAt
}
}
I also tried using an extension to address this, but as you probably know, I have to create a new stored property to store the lowercase version of the uuidString and then use the newly defined variable. My implementation is as follows:
extension UUID {
var uuidStringLowercased: String {
get {
return self.uuidString.lowercased()
}
}
}
Expected behavior
The ID should be a lowercased String in the UUID format. Since Apple gives an ALL CAPS string, I want a way to have it converted to lowercased string to create objects from the codegenerated models.
Something as simple as having id: String = UUID().uuidString.lowercased() in the constructors would do the trick while also respecting the best practices of using UUIDs, i.e., to use them in a lowercased form.
If the above mentioned method is troubling to implement, please explain to me why that's the case and how I can get around the issue.
I am open to using other ways to have either UUID().uuidString inherently give a lowercased string, if possible, OR have a script run to convert the line UUID().uuidString to UUID().uuidString.lowercased() in every single model. Currently, I have 18 files that each contain this line in 2 places, which makes it stupid to change every single file every time I do an amplify pull.
I want to avoid using uppercase strings at all if possible because it is prone to causing a system breakdown in case the same string exists as 2 different ids because if it being in different alphabetical cases.
Reproduction steps
- Set up using any generic graphQL schema which has ID! field.
- Do an
amplify codegen models - Go to the model and see the constructor first line to see what part of code I am talking about
- Create a new object and push it to DynamoDB via AppSync.
- Now use the newly created object's string -> convert it to lowercase -> use the lowercase string to create another object -> push it to dynamoDB via AppSync
- Notice how the same uuidString causes 2 different entries to be created on DynamoDB.
GraphQL schema(s)
# Put schemas below this line
type Blog @model @auth(rules: [{allow: public}]) {
id: ID!
name: String!
customs: [MyCustomModel]
notes: [String]
post: [Post] @hasMany(indexName: "postByBlog", fields: ["id"])
}
type Post @model @auth(rules: [{allow: public}]) {
id: ID!
name: String!
blog_id: ID @index(name: "postByBlog")
random_id: String @index(name: "byRandom")
blog: Blog @belongsTo(fields: ["blog_id"])
}
type MyCustomModel {
id: ID!
name: String!
desc: String
children: [MyNestedModel]
}
type MyNestedModel {
id: ID!
nestedName: String!
notes: [String]
}
Project Identifier
No response
Log output
# Put your logs below this line
Additional information
- Workaround: Add
.lowercased()statement after theUUID().uuidStringdeclaration to convert to lowercase. - Run a script to change all models to modify that particular line
- Create an extension of UUID and define a new stored property to store lowercase version of uuidString and use that in models, which would again require changing every single model.swift file.