Open gotexis opened 5 years ago
GraphQL servers usually generate a single schema.json for the app.
Never heard of that. Sounds interesting. Currently the plugin runs a introspection query against the GraphQL API to get the schema.
I wonder if there is a way to consume it, instead of declaring all models/fields manually, like I have read in vuex-orm-core documentation.
I thought about that: Based on the GraphQL schema, we could auto generate the Vuex-ORM models. This isn't easy, but we could do some investigation on this in the future.
@phortx You are right, based on my limited knowledge of GraphQL, I thought the OPTION introspection query on API was called "serving a cached JSON" .... lul So basically it was actually serving a cached JSON but I never thought the official way of calling it was "Introspection".
So regarding the boilerplate, because I was using Django-Graphene, I ended up writing a code generator that converts all models into VueX-ORM-GraphQL schema.
# jinja2 template
import {Model} from '@vuex-orm/core'
// import related models
// -------------------------------------------------------------------------------------
{% for model in related_models %}
import {{ model|name }} from 'models/{{ model|name }}'
{% endfor %}
// main
// -------------------------------------------------------------------------------------
export default class {{ model|name }} extends Model {
static entity = '{{ model|name|lower }}'
static fields() {
return {
{% for f in model_fields %}
{% if f|type(fields.related.ManyToOneRel) %} {# pass #}
{% elif f|type((fields.AutoField, fields.CharField, fields.TextField)) %} {# PK, Str #}
{{ f.attname | __ }}: this.string(''),
{% elif f|type(fields.IntegerField) %} {# int #}
{{ f.attname | __ }}: this.int(''),
{% elif f|type((fields.DateField, fields.TimeField, fields.DateTimeField)) %} {# datetime #}
{{ f.attname | __ }}: this.string(''), // defaulting to str as of now...
{% elif f|type(fields.related.ForeignKey) %} {# FK #}
{% with related_model = f.related_fields[0][1].model if f.related_fields else f._related_fields[0][1].model %}
{% if related_model not in exclude_models and related_model|name not in exclude_model_names %}
{{ f.attname|replace("_id", " ") | __ }}: this.belongsTo({{ related_model|name }}, '{{ related_model|name|lower }}Id'),
{% endif %}
{% endwith %}
{% elif f|type(fields.related.ManyToManyField) %}
{% if f.related_model not in exclude_models and f.related_model|name not in exclude_model_names %}
{# as per https://vuex-orm.github.io/plugin-graphql/guide/relationships.html#many-to-many #}
{{ f.attname | __ }}: this.belongsToMany({{ f.related_model|name }}, {{ f.remote_field.through|name }}, '{{ model|name|lower }}Id' , '{{ f.related_model|name|lower }}Id'),
{% else %}
{% endif %}
{% endif %}
{% endfor %}
}
}
}
converts to this:
import {Model} from '@vuex-orm/core'
// import related models
// -------------------------------------------------------------------------------------
import Shop from 'models/Shop'
import Order from 'models/Order'
import Cart from 'models/Cart'
import Item from 'models/Item'
// main
// -------------------------------------------------------------------------------------
export default class User extends Model {
static entity = 'user'
static fields() {
return {
id : this.string(''),
password : this.string(''),
last_login : this.string(''), // defaulting to str as of now...
username : this.string(''),
first_name : this.string(''),
last_name : this.string(''),
email : this.string(''),
date_joined : this.string(''), // defaulting to str as of now...
referer1 : this.belongsTo(User, 'userId'),
referer2 : this.belongsTo(User, 'userId'),
referer3 : this.belongsTo(User, 'userId'),
shop : this.belongsTo(Shop, 'shopId'),
name : this.string(''),
item : this.belongsToMany(Item, Cart, 'userId' , 'itemId'),
}
}
}
Surely I understand this isn't proper programming, but it helps me achieve a lot in a relatively short amount of time ;) Plus I love dark magic
This is a nice approach. I'm very open for the idea of initially generating the Vuex-ORM models via the introspection query. I think this would be a very useful feature.
Hi. this sounds super interesting. I am wondering. I haven't read the plugin's source, but at a high level, isn't it that your plugin does sort of the opposite? as in convert vuex queries to graphQL. Can't the same resolution logic then be used to figure out the vuex models definitions from the introspection?
Yes exactly. We just have to implement it 😎
I saw this from the documentation - the plugin does know of the schema of the grapheQL server.
https://vuex-orm.github.io/plugin-graphql/guide/faq.html#does-vuex-orm-graphql-know-my-graphql-schema
GraphQL servers usually generate a single schema.json for the app.
I wonder if there is a way to consume it, instead of declaring all models/fields manually, like I have read in vuex-orm-core documentation.
This may be too much to ask tho