create valid relay schema.json
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,2 @@
|
||||
node_modules/
|
||||
bin/
|
||||
data/example/
|
||||
|
||||
@@ -7,7 +7,7 @@ import graphQLHTTP from 'express-graphql';
|
||||
import path from 'path';
|
||||
import webpack from 'webpack';
|
||||
import WebpackDevServer from 'webpack-dev-server';
|
||||
import {Schema} from './data/schema';
|
||||
import {Schema} from './config/graphql/schema';
|
||||
|
||||
const APP_PORT = 3000;
|
||||
const GRAPHQL_PORT = 8080;
|
||||
|
||||
@@ -24,10 +24,10 @@ class Database {
|
||||
|
||||
// add associations
|
||||
for (var model of Database.models){
|
||||
model.associate();
|
||||
model.set();
|
||||
}
|
||||
|
||||
return sequelize.sync({force: true});
|
||||
return sequelize.sync();
|
||||
}
|
||||
}
|
||||
Database.sequelize = sequelize;
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
/**
|
||||
* We get the node interface and field from the Relay library.
|
||||
*
|
||||
* The first method defines the way we resolve an ID to its object.
|
||||
* The second defines the way we resolve an object to its GraphQL type.
|
||||
*/
|
||||
|
||||
import {
|
||||
fromGlobalId,
|
||||
nodeDefinitions,
|
||||
} from 'graphql-relay';
|
||||
|
||||
64
config/graphql/schema.graphql
Normal file
64
config/graphql/schema.graphql
Normal file
@@ -0,0 +1,64 @@
|
||||
type House implements Node {
|
||||
id: ID!
|
||||
name: String!
|
||||
power_data(after: String, first: Int, before: String, last: Int): PowerDatumConnection
|
||||
habitants(after: String, first: Int, before: String, last: Int): UserConnection
|
||||
}
|
||||
|
||||
type HouseConnection {
|
||||
pageInfo: PageInfo!
|
||||
edges: [HouseEdge]
|
||||
}
|
||||
|
||||
type HouseEdge {
|
||||
node: House
|
||||
cursor: String!
|
||||
}
|
||||
|
||||
interface Node {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type PageInfo {
|
||||
hasNextPage: Boolean!
|
||||
hasPreviousPage: Boolean!
|
||||
startCursor: String
|
||||
endCursor: String
|
||||
}
|
||||
|
||||
type PowerDatum implements Node {
|
||||
id: ID!
|
||||
power: Float
|
||||
time: Int
|
||||
}
|
||||
|
||||
type PowerDatumConnection {
|
||||
pageInfo: PageInfo!
|
||||
edges: [PowerDatumEdge]
|
||||
}
|
||||
|
||||
type PowerDatumEdge {
|
||||
node: PowerDatum
|
||||
cursor: String!
|
||||
}
|
||||
|
||||
type Query {
|
||||
node(id: ID!): Node
|
||||
viewer: User
|
||||
}
|
||||
|
||||
type User implements Node {
|
||||
id: ID!
|
||||
username: String!
|
||||
house(after: String, first: Int, before: String, last: Int): HouseConnection
|
||||
}
|
||||
|
||||
type UserConnection {
|
||||
pageInfo: PageInfo!
|
||||
edges: [UserEdge]
|
||||
}
|
||||
|
||||
type UserEdge {
|
||||
node: User
|
||||
cursor: String!
|
||||
}
|
||||
27
config/graphql/schema.js
Normal file
27
config/graphql/schema.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import {
|
||||
GraphQLObjectType,
|
||||
GraphQLSchema
|
||||
} from 'graphql';
|
||||
|
||||
import {nodeField} from './node';
|
||||
import DB from './../database';
|
||||
|
||||
export default function(){
|
||||
|
||||
var queryType = new GraphQLObjectType({
|
||||
name: 'Query',
|
||||
fields: () => ({
|
||||
node: nodeField,
|
||||
viewer: {
|
||||
type: DB.User.graphql_type,
|
||||
resolve: (_, args) => {
|
||||
return DB.User.findOne({where: {username: args.username}});
|
||||
}
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
return new GraphQLSchema({
|
||||
query: queryType
|
||||
});
|
||||
}
|
||||
@@ -95,20 +95,25 @@
|
||||
"possibleTypes": [
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "User",
|
||||
"name": "House",
|
||||
"ofType": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "Widget",
|
||||
"name": "PowerDatum",
|
||||
"ofType": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "User",
|
||||
"ofType": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "User",
|
||||
"description": "A person who uses our app",
|
||||
"name": "House",
|
||||
"description": "A house",
|
||||
"fields": [
|
||||
{
|
||||
"name": "id",
|
||||
@@ -127,8 +132,24 @@
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "widgets",
|
||||
"description": "A person's collection of widgets",
|
||||
"name": "name",
|
||||
"description": null,
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "power_data",
|
||||
"description": "Returns house's power data.",
|
||||
"args": [
|
||||
{
|
||||
"name": "after",
|
||||
@@ -173,7 +194,60 @@
|
||||
],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "WidgetConnection",
|
||||
"name": "PowerDatumConnection",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "habitants",
|
||||
"description": "Returns list of house's habitants.",
|
||||
"args": [
|
||||
{
|
||||
"name": "after",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "first",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "before",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "last",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "UserConnection",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
@@ -213,7 +287,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "WidgetConnection",
|
||||
"name": "PowerDatumConnection",
|
||||
"description": "A connection to a list of items.",
|
||||
"fields": [
|
||||
{
|
||||
@@ -241,7 +315,7 @@
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "WidgetEdge",
|
||||
"name": "PowerDatumEdge",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
@@ -333,7 +407,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "WidgetEdge",
|
||||
"name": "PowerDatumEdge",
|
||||
"description": "An edge in a connection.",
|
||||
"fields": [
|
||||
{
|
||||
@@ -342,7 +416,7 @@
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "Widget",
|
||||
"name": "PowerDatum",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
@@ -372,8 +446,8 @@
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "Widget",
|
||||
"description": "A shiny widget",
|
||||
"name": "PowerDatum",
|
||||
"description": "A person who uses our app",
|
||||
"fields": [
|
||||
{
|
||||
"name": "id",
|
||||
@@ -392,12 +466,24 @@
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"description": "The name of the widget",
|
||||
"name": "power",
|
||||
"description": null,
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"name": "Float",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "time",
|
||||
"description": "Time the power was recorded.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
@@ -415,6 +501,282 @@
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "SCALAR",
|
||||
"name": "Float",
|
||||
"description": "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ",
|
||||
"fields": null,
|
||||
"inputFields": null,
|
||||
"interfaces": null,
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "UserConnection",
|
||||
"description": "A connection to a list of items.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "pageInfo",
|
||||
"description": "Information to aid in pagination.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "PageInfo",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "edges",
|
||||
"description": "Information to aid in pagination.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "UserEdge",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "UserEdge",
|
||||
"description": "An edge in a connection.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "node",
|
||||
"description": "The item at the end of the edge",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "User",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "cursor",
|
||||
"description": "A cursor for use in pagination",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "User",
|
||||
"description": "A house",
|
||||
"fields": [
|
||||
{
|
||||
"name": "id",
|
||||
"description": "The ID of an object",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "username",
|
||||
"description": null,
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "house",
|
||||
"description": "Returns user's house.",
|
||||
"args": [
|
||||
{
|
||||
"name": "after",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "first",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "before",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "last",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Int",
|
||||
"ofType": null
|
||||
},
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "HouseConnection",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [
|
||||
{
|
||||
"kind": "INTERFACE",
|
||||
"name": "Node",
|
||||
"ofType": null
|
||||
}
|
||||
],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "HouseConnection",
|
||||
"description": "A connection to a list of items.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "pageInfo",
|
||||
"description": "Information to aid in pagination.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "PageInfo",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "edges",
|
||||
"description": "Information to aid in pagination.",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "HouseEdge",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "HouseEdge",
|
||||
"description": "An edge in a connection.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "node",
|
||||
"description": "The item at the end of the edge",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "House",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "cursor",
|
||||
"description": "A cursor for use in pagination",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "String",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "__Schema",
|
||||
@@ -1,33 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
// Model types
|
||||
class User extends Object {}
|
||||
class Widget extends Object {}
|
||||
|
||||
// Mock data
|
||||
var viewer = new User();
|
||||
viewer.id = '1';
|
||||
viewer.name = 'Anonymous';
|
||||
var widgets = ['What\'s-it', 'Who\'s-it', 'How\'s-it'].map((name, i) => {
|
||||
var widget = new Widget();
|
||||
widget.name = name;
|
||||
widget.id = `${i}`;
|
||||
return widget;
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
// Export methods that your schema can use to interact with your database
|
||||
getUser: (id) => id === viewer.id ? viewer : null,
|
||||
getViewer: () => viewer,
|
||||
getWidget: (id) => widgets.find(w => w.id === id),
|
||||
getWidgets: () => widgets,
|
||||
User,
|
||||
Widget,
|
||||
};
|
||||
89283
data/power_data.csv
Normal file
89283
data/power_data.csv
Normal file
File diff suppressed because it is too large
Load Diff
143
data/schema.js
143
data/schema.js
@@ -1,143 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
import {
|
||||
GraphQLBoolean,
|
||||
GraphQLFloat,
|
||||
GraphQLID,
|
||||
GraphQLInt,
|
||||
GraphQLList,
|
||||
GraphQLNonNull,
|
||||
GraphQLObjectType,
|
||||
GraphQLSchema,
|
||||
GraphQLString,
|
||||
} from 'graphql';
|
||||
|
||||
import {
|
||||
connectionArgs,
|
||||
connectionDefinitions,
|
||||
connectionFromArray,
|
||||
fromGlobalId,
|
||||
globalIdField,
|
||||
mutationWithClientMutationId,
|
||||
nodeDefinitions,
|
||||
} from 'graphql-relay';
|
||||
|
||||
import {
|
||||
// Import methods that your schema can use to interact with your database
|
||||
User,
|
||||
Widget,
|
||||
getUser,
|
||||
getViewer,
|
||||
getWidget,
|
||||
getWidgets,
|
||||
} from './database';
|
||||
|
||||
/**
|
||||
* We get the node interface and field from the Relay library.
|
||||
*
|
||||
* The first method defines the way we resolve an ID to its object.
|
||||
* The second defines the way we resolve an object to its GraphQL type.
|
||||
*/
|
||||
var {nodeInterface, nodeField} = nodeDefinitions(
|
||||
(globalId) => {
|
||||
var {type, id} = fromGlobalId(globalId);
|
||||
if (type === 'User') {
|
||||
return getUser(id);
|
||||
} else if (type === 'Widget') {
|
||||
return getWidget(id);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
(obj) => {
|
||||
if (obj instanceof User) {
|
||||
return userType;
|
||||
} else if (obj instanceof Widget) {
|
||||
return widgetType;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Define your own types here
|
||||
*/
|
||||
|
||||
var userType = new GraphQLObjectType({
|
||||
name: 'User',
|
||||
description: 'A person who uses our app',
|
||||
fields: () => ({
|
||||
id: globalIdField('User'),
|
||||
widgets: {
|
||||
type: widgetConnection,
|
||||
description: 'A person\'s collection of widgets',
|
||||
args: connectionArgs,
|
||||
resolve: (_, args) => connectionFromArray(getWidgets(), args),
|
||||
},
|
||||
}),
|
||||
interfaces: [nodeInterface],
|
||||
});
|
||||
|
||||
var widgetType = new GraphQLObjectType({
|
||||
name: 'Widget',
|
||||
description: 'A shiny widget',
|
||||
fields: () => ({
|
||||
id: globalIdField('Widget'),
|
||||
name: {
|
||||
type: GraphQLString,
|
||||
description: 'The name of the widget',
|
||||
},
|
||||
}),
|
||||
interfaces: [nodeInterface],
|
||||
});
|
||||
|
||||
/**
|
||||
* Define your own connection types here
|
||||
*/
|
||||
var {connectionType: widgetConnection} =
|
||||
connectionDefinitions({name: 'Widget', nodeType: widgetType});
|
||||
|
||||
/**
|
||||
* This is the type that will be the root of our query,
|
||||
* and the entry point into our schema.
|
||||
*/
|
||||
var queryType = new GraphQLObjectType({
|
||||
name: 'Query',
|
||||
fields: () => ({
|
||||
node: nodeField,
|
||||
// Add your own root fields here
|
||||
viewer: {
|
||||
type: userType,
|
||||
resolve: () => getViewer(),
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* This is the type that will be the root of our mutations,
|
||||
* and the entry point into performing writes in our schema.
|
||||
*/
|
||||
var mutationType = new GraphQLObjectType({
|
||||
name: 'Mutation',
|
||||
fields: () => ({
|
||||
// Add your own mutations here
|
||||
})
|
||||
});
|
||||
|
||||
/**
|
||||
* Finally, we construct our schema (whose starting query type is the query
|
||||
* type we defined above) and export it.
|
||||
*/
|
||||
export var Schema = new GraphQLSchema({
|
||||
query: queryType,
|
||||
// Uncomment the following after adding some mutation fields:
|
||||
// mutation: mutationType
|
||||
});
|
||||
5
data/users.csv
Normal file
5
data/users.csv
Normal file
@@ -0,0 +1,5 @@
|
||||
tom,1
|
||||
fred,1
|
||||
bethany,2
|
||||
sally,3
|
||||
saray,2
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import gulp from 'gulp';
|
||||
import yargs from 'yargs';
|
||||
import DB from './config/database';
|
||||
import {PowerDataSeed, HouseSeed} from './lib/tasks/seed_data'
|
||||
import {PowerDataSeed, HouseSeed, UserSeed} from './lib/tasks/seed_data'
|
||||
|
||||
gulp.task('generate_power_csv', function(done){
|
||||
DB.sync().then(()=>{
|
||||
@@ -20,3 +20,9 @@ gulp.task('save_house_csv', function(done){
|
||||
HouseSeed.saveCsv(yargs.argv, done);
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('save_user_csv', function(done){
|
||||
DB.sync().then(()=>{
|
||||
UserSeed.saveCsv(yargs.argv, done);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ export class PowerDataSeed {
|
||||
|
||||
static saveCsv(opts, done){
|
||||
opts = extend({
|
||||
path: __dirname + "/../../data/example/power_data.csv"
|
||||
path: __dirname + "/../../data/power_data.csv"
|
||||
}, opts || {});
|
||||
var stream = fs.createReadStream(opts.path),
|
||||
csvStream = csv.fromStream(stream, {headers: ['house_id', 'time', 'power']}),
|
||||
@@ -38,7 +38,7 @@ export class PowerDataSeed {
|
||||
end_date: moment().unix(),
|
||||
interval: 180, // every 3 minutes (in s)
|
||||
average: 1400, // Wh
|
||||
path: __dirname + "/../../data/example/power_data.csv"
|
||||
path: __dirname + "/../../data/power_data.csv"
|
||||
}, opts || {});
|
||||
|
||||
var row_date = opts.start_date,
|
||||
@@ -65,7 +65,7 @@ export class PowerDataSeed {
|
||||
export class HouseSeed {
|
||||
static saveCsv(opts, done){
|
||||
opts = extend({
|
||||
path: __dirname + "/../../data/example/houses.csv"
|
||||
path: __dirname + "/../../data/houses.csv"
|
||||
}, opts || {});
|
||||
var stream = fs.createReadStream(opts.path),
|
||||
csvStream = csv.fromStream(stream, {headers: ['id', 'name']}),
|
||||
@@ -85,3 +85,25 @@ export class HouseSeed {
|
||||
}
|
||||
}
|
||||
|
||||
export class UserSeed {
|
||||
static saveCsv(opts, done){
|
||||
opts = extend({
|
||||
path: __dirname + "/../../data/users.csv"
|
||||
}, opts || {});
|
||||
var stream = fs.createReadStream(opts.path),
|
||||
csvStream = csv.fromStream(stream, {headers: ['username', 'house_id']}),
|
||||
rows = [];
|
||||
|
||||
csvStream.on("data", function(data){
|
||||
console.log(JSON.stringify(data))
|
||||
rows.push(data);
|
||||
});
|
||||
csvStream.on("end", function(){
|
||||
console.log(rows);
|
||||
DB.User.bulkCreate(rows, {validate: true}).then(()=>{
|
||||
console.log("DONE!")
|
||||
done();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,27 @@
|
||||
import {
|
||||
GraphQLString,
|
||||
GraphQLNonNull,
|
||||
GraphQLObjectType
|
||||
GraphQLObjectType,
|
||||
GraphQLInt,
|
||||
GraphQLString
|
||||
} from 'graphql';
|
||||
|
||||
import {
|
||||
fromGlobalId,
|
||||
globalIdField,
|
||||
nodeDefinitions,
|
||||
connectionDefinitions,
|
||||
connectionArgs
|
||||
} from 'graphql-relay';
|
||||
|
||||
import extend from 'extend';
|
||||
import DB from "./../config/database";
|
||||
import {nodeInterface} from './../lib/node.relay';
|
||||
import {nodeInterface} from './../config/graphql/node';
|
||||
|
||||
const NAME = 'House';
|
||||
|
||||
/**
|
||||
* Define your own types here
|
||||
* Sequelize Definition
|
||||
*/
|
||||
|
||||
var House = DB.sequelize.define('House', {
|
||||
var House = DB.sequelize.define(NAME, {
|
||||
id: {
|
||||
type: DB.Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
@@ -25,25 +29,63 @@ var House = DB.sequelize.define('House', {
|
||||
},
|
||||
name: DB.Sequelize.STRING
|
||||
}, {
|
||||
tableName: "houses",
|
||||
paranoid: true,
|
||||
underscored: true,
|
||||
tableName: "houses",
|
||||
instanceMethods: {
|
||||
|
||||
},
|
||||
classMethods: {
|
||||
associate: ()=>{
|
||||
set: ()=>{
|
||||
House.hasMany(DB.PowerDatum, {as: 'PowerData'});
|
||||
House.hasMany(DB.User, {as: 'Habitants'});
|
||||
House.graphql_type = new GraphQLObjectType({
|
||||
name: NAME,
|
||||
description: 'A house',
|
||||
fields: () => ({
|
||||
id: globalIdField(NAME),
|
||||
name: {
|
||||
type: new GraphQLNonNull(GraphQLString)
|
||||
},
|
||||
power_data: {
|
||||
type: connectionDefinitions({name: DB.PowerDatum.name, nodeType: DB.PowerDatum.graphql_type}).connectionType,
|
||||
description: "Returns house's power data.",
|
||||
args: connectionArgs,
|
||||
resolve: (house, args) => {
|
||||
return house.getPowerDataByTime(args);
|
||||
}
|
||||
},
|
||||
habitants: {
|
||||
type: connectionDefinitions({name: DB.User.name, nodeType: DB.User.graphql_type}).connectionType,
|
||||
description: "Returns list of house's habitants.",
|
||||
args: connectionArgs,
|
||||
resolve: (house, args) => {
|
||||
var params = extend({
|
||||
order: 'name ASC',
|
||||
limit: 50,
|
||||
offset: 0,
|
||||
}, args);
|
||||
delete params.where; // don't allow any additional query params.
|
||||
return house.getHabitants(params);
|
||||
}
|
||||
}
|
||||
}),
|
||||
interfaces: [nodeInterface]
|
||||
});
|
||||
},
|
||||
getPowerDataByTime: (start_date, end_date, page)=>{
|
||||
var params = extend({
|
||||
order: 'time ASC',
|
||||
limit: 500
|
||||
}, args.page);
|
||||
params.where = {time: {}};
|
||||
if (start_date) params.where.time.$gt = moment.utc(start_date).toDate();
|
||||
if (end_date) params.where.time.$lt = moment.utc(end_date).toDate();
|
||||
|
||||
return House.getPowerData(params);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
House.graphql_type = new GraphQLObjectType({
|
||||
name: 'House',
|
||||
description: 'A house',
|
||||
fields: () => ({
|
||||
id: globalIdField('House'),
|
||||
name: GraphQLNonNull(GraphQLInt)
|
||||
}),
|
||||
interfaces: [nodeInterface],
|
||||
});
|
||||
House.name = 'House';
|
||||
House.name = NAME;
|
||||
module.exports = House;
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import {
|
||||
GraphQLFloat,
|
||||
GraphQLInt,
|
||||
GraphQLNonNull,
|
||||
GraphQLObjectType
|
||||
} from 'graphql';
|
||||
|
||||
import {
|
||||
fromGlobalId,
|
||||
globalIdField
|
||||
} from 'graphql-relay';
|
||||
|
||||
import DB from "./../config/database";
|
||||
import {nodeInterface} from './../lib/node.relay';
|
||||
import {nodeInterface} from './../config/graphql/node';
|
||||
|
||||
const NAME = 'PowerDatum'
|
||||
|
||||
/**
|
||||
* Define your own types here
|
||||
*/
|
||||
|
||||
var PowerDatum = DB.sequelize.define('PowerDatum', {
|
||||
var PowerDatum = DB.sequelize.define(NAME, {
|
||||
id: {
|
||||
type: DB.Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
@@ -26,27 +26,36 @@ var PowerDatum = DB.sequelize.define('PowerDatum', {
|
||||
time: DB.Sequelize.DATE,
|
||||
power: DB.Sequelize.FLOAT
|
||||
}, {
|
||||
paranoid: true,
|
||||
underscored: true,
|
||||
tableName: "power_data",
|
||||
instanceMethods: {
|
||||
|
||||
},
|
||||
classMethods: {
|
||||
associate: ()=>{
|
||||
set: ()=>{
|
||||
PowerDatum.belongsTo(DB.House);
|
||||
PowerDatum.graphql_type = new GraphQLObjectType({
|
||||
name: NAME,
|
||||
description: 'A person who uses our app',
|
||||
fields: () => ({
|
||||
id: globalIdField(NAME),
|
||||
power: {
|
||||
type: GraphQLFloat,
|
||||
},
|
||||
time: {
|
||||
type: GraphQLInt,
|
||||
description: "Time the power was recorded.",
|
||||
resolve: (power_datum, _) => {
|
||||
return power_datum.time.getTime();
|
||||
}
|
||||
},
|
||||
}),
|
||||
interfaces: [nodeInterface]
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
PowerDatum.graphql_type = new GraphQLObjectType({
|
||||
name: 'PowerDatum',
|
||||
description: 'A person who uses our app',
|
||||
fields: () => ({
|
||||
id: globalIdField('PowerDatum'),
|
||||
time: GraphQLInt,
|
||||
power: GraphQLFloat
|
||||
}),
|
||||
interfaces: [nodeInterface],
|
||||
});
|
||||
PowerDatum.name = 'PowerDatum';
|
||||
|
||||
PowerDatum.name = NAME;
|
||||
module.exports = PowerDatum;
|
||||
|
||||
67
models/user.js
Normal file
67
models/user.js
Normal file
@@ -0,0 +1,67 @@
|
||||
import {
|
||||
GraphQLString,
|
||||
GraphQLNonNull,
|
||||
GraphQLObjectType
|
||||
} from 'graphql';
|
||||
|
||||
import {
|
||||
globalIdField,
|
||||
connectionDefinitions,
|
||||
connectionArgs
|
||||
} from 'graphql-relay';
|
||||
|
||||
import DB from "./../config/database";
|
||||
import {nodeInterface} from './../config/graphql/node';
|
||||
|
||||
const NAME = 'User';
|
||||
|
||||
/**
|
||||
* Sequelize Definition
|
||||
*/
|
||||
|
||||
var User = DB.sequelize.define(NAME, {
|
||||
id: {
|
||||
type: DB.Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true // Automatically gets converted to SERIAL for postgres
|
||||
},
|
||||
username: {
|
||||
type: DB.Sequelize.STRING,
|
||||
unique: true
|
||||
}
|
||||
}, {
|
||||
paranoid: true,
|
||||
underscored: true,
|
||||
tableName: "users",
|
||||
instanceMethods: {
|
||||
|
||||
},
|
||||
classMethods: {
|
||||
set: ()=>{
|
||||
User.belongsTo(DB.House);
|
||||
User.graphql_type = new GraphQLObjectType({
|
||||
name: NAME,
|
||||
description: 'A house',
|
||||
fields: () => ({
|
||||
id: globalIdField(NAME),
|
||||
username: {
|
||||
type: new GraphQLNonNull(GraphQLString)
|
||||
},
|
||||
house: {
|
||||
type: connectionDefinitions({name: DB.House.name, nodeType: DB.House.graphql_type}).connectionType,
|
||||
description: "Returns user's house.",
|
||||
args: connectionArgs,
|
||||
ref: DB.PowerDatum.name,
|
||||
resolve: (user, args) => {
|
||||
return user.getHouse();
|
||||
}
|
||||
}
|
||||
}),
|
||||
interfaces: [nodeInterface]
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
User.name = NAME;
|
||||
module.exports = User;
|
||||
@@ -4,7 +4,7 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "babel-node ./app.express.js",
|
||||
"update-schema": "babel-node ./scripts/updateSchema.js"
|
||||
"update-schema": "babel-node --debug ./scripts/updateSchema.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"body-parser": "~1.12.0",
|
||||
|
||||
27
readme.md
27
readme.md
@@ -1 +1,28 @@
|
||||
[See necessary examples](https://drive.google.com/drive/u/0/folders/0B6Ys-9_Te2cFNktOU3VwSzA1VWs)
|
||||
|
||||
|
||||
## Problems
|
||||
|
||||
1. Setting type directly on field:
|
||||
|
||||
```js
|
||||
fields: ()=>{
|
||||
username: GraphQLString
|
||||
}
|
||||
```
|
||||
|
||||
threw this error:
|
||||
|
||||
```sh
|
||||
Unhandled rejection Error: Query.viewer field type must be Output Type but got: undefined
|
||||
```
|
||||
|
||||
Must pass object:
|
||||
|
||||
```js
|
||||
fields: ()=>{
|
||||
username: {
|
||||
type: GraphQLString
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -2,28 +2,35 @@
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { Schema } from '../data/schema';
|
||||
import { graphql } from 'graphql';
|
||||
import schema from '../config/graphql/schema';
|
||||
import { graphql, GraphQLSchema } from 'graphql';
|
||||
import { introspectionQuery, printSchema } from 'graphql/utilities';
|
||||
import DB from './../config/database';
|
||||
|
||||
// Save JSON of full schema introspection for Babel Relay Plugin to use
|
||||
(async () => {
|
||||
var result = await (graphql(Schema, introspectionQuery));
|
||||
if (result.errors) {
|
||||
console.error(
|
||||
'ERROR introspecting schema: ',
|
||||
JSON.stringify(result.errors, null, 2)
|
||||
);
|
||||
} else {
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, '../data/schema.json'),
|
||||
JSON.stringify(result, null, 2)
|
||||
);
|
||||
}
|
||||
})();
|
||||
DB.sync().then(()=>{
|
||||
|
||||
// Save user readable type system shorthand of schema
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, '../data/schema.graphql'),
|
||||
printSchema(Schema)
|
||||
);
|
||||
var Schema = schema();
|
||||
|
||||
// Save JSON of full schema introspection for Babel Relay Plugin to use
|
||||
(async () => {
|
||||
var result = await (graphql(Schema, introspectionQuery));
|
||||
if (result.errors) {
|
||||
console.error(
|
||||
'ERROR introspecting schema: ',
|
||||
JSON.stringify(result.errors, null, 2)
|
||||
);
|
||||
} else {
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, '../config/graphql/schema.json'),
|
||||
JSON.stringify(result, null, 2)
|
||||
);
|
||||
}
|
||||
})();
|
||||
|
||||
// Save user readable type system shorthand of schema
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, '../config/graphql/schema.graphql'),
|
||||
printSchema(Schema)
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user