graphql-genie
Advanced tools
Comparing version 0.3.0 to 0.3.1
- [GraphQLGenie API](#graphqlgenie-api) | ||
- [**constructor**](#constructor) | ||
- [**use**](#use) | ||
- [**getSchema**](#getschema) | ||
- [**printSchema**](#printschema) | ||
- [**getFragmentTypes**](#getfragmenttypes) | ||
- [**getRawData**](#getrawdata) | ||
- [**importRawData**](#importrawdata) | ||
- [**getDataResolver**](#getdataresolver) | ||
- [**getSchemaBuilder**](#getschemabuilder) | ||
- [**constructor**](#constructor) | ||
- [**use**](#use) | ||
- [**getSchema**](#getschema) | ||
- [**printSchema**](#printschema) | ||
- [**getFragmentTypes**](#getfragmenttypes) | ||
- [**getRawData**](#getrawdata) | ||
- [**importRawData**](#importrawdata) | ||
- [**getDataResolver**](#getdataresolver) | ||
- [Hooks](#hooks) | ||
- [**getSchemaBuilder**](#getschemabuilder) | ||
- [GraphQLSchemaBuilder API](#graphqlschemabuilder-api) | ||
- [**printSchemaWithDirectives**](#printschemawithdirectives) | ||
- [**addTypeDefsToSchema**](#addtypedefstoschema) | ||
- [**setResolvers**](#setresolvers) | ||
- [**setIResolvers**](#setiresolvers) | ||
- [**isUserType**](#isusertype) | ||
- [**printSchemaWithDirectives**](#printschemawithdirectives) | ||
- [**addTypeDefsToSchema**](#addtypedefstoschema) | ||
- [**setResolvers**](#setresolvers) | ||
- [**setIResolvers**](#setiresolvers) | ||
- [**isUserType**](#isusertype) | ||
@@ -102,7 +103,10 @@ ### GraphQLGenie API | ||
``` | ||
getRawData(): Promise<any[]> | ||
getRawData(types?: string[], context?): Promise<any[]> | ||
``` | ||
Returns all of the data in the database, this will look a little different than what is returned by graphql. Every object will have a __typename field and relations will just be ids or an array of ids rather than objects. It will look something like: | ||
**types** - Optional. List of the GraphQL Object Types you want data for. If null or blank all data will be returned | ||
**context** - Optional. Context object that will be sent to input/output hooks, may be needed if using the authentication plugin | ||
Returns data in the database, this will look a little different than what is returned by graphql. Every object will have a __typename field and relations will just be ids or an array of ids rather than objects. Also if you use interfaces and unions there may be null fields you weren't expecting on that type. It will look something like: | ||
```json | ||
@@ -146,3 +150,3 @@ [ | ||
``` | ||
importRawData(data: any[], merge = false, defaultTypename?: string): Promise | ||
importRawData(data: any[], merge = false, defaultTypename?: string, context?): Promise | ||
``` | ||
@@ -152,3 +156,3 @@ | ||
**data** | ||
**data** | ||
@@ -158,3 +162,3 @@ an array of objects to import. It can be either in the format of raw data (as exported from `getRawData` ) or in the format returned from a graphql query. Note that if it is in the format of the graphql query and __typename fields are not added the defaultTypename must be provided | ||
**merge** | ||
**merge** - Default = false | ||
@@ -177,6 +181,11 @@ If false every object will create a new object, the id won't be preserved from the current data but relationships will still be built as they were in the provided data. | ||
**defaultTypename** | ||
**defaultTypename** - Optional. | ||
Must be provided if every object in data does not have a `__typename` property | ||
**context** - Optional. | ||
Context object that will be sent to input/output hooks, may be needed if using the authentication plugin | ||
--- | ||
@@ -190,4 +199,29 @@ | ||
DataResolver handles all the operations with your actual data. Such as CRUD and hooks. | ||
DataResolver handles all the operations with your actual data. Such as CRUD and hooks. It has the following functions | ||
```typescript | ||
export interface DataResolver { | ||
create(graphQLTypeName: string, records, meta?): Promise<any>; | ||
find(graphQLTypeName: string, ids?: string[], options?, meta?): Promise<any>; | ||
update(graphQLTypeName: string, updates: object, meta?, options?: object): Promise<any>; | ||
delete(graphQLTypeName: string, ids?: string[], meta?): Promise<any>; | ||
addOutputHook(graphQLTypeName: string, hook: DataResolverOutputHook); | ||
addInputHook(graphQLTypeName: string, hook: DataResolverInputHook); | ||
getValueByUnique(returnTypeName: string, args, meta): Promise<Object>; | ||
canAdd(graphQLTypeName: string, records: Object, meta): Promise<boolean>; | ||
getConnection(allEdges: any[], before: string, after: string, first: number, last: number): Connection; | ||
getFeatures(): Features; | ||
applyOptions(graphQLTypeName: string, records, options, meta?); | ||
getStore(): any; | ||
beginTransaction(): Promise<void>; | ||
endTransaction(): Promise<void>; | ||
computeId(graphType: string, id?: string): string; | ||
getTypeFromId(inputId: string): string; | ||
getOriginalIdFromObjectId(inputId: string): string; | ||
getLink(graphQLTypeName: string, field: string): string; | ||
} | ||
``` | ||
##### Hooks | ||
Most likely use of this is to add hooks into the CRUD operations against your database. The DataResolver has 2 functions to add hooks. For more info on the context, record and update objects see the [fortune documentation](http://fortune.js.org/#input-and-output-hooks). | ||
@@ -197,2 +231,3 @@ | ||
```typescript | ||
@@ -205,4 +240,2 @@ interface DataResolverInputHook { | ||
} | ||
addOutputHook(graphQLTypeName: string, hook: DataResolverOutputHook); | ||
addInputHook(graphQLTypeName: string, hook: DataResolverInputHook); | ||
``` | ||
@@ -209,0 +242,0 @@ |
@@ -27,6 +27,6 @@ import { GraphQLSchema } from 'graphql'; | ||
private mapIdsToCreatedIds; | ||
importRawData: (data: any[], merge?: boolean, defaultTypename?: string) => Promise<void>; | ||
getRawData: () => Promise<any>; | ||
importRawData: (data: any[], merge?: boolean, defaultTypename?: string, context?: any) => Promise<void>; | ||
getRawData: (types?: any[], context?: any) => Promise<any[]>; | ||
getFragmentTypes: () => Promise<any>; | ||
} | ||
//# sourceMappingURL=GraphQLGenie.d.ts.map |
@@ -192,3 +192,4 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
}; | ||
this.importRawData = (data, merge = false, defaultTypename) => __awaiter(this, void 0, void 0, function* () { | ||
this.importRawData = (data, merge = false, defaultTypename, context) => __awaiter(this, void 0, void 0, function* () { | ||
const meta = context ? { context } : undefined; | ||
let index = 0; | ||
@@ -251,3 +252,3 @@ const createPromises = []; | ||
createPromises.push(new Promise((resolve, reject) => { | ||
this.graphQLFortune.create(typeName, record).then(createdObj => { | ||
this.graphQLFortune.create(typeName, record, meta).then(createdObj => { | ||
objectsMap.set(object['id'], createdObj); | ||
@@ -336,3 +337,3 @@ resolve(createdObj); | ||
// console.log(typeName, update); | ||
updatePromies.push(this.graphQLFortune.update(typeName, update, undefined, { fortuneFormatted: true })); | ||
updatePromies.push(this.graphQLFortune.update(typeName, update, meta, { fortuneFormatted: true })); | ||
} | ||
@@ -343,18 +344,21 @@ index++; | ||
}); | ||
this.getRawData = () => __awaiter(this, void 0, void 0, function* () { | ||
this.getRawData = (types = [], context) => __awaiter(this, void 0, void 0, function* () { | ||
const meta = context ? { context } : undefined; | ||
let nodes = []; | ||
const result = yield graphql(this.schema, `{ | ||
__schema { | ||
types { | ||
name | ||
kind | ||
if (isEmpty(types)) { | ||
const result = yield graphql(this.schema, `{ | ||
__schema { | ||
types { | ||
name | ||
kind | ||
} | ||
} | ||
} | ||
}`); | ||
const types = get(result, 'data.__schema.types'); | ||
}`); | ||
types = get(result, 'data.__schema.types'); | ||
types = types.filter(type => type.kind === 'OBJECT' && this.schemaBuilder.isUserTypeByName(type.name)).map(type => type.name); | ||
} | ||
if (types) { | ||
const userObjects = result.data.__schema.types.filter(type => type.kind === 'OBJECT' && this.schemaBuilder.isUserTypeByName(type.name)); | ||
const promises = []; | ||
userObjects.forEach(object => { | ||
promises.push(this.graphQLFortune.find(object.name)); | ||
types.forEach(typeName => { | ||
promises.push(this.graphQLFortune.find(typeName, undefined, undefined, meta)); | ||
}); | ||
@@ -361,0 +365,0 @@ const allData = yield Promise.all(promises); |
@@ -27,7 +27,8 @@ import { GraphQLFieldResolver } from 'graphql'; | ||
export interface DataResolver { | ||
getLink(graphQLTypeName: string, field: string): string; | ||
create(graphQLTypeName: string, records: any, meta?: any): Promise<any>; | ||
find(graphQLTypeName: string, ids?: string[], options?: any, meta?: any): Promise<any>; | ||
update(graphQLTypeName: string, updates: object, meta?: any, options?: object): Promise<any>; | ||
delete(graphQLTypeName: string, ids?: string[], meta?: any): Promise<any>; | ||
update(graphQLTypeName: string, updates: object, meta?: any, options?: object): Promise<any>; | ||
find(graphQLTypeName: string, ids?: string[], options?: any, meta?: any): Promise<any>; | ||
create(graphQLTypeName: string, records: any, meta?: any): Promise<any>; | ||
addOutputHook(graphQLTypeName: string, hook: DataResolverOutputHook): any; | ||
addInputHook(graphQLTypeName: string, hook: DataResolverInputHook): any; | ||
getValueByUnique(returnTypeName: string, args: any, meta: any): Promise<Object>; | ||
@@ -39,4 +40,2 @@ canAdd(graphQLTypeName: string, records: Object, meta: any): Promise<boolean>; | ||
getStore(): any; | ||
addOutputHook(graphQLTypeName: string, hook: DataResolverOutputHook): any; | ||
addInputHook(graphQLTypeName: string, hook: DataResolverInputHook): any; | ||
beginTransaction(): Promise<void>; | ||
@@ -47,2 +46,3 @@ endTransaction(): Promise<void>; | ||
getOriginalIdFromObjectId(inputId: string): string; | ||
getLink(graphQLTypeName: string, field: string): string; | ||
} | ||
@@ -49,0 +49,0 @@ export interface GenerateConfig { |
{ | ||
"name": "graphql-genie", | ||
"version": "0.3.0", | ||
"version": "0.3.1", | ||
"description": "GraphQL Genie", | ||
@@ -5,0 +5,0 @@ "browser": "./lib/browser.umd.js", |
126
README.md
@@ -6,2 +6,3 @@ <h1 align="center"> | ||
# GraphQL Genie <!-- omit in toc --> | ||
@@ -15,4 +16,20 @@ | ||
## Overview <!-- omit in toc --> | ||
- [Overview](#overview) | ||
- [Installation](#installation) | ||
- [Demo](#demo) | ||
- [Getting started](#getting-started) | ||
- [Documentation and Features](#documentation-and-features) | ||
- [Data Store Options](#data-store-options) | ||
- [GraphQL Genie Schema API (queries and mutations)](#graphql-genie-schema-api-queries-and-mutations) | ||
- [GraphQLGenie API](#graphqlgenie-api) | ||
- [Subscriptions](#subscriptions) | ||
- [Authentication](#authentication) | ||
- [Examples](#examples) | ||
- [Client](#client) | ||
- [Server](#server) | ||
- [Features/Advantages/Differences](#featuresadvantagesdifferences) | ||
- [Roadmap](#roadmap) | ||
## Overview | ||
Write a [GraphQL Type Schema](https://graphql.org/learn/schema/) and [GraphQL Genie](https://github.com/genie-team/graphql-genie) automatically generates a fully featured GraphQL API with referential integrity and inverse updates that can be used client side or server side. | ||
@@ -24,3 +41,3 @@ | ||
- **Works with other GraphQL libraries** like [Relay](https://facebook.github.io/relay/)(react) and [Apollo Client](https://github.com/apollographql/apollo-client)(vanilla js or any framework) | ||
- **Portable data** with a variety of [data stores](#data-store-options) including client and server side supported and import/export/merge functions. | ||
- **Portable data** with a variety of [data stores](#data-store-options) including client and server side support and [Export](https://github.com/genie-team/graphql-genie/blob/master/docs/GraphQLGenieAPI.md#getrawdata)/[Import/Merge](https://github.com/genie-team/graphql-genie/blob/master/docs/GraphQLGenieAPI.md#importrawdata) functions. | ||
- **FortuneJS Storage** allows many storage options and the ability to easily create your own. See [data store options](#data-store-options) | ||
@@ -32,5 +49,5 @@ | ||
<!-- omit in toc --> | ||
## Installation <!-- omit in toc --> | ||
## Installation | ||
`npm install graphql-genie fortune graphql graphql-tools lodash` | ||
@@ -42,5 +59,5 @@ | ||
<!-- omit in toc --> | ||
## Demo <!-- omit in toc --> | ||
## Demo | ||
[See the fully featured demo](https://genie-team.github.io/graphql-genie-client/). Create a schema (or use the default provided) and a fully featured api is created. Click the search icon to use GraphiQL to view docs and create or mock data. See [graphql genie client](https://github.com/genie-team/graphql-genie-client) on github for more info on the demo. | ||
@@ -50,5 +67,5 @@ | ||
<!-- omit in toc --> | ||
## Getting started <!-- omit in toc --> | ||
## Getting started | ||
1. [Create your type definitions.](https://github.com/genie-team/graphql-genie/blob/master/docs/sdl.md) These are GraphQL Type definitions, GraphQL Genie does have some additional directives which may be useful (unique, relations, timestamps, default values). [Documentation in docs/sdl.md](https://github.com/genie-team/graphql-genie/blob/master/docs/sdl.md) | ||
@@ -67,13 +84,27 @@ 2. Setup fortune options with your adapter and other settings. See example below or [fortune docs](http://fortune.js.org/api/#fortune-constructor) and documentation for your adapter | ||
const fortuneOptions: FortuneOptions = { | ||
adapter: [ | ||
mongodbAdapter, | ||
{ | ||
// options object, URL is mandatory. | ||
url: config.mongodbURL | ||
} | ||
], | ||
settings: { enforceLinks: true } | ||
// see the documentation for your specific adapter | ||
adapter: [ | ||
mongodbAdapter, | ||
{ | ||
// options object, URL is mandatory. | ||
url: config.mongodbURL | ||
} | ||
] | ||
}; | ||
// Instantiate Genie with your type defintions as a string | ||
const typeDefs = `[TYPEDEFS]` | ||
const typeDefs = ` | ||
type City { | ||
id: ID! @unique | ||
name: String! | ||
neighborhoods: [String] @unique | ||
residents: [User] @relation(name: "city") | ||
founded: Date | ||
population: Int | ||
} | ||
type User { | ||
id: ID! @unique | ||
displayname: String @unique | ||
email: String! @unique | ||
location: City @relation(name: "city") | ||
}`; | ||
const genie = new GraphQLGenie({ | ||
@@ -93,26 +124,5 @@ typeDefs: typeDefs, | ||
- [Documentation and Features](#documentation-and-features) | ||
- [Data Store Options](#data-store-options) | ||
- [GraphQL Genie Schema API (queries and mutations)](#graphql-genie-schema-api-queries-and-mutations) | ||
- [GraphQLGenie API](#graphqlgenie-api) | ||
- [Subscriptions](#subscriptions) | ||
- [Authentication](#authentication) | ||
- [How do I do/add [thing]](#how-do-i-doadd-thing) | ||
- [Examples](#examples) | ||
- [Client](#client) | ||
- [Memory](#memory) | ||
- [IndexedDB](#indexeddb) | ||
- [Server](#server) | ||
- [Apollo Server 2 Redis with JWT Authentication](#apollo-server-2-redis-with-jwt-authentication) | ||
- [GrapqhQL Yoga Redis with Session Authentication](#grapqhql-yoga-redis-with-session-authentication) | ||
- [GrapqhQL Yoga Redis with Firebase Authentication](#grapqhql-yoga-redis-with-firebase-authentication) | ||
- [GraphQL Yoga PostgreSQL](#graphql-yoga-postgresql) | ||
- [Other](#other) | ||
- [MongoDB](#mongodb) | ||
- [Features/Advantages/Differences](#featuresadvantagesdifferences) | ||
- [Thanks/Credit](#thankscredit) | ||
### Data Store Options | ||
GraphQLGenie uses [FortuneJS](http://fortune.js.org) for accessing the data store. This means any [fortune adapter](http://fortune.js.org/plugins/) will work, plugins currently exist for memory ([example](https://github.com/genie-team/graphql-genie/tree/master/examples/memory)), [IndexedDB](https://github.com/fortunejs/fortune-indexeddb) ([example](https://github.com/genie-team/graphql-genie/tree/master/examples/indexeddb)), [MongoDB](https://github.com/fortunejs/fortune-mongodb) ([example](https://github.com/genie-team/graphql-genie/tree/master/examples/mongodb)), [Postgres](https://github.com/fortunejs/fortune-postgres) ([example](https://github.com/genie-team/graphql-genie/tree/master/examples/graphql-yoga-postgresql)), [Redis](https://github.com/thibremy/fortune-redis) ([examples](#server)), [Google Cloud Datastore](https://github.com/patrinhani-ciandt/fortune-datastore), [NeDB](https://github.com/fortunejs/fortune-nedb) and [File System](https://github.com/fortunejs/fortune-fs). Or you could [write your own adapter](http://fortune.js.org/api/#adapter). | ||
GraphQLGenie uses [FortuneJS](http://fortune.js.org) for accessing the data store. This means any [fortune adapter](http://fortune.js.org/plugins/) will work, plugins currently exist for memory ([example](https://github.com/genie-team/graphql-genie/tree/master/examples/memory)), [IndexedDB](https://github.com/fortunejs/fortune-indexeddb) ([example](https://github.com/genie-team/graphql-genie/tree/master/examples/indexeddb)), [MongoDB](https://github.com/fortunejs/fortune-mongodb) ([example](https://github.com/genie-team/graphql-genie/tree/master/examples/mongodb)), [PostgreSQL](https://github.com/fortunejs/fortune-postgres) ([example](https://github.com/genie-team/graphql-genie/tree/master/examples/graphql-yoga-postgresql)), [Redis](https://github.com/thibremy/fortune-redis) ([examples](#server)), [Google Cloud Datastore](https://github.com/patrinhani-ciandt/fortune-datastore), [NeDB](https://github.com/fortunejs/fortune-nedb) and [File System](https://github.com/fortunejs/fortune-fs). Or you could [write your own adapter](http://fortune.js.org/api/#adapter). | ||
@@ -124,5 +134,5 @@ ### GraphQL Genie Schema API (queries and mutations) | ||
* Also see the [subscriptions plugin](https://github.com/genie-team/graphql-genie/tree/master/plugins/subscriptions) | ||
### GraphQLGenie API | ||
### GraphQLGenie API | ||
@@ -150,5 +160,5 @@ The [api documentation](https://github.com/genie-team/graphql-genie/blob/master/docs/GraphQLGenieAPI.md) can be found in the docs folder | ||
* At the resolver level by wrapping the resolver functions that GraphQL Genie created in the schema, or use a tool like [graphql-resolvers](https://github.com/lucasconstantino/graphql-resolvers) to combine resolver, with authentication logic. | ||
* At the data level create an input hook and add it to the DataResolver (returned by getDataResolver, see the [api documentation](https://github.com/genie-team/graphql-genie/blob/master/docs/GraphQLGenieAPI.md)) and throw an error if not authorized. | ||
* At the data level create an [input hook](https://github.com/genie-team/graphql-genie/blob/master/docs/GraphQLGenieAPI.md#getdataresolver) and add it to the DataResolver (returned by getDataResolver, see the [api documentation](https://github.com/genie-team/graphql-genie/blob/master/docs/GraphQLGenieAPI.md)) and throw an error if not authorized. | ||
### How do I do/add [thing] | ||
### How do I do/add [thing] <!-- omit in toc --> | ||
@@ -163,7 +173,7 @@ You can use the methods on the GraphQLSchemaBuilder (returned by getSchemaBuilder()) to add types and resolvers to the generated schema. Or since it is just a normal schema you can use any tool you want (such as [graphql-tools](https://www.apollographql.com/docs/graphql-tools)) to alter the schema in any way. Including adding resolvers, mocking, stitching, transforming, etc. | ||
#### [Memory](https://github.com/genie-team/graphql-genie/tree/master/examples/memory) | ||
#### [Memory](https://github.com/genie-team/graphql-genie/tree/master/examples/memory) <!-- omit in toc --> | ||
Sets up an API that stores data in browser memory | ||
#### [IndexedDB](https://github.com/genie-team/graphql-genie/tree/master/examples/indexeddb) | ||
#### [IndexedDB](https://github.com/genie-team/graphql-genie/tree/master/examples/indexeddb) <!-- omit in toc --> | ||
@@ -174,21 +184,21 @@ Sets up an API that stores data in browser Indexed DB | ||
#### [Apollo Server 2 Redis with JWT Authentication](https://github.com/genie-team/graphql-genie/tree/master/examples/apollo-server2-redis-jwt-auth) | ||
#### [Apollo Server 2 Redis with JWT Authentication](https://github.com/genie-team/graphql-genie/tree/master/examples/apollo-server2-redis-jwt-auth) <!-- omit in toc --> | ||
Sets up a server using [Apollo Server 2](https://github.com/apollographql/apollo-server) and an api that stores to a mock Redis with json web token based signup and login. Uses the [authentication plugin](https://github.com/genie-team/graphql-genie/tree/master/plugins/authentication) for role based access control. | ||
#### [GrapqhQL Yoga Redis with Session Authentication](https://github.com/genie-team/graphql-genie/tree/master/examples/graphql-yoga-redis-authentication) | ||
#### [GrapqhQL Yoga Redis with Session Authentication](https://github.com/genie-team/graphql-genie/tree/master/examples/graphql-yoga-redis-authentication) <!-- omit in toc --> | ||
Sets up a server using [GrapqhQL Yoga](https://github.com/prismagraphql/graphql-yoga) and an api that stores to a mock Redis with session based signup and login. Uses the [authentication plugin](https://github.com/genie-team/graphql-genie/tree/master/plugins/authentication) for role based access control. | ||
#### [GrapqhQL Yoga Redis with Firebase Authentication](https://github.com/genie-team/graphql-genie/tree/master/examples/graphql-yoga-redis-firebase-auth) | ||
#### [GrapqhQL Yoga Redis with Firebase Authentication](https://github.com/genie-team/graphql-genie/tree/master/examples/graphql-yoga-redis-firebase-auth) <!-- omit in toc --> | ||
Sets up a server using [GrapqhQL Yoga](https://github.com/prismagraphql/graphql-yoga) and an api that stores to a mock Redis. Serves static html for [firebase](https://firebase.google.com/docs/auth/) signup and login. Uses the [authentication plugin](https://github.com/genie-team/graphql-genie/tree/master/plugins/authentication) for role based access control. | ||
#### [GraphQL Yoga PostgreSQL](https://github.com/genie-team/graphql-genie/tree/master/examples/graphql-yoga-postgresql) | ||
#### [GraphQL Yoga PostgreSQL](https://github.com/genie-team/graphql-genie/tree/master/examples/graphql-yoga-postgresql) <!-- omit in toc --> | ||
Sets up a server using [GrapqhQL Yoga](https://github.com/prismagraphql/graphql-yoga) and an API that stores to PostgreSQL. | ||
### Other | ||
### Other <!-- omit in toc --> | ||
#### [MongoDB](https://github.com/genie-team/graphql-genie/tree/master/examples/mongodb) | ||
#### [MongoDB](https://github.com/genie-team/graphql-genie/tree/master/examples/mongodb) <!-- omit in toc --> | ||
@@ -202,4 +212,4 @@ Creates a simple node script that uses the GraphQL Genie api to store in a MongoDB database | ||
* Bi-directional relationships in any database with a GraphQL API | ||
* Portable storage options, use anywhere for any purpose which is essential for some applications. | ||
* Export/Import/Merge data between data sources | ||
* Portable storage options, great for Progressive Web Apps. Use anywhere for any purpose. | ||
* [Export](https://github.com/genie-team/graphql-genie/blob/master/docs/GraphQLGenieAPI.md#getrawdata)/[Import/Merge](https://github.com/genie-team/graphql-genie/blob/master/docs/GraphQLGenieAPI.md#importrawdata) data between data sources | ||
* Share GraphQL data model on server and client | ||
@@ -210,5 +220,13 @@ * You can use [The Apollo Platform](https://www.apollographql.com/), [Relay](https://facebook.github.io/relay/), [GraphQL Bindings](https://github.com/graphql-binding/graphql-binding) or any of the many other tools in the growing GraphQL ecosystem. | ||
* You can make your api logic completely serverless | ||
* You can use all the features of the type schema, including interfaces and unions. | ||
* [Input and Output hooks](https://github.com/genie-team/graphql-genie/blob/master/docs/GraphQLGenieAPI.md#getdataresolver) against the actual data resolver add more possibilities for advanced functionality | ||
* [FortuneJS](http://fortune.js.org) allows easy creation of new adapters | ||
## Thanks/Credit | ||
## Roadmap | ||
* Singular queries | ||
* Import/Export mutations | ||
* Progressive Web App example | ||
## Thanks/Credit <!-- omit in toc --> | ||
[Prisma GraphQL / Graphcool](https://github.com/prismagraphql/prisma) for inspiration | ||
@@ -215,0 +233,0 @@ |
@@ -247,3 +247,4 @@ | ||
public importRawData = async (data: any[], merge = false, defaultTypename?: string) => { | ||
public importRawData = async (data: any[], merge = false, defaultTypename?: string, context?) => { | ||
const meta = context ? {context} : undefined; | ||
let index = 0; | ||
@@ -305,3 +306,3 @@ const createPromises = []; | ||
new Promise((resolve, reject) => { | ||
this.graphQLFortune.create(typeName, record).then(createdObj => { | ||
this.graphQLFortune.create(typeName, record, meta).then(createdObj => { | ||
objectsMap.set(object['id'], createdObj); | ||
@@ -392,3 +393,3 @@ resolve(createdObj); | ||
// console.log(typeName, update); | ||
updatePromies.push(this.graphQLFortune.update(typeName, update, undefined, { fortuneFormatted: true })); | ||
updatePromies.push(this.graphQLFortune.update(typeName, update, meta, { fortuneFormatted: true })); | ||
} | ||
@@ -400,20 +401,23 @@ index++; | ||
public getRawData = async (): Promise<any> => { | ||
public getRawData = async (types = [], context?): Promise<any[]> => { | ||
const meta = context ? {context} : undefined; | ||
let nodes = []; | ||
const result = await graphql(this.schema, `{ | ||
__schema { | ||
types { | ||
name | ||
kind | ||
if (isEmpty(types)) { | ||
const result = await graphql(this.schema, `{ | ||
__schema { | ||
types { | ||
name | ||
kind | ||
} | ||
} | ||
} | ||
}`); | ||
const types = get(result, 'data.__schema.types'); | ||
}`); | ||
types = get(result, 'data.__schema.types'); | ||
types = types.filter( | ||
type => type.kind === 'OBJECT' && this.schemaBuilder.isUserTypeByName(type.name) | ||
).map(type => type.name); | ||
} | ||
if (types) { | ||
const userObjects = result.data.__schema.types.filter( | ||
type => type.kind === 'OBJECT' && this.schemaBuilder.isUserTypeByName(type.name) | ||
); | ||
const promises = []; | ||
userObjects.forEach(object => { | ||
promises.push(this.graphQLFortune.find(object.name)); | ||
types.forEach(typeName => { | ||
promises.push(this.graphQLFortune.find(typeName, undefined, undefined, meta)); | ||
}); | ||
@@ -420,0 +424,0 @@ const allData = await Promise.all(promises); |
@@ -42,7 +42,8 @@ import { GraphQLFieldResolver } from 'graphql'; | ||
export interface DataResolver { | ||
getLink(graphQLTypeName: string, field: string): string; | ||
create(graphQLTypeName: string, records, meta?): Promise<any>; | ||
find(graphQLTypeName: string, ids?: string[], options?, meta?): Promise<any>; | ||
update(graphQLTypeName: string, updates: object, meta?, options?: object): Promise<any>; | ||
delete(graphQLTypeName: string, ids?: string[], meta?): Promise<any>; | ||
update(graphQLTypeName: string, updates: object, meta?, options?: object): Promise<any>; | ||
find(graphQLTypeName: string, ids?: string[], options?, meta?): Promise<any>; | ||
create(graphQLTypeName: string, records, meta?): Promise<any>; | ||
addOutputHook(graphQLTypeName: string, hook: DataResolverOutputHook); | ||
addInputHook(graphQLTypeName: string, hook: DataResolverInputHook); | ||
getValueByUnique(returnTypeName: string, args, meta): Promise<Object>; | ||
@@ -54,4 +55,2 @@ canAdd(graphQLTypeName: string, records: Object, meta): Promise<boolean>; | ||
getStore(): any; | ||
addOutputHook(graphQLTypeName: string, hook: DataResolverOutputHook); | ||
addInputHook(graphQLTypeName: string, hook: DataResolverInputHook); | ||
beginTransaction(): Promise<void>; | ||
@@ -62,2 +61,3 @@ endTransaction(): Promise<void>; | ||
getOriginalIdFromObjectId(inputId: string): string; | ||
getLink(graphQLTypeName: string, field: string): string; | ||
} | ||
@@ -64,0 +64,0 @@ |
import { ApolloClient } from 'apollo-client'; | ||
import gql from 'graphql-tag'; | ||
import { getClient } from '../setupTests'; | ||
import { genie, getClient } from '../setupTests'; | ||
let client: ApolloClient<any>; | ||
@@ -889,2 +889,20 @@ beforeAll(async () => { | ||
}); | ||
test('genie - getRawData', async () => { | ||
const nodes = await genie.getRawData(); | ||
expect(nodes).not.toBeNull(); | ||
expect(nodes.length).toBeGreaterThan(0); | ||
}); | ||
test('genie - getRawData Address only, then import', async () => { | ||
let nodes = await genie.getRawData(['Address']); | ||
expect(nodes).not.toBeNull(); | ||
expect(nodes.length).toBe(1); | ||
nodes[0].city = 'Olympus'; | ||
await genie.importRawData(nodes, true); | ||
nodes = await genie.getRawData(['Address']); | ||
expect(nodes).not.toBeNull(); | ||
expect(nodes.length).toBe(1); | ||
expect(nodes[0].city).toBe('Olympus'); | ||
}); | ||
}); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
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
994389
22018
223