feat: auto-increment for entity id#244
Conversation
Sekhmet
left a comment
There was a problem hiding this comment.
@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.
This shouldn't be handled with regexes. Directive can be handled natively with GraphQL.
There was a problem hiding this comment.
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.
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:
https://github.com/checkpoint-labs/checkpoint/blob/e6dd8b3580604d39de79f4c8c41fb2103582677c/src/graphql/resolvers.ts#L182-L186
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:
https://github.com/checkpoint-labs/checkpoint/blob/23698a4587b4fe2b1160fe0224401e0d5d1bb90f/src/graphql/controller.ts#L223-L228
There was a problem hiding this comment.
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 ! |
Sekhmet
left a comment
There was a problem hiding this comment.
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
|
|
||
| it('should work', async () => { | ||
| const controller = new GqlEntityController(` | ||
| const schema = ` |
There was a problem hiding this comment.
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.
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.
Thanks a lot for the review. I updated code based on your comments.
Regarding ORM, i could take a look ?
package.json
Outdated
| "src/**/*" | ||
| ] | ||
| } | ||
| } No newline at end of file |
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.
| //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.
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 :
