Skip to content

Commit

Permalink
Nested fragment fields with arguments are here + refactoring + readme
Browse files Browse the repository at this point in the history
  • Loading branch information
mrspartak committed May 25, 2020
1 parent b0de3a2 commit 24d33f0
Show file tree
Hide file tree
Showing 9 changed files with 616 additions and 330 deletions.
57 changes: 52 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Node.js Package](https://github.com/mrspartak/hasura-om/workflows/Node.js%20Package/badge.svg)](https://nodei.co/npm/hasura-om/)
[![Coverage Status](https://coveralls.io/repos/github/mrspartak/hasura-om/badge.svg?branch=master)](https://coveralls.io/github/mrspartak/hasura-om?branch=master)
[![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo)

[![Codacy Badge](https://app.codacy.com/project/badge/Grade/5489a27a08094fd6b34f54ce32b0dcef)](https://www.codacy.com/manual/assorium/hasura-om?utm_source=github.com&utm_medium=referral&utm_content=mrspartak/hasura-om&utm_campaign=Badge_Grade)

This library provides an object way to interact with Hasura from backend. Main focus is on fragments, queries are autogenerated.
Base fragments (base - all table fields/pk - primary keys) are autogenerated, then you can extend them or create new.
Expand All @@ -26,12 +26,13 @@ If you know a better way to solve this problem, you are welcome to issues or ema
- [x] Fragment extending (v0.0.7)
- [x] Subscriptions (v0.0.10)
- [x] Aggregate queries (v0.0.12)
- [ ] Nested queries
- [x] Nested queries
- [ ] Hasura class extend EventEmitter
- [ ] Refactor query builder code
- [ ] Docs
- [ ] Support directives

# Simple example
## Simple example
```javascript
const { Hasura } = require('hasura-om')

Expand Down Expand Up @@ -184,6 +185,7 @@ let unsub = om.subscribe({
})
```

## Fragments
The only control you have is fragments. So this library provides base fragments with all table fields without relations. Of course you need them, so you have many ways to do so.
```javascript

Expand Down Expand Up @@ -260,12 +262,57 @@ let baseUserFragment = orm.table('user').fragment('base')
let basePostFragment = orm.table('post').fragment('base')

orm.table('user').createFragment('some_unique_name', [
baseUserFragment.gqlFields(),
baseUserFragment,
{
key: 'posts',
values: [
basePostFragment.gqlFields(),
basePostFragment,
]
}
])
```

## Nested fields arguments
This is really hard to implement and I hope current implementation works fine. I will investigate it later, when I will have troubles or get any issues.
```javascript

const fragment2 = new Fragment({
table: 'test',
name: 'with_nested_args',
fields: [
'id',
[
'logo',
['url'],
{
_table: 'images',
limit: 'logo_limit',
offset: 'logo_offset',
where: 'logo_where',
order_by: 'logo_order_by',
distinct_on: 'logo_distinct_on',
},
],
],
});

/*
This will generate such fragment
Fragment with_nested_args_fragment_test on test {
id
logo (limit: $logo_limit, ...) {
url
}
}
*/

await orm.query({
test: {
fragment: 'with_nested_args',
variables: {
'logo_limit': 1
}
}
})
```
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hasura-om",
"version": "0.0.6",
"version": "0.0.15",
"description": "Hasura Fragment focused ORM library",
"author": "Spartak <[email protected]> (https://spartak.io/)",
"keywords": [
Expand Down Expand Up @@ -40,7 +40,8 @@
"no-return-assign": 0,
"camelcase": 0,
"block-scoped-var": 0,
"no-sequences": 0
"no-sequences": 0,
"no-negated-condition": 0
}
},
"ava": {
Expand Down
73 changes: 59 additions & 14 deletions src/orm/fragment.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const {fieldsToGql} = require('../utils/builders');
const {fieldsToGql, template} = require('../utils/builders');

class Fragment {
constructor(parameters) {
this._isFragment = true;

const defaultParameters = {
name: 'base',
table: null,
Expand All @@ -14,28 +16,71 @@ class Fragment {
throw new Error('table is required');
}

if (Object.keys(this.params.fields).length === 0) {
if (Object.keys(this.rawFields()).length === 0 || this.rawFields() === '') {
throw new Error('fields are required');
}

this._gqlFields = fieldsToGql(this.params.fields);
// Builded fields part of fragment
const {fields, fragmentOperationArgument} = fieldsToGql(this.rawFields());
this._fields = fields;
this._arguments = fragmentOperationArgument;

// Templates to create parts local parts of fragment
this._fragmentTemplate = template`
fragment ${'fragmentName'} on ${'table'} {
${'fields'}
}
`;
this._nameTemplate = template`${'name'}_fragment_${'table'}`;
}

gqlFields() {
return this._gqlFields;
/*
Fields passed to Fragment constructor
*/
rawFields() {
return this.params.fields;
}

build() {
const fragmentName = `${this.params.name}_fragment_${this.params.table}`;
const fields = this.gqlFields();
/*
Generated fields to string
*/
fields() {
return this._fields;
}

/*
Generated arguments if fragment contains them
*/
arguments() {
return this._arguments;
}

/*
Generated Fragment name
*/
name() {
return this._nameTemplate({
name: this.params.name,
table: this.params.table,
});
}

/*
Generated Fragment
*/
fragment() {
return this._fragmentTemplate({
fragmentName: this.name(),
table: this.params.table,
fields: this.fields(),
});
}

build() {
return {
name: fragmentName,
raw: `
fragment ${fragmentName} on ${this.params.table} {
${fields}
}
`,
name: this.name(),
raw: this.fragment(),
arguments: this.arguments(),
};
}
}
Expand Down
58 changes: 42 additions & 16 deletions src/orm/hasura.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ class Hasura {
return [error];
}

// Console.log(query);

settings = __.mergeDeep({}, this.params.query, settings);

const [err, response] = await this.$gql.run({
Expand All @@ -180,8 +182,8 @@ class Hasura {
buildQuery(parameters, queryType = 'query') {
const tables = Object.keys(parameters);

const queryName = [];
const queryVariables = [];
const operationName = [];
const operationArguments = [];
const queryFields = [];
const queryFragments = {};
const queryFlatSetting = [];
Expand All @@ -194,9 +196,12 @@ class Hasura {
queryType,
});

variables = Object.assign({}, parameters[tableName].variables);

builts.forEach((built) => {
queryName.push(built.query.name);
queryVariables.push(...built.query.variables);
operationName.push(built.query.name);
operationArguments.push(...built.query.arguments);

queryFields.push(built.query.fields);
if (built.query.fragment) {
queryFragments[built.query.fragment.fragmentName] = built.query.fragment.fragment;
Expand All @@ -205,17 +210,37 @@ class Hasura {
queryFlatSetting.push(built.query.flatSetting);
variables = Object.assign({}, variables, built.variables);
});

/* QueryName.push(built.query.name);
queryVariables.push(...built.query.variables);
queryFields.push(built.query.fields);
queryFragments[built.query.fragment.fragmentName] = built.query.fragment.fragment;
variables = Object.assign({}, variables, built.variables); */
});

/*
//!queryFragments[]
fragment pk_fragment_user on user {
id
}
//!queryType - query | subscription
//!operationName - [S_s_user, S_a_user]
//!operationArguments - [$user_where: user_bool_exp]
query S_s_user_S_a_user($user_where: user_bool_exp) {
//!queryFields - [user , user_aggregate]
user(where: $user_where) {
...pk_fragment_user
}
user_aggregate {
aggregate {
count
sum {
id
money
}
}
}
}
*/
const query = `
${Object.values(queryFragments).join('\n')}
${queryType} ${queryName.join('_')} ${queryVariables.length > 0 ? '(' + queryVariables.join(', ') + ')' : ''} {
${queryType} ${operationName.join('_')} ${operationArguments.length > 0 ? '(' + operationArguments.join(', ') + ')' : ''} {
${queryFields.join('\n')}
}
`;
Expand Down Expand Up @@ -278,8 +303,8 @@ class Hasura {
buildMutation(parameters) {
const tables = Object.keys(parameters);

const queryName = [];
const queryVariables = [];
const operationName = [];
const operationArguments = [];
const queryFields = [];
const queryFragments = {};
const queryFlatSetting = [];
Expand All @@ -292,8 +317,9 @@ class Hasura {
});

builts.forEach((built) => {
queryName.push(built.query.name);
queryVariables.push(...built.query.variables);
operationName.push(built.query.name);
operationArguments.push(...built.query.arguments);

queryFields.push(built.query.fields);
queryFragments[built.query.fragment.fragmentName] = built.query.fragment.fragment;
queryFlatSetting.push(built.query.flatSetting);
Expand All @@ -303,7 +329,7 @@ class Hasura {

const query = `
${Object.values(queryFragments).join('\n')}
mutation ${queryName.join('_')} (${queryVariables.join(', ')}) {
mutation ${operationName.join('_')} (${operationArguments.join(', ')}) {
${queryFields.join('\n')}
}
`;
Expand Down
Loading

0 comments on commit 24d33f0

Please sign in to comment.