-
Notifications
You must be signed in to change notification settings - Fork 23
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: auto-increment for entity id #244
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@autoincrement
can be handled as native GraphQL directive, like @derivedFrom
Ok thx, will check that. |
Update done. New directive @autoincrement added. |
src/graphql/controller.ts
Outdated
* @param schema | ||
* @returns A map where key is table name and values a list of fields with annotation autoIncrement | ||
*/ | ||
private extractAutoIncrementFields(schema: string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be handled with regexes. Directive can be handled natively with GraphQL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, can you guide me to some example of what you want. From my understanding autoIncrement directive is not native in GraphQL so i need to implement the logic behind this new directive. Thank you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we extended GraphQL with our custom directive here, we can then access that directive directly from our GraphQL tree.
This way you can look at the field (id field in this example, and check if it has @autoincrement
directive, same as we do with @derivedFrom
:
checkpoint/src/graphql/resolvers.ts
Lines 182 to 186 in e6dd8b3
const directives = field.astNode?.directives ?? []; | |
const derivedFromDirective = directives.find(dir => dir.name.value === 'derivedFrom'); | |
if (!derivedFromDirective) { | |
throw new Error(`field ${field.name} is missing derivedFrom directive`); | |
} |
That means we don't have to bother with writing our own dummy parser for GraphQL to extract autoIncrementFields, and just check for field.astNode.directives
here:
checkpoint/src/graphql/controller.ts
Lines 223 to 228 in 23698a4
if ( | |
autoIncrementFieldsMap.size == 0 || | |
autoIncrementFieldsMap.get(tableName)?.length === 0 | |
) { | |
t.primary(['id']); | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK thx for the hint. I will check it and modify accordingly.
@0xTitan thank you for your contribution so far. Are you still expecting to work on this issue? If not I could push it across finish line. |
Hello @Sekhmet, sorry i didn't had time to continue on this, i was involved in other starknet project. I would like to finish this task. But if it's easier for you can push it across finish line and i can create a new PR later with correct implementation. |
Hi @Sekhmet, i pushed changes to remove regex and use directive. Huge thanks for your help and your patience ! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks way cleaner thank you!
General thoughts:
- can you revert any unrelated changes to the formatting? Most of it would be solved by running Prettier or
yarn lint
. - the comments added are a bit too much in my opinion as they explain pretty self-explanatory code, so they could be removed
- we have added ORM since and it won't work well with it (as currently ORM requires you to create new instances of ORM models by passing ID to a constructor) - is this something you are also willing to take a look at? Otherwise we probably should at least prevent ORM models from being created for entities with autoincrement fields until it's implemented. If you don't want to work on that I could at this logic so we could get your PR merged.
test/unit/graphql/controller.test.ts
Outdated
@@ -56,7 +56,7 @@ type Vote { | |||
}); | |||
|
|||
it('should work', async () => { | |||
const controller = new GqlEntityController(` | |||
const schema = ` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd use just a single test case to test everything (just put autoincrement and nested properties in here) or
use it.each
to avoid duplication of code.
src/graphql/controller.ts
Outdated
//if there is no autoIncrement fields on current table, mark the id as primary | ||
const tableHasAutoIncrement = this.getTypeFields(type).some(field => { | ||
const directives = field.astNode?.directives ?? []; | ||
const autoIncrementDirective = directives.find(dir => dir.name.value === 'autoIncrement'); | ||
return autoIncrementDirective; | ||
}) | ||
|
||
if (!tableHasAutoIncrement) | ||
t.primary(['id']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code duplicates quite a bit of logic from below.
I wonder if it wouldn't be cleaner to remove this initial lookup and instead use original forEach:
let tableHasAutoIncrement = false
// ...
this.getTypeFields(type).forEach(field => {
// ...
if (autoIncrementDirective) {
tableHasAutoIncrement = true
t.increments(field.name, { primaryKey: true });
}
}
// ...
if (!tableHasAutoIncrement) {
t.primary(['id'])
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the review. I updated code based on your comments.
Regarding ORM, i could take a look ?
package.json
Outdated
@@ -61,4 +61,4 @@ | |||
"dist/**/*", | |||
"src/**/*" | |||
] | |||
} | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you revert this change?
src/graphql/controller.ts
Outdated
const directives = field.astNode?.directives ?? []; | ||
const autoIncrementDirective = directives.find(dir => dir.name.value === 'autoIncrement'); | ||
|
||
//Check if field is declared as autoincrement |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//Check if field is declared as autoincrement |
test/unit/graphql/controller.test.ts
Outdated
expect(createQuery).toMatchSnapshot(); | ||
}); | ||
|
||
it('should work with autoincrement and nested objects', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like it could just be the only test case in this file (it should work
).
Thanks for your comments. Update done. |
Hello.
Implementation done. Auto increment annotation can be added only once on entity definition. Only Int, BigInt and ID (for nested object) are managed.
Eg :
`scalar Text
type Post {
id: Int! @autoincrement
author: String!
content: Text!
tag: String
tx_hash: String!
created_at: Int!
created_at_block: Int!
poster: Poster
}
type Poster {
id: ID! @autoincrement
name: String!
}`
Unfortunately i'm struggling with knex implementation and the primaryKey definition. There is normally the possiblity to define if an autoIncrement field should be defined as primaryKey, this is not working when i'm setting it false. Due to that i can only managed one autoIncrement field per table. Maybe enought for now.
Eg :
Knex increment
knex.schema.createTable('users', function (table) { table.increments('id'); table.increments('other_id', { primaryKey: false }); });
I added two more tests :
I put the constant needed under type.ts. Let me know if it's suitable.
The result under myssql for the schema above :
![image](https://private-user-images.githubusercontent.com/104304962/251578337-7fe3babf-6eb6-4bf1-bd30-1e47291e8ec4.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkyNTI4OTksIm5iZiI6MTczOTI1MjU5OSwicGF0aCI6Ii8xMDQzMDQ5NjIvMjUxNTc4MzM3LTdmZTNiYWJmLTZlYjYtNGJmMS1iZDMwLTFlNDcyOTFlOGVjNC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMjExJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDIxMVQwNTQzMTlaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1lYTIxMGE5MDJkNjlmM2FhYWNjNDk3M2FkNjUwMjYyOGI1M2UxZDY3ZDkyMWM2MTJjMjI1YWFlYjYwNjFiNmVjJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.4KRyYzBaJbCFQ0iSvZ3llW2nWVLBWWS_ccaDzODtAPc)