graphql-extended / gqlx-js Goto Github PK
View Code? Open in Web Editor NEWJavaScript tools for using the gqlx language. :palm_tree:
Home Page: https://graphql-extended.github.io
License: MIT License
JavaScript tools for using the gqlx language. :palm_tree:
Home Page: https://graphql-extended.github.io
License: MIT License
Consider the following line in a resolver:
items.push(...newItems);
we only get items.push()
instead of the spread.
Consider the following schema:
type Translation {
key: String
content: String
language: String
}
type Query {
translations(language: String, key: String): [Translation] {
language ? get(cq(`api/snippet/${language}`, { key })).snippets.map(snippet => ({ ...snippet, language })) : use(get(cq(`api/snippet`, { key })), res => {
const items = [];
return items;
})
}
}
Expectation is that depending on if language
is set we either get from one or the other endpoint. However, in reality we see that the initial get is moved up due to simplification.
We get
try {
const cq = (url, obj) =>
url +
(Object.keys(obj).filter(m => obj[m] !== undefined && obj[m] !== null)
.length
? `?${Object.keys(obj)
.filter(m => obj[m] !== undefined && obj[m] !== null)
.map(m => `${m}=${obj[m]}`)
.join('&')}`
: '');
const use = (x, cb) => cb(x);
const _0 = await $api.get(
cq(`api/snippet/${$data.language}`, { key: $data.key }),
);
return $data.language
? _0.snippets.map(snippet => ({ ...snippet, language: $data.language }))
: use(await $api.get(cq(`api/snippet`, { key: $data.key })), res => {
const items = [];
return items;
});
} catch (err) {
throw new Error(JSON.stringify(err));
}
But we expected
try {
const cq = (url, obj) =>
url +
(Object.keys(obj).filter(m => obj[m] !== undefined && obj[m] !== null)
.length
? `?${Object.keys(obj)
.filter(m => obj[m] !== undefined && obj[m] !== null)
.map(m => `${m}=${obj[m]}`)
.join('&')}`
: '');
const use = (x, cb) => cb(x);
return $data.language
? (await $api.get(
cq(`api/snippet/${$data.language}`, { key: $data.key }),
)).snippets.map(snippet => ({ ...snippet, language: $data.language }))
: use(await $api.get(cq(`api/snippet`, { key: $data.key })), res => {
const items = [];
return items;
});
} catch (err) {
throw new Error(JSON.stringify(err));
}
The following gqlx is perfectly valid.
type Foo {
product: String
version: String
}
type Query {
foo: [Foo] {
get('api/product').items.map(product => {
const versions = get(`api/product/${product.id}/version`).items;
return {
product,
versions,
};
})
}
}
However, it turns out without the necessary async
in the map
function callback.
This is what we get:
try {
const _0 = await $api.get('api/product');
return await Promise.all(
_0.items.map(product => {
const _1 = await $api.get(`api/product/${product.id}/version`);
const versions = _1.items;
return { product, versions };
}),
);
} catch (err) {
throw new Error(JSON.stringify(err, Object.getOwnPropertyNames(err)));
}
And this is what we expect:
try {
const _0 = await $api.get('api/product');
return await Promise.all(
_0.items.map(async product => {
const _1 = await $api.get(`api/product/${product.id}/version`);
const versions = _1.items;
return { product, versions };
}),
);
} catch (err) {
throw new Error(JSON.stringify(err, Object.getOwnPropertyNames(err)));
}
Using a syntax like
{ [c.id]: c }
is transpiled to
{ c.id: c }
and thus being invalid. The transformation should preserve the correct value.
Having a mutation like
reorderRules(rules: [ReorderRule]): [Rule] {
use(get('api/rule'), ({ items }) => {
const priorities = rules.reduce((obj, cur) => {
obj[cur.id] = cur.priority;
return obj;
}, {});
const newRules = items
.filter(m => priorities[m.id] !== undefined)
.map(m => ({
...m,
rule: {
...m.rule,
priority: priorities[m.id],
},
}));
return newRules.map(rule => put('api/rule/' + rule.id, { rule }));
})
}
currently yields
try {
const use = (x, cb) => cb(x);
return await use(await $api.get('api/rule'), async ({ items }) => {
const priorities = $data.rules.reduce((obj, cur) => {
obj[cur.id] = cur.priority;
return obj;
}, {});
const newRules = items
.filter(m => priorities[m.id] !== undefined)
.map(m => ({ ...m, rule: { ...m.rule, priority: priorities[m.id] } }));
return await newRules.map(rule => {
return $api.put('api/rule/' + rule.id, { rule });
});
});
} catch (err) {
throw new Error(JSON.stringify(err));
}
but instead should, as specified, wrap the async _.map
in a Promise.all()
call. As of now the map does not return a promise as such it is not awaited and nothing is being done.
Local variables should be respected before replacements with parameters / data properties. Nevertheless, this is inconsistent with, e.g., shorthand properties.
Consider the following code:
type Translation {
key: String
content: String
language: String
}
type Query {
translations(language: String): [Translation] {
use(get(`api/snippet`), res => {
const { snippets, languages } = res;
languages.forEach(language => {
snippets[language].map(snippet => ({ ...snippet, language }));
});
})
}
}
Actually, we get:
const use = (x, cb) => cb(x);
return use(await $api.get(`api/snippet`), res => {
const { snippets, languages } = res;
languages.forEach(language => {
snippets[language].map(snippet => ({
...snippet,
language: $data.language,
}));
});
});
but we expected:
const use = (x, cb) => cb(x);
return use(await $api.get(`api/snippet`), res => {
const { snippets, languages } = res;
languages.forEach(language => {
snippets[language].map(snippet => ({
...snippet,
language,
}));
});
});
Currently, having the following resolver does not work
({ x, y, ... })
Instead, if the parentheses are omitted it works
{ x, y, ... }
Ideally, any number of parentheses should be acceptable.
Defining an API such as { foo: true }
works flawlessly in most scenarios, except when the return of calling foo
returns an object that should be spread, e.g.,
{ x, y, ...foo() }
In this case just nothing is appearing - meaning that potentially the code is taken literally instead of properly transforming it to
{ x, y, ...(await $api.foo()) }
This transformation is missing for spread operations.
Right now cq
only does some object creation / parameter appending, however, it does not do any normalization to ensure proper name / value pairs for query parameters. As such names or values that contain ampersands (or other reserved characters) will lead to problems.
This should be fixed to ensure all consumers of gqlx-js
can use query parameters without any trouble.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.