{ person(personID: 4) { name birthYear homeworld { name } filmConnection { films { title } } } }
{ person(personID: 4) { name birthYear homeworld { name } filmConnection { films { title } } } }
{ person(personID: 4) { name birthYear } }
{ viewer { repositories(last: 10) { nodes { name description } } } }
{ licenses { name url } }
{ repository(owner: "facebook", name: "graphql") { issues(first: 10) { nodes { title createdAt author { login } } } } }
mutation { addStar(input: {starrableId: "MDEwOlJlcG9zaXRvcnkzODM0MjIyMQ=="}) { starrable { stargazers { totalCount } } } }
{ repository(name: "graphql", owner: "facebook") { id } }
query GetIssueInfo { repository(owner: "jscomplete", name: "graphql-in-action") { issue(number: 1) { id title } } }
mutation AddCommentToIssue { addComment(input: { subjectId: "MDU6SXNzdWUzMDYyMDMwNzk=", body: "Hello GraphQL" }) { commentEdge { node { createdAt } } } }
{ __schema { types { name description } } }
{ __type(name: "Commit") { fields { name args { name } } } }
query OrgInfo { organization(login: "facebook") { name description websiteUrl } }
query First10Repos { organization(login: "facebook") { name description websiteUrl repositories(first: 10) { nodes { name } } } }
query orgReposByName { organization(login: "facebook") { repositories(first:10, orderBy:{field: NAME, direction: ASC}) { nodes { name } } } }
query OrgPopularRepos { organization(login: "facebook") { repositories(first:10, orderBy:{field: STARGAZERS, direction: DESC}) { nodes { name } } } }
query OrgRepoConnectionExample { organization(login: "facebook") { repositories(first:10, orderBy:{field: STARGAZERS, direction: DESC}) { edges { cursor node { name } } } } }
query OrgPopularReposPage2 { organization(login: "facebook") { repositories( first: 10, after: "Y3Vyc29yOnYyOpLNOE7OAeErrQ==", orderBy: {field: STARGAZERS, direction: DESC} ) { edges { cursor node { name } } } } }
query OrgReposMetaInfoExample { organization(login: "facebook") { repositories( first: 10, after: "Y3Vyc29yOnYyOpLNOE7OAeErrQ==", orderBy: {field: STARGAZERS, direction: DESC} ) { totalCount pageInfo { hasNextPage } edges { cursor node { name } } } } }
query SearchExample { repository(owner: "twbs", name: "bootstrap") { projects(search: "v4.1", first: 10) { nodes { name } } } }
query FilterExample { viewer { repositories(first: 10, affiliations: OWNER) { totalCount nodes { name } } } }
mutation StarARepo { addStar(input: {starrableId: "MDEwOlJlcG9zaXRvcnkzODM0MjIyMQ=="}) { starrable { stargazers { totalCount } } } }
query ProfileInfo { user(login: "samerbuna") { name company bio } }
query ProfileInfoWithAlias { user(login: "samerbuna") { name companyName: company bio } }
query AllDirectives { __schema { directives { name description locations args { name description defaultValue } } } }
query OrgInfo($orgLogin: String!) { organization(login: $orgLogin) { name description websiteUrl } }
query OrgInfoWithDefault($orgLogin: String = "facebook") { organization(login: $orgLogin) { name description websiteUrl } }
query OrgInfo($orgLogin: String!, $fullDetails: Boolean!) { organization(login: $orgLogin) { name description websiteUrl @include(if: $fullDetails) } }
query OrgInfo($orgLogin: String!, $partialDetails: Boolean!) { organization(login: $orgLogin) { name description websiteUrl @skip(if: $partialDetails) } }
query OrgInfo($orgLogin: String!, $partialDetails: Boolean!) { organization(login: $orgLogin) { name description websiteUrl @skip(if: $partialDetails) @include(if: false) } }
query MyRepos { viewer { ownedRepos: repositories(affiliations: OWNER, first: 10) { nodes { nameWithOwner description forkCount } } orgsRepos: repositories(affiliations: ORGANIZATION_MEMBER, first: 10) { nodes { nameWithOwner description forkCount } } } }
query MyRepos { viewer { ownedRepos: repositories(affiliations: OWNER, first: 10) { ...repoInfo } orgsRepos: repositories(affiliations: ORGANIZATION_MEMBER, first: 10) { ...repoInfo } } } fragment repoInfo on RepositoryConnection { nodes { nameWithOwner description forkCount } }
query InlineFragmentExample { repository(owner: "facebook", name: "graphql") { ref(qualifiedName: "master") { target { ... on Commit { message } } } } }
query RepoUnionExample { repository(owner: "facebook", name: "graphql") { issueOrPullRequest(number: 3) { __typename } } }
query RepoUnionExampleFull { repository(owner: "facebook", name: "graphql") { issueOrPullRequest(number: 5) { ... on PullRequest { merged mergedAt } ... on Issue { closed closedAt } } } }
query TestSearch { search(first: 100, query: "graphql", type: USER) { nodes { ... on User { name bio } ... on Organization { login description } } } }
CREATE TABLE azdev.users ( id serial PRIMARY KEY, email text NOT NULL UNIQUE, hashed_password text NOT NULL, first_name text, last_name text, is_admin boolean NOT NULL DEFAULT false, hashed_auth_token text, created_at timestamp without time zone NOT NULL DEFAULT (now() at time zone 'utc'), CHECK (lower(email) = email) );
CREATE TABLE azdev.needs ( id serial PRIMARY KEY, content text NOT NULL, tags text, user_id integer NOT NULL, is_public boolean NOT NULL, is_featured boolean NOT NULL DEFAULT FALSE, created_at timestamp without time zone NOT NULL DEFAULT (now() at time zone 'utc'), FOREIGN KEY (user_id) REFERENCES azdev.users, CHECK (is_public = true OR is_featured = false) );
CREATE TABLE azdev.approaches ( id serial PRIMARY KEY, content text NOT NULL, user_id integer NOT NULL, need_id integer NOT NULL, vote_count integer NOT NULL DEFAULT 0, created_at timestamp without time zone NOT NULL DEFAULT (now() at time zone 'utc'), FOREIGN KEY (user_id) REFERENCES azdev.users, FOREIGN KEY (need_id) REFERENCES azdev.needs );
db.createCollection("approachDetails", { validator: { $jsonSchema: { bsonType: "object", required: ["pgId"], properties: { pgId: { bsonType: "int", description: "must be an integer and is required" }, } } } });
type User implement Node {
id: ID!
createdAt: String!
email: String!
name: String!
needList: [Need!]!
}
enum ApproachDetailCategory {
NOTE
EXPLANATION
WARNING
}
type ApproachDetail {
content: String!
category: ApproachDetailCategory!
}
type Approach implement Node {
id: ID!
createdAt: String!
content: String!
voteCount: Int!
author: User!
detailList: [ApproachDetail!]!
}
type Need implement Node {
id: ID!
createdAt: String!
content: String!
tags: [String!]!
author: User!
approachList: [Approach!]!
}
union NeedOrApproach = Need | Approach
type Query {
needFeaturedList: [Need!]!
search(query: String!): [NeedOrApproach!]!
needInfo(id: ID!): Need
viewer(authToken: String!): User
}
input UserInput {
email: String!
password: String!
firstName: String
lastName: String
}
input AuthInput {
email: String!
password: String!
}
input ApproachDetailInput {
content: String!
category: ApproachCategory!
}
input ApproachInput {
content: String!
detailList: [ApproachDetailInput!]!
}
input NeedInput {
content: String!
approachList: [ApproachInput!]!
}
input ApproactVoteInput {
"""true for up-vote and false for down-vote"""
up: Boolean!
}
type UserError {
message: String!
field: [String!]
}
type UserPayload {
userErrors: [UserError!]!
user: User
currentAuthToken: String!
}
type NeedPayload {
userErrors: [UserError!]!
need: Need
}
type ApproachPayload {
userErrors: [UserError!]!
approach: Approach
}
type Mutation {
userCreate(
input: UserInput!
): UserPayload!
userLogin(
input: AuthInput!
): UserPayload!
needCreate(
authToken: String!
input: NeedInput!
): NeedPayload!
needUpdate(
authToken: String!
needId: ID!
input: NeedInput!
): NeedPayload!
approachCreate(
authToken: String!
needId: String!
input: ApproachInput!
): ApproachPayload!
approachVote(
authToken: String!
approachId: String!
input: ApproachVoteInput!
): ApproachPayload!
}
type Subscription {
needListActivity: [Need!]
approachListActivity(
needId: String!
): [Approach!]
}
export const pgConfig = { database: process.env.PG_DATABASE, }; export const mongoConfig = { database: process.env.MONGO_DATABASE, url: process.env.MONGO_URL, };
export PG_DATABASE="YOUR_PG_DEV_DB_NAME_HERE" export MONGO_DATABASE="azdev" export MONGO_URL="mongodb://localhost:27017"
import pg from 'pg';
import { pgConfig } from '../config.js';
export default async () => {
const pgPool = new pg.Pool(pgConfig);
// Test the connection
const client = await pgPool.connect();
const tableCountResp = await client.query(
'select count(*) from information_schema.tables where table_schema = $1;',
['azdev']
);
client.release();
console.log(
'Connected to PostgreSQL | Tables count:',
tableCountResp.rows[0].count
);
pgPool.on('error', (err) => {
console.error('Unexpected PG client error', err);
process.exit(-1);
});
return {
pgPool,
pgClose: async () => await pgPool.end(),
};
};
import mdb from 'mongodb';
import { mongoConfig } from '../config.js';
export default async () => {
const client = new mdb.MongoClient(mongoConfig.url, {
useNewUrlParser: true,
});
try {
await client.connect();
const mdb = client.db(mongoConfig.database);
// Test the connection
const collections = await mdb.collections();
console.log(
'Connected to MongoDB | Collections count:',
collections.length
);
return {
mdb,
mdbClose: () => client.close(),
};
} catch (err) {
console.error('Error in MongoDB Client', err);
process.exit(1);
}
};
SELECT * FROM azdev.users; SELECT * FROM azdev.needs; SELECT * FROM azdev.approaches;
db.approachDetails.find({});
import { graphql } from 'graphql'; import { schema, rootValue } from './schema/index.js'; const executeGraphQLRequest = async request => { const resp = await graphql(schema, request, rootValue); console.log(resp.data); }; executeGraphQLRequest(process.argv[2]);
import express from 'express'; import graphqlHTTP from 'express-graphql'; import { schema, rootValue } from './schema/index.js';
const server = express(); server.listen(8484, () => { console.log('API server is running'); });
server.use( '/', graphqlHTTP({ schema, rootValue, graphiql: true, }) );
import { GraphQLID, GraphQLObjectType, GraphQLString, GraphQLNonNull, GraphQLList, } from 'graphql'; const Need = new GraphQLObjectType({ name: 'Need', fields: { id: { type: new GraphQLNonNull(GraphQLID), }, content: { type: new GraphQLNonNull(GraphQLString), }, tags: { type: new GraphQLNonNull( new GraphQLList(new GraphQLNonNull(GraphQLString)) ), }, createdAt: { type: new GraphQLNonNull(GraphQLString), }, }, }); export default Need;
import express from 'express'; import graphqlHTTP from 'express-graphql'; import { schema } from './schema/index.js'; import pgClient from './db-clients/pg.js'; const startGraphQLWebServer = async () => { const { pgPool } = await pgClient(); const server = express(); server.use( '/', graphqlHTTP({ schema, context: { pgPool }, graphiql: true, }) ); server.listen(8484, () => { console.log('API server is running'); }); }; startGraphQLWebServer();
import { // ... GraphQLList, } from 'graphql'; import Need from './types/need.js'; // ... const QueryType = new GraphQLObjectType({ name: 'Query', fields: { // ... needFeaturedList: { type: new GraphQLNonNull( new GraphQLList(new GraphQLNonNull(Need)) ), resolve: async (source, args, { pgPool }) => { const pgResp = await pgPool.query(` SELECT * FROM azdev.needs WHERE is_featured = true `); return pgResp.rows; }, }, }, }); // ...
import pgClient from '../db-clients/pg.js'; const sqls = { featuredNeeds: 'SELECT * FROM azdev.needs WHERE is_featured = true;', }; const pgApiWrapper = async () => { const { pgPool } = await pgClient(); const pgQuery = (text, params) => pgPool.query(text, params); return { needs: { allFeatured: async () => { const pgResp = await pgQuery(sqls.featuredNeeds); return pgResp.rows; }, }, }; }; export default pgApiWrapper;
import pgApiWrapper from './db-api/pg.js'; const server = express(); const startGraphQLWebServer = async () => { const pgApi = await pgApiWrapper(); server.use( '/', graphqlHTTP({ schema, context: { pgApi }, graphiql: true, }) );
needFeaturedList: { type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(Need))), resolve: async (source, args, { pgApi }) => { return pgApi.needs.allFeatured(); }, },
{ needFeaturedList { id content tags createdAt author { id email name createdAt } approachList { id content createdAt author { id email name createdAt } } } }
const sqls = {
// ...
userInfo: 'SELECT * FROM azdev.users WHERE id = $1',
};
const pgApiWrapper = async () => { // ... return { // ... users: { byId: async (userId) => { const pgResp = await pgQuery(sqls.userInfo, [userId]); return pgResp.rows[0]; }, }, }; };
import { GraphQLID, GraphQLObjectType, GraphQLString, GraphQLNonNull, } from 'graphql'; const User = new GraphQLObjectType({ name: 'User', fields: { id: { type: new GraphQLNonNull(GraphQLID), }, email: { type: new GraphQLNonNull(GraphQLString), }, name: { type: GraphQLString, resolve: ({ first_name, last_name }) => `${first_name} ${last_name}`, }, createdAt: { type: new GraphQLNonNull(GraphQLString), resolve: ({ created_at }) => created_at.toISOString(), }, }, }); export default User;
import User from './user.js';
const Need = new GraphQLObjectType({
name: 'Need',
fields: {
// ...
author: {
type: new GraphQLNonNull(User),
resolve: (source, args, { pgApi }) =>
pgApi.users.byId(source.user_id),
},
},
});
name: { type: new GraphQLNonNull(GraphQLString), resolve: ({ first_name, last_name }) => [first_name, last_name].filter(Boolean).join(' '), },
const views = { needsAndUsers: ` SELECT n.*, u.id AS author_id, u.email AS author_email, u.first_name AS author_first_name, u.last_name AS author_last_name, u.created_at AS author_created_at FROM azdev.needs n JOIN azdev.users u ON (n.user_id = u.id) `, };
const sqls = { featuredNeeds: ` SELECT * FROM (${views.needsAndUsers}) nau WHERE is_featured = true; `, };
import { extractPrefixedColumns } from '../utils.js';
const Need = new GraphQLObjectType({
name: 'Need',
fields: {
// ...
author: {
type: new GraphQLNonNull(User),
resolve: prefixedObject =>
extractPrefixedColumns({ prefixedObject, prefix: 'author' }),
},
},
});
export const extractPrefixedColumns = ({ prefixedObject, prefix }) => { const prefixRexp = new RegExp(`^${prefix}_(.*)`); return Object.entries(prefixedObject).reduce((acc, [key, value]) => { const match = key.match(prefixRexp); if (match) { acc[match[1]] = value; } return acc; }, {}); };
import Approach from './approach.js';
const Need = new GraphQLObjectType({
name: 'Need',
fields: {
// ...
approachList: {
type: new GraphQLNonNull(
new GraphQLList(new GraphQLNonNull(Approach))
),
resolve: (source, args, { pgApi }) =>
pgApi.needs.approachList(source.id),
},
},
});
import { GraphQLID, GraphQLObjectType, GraphQLString, GraphQLNonNull, } from 'graphql'; import User from './user.js'; const Approach = new GraphQLObjectType({ name: 'Approach', fields: { id: { type: new GraphQLNonNull(GraphQLID), }, content: { type: new GraphQLNonNull(GraphQLString), }, createdAt: { type: new GraphQLNonNull(GraphQLString), resolve: ({ created_at }) => created_at.toISOString(), }, author: { type: new GraphQLNonNull(User), resolve: (source, args, { pgApi }) => pgApi.users.byId(source.user_id), }, }, }); export default Approach;
const sqls = {
// ...
approachesForNeed:
'SELECT * FROM azdev.approaches WHERE need_id = $1',
};
const pgApiWrapper = async () => { // ... return { needs: { // ... approachList: async (needId) => { const pgResp = await pgQuery(sqls.approachesForNeed, [ needId, ]); return pgResp.rows; }, }, // ... }; };