2022 Desk setup:
atulmy / gql-query-builder Goto Github PK
View Code? Open in Web Editor NEW🔧 Simple GraphQL Query Builder
Home Page: https://npmjs.com/package/gql-query-builder
License: MIT License
🔧 Simple GraphQL Query Builder
Home Page: https://npmjs.com/package/gql-query-builder
License: MIT License
consider this code server-side
type Mutation {
updateMessage(id: Number!, text: String): Boolean
}
and this code client-side
const mutation = gql.mutation({
operation: 'updateMessage',
variables: {
id: {value: 1, required: true},
text: null
}
})
now if you print out the mutation, text
variable has Object
type
console.log(mutation);
//query
mutation ($id: Int!, $text: Object) {
updateMessage (id: $id, text: $text)
}
//variables
{
id: 1,
text: null
}
the reason is obvious, gql-query-builder
cannot determine the type when just null
is provided - it might be any type.
if you send this mutation to the server-side, in response you get error
message: "Unknown type "Object"."
server-side does not know type Object
; moreover the type coming from client-side (infered by gql-query-builder
) has to correspond with the type defined on server-side (in graphql schema)
by now, i use workaround by specifing the variable type explicitly
const mutation = gql.mutation({
operation: 'updateMessage',
variables: {
id: {value: 1, required: true},
text: {value: null, type: "String"}
}
})
is this workaround alright or is there a better way?
i cannot think of any other ways, as it is impossible to know the intended type when just null
is provided.
thanks in advance!
Hey @atulmy,
I'm not sure why or how, but something is really broken in the v3.5.2
package published on npm.
Just try npm i gql-query-builder
or yarn add gql-query-builder
in an empty project and you'll see the only files you end up with in node_modules/gql-query-builder
are these:
-rw-r--r-- 1 user user 1.1K Dec 5 12:49 LICENSE
-rw-r--r-- 1 user user 13K Dec 5 12:49 README.md
-rw-r--r-- 1 user user 1.5K Dec 5 12:49 package.json
There must be something wrong with your npm-publish.yml workflow.
Let me know if there's anything I can do to help.
Developers who use gql-query-builder may want to see their queries/mutations values of output/variable.
Thanks for the commit, by the way. Look at the failing test here:
Is this the way it should work ? It seems like nested variables aren't pulled up to the top
variables should have a type, it is well defined in the README but uses any
.
My suggestion:
type Value = string | number | boolean | Record<string, any>;
interface Variables {
value: Value;
type?: string;
required?: true;
}
type VariablesRecord<T extends Record<string, any> = Record<string, any>> = Record<keyof T, Variables>;
and query<T>()
mutate<T>()
etc
After creating a custom mutation adapter it throws an error when I pass it's type on mutation function.
In order to check if the problem was related with my adapter code I tried to pass the default mutation adapter directly and the same error occurs.
Steps to reproduce:
Argument of type 'typeof DefaultMutationAdapter' is not assignable to parameter of type 'IMutationAdapter'. Type 'typeof DefaultMutationAdapter' is missing the following properties from type 'IMutationAdapter': mutationBuilder, mutationsBuilder'. Type 'IMutationAdapter' is missing the following properties from type 'IMutationAdapter': mutationBuilder, mutationsBuilder
Example:
`
import * as gql from 'gql-query-builder';
import DefaultMutationAdapter from 'gql-query-builder/build/adapters/DefaultMutationAdapter';
const query = gql.mutation({
operation: 'thoughtCreate',
variables: {
name: 'Tyrion Lannister',
thought: 'I drink and I know things.'
},
fields: ['id']
}, DefaultMutationAdapter);
console.log(query);
// Output
mutation ($name: String, $thought: String) {
thoughtCreate (name: $name, thought: $thought) {
id
}
}
// Variables
{
"name": "Tyrion Lannister",
"thought": "I drink and I know things."
}
`
Hi,
I have this following code :
import {Component, OnInit} from '@angular/core';
import {MaerdoBaseAdminComponent} from "../maerdo-core/_helpers/MaerdoBaseAdminComponent.class";
import {Apollo} from 'apollo-angular';
import * as builder from 'gql-query-builder'
@Component({
selector: 'maerdo-admin-modules-create',
templateUrl: './maerdo-admin-modules-create.component.html',
styleUrls: ['./maerdo-admin-modules-create.component.scss']
})
export class MaerdoAdminModulesCreateComponent extends MaerdoBaseAdminComponent implements OnInit {
protected moduleEntity = {
"name": "rezrez",
"slug": "rezrze",
"desc_fr": "rezrez",
"desc_en": "rzerez",
"desc_es": "rezrez"
};
constructor(protected apollo: Apollo) {
super();
}
ngOnInit() {
}
nameToSlug() {
this.moduleEntity.slug = this.toSlug(this.moduleEntity.name);
}
screenshotUploader(event) {
}
createModule() {
const createModuleQuery = builder.mutation({
operation: 'createModule',
variables: this.moduleEntity,
fields: ['id','name','slug']
});
console.log(createModuleQuery);
this.update(createModuleQuery, "moduleEntity", this);
}
}
And when i try to call builder.mutation i have this error msg :
MaerdoAdminModulesCreateComponent.html:37 ERROR TypeError: builder.mutation is not a function
at MaerdoAdminModulesCreateComponent.push../src/app/maerdo-admin-modules-create/maerdo-admin-modules-create.component.ts.MaerdoAdminModulesCreateComponent.createModule (maerdo-admin-modules-create.component.ts:38)
at Object.eval [as handleEvent] (MaerdoAdminModulesCreateComponent.html:37)
at handleEvent (core.js:23106)
at callWithDebugContext (core.js:24176)
at Object.debugHandleEvent [as handleEvent] (core.js:23903)
at dispatchEvent (core.js:20555)
at core.js:21002
at HTMLButtonElement.<anonymous> (platform-browser.js:993)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:17289)
View_MaerdoAdminModulesCreateComponent_0 @ MaerdoAdminModulesCreateComponent.html:37
proxyClass @ compiler.js:18239
push../node_modules/@angular/core/fesm5/core.js.DebugContext_.logError @ core.js:24138
push../node_modules/@angular/core/fesm5/core.js.ErrorHandler.handleError @ core.js:15771
dispatchEvent @ core.js:20559
(anonymous) @ core.js:21002
(anonymous) @ platform-browser.js:993
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:423
onInvokeTask @ core.js:17289
push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:422
push../node_modules/zone.js/dist/zone.js.Zone.runTask @ zone.js:195
push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:498
invokeTask @ zone.js:1744
globalZoneAwareCallback @ zone.js:1770
MaerdoAdminModulesCreateComponent.html:37 ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 71, nodeDef: {…}, elDef: {…}, elView: {…}}
I'm attempting a fairly simple multi-query where I want to retrieve multiple counts from a single request with varying values. (i.e. get the count of fruit for several different statuses)
Given the example query below:
[
{
"operation": "statusId1: fruit",
"variables": {
"fruit_id": {
"required": true,
"value": 36
},
"where": {
"type": "QueryFruitWhereConditions",
"value": {
"AND": [
{
"column": "status_id",
"operator": "EQ",
"value": 1
}
]
}
}
},
"fields": [
{
"meta": [
"total"
]
}
]
},
{
"operation": "statusId2: fruit",
"variables": {
"fruit_id": {
"required": true,
"value": 36
},
"where": {
"type": "QueryFruitWhereConditions",
"value": {
"AND": [
{
"column": "status_id",
"operator": "EQ",
"value": 2
}
]
}
}
},
"fields": [
{
"meta": [
"total"
]
}
]
}
]
The following query will be built out:
{
"query": "query ($fruit_id: Int!, $where: QueryFruitWhereConditions) { statusId1: fruit (fruit_id: $fruit_id, where: $where) { meta { total } } statusId2: fruit (fruit_id: $fruit_id, where: $where) { meta { total } } }",
"variables": {
"fruit_id": 36,
"where": {
"AND": [
{
"column": "status_id",
"operator": "EQ",
"value": 2
}
]
}
}
}
This is an issue because the where
variable is intentionally different between queries; however, the last query's value for the variable is used for the entire query set. Is this a bug or is there some sort of workaround I could do?
Code : const getTopPostsByGroupIdQuery = query({
operation: getTopPostsByGroupId
,
variables: {
groupId: {value: 3d42529f-e129-4e8f-87a8-e53a0a0fccbe
, required: true},
postType: {value: Text
, required: true},
limit: {value: 10, required: true},
startMonth: {value: 10, required: true},
endMonth: {value: 10, required: true},
startYear: {value: 2019, required: true},
endYear: {value: 2020, required: true}
},
fields: [activityRate
, postCreatedAtUTC
, commentCount
]
cy.api({
method: POST
,
url: appSyncUrl,
headers: {
authorization:noGroupAdminAuth
},
body: getTopPostsByGroupIdQuery
}).then(({body}) => {
const {
data: {getTopPostsByGroupId},
errors: [{errorType, message}]
} = body;
Can you please check if anything is missing in above code.
Hi!
Is there any support or examples for query aliases?
https://graphql.org/learn/queries/#aliases
I try to send de query but send me an error
Query:
{
metrics {
id
name
paginatorInfo{
count
currentPage
firstItem
hasMorePages
lastItem
lastPage
perPage
total
}
}
}
Correct query:
{
metrics {
data {
id
name
}
paginatorInfo{
count
currentPage
firstItem
hasMorePages
lastItem
lastPage
perPage
total
}
}
}
Need put fields into object named "data {}", how can make if??
For example:-
const gqlquery = query([
{
operation: 'someoperation',
fields: [
{
operation: 'nestedoperation',
fields: [],
variables: {
id2: {
type: 'ID',
value: 123
}
}
}
],
variables: {
id1: {
type: 'ID',
value: 456
}
}
}
]);
// Output
query ($id2: ID, $id1: ID) { someoperation (id1: $id1) { nestedoperation (id2: $id2) { } } }
Maybe add the ability in the variable definition to add a name property to change the argument name
const gqlquery = query([
{
operation: 'someoperation',
fields: [
{
operation: 'nestedoperation',
fields: [],
variables: {
id2: {
type: 'ID',
value: 123,
name: 'id'
}
}
}
],
variables: {
id1: {
type: 'ID',
value: 456,
name: 'id'
}
}
}
]);
// Output
query ($id2: ID, $id1: ID) { someoperation (id: $id1) { nestedoperation (id: $id2) { } } }
By default it could be the keyname but, I think adding the ability to separate the argument name and variable name could be helpful in some instances. Let me try to submit a PR resolving this issue
PR#35 did solve the issue on nested fields, but unfortunately when using multiple operations the problem persists.
For example for the below query ...
const gqlquery = query([
{
operation: "getPublicationCount",
variables: {
round: true
}
},
{
operation: "getPublicationCount",
variables: {
ceil: true
}
}
]);
gqlquery.query
is ...
query ($ceil: Boolean) { getPublicationCount (round: $round) { } getPublicationCount (ceil: $ceil) { } }
But it should be
query ($round: Boolean, $ceil: Boolean) { getPublicationCount (round: $round) getPublicationCount (ceil: $ceil) }
My PR solves the case with extraneous brackets but, it seems only the latest variables are set at the root query operation.
is there support for unions and/or interfaces? one of my api calls returns content
and content
is a union type that can return diff types of models.
Example desired query output:
{
vehicle {
... on Car {
name
isSedan
NumSeats
topSpeed
}
... on Scooter {
name
isElectric
numMiles
topSpeed
}
}
}
Does the library support params on nested fields ?
The query string contains "[object Object](" rather than "alias: operation("
when build a query
should be able to check required type
mutation Login($email: String!, $password:String!){
Login(email:$email, password: $password){
success
error
token
}
}
The gql.query
function takes an optional config object in which I can pass an operationName
to name my query. This makes testing queries against a mock GQL server using MSW very easy as I can configure it to respond to incoming queries by the operationName
https://mswjs.io/docs/getting-started/mocks/graphql-api#request-handler
The gql.mutation
function doesn't take this config object so I can't easily name mutations. This makes testing them with MSW much harder as I have to separately parse the GQL into an AST and locate the name of the underlying mutation that is called.
Could you add this config object to gql-query-builder?
Hello!
I'm using the Crate application and it is really good as a starting point for new projects! So thanks for that 😊
In the Crate code for the API part, I wanted to create a new custom type for my query. But it seems that gql-query-builder does not support custom types yet.
I wanted to get this working right now so I did the following not so good looking change in the queryDataType function 😑
// Get GraphQL equivalent type of data passed (String, Int, Float, Boolean)
function queryDataType(variable: any) {
let type = "String";
const value = typeof variable === "object" ? variable.value : variable;
if (variable.type !== undefined) {
type = variable.type;
} else {
switch (typeof value) {
case "object":
type = "Object";
break;
case "boolean":
type = "Boolean";
break;
case "number":
type = value % 1 === 0 ? "Int" : "Float";
break;
}
}
if (typeof variable === "object" && variable.required) {
type += "!";
}
return type;
}
As you can see, I only added a variable.type check/assing for now to make it work.
Is this something you would consider adding to this lib?
for example
const query = {
operation,
variables: {
id: {
value: id,
type: 'String!',
},
uid: {
value: uid,
type: 'Int!',
},
key: {
value: key,
type: 'String',
}
},
fields // this is undefined
}
//output
query: "query ($id: String!, $uid: Int!, $key: String) { a…orize_info (id: $id, uid: $uid, key: $key) **{ }**"
Hello. First of all thanks for great tool!
I updated my app to webpack 5 and it got smarter :)
For now I receive warnings that webpack can't find source maps for gql-query-builder
Failed to parse source map from '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/NestedField.ts' file: Error: ENOENT: no such file or directory, open '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/NestedField.ts'
Failed to parse source map from '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/OperationType.ts' file: Error: ENOENT: no such file or directory, open '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/OperationType.ts'
Failed to parse source map from '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/Utils.ts' file: Error: ENOENT: no such file or directory, open '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/Utils.ts'
Failed to parse source map from '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/adapters/DefaultAppSyncMutationAdapter.ts' file: Error: ENOENT: no such file or directory, open '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/adapters/DefaultAppSyncMutationAdapter.ts'
Failed to parse source map from '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/adapters/DefaultAppSyncQueryAdapter.ts' file: Error: ENOENT: no such file or directory, open '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/adapters/DefaultAppSyncQueryAdapter.ts'
Failed to parse source map from '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/adapters/DefaultMutationAdapter.ts' file: Error: ENOENT: no such file or directory, open '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/adapters/DefaultMutationAdapter.ts'
Failed to parse source map from '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/adapters/DefaultQueryAdapter.ts' file: Error: ENOENT: no such file or directory, open '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/adapters/DefaultQueryAdapter.ts'
Failed to parse source map from '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/adapters/DefaultSubscriptionAdapter.ts' file: Error: ENOENT: no such file or directory, open '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/adapters/DefaultSubscriptionAdapter.ts'
Failed to parse source map from '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/adapters/index.ts' file: Error: ENOENT: no such file or directory, open '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/adapters/index.ts'
Failed to parse source map from '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/index.ts' file: Error: ENOENT: no such file or directory, open '/home/eugene/projects/front-tm2/node_modules/gql-query-builder/src/index.ts'
And, for example node_modules/gql_query_builder/build/Fields.js.map
has this code
{"version":3,"file":"Fields.js","sourceRoot":"","sources":["../src/Fields.ts"],"names":[],"mappings":""}
"sources":["../src/Fields.ts"]
points to a non-existent file
Can I use fragments?
Hi,
could you please add relay input support?
Sample mutation query:
mutation categoriesUpdate($input: CategoriesUpdateInput!) {
categoriesUpdate(input: $input) {
category { id }
errors
}
}
Regards!
Hey! Was reading through the latest version changes and noticed a .only that was introduced in this pr, as seen here:
https://github.com/atulmy/gql-query-builder/blob/master/src/index.test.ts#L1036
I may have time to open a PR tomorrow
Let's assume:
i have query:
gql.query({
operation: 'user',
fields: ['name'],
});
and one more:
gql.query({
operation: 'profile',
fields: ['id', 'photo'],
});
Everything is nice now.
But what if i need to get both user and profile in one query? What should I do? Is there mechanism to merge these queries. Especially, due to the fact, that one of the best features of GraphQL (comparing with REST) is to combine queries into one.
when variable is undefined return a error
how to handling this error ?
Hello,
I was testing today and it seems like there is a difference between the builds from my local build output and what was in the 3.1.0 npm package. It's like it wasn't built before being published? I don't know.
1a2,12
> var __assign = (this && this.__assign) || function () {
> __assign = Object.assign || function(t) {
> for (var s, i = 1, n = arguments.length; i < n; i++) {
> s = arguments[i];
> for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
> t[p] = s[p];
> }
> return t;
> };
> return __assign.apply(this, arguments);
> };
3,9c14,19
< var adapters_1 = require("./adapters");
< exports.adapters = adapters_1.default;
< var DefaultMutationAdapter_1 = require("./adapters/DefaultMutationAdapter");
< var DefaultQueryAdapter_1 = require("./adapters/DefaultQueryAdapter");
< var DefaultSubscriptionAdapter_1 = require("./adapters/DefaultSubscriptionAdapter");
< function queryOperation(options, adapter) {
< var defaultAdapter;
---
> var OperationType;
> (function (OperationType) {
> OperationType["Mutation"] = "mutation";
> OperationType["Query"] = "query";
> })(OperationType || (OperationType = {}));
> function queryOperation(options) {
11,20c21
< if (adapter) {
< var customAdapter = new adapter(options);
< return customAdapter.queriesBuilder(options);
< }
< defaultAdapter = new DefaultQueryAdapter_1.default(options);
< return defaultAdapter.queriesBuilder(options);
< }
< if (adapter) {
< var customAdapter = new adapter(options);
< return customAdapter.queryBuilder();
---
> return queriesBuilder(options);
22,23c23
< defaultAdapter = new DefaultQueryAdapter_1.default(options);
< return defaultAdapter.queryBuilder();
---
> return queryBuilder(options);
26,28c26,33
< function mutationOperation(options, adapter) {
< var customAdapter;
< var defaultAdapter;
---
> function queryBuilder(_a) {
> var operation = _a.operation, _b = _a.fields, fields = _b === void 0 ? [] : _b, _c = _a.variables, variables = _c === void 0 ? {} : _c;
> return operationWrapperTemplate(OperationType.Query, variables, operationTemplate({ variables: variables, operation: operation, fields: fields }));
> }
> function queriesBuilder(queries) {
> return operationWrapperTemplate(OperationType.Query, resolveVariables(queries), queries.map(operationTemplate).join("\n "));
> }
> function mutationOperation(options) {
30,41c35
< if (adapter) {
< // @ts-ignore
< customAdapter = new adapter(options);
< return customAdapter.mutationsBuilder(options);
< }
< defaultAdapter = new DefaultMutationAdapter_1.default(options);
< return defaultAdapter.mutationsBuilder(options);
< }
< if (adapter) {
< // @ts-ignore
< customAdapter = new adapter(options);
< return customAdapter.mutationBuilder();
---
> return mutationsBuilder(options);
43,44c37
< defaultAdapter = new DefaultMutationAdapter_1.default(options);
< return defaultAdapter.mutationBuilder();
---
> return mutationBuilder(options);
47,54c40,123
< function subscriptionOperation(options, adapter) {
< var customAdapter;
< var defaultAdapter;
< if (Array.isArray(options)) {
< if (adapter) {
< // @ts-ignore
< customAdapter = new adapter(options);
< return customAdapter.subscriptionsBuilder(options);
---
> function mutationBuilder(_a) {
> var operation = _a.operation, _b = _a.fields, fields = _b === void 0 ? [] : _b, _c = _a.variables, variables = _c === void 0 ? {} : _c;
> return operationWrapperTemplate(OperationType.Mutation, variables, operationTemplate({ variables: variables, operation: operation, fields: fields }));
> }
> function mutationsBuilder(mutations) {
> return operationWrapperTemplate(OperationType.Mutation, resolveVariables(mutations), mutations.map(operationTemplate).join("\n "));
> }
> function resolveVariables(operations) {
> var ret = {};
> operations.forEach(function (_a) {
> var variables = _a.variables;
> ret = __assign({}, ret, variables);
> });
> return ret;
> }
> function operationWrapperTemplate(type, variables, content) {
> return {
> query: type + " " + queryDataArgumentAndTypeMap(variables) + " {\n " + content + "\n}",
> variables: queryVariablesMap(variables)
> };
> }
> function operationTemplate(_a) {
> var variables = _a.variables, operation = _a.operation, fields = _a.fields;
> return operation + " " + queryDataNameAndArgumentMap(variables) + " " + (fields && fields.length > 0
> ? "{\n " + queryFieldsMap(fields) + "\n }"
> : "");
> }
> // Convert object to name and argument map. eg: (id: $id)
> function queryDataNameAndArgumentMap(variables) {
> return variables && Object.keys(variables).length
> ? "(" + Object.keys(variables).reduce(function (dataString, key, i) {
> return "" + dataString + (i !== 0 ? ", " : "") + key + ": $" + key;
> }, "") + ")"
> : "";
> }
> // Convert object to argument and type map. eg: ($id: Int)
> function queryDataArgumentAndTypeMap(variables) {
> return Object.keys(variables).length
> ? "(" + Object.keys(variables).reduce(function (dataString, key, i) {
> return "" + dataString + (i !== 0 ? ", " : "") + "$" + key + ": " + queryDataType(variables[key]);
> }, "") + ")"
> : "";
> }
> // Fields selection map. eg: { id, name }
> function queryFieldsMap(fields) {
> return fields
> ? fields
> .map(function (field) {
> return typeof field === "object"
> ? Object.keys(field)[0] + " { " + queryFieldsMap(Object.values(field)[0]) + " }"
> : "" + field;
> })
> .join(", ")
> : "";
> }
> // Variables map. eg: { "id": 1, "name": "Jon Doe" }
> function queryVariablesMap(variables) {
> var variablesMapped = {};
> Object.keys(variables).map(function (key) {
> variablesMapped[key] =
> typeof variables[key] === "object"
> ? variables[key].value
> : variables[key];
> });
> return variablesMapped;
> }
> // Get GraphQL equivalent type of data passed (String, Int, Float, Boolean)
> function queryDataType(variable) {
> var type = "String";
> var value = typeof variable === "object" ? variable.value : variable;
> if (variable.type !== undefined) {
> type = variable.type;
> }
> else {
> switch (typeof value) {
> case "object":
> type = "Object";
> break;
> case "boolean":
> type = "Boolean";
> break;
> case "number":
> type = value % 1 === 0 ? "Int" : "Float";
> break;
56,57d124
< defaultAdapter = new DefaultSubscriptionAdapter_1.default(options);
< return defaultAdapter.subscriptionsBuilder(options);
59,62c126,127
< if (adapter) {
< // @ts-ignore
< customAdapter = new adapter(options);
< return customAdapter.subscriptionBuilder();
---
> if (typeof variable === "object" && variable.required) {
> type += "!";
64,65c129
< defaultAdapter = new DefaultSubscriptionAdapter_1.default(options);
< return defaultAdapter.subscriptionBuilder();
---
> return type;
67d130
< exports.subscription = subscriptionOperation;
gql-query-builder/src/NestedField.ts
Line 11 in 3dc8019
Please refer to the above line, the type of variables in NestedField was set to IQueryBuilderOptions[], just wondering if that's correct at all?
If we look at it here:
gql-query-builder/src/index.test.ts
Line 147 in 3dc8019
The variables object inside nested field would certainly fail the type check IQueryBuilderOptions[].
I have a case roughly like this:
query SpeakerTweetTemplateQuery($conferenceId: ID!, $contactName: String!) {
contact(contactName: $contactName, conferenceId: $conferenceId) {
name
}
conference(id: $conferenceId) {
name
}
}
The point is that I would like to execute multiple operations within a single query. As far as I can see, the current API isn't flexible enough for this purpose.
I can work around this by performing multiple separate requests. Any better ideas? Should I try to PR a generalization like this?
hello dears,
i want to create a fragment to use it in my query how can i do it ?
Since v3.1.2 importing breaks typescript builds (not sure if the same happens with js)
i have some query that need add Enum like that:
{
diagnostic__defects(page: 1, orderBy: [{field: IS_FUNCTIONAL_DEFECT, order: DESC}]) {
data {
id
name
}
}
}
IS_FUNCTIONAL_DEFECT and DESC are ENUM, can't be wrapped by quote
Reference: https://graphql.org/learn/queries/#operation-name
Current:
query {
thoughts {
id,
name,
thought
}
}
Option to pass query name ThoughtList
query ThoughtList {
thoughts {
id,
name,
thought
}
}
Hi!
I get an error when I try to collect a query
TypeError: innerFields.forEach is not a function
For example, the query is as follows
[ { operation: 'someoperation', fields: [ 'id', { operation: 'someoperation2', fields: [ 'name' ] } ] } ]
There is a test.only hiding in src/index.test.ts which is causing jest to only run two out of the 92 tests in the test suite. Running them results in 13 tests failing, all for white space issues. I suggest making a new jest matcher which removes any whitespace that's ignored by graphql anyway.
Hello.
Angular 10 show a warning for every dependency that is imported in ES5. From now, angular require ES6 module to optimize build process.
More info here:
https://angular.io/guide/build#configuring-commonjs-dependencies
Gql-query-builder show warning like this:
my-service.ts depends on 'gql-query-builder'. CommonJS or AMD dependencies can cause optimization bailouts.
Can this cool stuff for sure have ES6 export module as well within current commonJS?
Thanks and have a great day:)
Hi, thank you all for the wonderful library,
I have to create a quey as follow:
"query":"mutation($params:StoreCreateRequest!){
createStore(params: $params){
name
}
}",
"variables":{
"params":{
"organization_id":"abc-def",
"name":"my-store",
"type":"Kafka",
"uris":["http://ds.io"],
"availability_zone":"a",
"secret":{"value":[ { key: "a", value: "b" }] },
"metadata":{"value":[ { key: "c", value: "d" } ]}
}
}
Is it possible to generate it with gql-query-builder?
Many thanks in advance!
I'm using gql-query-builder with an object that I insert into the query as a variable, however, console.log
shows that all the fields in the object are being printed with single and not double quotes, which violates the GraphQL syntax?
throughout the code there are checks like;
const value = typeof variable === "object" ? variable.value : variable;
however, typeof
will also result in "object"
if value
is null
in which case the above code will simply fail
I'm considering making a PR in a few days to address this issue
it seems the builder expects an object to always be returned in a graphql response since the fields
arg is required. But what if the graphql server responds with a primitive? (eg. GraphQLBoolean)
Example:
// mutation portion of schema
new GraphQLObjectType({
name: 'RootMutation',
fields: {
logout: {
type: GraphQLBoolean,
resolve: async () => await pretendToLogUserOut(), // returns boolean
}
}
});
// query
import { mutation } from 'gql-query-builder';
const logoutMutation = mutation({ operation: 'logout', fields: [] });
console.log(logoutMutation.query);
// query output
mutation {
logout {
// this causes a 400 since i dont list any fields but that's because the response doesnt return `fields`, it just returns a bool
}
}
// desired query output
mutation {
logout
}
The result is a 400 since this is a malformed query string so it seems the query builder does not have support for handling primitive return values?
Can i using this lib to create graphql for gatsby
const { graphql } = require('gatsby')
If can, can you give me example to use this lib for useStaticQuery
of graphql
with gatsby
?
below codes is gatsby method
import { graphql, useStaticQuery } from "gatsby"
const imagesData = useStaticQuery(graphql`
query {
images: allFile(filter: { sourceInstanceName: { eq: "images" } }) {
edges {
node {
relativePath
absolutePath
name
childImageSharp {
gatsbyImageData
}
}
}
}
}
`)
Hey,
I found this library and is really nice and easy to use, however I found a case where I would need a help
I need to write query like
query ($owner: String!) {
nftEntities(where: {currentOwner_eq: $owner}) {
id
metadata
}
}
and so far my hack is
query({
operation: 'nfts: nfts: nftEntities(where: {currentOwner_eq: "vikiival"})',
fields: ['id', 'metadata']
})
The thing I need is to somehow wrap the variable into the object.
Question is: Is it possible to do that? Or should I just pass the whole object ({currentOwner_eq: "vikiival"}
) as the variable ?
Hi its not really an issue more of question and if the answer is no then a feature request
query gamesAndLeagues {
games(query: {result: "void"}) {
teamOne {
id
}
teamTwo {
id
}
result
}
leagues(query: {vip: false}) {
_id
}
}
this is a query i hit to get data from mongodb realms via gql.
I was wondering if it is possible to build this query that calls 2 collections via a single call?
Im thinking its not possible based on the docs
Thanks
Hello. Help me, please.
gql.query({
operation: 'user',
variables: { id: 333 },
fields: ['name', 'balance'],
}).query;
returns
query ($id: Int) { user (id: $id) { name, balance } }
instead of
query ($id: Int) { user (id: 333) { name, balance } }
Shortly, your feature doesn't inject variables values into resulting query string.
We've been using gql-query-builder
to replace hand-written queries in our service layer and so far it's working really well, thanks for creating this library.
I noticed recently that the GraphQL spec includes the following recommendation:
A standard GraphQL POST request should use the application/json content type, and include a JSON-encoded body of the following form:
{
"query": "...",
"operationName": "...",
"variables": { "myVariable": "someValue", ... }
}
We've started work to stub out different gql queries and responses in our cypress test suite, and one of the recommendations is to use an explicit operationName
in your queries, and then use this part of the request object to determine which response to send:
// Utility to match GraphQL mutation based on the operation name
export const hasOperationName = (req, operationName) => {
const { body } = req
return (
body.hasOwnProperty('operationName') && body.operationName === operationName
)
}
cypress.intercept('POST', '/graphql', req => {
if (hasOperationName(req, 'getSite') {
req.alias = 'getSite';
req.send({ fixture: 'getSiteFixturre' });
}
});
This code looks for the operationName
in the root of the request body, and it seems this approach works well for a lot of developers, but isn't working for us because gql-query-builder
only includes the operationName
in the query itself.
For now we're working around this simply like:
const gqlQuery = query({
operation: 'site',
variables: ...,
fields: ...,
}, null, { operationName: 'getSite' }));
// manually add operationName
gqlQuery.operationName = 'getSite';
However, if gql-query-builder
did this for us we could use the intended syntax:
const gqlQuery = query({
operation: 'site',
variables: ...,
fields: ...,
}, null, { operationName: 'getSite' });
Do you think this is something the library should support in the default adapter, and if so would you like me to make a pull request?
how to using other http request, if not using axios ?
https://github.com/request/request
When generating a mutation and passing in an array of options, the name
field is ignored for variables:
Mutation generation:
import { mutation } from 'gql-query-builder';
mutation(itemIds.map((_, index) => ({
operation: `delete_${index}: deleteThing`,
fields: [
{
userErrors: ['message', 'path'],
},
],
variables: {
[`input${index}`]: {
name: 'input',
type: `DeleteThingInput`,
required: true
}
}
}))).query;
Expected output:
mutation ($input0: DeleteThingInput!, $input1: DeleteThingInput!, $input2: DeleteThingInput!) {
delete_0: deleteThing (input: $input0) {
userErrors { message, path }
}
delete_1: deleteThing (input: $input1) {
userErrors { message, path }
}
delete_2: deleteThing (input: $input2) {
userErrors { message, path }
}
}
Actual output:
mutation ($input0: DeleteThingInput!, $input1: DeleteThingInput!, $input2: DeleteThingInput!) {
delete_0: deleteThing (input0: $input0) {
userErrors { message, path }
}
delete_1: deleteThing (input1: $input1) {
userErrors { message, path }
}
delete_2: deleteThing (input2: $input2) {
userErrors { message, path }
}
}
When provided, the variable name
should be used as input to each mutation, rather than the key. The problematic code appears to be:
gql-query-builder/src/adapters/DefaultMutationAdapter.ts
Lines 49 to 57 in 485e7db
The queryDataNameAndArgumentMap
in src/Utils.ts
could be used to solve the issue, as it already handles name
.
hi
I make my geoserver using Hasura.
I use your library to generate requests with apollo-client.
I need to get a graphql request like:
query network($geom: Geometry!){
network(where: {geom: {_st_intersects: $geom}}){
geom
}
}
I think that you need to do this custom filter like example
I want to pass an array of strings as a variable to a query (e.g. a list of tags that should be searched), I have no choice except change my type from String
to [String]
. Also, if none of the array items can be null or undefined, I should change this to [String!]
.
It doesn't seem good practice, so I suggest using something like Nexus list
to specify both array and nullability of array items.
For example a variable input like this:
tags: {
type: 'String',
value: tags,
list: [true],
required: true,
}
should be generated as: $tags: [String!]!
So the type of Variable should be:
interface Variable {
type: String;
value: any;
list?: true | [boolean];
required: boolean;
}
list: true
means the variable should be in array format but its items are nullable (that equals to list: [false]
list: [true]
means the variable should be in array format and its items are not nullable
and list: undefined
means the variable is not in array format
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.