graphql-helper
Advanced tools
Comparing version 0.0.5 to 0.0.6
131
lib.js
@@ -14,2 +14,3 @@ 'use strict'; | ||
exports.mutation = mutation; | ||
exports.batch = batch; | ||
@@ -31,2 +32,13 @@ var _isomorphicFetch = require('isomorphic-fetch'); | ||
function decorate(target, props) { | ||
Object.keys(props).forEach(function (key) { | ||
return target[key] = props[key]; | ||
}); | ||
return target; | ||
} | ||
function invariant(condition, message) { | ||
if (!condition) throw new Error(message); | ||
} | ||
// TODO: schema validation | ||
@@ -51,10 +63,12 @@ | ||
var variables = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; | ||
var operations = arguments[2]; | ||
return (0, _isomorphicFetch2.default)(gqlHost, { method: 'post', | ||
headers: gqlHeaders, | ||
body: JSON.stringify({ query: query, variables: JSON.stringify(variables) }) | ||
body: JSON.stringify({ query: query, | ||
variables: JSON.stringify(variables), | ||
operations: operations | ||
}) | ||
}).then(function (r) { | ||
return r.json(); | ||
}).then(function (r) { | ||
return r.errors ? Promise.reject(r.errors) : Promise.resolve(r.data); | ||
}); | ||
@@ -65,12 +79,16 @@ } | ||
var operationDefinitions = {}; | ||
var wrapParens = function wrapParens(str) { | ||
return str ? '(' + str + ')' : ''; | ||
}; | ||
function query(name, varsDef) { | ||
var paramsList = runMaybe(varsDef, function (v) { | ||
var params = wrapParens(runMaybe(varsDef, function (v) { | ||
return Object.keys(v).map(function (k) { | ||
return '$' + k + ':' + v[k]; | ||
}).join(','); | ||
}); | ||
})); | ||
var params = paramsList ? '(' + paramsList + ')' : ''; | ||
return function (target) { | ||
@@ -81,16 +99,22 @@ for (var _len = arguments.length, values = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
var fragmentDefinitions = collectFragments(values).join(' '); | ||
invariant(!operationDefinitions[name], 'ERROR: There is already an operation named ' + name); | ||
var query = 'query ' + name + ' ' + params + ' ' + String.raw.apply(String, [target].concat(values)) + ' ' + fragmentDefinitions; | ||
var fragments = mergeFragments(values); | ||
var fn = function fn(variables) { | ||
return request(query, variables); | ||
}; | ||
var operation = 'query ' + name + ' ' + params + ' ' + String.raw.apply(String, [target].concat(values)); | ||
var queryString = operation + ' ' + valuesOf(fragments).join(' '); | ||
fn.queryString = query; | ||
fn.toString = function () { | ||
return query; | ||
}; | ||
return fn; | ||
return operationDefinitions[name] = decorate(function (variables) { | ||
return request(queryString, variables).then(function (r) { | ||
return r.errors ? Promise.reject(r.errors) : Promise.resolve(r.data); | ||
}); | ||
}, { __GRAPHQL_QUERY__: true, | ||
operationName: name, | ||
operation: operation, | ||
fragments: fragments, | ||
queryString: queryString, | ||
toString: function toString() { | ||
return queryString; | ||
} | ||
}); | ||
}; | ||
@@ -112,21 +136,52 @@ } | ||
var fragmentDefinitions = collectFragments(values).join(' '); | ||
invariant(!operationDefinitions[capitalized], 'ERROR: There is already an operation named ' + capitalized); | ||
var query = 'mutation ' + capitalized + '($input: ' + inputType + '!) {\n payload: ' + name + '(input: $input) {\n clientMutationId\n ... on ' + payloadType + ' ' + String.raw.apply(String, [target].concat(values)) + '\n }\n } ' + fragmentDefinitions; | ||
var fragments = mergeFragments(values); | ||
var fn = function fn(variables) { | ||
return request(query, { input: _extends({ clientMutationId: gqlClientMutationId() | ||
var operation = 'mutation ' + capitalized + '($input: ' + inputType + '!){\n payload: ' + name + '(input: $input) {\n clientMutationId\n ... on ' + payloadType + ' ' + String.raw.apply(String, [target].concat(values)) + '\n }\n }'; | ||
var queryString = operation + ' ' + valuesOf(fragments).join(' '); | ||
return operationDefinitions[capitalized] = decorate(function (variables) { | ||
return request(queryString, { input: _extends({ clientMutationId: gqlClientMutationId() | ||
}, variables) | ||
}).then(function (data) { | ||
return Promise.resolve(data.payload); | ||
}).then(function (r) { | ||
return r.errors ? Promise.reject(r.errors) : Promise.resolve(r.data.payload); | ||
}); | ||
}; | ||
}, { __GRAPHQL_MUTATION__: true, | ||
operationName: capitalized, | ||
operation: operation, | ||
fragments: fragments, | ||
queryString: queryString, | ||
toString: function toString() { | ||
return queryString; | ||
} | ||
}); | ||
}; | ||
} | ||
fn.queryString = query; | ||
fn.toString = function () { | ||
return query; | ||
}; | ||
// Batch | ||
return fn; | ||
}; | ||
function batch(ops, variables) { | ||
// TEMPORARY: come up with a reasonable workaround for this: | ||
var names = ops.map(function (op) { | ||
return op.operationName; | ||
}); | ||
var fragments = mergeFragments(ops.map(function (op) { | ||
return op.fragments; | ||
})); | ||
var doc = ops.map(function (op) { | ||
return op.operation; | ||
}).join(' ') + ' ' + valuesOf(fragments).join(' '); | ||
return request(doc, variables, names).then(function (r) { | ||
return r.map(function (_ref2, i) { | ||
var data = _ref2.data; | ||
var errors = _ref2.errors; | ||
if (errors) throw new Error(errors); | ||
return data; | ||
}); | ||
}); | ||
} | ||
@@ -151,2 +206,4 @@ | ||
var fragmentDefinitions = {}; | ||
var fragment = exports.fragment = function fragment(name) { | ||
@@ -159,3 +216,5 @@ var type = arguments.length <= 1 || arguments[1] === undefined ? name : arguments[1]; | ||
return { __GRAPHQL_QUERY_PARTIAL__: true, | ||
invariant(!fragmentDefinitions[name], 'ERROR: there is already a fragment with name ' + name); | ||
return fragmentDefinitions[name] = { __GRAPHQL_QUERY_PARTIAL__: true, | ||
__GRAPHQL_FRAGMENT__: true, | ||
@@ -198,4 +257,4 @@ name: name, | ||
return !!x; | ||
}).reduce(function (acc, _ref2) { | ||
var fragments = _ref2.fragments; | ||
}).reduce(function (acc, _ref3) { | ||
var fragments = _ref3.fragments; | ||
return Object.assign(acc, fragments); | ||
@@ -205,6 +264,2 @@ }, {}); | ||
var collectFragments = function collectFragments(values) { | ||
return valuesOf(mergeFragments(values)); | ||
}; | ||
// General Utils: | ||
@@ -211,0 +266,0 @@ |
{ | ||
"name": "graphql-helper", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"description": "A simple helper library for making GraphQL queries. For browser usage, ensure that you have a Promise polyfill.", | ||
@@ -5,0 +5,0 @@ "main": "lib.js", |
160
src.js
@@ -11,2 +11,13 @@ /* @flow */ | ||
type StrMap<V> = { [key: string]: V } | ||
function decorate<T,K,V>(target: T, props: { [key: K]: V }): T { | ||
Object.keys(props).forEach(key => (target: any)[(key: any)] = props[(key: any)]) | ||
return target | ||
} | ||
function invariant(condition: mixed, message: string): void { | ||
if (!condition) throw new Error(message) | ||
} | ||
declare class String { | ||
@@ -20,3 +31,3 @@ static raw: TemplateString<string>; | ||
{ host: string | ||
, headers?: { [key: string]: string } | ||
, headers?: StrMap<string> | ||
, clientMutationId?: () => string | ||
@@ -33,3 +44,3 @@ } | ||
// TODO: support operationName | ||
export function request<U,V>(query: string, variables: ?U = null): Promise<V> { | ||
export function request<U,V>(query: string, variables: ?U = null, operations: ?Array<string>): Promise<V> { | ||
return fetch | ||
@@ -39,7 +50,11 @@ ( gqlHost | ||
, headers: gqlHeaders | ||
, body: JSON.stringify({ query, variables: JSON.stringify(variables) }) | ||
, body: JSON.stringify( | ||
{ query | ||
, variables: JSON.stringify(variables) | ||
, operations | ||
} | ||
) | ||
} | ||
) | ||
.then(r => r.json()) | ||
.then(r => r.errors ? Promise.reject(r.errors) : Promise.resolve(r.data)) | ||
} | ||
@@ -49,27 +64,41 @@ | ||
type VariablesDef<U> = { [key: string]: string } | ||
type VariablesDef<U> = StrMap<string> | ||
type Query<U,V> = (variables: U) => Promise<V> | ||
const operationDefinitions: StrMap<Query<mixed,mixed>> = {} | ||
const wrapParens = (str: ?string): string => str ? `(${str})` : '' | ||
export function query<U,V>(name: string, varsDef: ?VariablesDef<U>): TemplateString<Query<U,V>> { | ||
const paramsList: ?string = runMaybe(varsDef, v => | ||
Object.keys(v).map(k => `$${k}:${v[k]}`).join(',') | ||
const params: string = wrapParens( | ||
runMaybe(varsDef, v => | ||
Object.keys(v).map(k => `$${k}:${v[k]}`).join(',') | ||
) | ||
) | ||
const params: string = paramsList ? `(${paramsList})` : '' | ||
return (target, ...values) => { | ||
const fragmentDefinitions: string = | ||
collectFragments(values).join(' ') | ||
invariant | ||
( !operationDefinitions[name] | ||
, `ERROR: There is already an operation named ${name}` | ||
) | ||
const query = `query ${name} ${params} ${String.raw(target, ...values)} ${fragmentDefinitions}` | ||
const fragments: StrMap<FragmentDefinition> = mergeFragments(values) | ||
const fn = variables => request(query, variables) | ||
const operation = `query ${name} ${params} ${String.raw(target, ...values)}` | ||
const queryString = operation + ' ' +valuesOf(fragments).join(' ') | ||
fn.queryString = query | ||
fn.toString = () => query | ||
return fn | ||
return operationDefinitions[name] = decorate | ||
( variables => request(queryString, variables) | ||
.then(r => r.errors ? Promise.reject(r.errors) : Promise.resolve(r.data)) | ||
, { __GRAPHQL_QUERY__: true | ||
, operationName: name | ||
, operation | ||
, fragments | ||
, queryString | ||
, toString: () => queryString | ||
} | ||
) | ||
} | ||
@@ -89,6 +118,10 @@ | ||
const fragmentDefinitions: string = | ||
collectFragments(values).join(' ') | ||
invariant | ||
( !operationDefinitions[capitalized] | ||
, `ERROR: There is already an operation named ${capitalized}` | ||
) | ||
const query = `mutation ${capitalized}($input: ${inputType}!) { | ||
const fragments: StrMap<FragmentDefinition> = mergeFragments(values) | ||
const operation = `mutation ${capitalized}($input: ${inputType}!){ | ||
payload: ${name}(input: $input) { | ||
@@ -98,19 +131,43 @@ clientMutationId | ||
} | ||
} ${fragmentDefinitions}` | ||
}` | ||
const fn = variables => request | ||
( query | ||
, { input: { clientMutationId: gqlClientMutationId() | ||
, ...variables | ||
} | ||
const queryString = operation + ' ' + valuesOf(fragments).join(' ') | ||
return operationDefinitions[capitalized] = decorate | ||
( variables => request | ||
( queryString | ||
, { input: { clientMutationId: gqlClientMutationId() | ||
, ...variables | ||
} | ||
} | ||
).then(r => r.errors ? Promise.reject(r.errors) : Promise.resolve(r.data.payload)) | ||
, { __GRAPHQL_MUTATION__: true | ||
, operationName: capitalized | ||
, operation | ||
, fragments | ||
, queryString | ||
, toString: () => queryString | ||
} | ||
).then(data => Promise.resolve(data.payload)) | ||
) | ||
} | ||
fn.queryString = query | ||
fn.toString = () => query | ||
} | ||
return fn | ||
// Batch | ||
} | ||
export function batch(ops: Array<Query<mixed,mixed>>, variables: mixed): Promise<mixed> { | ||
// TEMPORARY: come up with a reasonable workaround for this: | ||
const names = ops.map(op => op.operationName) | ||
const fragments = mergeFragments(ops.map(op => op.fragments)) | ||
const doc = ops.map(op => op.operation).join(' ') | ||
+ ' ' | ||
+ valuesOf(fragments).join(' ') | ||
return request(doc, variables, names) | ||
.then(r => r.map(({ data, errors }, i) => { | ||
if (errors) throw new Error(errors) | ||
return data | ||
})) | ||
} | ||
@@ -123,3 +180,3 @@ | ||
, toString: () => string | ||
, fragments: { [key: string]: FragmentDefinition } | ||
, fragments: StrMap<FragmentDefinition> | ||
} | ||
@@ -144,19 +201,29 @@ | ||
, toString: () => string | ||
, fragments: { [key: string]: FragmentDefinition } | ||
, fragments: StrMap<FragmentDefinition> | ||
} | ||
const fragmentDefinitions: StrMap<Fragment> = {} | ||
export const fragment = (name: string, type: string = name): TemplateString<Fragment> => | ||
(target, ...values) => ( | ||
{ __GRAPHQL_QUERY_PARTIAL__: true | ||
, __GRAPHQL_FRAGMENT__: true | ||
, name | ||
, type | ||
, toString: () => `...${name}` | ||
, fragments: | ||
{ ...mergeFragments(values) | ||
, [name]: `fragment ${name} on ${type} ${String.raw(target, ...values)}` | ||
(target, ...values) => { | ||
invariant | ||
( !fragmentDefinitions[name] | ||
, `ERROR: there is already a fragment with name ${name}` | ||
) | ||
return fragmentDefinitions[name] = | ||
{ __GRAPHQL_QUERY_PARTIAL__: true | ||
, __GRAPHQL_FRAGMENT__: true | ||
, name | ||
, type | ||
, toString: () => `...${name}` | ||
, fragments: | ||
{ ...mergeFragments(values) | ||
, [name]: `fragment ${name} on ${type} ${String.raw(target, ...values)}` | ||
} | ||
} | ||
} | ||
) | ||
} | ||
// Union | ||
@@ -176,9 +243,6 @@ | ||
const mergeFragments = (values: Array<mixed>): { [key: string]: FragmentDefinition } => | ||
const mergeFragments = (values: Array<mixed>): StrMap<FragmentDefinition> => | ||
( values.map(asPartial).filter(x => !!x) : any ) | ||
.reduce((acc, { fragments }) => Object.assign(acc, fragments), {}) | ||
const collectFragments = (values: Array<mixed>): Array<FragmentDefinition> => | ||
valuesOf(mergeFragments(values)) | ||
// General Utils: | ||
@@ -185,0 +249,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
21343
410