mirror of
https://github.com/vale981/Vulcan
synced 2025-03-05 09:31:43 -05:00
prettier commit
This commit is contained in:
parent
c7aeaea949
commit
f51f558cb1
10 changed files with 244 additions and 195 deletions
|
@ -6,42 +6,42 @@ export * from 'meteor/vulcan:lib';
|
|||
export * from './default_mutations.js';
|
||||
export * from './default_resolvers.js';
|
||||
|
||||
export { default as Layout } from './components/Layout.jsx';
|
||||
export { default as App } from './components/App.jsx';
|
||||
export { default as Icon } from './components/Icon.jsx';
|
||||
export { default as Loading } from './components/Loading.jsx';
|
||||
export { default as ShowIf } from './components/ShowIf.jsx';
|
||||
export { default as NewButton } from './components/NewButton.jsx';
|
||||
export { default as EditButton } from './components/EditButton.jsx';
|
||||
export { default as MutationButton } from './components/MutationButton.jsx';
|
||||
export { default as Error404 } from './components/Error404.jsx';
|
||||
export { default as DynamicLoading } from './components/DynamicLoading.jsx';
|
||||
export { default as HeadTags } from './components/HeadTags.jsx';
|
||||
export { default as Avatar } from './components/Avatar.jsx';
|
||||
export { default as Card } from './components/Card.jsx';
|
||||
export { default as Datatable } from './components/Datatable.jsx';
|
||||
export { default as Flash } from './components/Flash.jsx';
|
||||
export { default as HelloWorld } from './components/HelloWorld.jsx';
|
||||
export { default as Welcome } from './components/Welcome.jsx';
|
||||
export { default as RouterHook } from './components/RouterHook.jsx';
|
||||
export { default as ScrollToTop } from './components/ScrollToTop.jsx';
|
||||
export {default as Layout} from './components/Layout.jsx';
|
||||
export {default as App} from './components/App.jsx';
|
||||
export {default as Icon} from './components/Icon.jsx';
|
||||
export {default as Loading} from './components/Loading.jsx';
|
||||
export {default as ShowIf} from './components/ShowIf.jsx';
|
||||
export {default as NewButton} from './components/NewButton.jsx';
|
||||
export {default as EditButton} from './components/EditButton.jsx';
|
||||
export {default as MutationButton} from './components/MutationButton.jsx';
|
||||
export {default as Error404} from './components/Error404.jsx';
|
||||
export {default as DynamicLoading} from './components/DynamicLoading.jsx';
|
||||
export {default as HeadTags} from './components/HeadTags.jsx';
|
||||
export {default as Avatar} from './components/Avatar.jsx';
|
||||
export {default as Card} from './components/Card.jsx';
|
||||
export {default as Datatable} from './components/Datatable.jsx';
|
||||
export {default as Flash} from './components/Flash.jsx';
|
||||
export {default as HelloWorld} from './components/HelloWorld.jsx';
|
||||
export {default as Welcome} from './components/Welcome.jsx';
|
||||
export {default as RouterHook} from './components/RouterHook.jsx';
|
||||
export {default as ScrollToTop} from './components/ScrollToTop.jsx';
|
||||
|
||||
export { default as withAccess } from './containers/withAccess.js';
|
||||
export { default as withMessages } from './containers/withMessages.js';
|
||||
export { default as withMulti } from './containers/withMulti.js';
|
||||
export { default as withSingle } from './containers/withSingle.js';
|
||||
export { default as withCreate } from './containers/withCreate.js';
|
||||
export { default as withUpdate } from './containers/withUpdate.js';
|
||||
export { default as withDelete } from './containers/withDelete.js';
|
||||
export { default as withCurrentUser } from './containers/withCurrentUser.js';
|
||||
export { default as withMutation } from './containers/withMutation.js';
|
||||
export { default as withUpsert } from './containers/withUpsert.js';
|
||||
export {default as withAccess} from './containers/withAccess.js';
|
||||
export {default as withMessages} from './containers/withMessages.js';
|
||||
export {default as withMulti} from './containers/withMulti.js';
|
||||
export {default as withSingle} from './containers/withSingle.js';
|
||||
export {default as withCreate} from './containers/withCreate.js';
|
||||
export {default as withUpdate} from './containers/withUpdate.js';
|
||||
export {default as withDelete} from './containers/withDelete.js';
|
||||
export {default as withCurrentUser} from './containers/withCurrentUser.js';
|
||||
export {default as withMutation} from './containers/withMutation.js';
|
||||
export {default as withUpsert} from './containers/withUpsert.js';
|
||||
|
||||
export { default as withComponents } from './containers/withComponents';
|
||||
export {default as withComponents} from './containers/withComponents';
|
||||
|
||||
// OpenCRUD backwards compatibility
|
||||
export { default as withNew } from './containers/withCreate.js';
|
||||
export { default as withEdit } from './containers/withUpdate.js';
|
||||
export { default as withRemove } from './containers/withDelete.js';
|
||||
export { default as withList } from './containers/withMulti.js';
|
||||
export { default as withDocument } from './containers/withSingle.js';
|
||||
export {default as withNew} from './containers/withCreate.js';
|
||||
export {default as withEdit} from './containers/withUpdate.js';
|
||||
export {default as withRemove} from './containers/withDelete.js';
|
||||
export {default as withList} from './containers/withMulti.js';
|
||||
export {default as withDocument} from './containers/withSingle.js';
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import { addTrackFunction } from 'meteor/vulcan:events';
|
||||
import { getApolloClient, getFragment, createClientTemplate } from 'meteor/vulcan:lib';
|
||||
import {addTrackFunction} from 'meteor/vulcan:events';
|
||||
import {
|
||||
getApolloClient,
|
||||
getFragment,
|
||||
createClientTemplate,
|
||||
} from 'meteor/vulcan:lib';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
function trackInternal(eventName, eventProperties) {
|
||||
|
@ -8,7 +12,10 @@ function trackInternal(eventName, eventProperties) {
|
|||
const fragmentName = 'AnalyticsEventFragment';
|
||||
const fragment = getFragment(fragmentName);
|
||||
|
||||
const mutation = gql`${createClientTemplate({ typeName: 'AnalyticsEvent', fragmentName })}${fragment}`;
|
||||
const mutation = gql`
|
||||
${createClientTemplate({typeName: 'AnalyticsEvent', fragmentName})}
|
||||
${fragment}
|
||||
`;
|
||||
|
||||
const variables = {
|
||||
data: {
|
||||
|
@ -16,7 +23,7 @@ function trackInternal(eventName, eventProperties) {
|
|||
properties: eventProperties,
|
||||
},
|
||||
};
|
||||
apolloClient.mutate({ mutation, variables });
|
||||
apolloClient.mutate({mutation, variables});
|
||||
}
|
||||
|
||||
addTrackFunction(trackInternal);
|
||||
|
|
|
@ -6,28 +6,28 @@
|
|||
// Meteor WebApp use a Connect server, so we need to
|
||||
// use apollo-server-express integration
|
||||
//import express from 'express';
|
||||
import { ApolloServer } from 'apollo-server-express';
|
||||
import {ApolloServer} from 'apollo-server-express';
|
||||
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import {Meteor} from 'meteor/meteor';
|
||||
|
||||
import { WebApp } from 'meteor/webapp';
|
||||
import {WebApp} from 'meteor/webapp';
|
||||
import bodyParser from 'body-parser';
|
||||
|
||||
// import cookiesMiddleware from 'universal-cookie-express';
|
||||
// import Cookies from 'universal-cookie';
|
||||
import voyagerMiddleware from 'graphql-voyager/middleware/express';
|
||||
import getVoyagerConfig from './voyager';
|
||||
import { graphiqlMiddleware, getGraphiqlConfig } from './graphiql';
|
||||
import {graphiqlMiddleware, getGraphiqlConfig} from './graphiql';
|
||||
import getPlaygroundConfig from './playground';
|
||||
|
||||
import initGraphQL from './initGraphQL';
|
||||
import './settings';
|
||||
import { engineConfig } from './engine';
|
||||
import { initContext, computeContextFromReq } from './context.js';
|
||||
import {engineConfig} from './engine';
|
||||
import {initContext, computeContextFromReq} from './context.js';
|
||||
|
||||
import { GraphQLSchema } from '../../modules/graphql.js';
|
||||
import {GraphQLSchema} from '../../modules/graphql.js';
|
||||
|
||||
import { enableSSR } from '../apollo-ssr';
|
||||
import {enableSSR} from '../apollo-ssr';
|
||||
|
||||
import universalCookiesMiddleware from 'universal-cookie-express';
|
||||
|
||||
|
@ -36,10 +36,14 @@ import {
|
|||
getApolloServerOptions,
|
||||
} from './settings';
|
||||
|
||||
import { getSetting } from '../../modules/settings.js';
|
||||
import { formatError } from 'apollo-errors';
|
||||
import {getSetting} from '../../modules/settings.js';
|
||||
import {formatError} from 'apollo-errors';
|
||||
|
||||
export const setupGraphQLMiddlewares = (apolloServer, config, apolloApplyMiddlewareOptions) => {
|
||||
export const setupGraphQLMiddlewares = (
|
||||
apolloServer,
|
||||
config,
|
||||
apolloApplyMiddlewareOptions
|
||||
) => {
|
||||
// DEBUG LOG
|
||||
const logReqMiddleware = (req, res, next) => {
|
||||
console.log('REQ', req.url, req.headers), next();
|
||||
|
@ -59,11 +63,11 @@ export const setupGraphQLMiddlewares = (apolloServer, config, apolloApplyMiddlew
|
|||
// parse request (order matters)
|
||||
WebApp.connectHandlers.use(
|
||||
config.path,
|
||||
bodyParser.json({ limit: getSetting('apolloServer.jsonParserOptions.limit') })
|
||||
bodyParser.json({limit: getSetting('apolloServer.jsonParserOptions.limit')})
|
||||
);
|
||||
WebApp.connectHandlers.use(
|
||||
config.path,
|
||||
bodyParser.text({ type: 'application/graphql' })
|
||||
bodyParser.text({type: 'application/graphql'})
|
||||
);
|
||||
|
||||
// Provide the Meteor WebApp Connect server instance to Apollo
|
||||
|
@ -75,10 +79,9 @@ export const setupGraphQLMiddlewares = (apolloServer, config, apolloApplyMiddlew
|
|||
...apolloApplyMiddlewareOptions,
|
||||
});
|
||||
|
||||
|
||||
// setup the end point otherwise the request hangs
|
||||
// TODO: undestand why this is necessary
|
||||
// @see
|
||||
// @see
|
||||
WebApp.connectHandlers.use(config.path, (req, res) => {
|
||||
if (req.method === 'GET') {
|
||||
res.end();
|
||||
|
@ -108,7 +111,6 @@ export const createApolloServer = ({
|
|||
apolloServerOptions = {}, // apollo options
|
||||
config = {}, // Vulcan options
|
||||
}) => {
|
||||
|
||||
// given options contains the schema
|
||||
const apolloServer = new ApolloServer({
|
||||
// graphql playground (replacement to graphiql), available on the app path
|
||||
|
@ -129,7 +131,7 @@ export const onStart = () => {
|
|||
const config = {
|
||||
path: '/graphql',
|
||||
maxAccountsCacheSizeInMB: 1,
|
||||
configServer: apolloServer => { },
|
||||
configServer: apolloServer => {},
|
||||
voyagerPath: '/graphql-voyager',
|
||||
graphiqlPath: '/graphiql',
|
||||
// customConfigFromReq
|
||||
|
@ -160,7 +162,7 @@ export const onStart = () => {
|
|||
formatError,
|
||||
tracing: getSetting('apolloTracing', Meteor.isDevelopment),
|
||||
cacheControl: true,
|
||||
context: ({ req }) => context(req),
|
||||
context: ({req}) => context(req),
|
||||
...getApolloServerOptions(),
|
||||
},
|
||||
});
|
||||
|
@ -172,7 +174,7 @@ export const onStart = () => {
|
|||
setupToolsMiddlewares(config);
|
||||
}
|
||||
// ssr
|
||||
enableSSR({ computeContext: context });
|
||||
enableSSR({computeContext: context});
|
||||
};
|
||||
// createApolloServer when server startup
|
||||
Meteor.startup(onStart);
|
||||
|
|
|
@ -124,7 +124,10 @@ export const computeContextFromReq = (currentContext, customContextFromReq) => {
|
|||
// console.log('// apollo_server.js user-agent:', req.headers['user-agent']);
|
||||
// console.log('// apollo_server.js locale:', req.headers.locale);
|
||||
|
||||
context.locale = getHeaderLocale(req.headers, context.currentUser && context.currentUser.locale);
|
||||
context.locale = getHeaderLocale(
|
||||
req.headers,
|
||||
context.currentUser && context.currentUser.locale
|
||||
);
|
||||
|
||||
return context;
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export * from './apollo_server2';
|
||||
export * from './settings';
|
||||
|
||||
export { default as initGraphQL } from './initGraphQL';
|
||||
export {default as initGraphQL} from './initGraphQL';
|
||||
|
|
|
@ -3,33 +3,48 @@
|
|||
Run a GraphQL request from the server with the proper context
|
||||
|
||||
*/
|
||||
import { graphql } from 'graphql';
|
||||
import { Collections } from '../modules/collections.js';
|
||||
import {graphql} from 'graphql';
|
||||
import {Collections} from '../modules/collections.js';
|
||||
import DataLoader from 'dataloader';
|
||||
import findByIds from '../modules/findbyids.js';
|
||||
import { getDefaultFragmentText, extractFragmentName, getFragmentText } from '../modules/fragments.js';
|
||||
import { getSetting } from '../modules/settings';
|
||||
import {
|
||||
getDefaultFragmentText,
|
||||
extractFragmentName,
|
||||
getFragmentText,
|
||||
} from '../modules/fragments.js';
|
||||
import {getSetting} from '../modules/settings';
|
||||
import merge from 'lodash/merge';
|
||||
import { singleClientTemplate } from '../modules/graphql_templates';
|
||||
import { Utils } from './utils';
|
||||
import { GraphQLSchema } from '../modules/graphql';
|
||||
import {singleClientTemplate} from '../modules/graphql_templates';
|
||||
import {Utils} from './utils';
|
||||
import {GraphQLSchema} from '../modules/graphql';
|
||||
|
||||
// note: if no context is passed, default to running requests with full admin privileges
|
||||
export const runGraphQL = async (query, variables = {}, context ) => {
|
||||
|
||||
const defaultContext = { currentUser: {isAdmin: true}, locale: getSetting('locale') };
|
||||
export const runGraphQL = async (query, variables = {}, context) => {
|
||||
const defaultContext = {
|
||||
currentUser: {isAdmin: true},
|
||||
locale: getSetting('locale'),
|
||||
};
|
||||
const queryContext = merge(defaultContext, context);
|
||||
const executableSchema = GraphQLSchema.getExecutableSchema();
|
||||
|
||||
// within the scope of this specific request,
|
||||
|
||||
// within the scope of this specific request,
|
||||
// decorate each collection with a new Dataloader object and add it to context
|
||||
Collections.forEach(collection => {
|
||||
collection.loader = new DataLoader(ids => findByIds(collection, ids, queryContext), { cache: true });
|
||||
collection.loader = new DataLoader(
|
||||
ids => findByIds(collection, ids, queryContext),
|
||||
{cache: true}
|
||||
);
|
||||
queryContext[collection.options.collectionName] = collection;
|
||||
});
|
||||
|
||||
// see http://graphql.org/graphql-js/graphql/#graphql
|
||||
const result = await graphql(executableSchema, query, {}, queryContext, variables);
|
||||
const result = await graphql(
|
||||
executableSchema,
|
||||
query,
|
||||
{},
|
||||
queryContext,
|
||||
variables
|
||||
);
|
||||
|
||||
if (result.errors) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
@ -51,42 +66,51 @@ If no fragment is passed, default to default fragment
|
|||
|
||||
*/
|
||||
export const buildQuery = (collection, {fragmentName, fragmentText}) => {
|
||||
|
||||
const collectionName = collection.options.collectionName;
|
||||
const typeName = collection.options.typeName;
|
||||
|
||||
|
||||
const defaultFragmentName = `${collectionName}DefaultFragment`;
|
||||
const defaultFragmentText = getDefaultFragmentText(collection, { onlyViewable: false });
|
||||
const defaultFragmentText = getDefaultFragmentText(collection, {
|
||||
onlyViewable: false,
|
||||
});
|
||||
|
||||
// default to default name and text
|
||||
let name = defaultFragmentName;
|
||||
let text = defaultFragmentText;
|
||||
|
||||
if (fragmentName) { // if fragmentName is passed, use that to get name and text
|
||||
if (fragmentName) {
|
||||
// if fragmentName is passed, use that to get name and text
|
||||
name = fragmentName;
|
||||
text = getFragmentText(fragmentName);
|
||||
} else if (fragmentText) { // if fragmentText is passed, use that to get name and text
|
||||
} else if (fragmentText) {
|
||||
// if fragmentText is passed, use that to get name and text
|
||||
name = extractFragmentName(fragmentText);
|
||||
text = fragmentText;
|
||||
}
|
||||
|
||||
const query = `${singleClientTemplate({ typeName, fragmentName: name })}${text}`;
|
||||
const query = `${singleClientTemplate({
|
||||
typeName,
|
||||
fragmentName: name,
|
||||
})}${text}`;
|
||||
|
||||
return query;
|
||||
};
|
||||
|
||||
Meteor.startup(() => {
|
||||
|
||||
Collections.forEach(collection => {
|
||||
|
||||
const typeName = collection.options.typeName;
|
||||
|
||||
collection.queryOne = async (documentId, { fragmentName, fragmentText, context }) => {
|
||||
const query = buildQuery(collection, { fragmentName, fragmentText });
|
||||
const result = await runQuery(query, { input: { selector: { documentId } } }, context);
|
||||
collection.queryOne = async (
|
||||
documentId,
|
||||
{fragmentName, fragmentText, context}
|
||||
) => {
|
||||
const query = buildQuery(collection, {fragmentName, fragmentText});
|
||||
const result = await runQuery(
|
||||
query,
|
||||
{input: {selector: {documentId}}},
|
||||
context
|
||||
);
|
||||
return result.data[Utils.camelCaseify(typeName)].result;
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -4,55 +4,54 @@ import {
|
|||
defaultConfig,
|
||||
initGraphQL,
|
||||
initContext,
|
||||
computeContextFromReq
|
||||
computeContextFromReq,
|
||||
} from '../../lib/server/apollo-server';
|
||||
import {GraphQLSchema} from '../../lib/modules/graphql';
|
||||
import expect from 'expect';
|
||||
import { executableSchema } from './fixtures/minimalSchema';
|
||||
import {executableSchema} from './fixtures/minimalSchema';
|
||||
|
||||
const test = it; // TODO: just before we switch to jest
|
||||
// @see https://www.apollographql.com/docs/apollo-server/features/testing.html
|
||||
|
||||
describe('apollo-server', function() {
|
||||
let options;
|
||||
before(function () {
|
||||
initGraphQL();
|
||||
let options;
|
||||
before(function() {
|
||||
initGraphQL();
|
||||
|
||||
options = {
|
||||
config: defaultConfig,
|
||||
// Apollo options
|
||||
apolloServerOptions: {
|
||||
// TODO: check why this fails. One of the schema defined
|
||||
// in one of the test file (when running createCollection in a test)
|
||||
// is not working as expected
|
||||
//schema: GraphQLSchema.getExecutableSchema(),
|
||||
schema: executableSchema,
|
||||
//formatError,
|
||||
//tracing: getSetting('apolloTracing', Meteor.isDevelopment),
|
||||
cacheControl: true,
|
||||
//context
|
||||
},
|
||||
// Apollo applyMiddleware Option
|
||||
apolloApplyMiddlewareOptions: {},
|
||||
};
|
||||
options = {
|
||||
config: defaultConfig,
|
||||
// Apollo options
|
||||
apolloServerOptions: {
|
||||
// TODO: check why this fails. One of the schema defined
|
||||
// in one of the test file (when running createCollection in a test)
|
||||
// is not working as expected
|
||||
//schema: GraphQLSchema.getExecutableSchema(),
|
||||
schema: executableSchema,
|
||||
//formatError,
|
||||
//tracing: getSetting('apolloTracing', Meteor.isDevelopment),
|
||||
cacheControl: true,
|
||||
//context
|
||||
},
|
||||
// Apollo applyMiddleware Option
|
||||
apolloApplyMiddlewareOptions: {},
|
||||
};
|
||||
});
|
||||
describe('createServer', function() {
|
||||
test('init server', function() {
|
||||
const server = createApolloServer(options);
|
||||
expect(server).toBeDefined();
|
||||
});
|
||||
describe('createServer', function () {
|
||||
test('init server', function () {
|
||||
const server = createApolloServer(options);
|
||||
expect(server).toBeDefined();
|
||||
});
|
||||
});
|
||||
describe('setupWebApp', function() {});
|
||||
describe('compute context', function() {
|
||||
test.skip('inital context contains data loaders', function() {
|
||||
// TODO
|
||||
});
|
||||
describe('setupWebApp', function () { });
|
||||
describe('compute context', function(){
|
||||
test.skip('inital context contains data loaders', function(){
|
||||
// TODO
|
||||
});
|
||||
test.skip('initial context contains graphQLSchema context', function(){
|
||||
// TODO
|
||||
});
|
||||
test.skip('initial context is merged with provided context', function(){
|
||||
// TODO
|
||||
});
|
||||
|
||||
test.skip('initial context contains graphQLSchema context', function() {
|
||||
// TODO
|
||||
});
|
||||
});
|
||||
test.skip('initial context is merged with provided context', function() {
|
||||
// TODO
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// blatantly stolen from https://www.apollographql.com/docs/graphql-tools/generate-schema.html
|
||||
import find from 'lodash/find';
|
||||
import filter from 'lodash/filter';
|
||||
import { makeExecutableSchema } from 'graphql-tools';
|
||||
import {makeExecutableSchema} from 'graphql-tools';
|
||||
|
||||
const typeDefs = `
|
||||
type Author {
|
||||
|
@ -34,27 +34,27 @@ const typeDefs = `
|
|||
|
||||
// example data
|
||||
const authors = [
|
||||
{ id: 1, firstName: 'Tom', lastName: 'Coleman' },
|
||||
{ id: 2, firstName: 'Sashko', lastName: 'Stubailo' },
|
||||
{ id: 3, firstName: 'Mikhail', lastName: 'Novikov' },
|
||||
{id: 1, firstName: 'Tom', lastName: 'Coleman'},
|
||||
{id: 2, firstName: 'Sashko', lastName: 'Stubailo'},
|
||||
{id: 3, firstName: 'Mikhail', lastName: 'Novikov'},
|
||||
];
|
||||
|
||||
const posts = [
|
||||
{ id: 1, authorId: 1, title: 'Introduction to GraphQL', votes: 2 },
|
||||
{ id: 2, authorId: 2, title: 'Welcome to Meteor', votes: 3 },
|
||||
{ id: 3, authorId: 2, title: 'Advanced GraphQL', votes: 1 },
|
||||
{ id: 4, authorId: 3, title: 'Launchpad is Cool', votes: 7 },
|
||||
{id: 1, authorId: 1, title: 'Introduction to GraphQL', votes: 2},
|
||||
{id: 2, authorId: 2, title: 'Welcome to Meteor', votes: 3},
|
||||
{id: 3, authorId: 2, title: 'Advanced GraphQL', votes: 1},
|
||||
{id: 4, authorId: 3, title: 'Launchpad is Cool', votes: 7},
|
||||
];
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
posts: () => posts,
|
||||
author: (_, { id }) => find(authors, { id }),
|
||||
author: (_, {id}) => find(authors, {id}),
|
||||
},
|
||||
|
||||
Mutation: {
|
||||
upvotePost: (_, { postId }) => {
|
||||
const post = find(posts, { id: postId });
|
||||
upvotePost: (_, {postId}) => {
|
||||
const post = find(posts, {id: postId});
|
||||
if (!post) {
|
||||
throw new Error(`Couldn't find post with id ${postId}`);
|
||||
}
|
||||
|
@ -64,15 +64,15 @@ const resolvers = {
|
|||
},
|
||||
|
||||
Author: {
|
||||
posts: author => filter(posts, { authorId: author.id }),
|
||||
posts: author => filter(posts, {authorId: author.id}),
|
||||
},
|
||||
|
||||
Post: {
|
||||
author: post => find(authors, { id: post.authorId }),
|
||||
author: post => find(authors, {id: post.authorId}),
|
||||
},
|
||||
};
|
||||
|
||||
export const executableSchema = makeExecutableSchema({
|
||||
typeDefs,
|
||||
resolvers
|
||||
});
|
||||
typeDefs,
|
||||
resolvers,
|
||||
});
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
import './graphql.test';
|
||||
import './apollo-server.test';
|
||||
import './apollo-server.test';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Utils } from 'meteor/vulcan:lib';
|
||||
import {Utils} from 'meteor/vulcan:lib';
|
||||
import Users from './collection.js';
|
||||
import moment from 'moment';
|
||||
import _ from 'underscore';
|
||||
|
@ -11,7 +11,7 @@ import _ from 'underscore';
|
|||
* @summary Get a user
|
||||
* @param {String} userOrUserId
|
||||
*/
|
||||
Users.getUser = function (userOrUserId) {
|
||||
Users.getUser = function(userOrUserId) {
|
||||
if (typeof userOrUserId === 'undefined') {
|
||||
if (!Meteor.user()) {
|
||||
throw new Error();
|
||||
|
@ -29,44 +29,51 @@ Users.getUser = function (userOrUserId) {
|
|||
* @summary Get a user's username (unique, no special characters or spaces)
|
||||
* @param {Object} user
|
||||
*/
|
||||
Users.getUserName = function (user) {
|
||||
try{
|
||||
if (user.username)
|
||||
return user.username;
|
||||
if (user && user.services && user.services.twitter && user.services.twitter.screenName)
|
||||
Users.getUserName = function(user) {
|
||||
try {
|
||||
if (user.username) return user.username;
|
||||
if (
|
||||
user &&
|
||||
user.services &&
|
||||
user.services.twitter &&
|
||||
user.services.twitter.screenName
|
||||
)
|
||||
return user.services.twitter.screenName;
|
||||
}
|
||||
catch (error){
|
||||
} catch (error) {
|
||||
console.log(error); // eslint-disable-line
|
||||
return null;
|
||||
}
|
||||
};
|
||||
Users.getUserNameById = function (userId) {return Users.getUserName(Users.findOne(userId));};
|
||||
Users.getUserNameById = function(userId) {
|
||||
return Users.getUserName(Users.findOne(userId));
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Get a user's display name (not unique, can take special characters and spaces)
|
||||
* @param {Object} user
|
||||
*/
|
||||
Users.getDisplayName = function (user) {
|
||||
Users.getDisplayName = function(user) {
|
||||
if (!user) {
|
||||
return '';
|
||||
} else {
|
||||
return (user.displayName) ? user.displayName : Users.getUserName(user);
|
||||
return user.displayName ? user.displayName : Users.getUserName(user);
|
||||
}
|
||||
};
|
||||
Users.getDisplayNameById = function (userId) {return Users.getDisplayName(Users.findOne(userId));};
|
||||
Users.getDisplayNameById = function(userId) {
|
||||
return Users.getDisplayName(Users.findOne(userId));
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Get a user's profile URL
|
||||
* @param {Object} user (note: we only actually need either the _id or slug properties)
|
||||
* @param {Boolean} isAbsolute
|
||||
*/
|
||||
Users.getProfileUrl = function (user, isAbsolute) {
|
||||
Users.getProfileUrl = function(user, isAbsolute) {
|
||||
if (typeof user === 'undefined') {
|
||||
return '';
|
||||
}
|
||||
isAbsolute = typeof isAbsolute === 'undefined' ? false : isAbsolute; // default to false
|
||||
var prefix = isAbsolute ? Utils.getSiteUrl().slice(0,-1) : '';
|
||||
var prefix = isAbsolute ? Utils.getSiteUrl().slice(0, -1) : '';
|
||||
if (user.slug) {
|
||||
return `${prefix}/users/${user.slug}`;
|
||||
} else {
|
||||
|
@ -79,7 +86,7 @@ Users.getProfileUrl = function (user, isAbsolute) {
|
|||
* @param {Object} user (note: we only actually need either the _id or slug properties)
|
||||
* @param {Boolean} isAbsolute
|
||||
*/
|
||||
Users.getEditUrl = function (user, isAbsolute) {
|
||||
Users.getEditUrl = function(user, isAbsolute) {
|
||||
return `${Users.getProfileUrl(user, isAbsolute)}/edit`;
|
||||
};
|
||||
|
||||
|
@ -87,55 +94,64 @@ Users.getEditUrl = function (user, isAbsolute) {
|
|||
* @summary Get a user's Twitter name
|
||||
* @param {Object} user
|
||||
*/
|
||||
Users.getTwitterName = function (user) {
|
||||
Users.getTwitterName = function(user) {
|
||||
// return twitter name provided by user, or else the one used for twitter login
|
||||
if (typeof user !== 'undefined') {
|
||||
if (user.twitterUsername) {
|
||||
return user.twitterUsername;
|
||||
} else if(Utils.checkNested(user, 'services', 'twitter', 'screenName')) {
|
||||
} else if (Utils.checkNested(user, 'services', 'twitter', 'screenName')) {
|
||||
return user.services.twitter.screenName;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
Users.getTwitterNameById = function (userId) {return Users.getTwitterName(Users.findOne(userId));};
|
||||
Users.getTwitterNameById = function(userId) {
|
||||
return Users.getTwitterName(Users.findOne(userId));
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Get a user's GitHub name
|
||||
* @param {Object} user
|
||||
*/
|
||||
Users.getGitHubName = function (user) {
|
||||
Users.getGitHubName = function(user) {
|
||||
// return twitter name provided by user, or else the one used for twitter login
|
||||
if(Utils.checkNested(user, 'profile', 'github')){
|
||||
if (Utils.checkNested(user, 'profile', 'github')) {
|
||||
return user.profile.github;
|
||||
}else if(Utils.checkNested(user, 'services', 'github', 'screenName')){ // TODO: double-check this with GitHub login
|
||||
} else if (Utils.checkNested(user, 'services', 'github', 'screenName')) {
|
||||
// TODO: double-check this with GitHub login
|
||||
return user.services.github.screenName;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
Users.getGitHubNameById = function (userId) {return Users.getGitHubName(Users.findOne(userId));};
|
||||
Users.getGitHubNameById = function(userId) {
|
||||
return Users.getGitHubName(Users.findOne(userId));
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Get a user's email
|
||||
* @param {Object} user
|
||||
*/
|
||||
Users.getEmail = function (user) {
|
||||
if(user.email){
|
||||
Users.getEmail = function(user) {
|
||||
if (user.email) {
|
||||
return user.email;
|
||||
}else{
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
Users.getEmailById = function (userId) {return Users.getEmail(Users.findOne(userId));};
|
||||
Users.getEmailById = function(userId) {
|
||||
return Users.getEmail(Users.findOne(userId));
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Get a user's email hash
|
||||
* @param {Object} user
|
||||
*/
|
||||
Users.getEmailHash = function (user) {
|
||||
Users.getEmailHash = function(user) {
|
||||
return user.emailHash;
|
||||
};
|
||||
Users.getEmailHashById = function (userId) {return Users.getEmailHash(Users.findOne(userId));};
|
||||
Users.getEmailHashById = function(userId) {
|
||||
return Users.getEmailHash(Users.findOne(userId));
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Get a user setting
|
||||
|
@ -143,7 +159,7 @@ Users.getEmailHashById = function (userId) {return Users.getEmailHash(Users.find
|
|||
* @param {String} settingName
|
||||
* @param {Object} defaultValue
|
||||
*/
|
||||
Users.getSetting = function (user = null, settingName, defaultValue = null) {
|
||||
Users.getSetting = function(user = null, settingName, defaultValue = null) {
|
||||
if (user) {
|
||||
const settingValue = Users.getProperty(user, settingName);
|
||||
return typeof settingValue === 'undefined' ? defaultValue : settingValue;
|
||||
|
@ -160,51 +176,50 @@ Users.getSetting = function (user = null, settingName, defaultValue = null) {
|
|||
* @summary Check if the user has completed their profile.
|
||||
* @param {Object} user
|
||||
*/
|
||||
Users.hasCompletedProfile = function (user) {
|
||||
|
||||
Users.hasCompletedProfile = function(user) {
|
||||
if (!user) return false;
|
||||
|
||||
return _.every(Users.getRequiredFields(), function (fieldName) {
|
||||
return _.every(Users.getRequiredFields(), function(fieldName) {
|
||||
return !!Utils.getNestedProperty(user, fieldName);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
///////////////////
|
||||
// Other Helpers //
|
||||
///////////////////
|
||||
|
||||
Users.findLast = function (user, collection) {
|
||||
Users.findLast = function(user, collection) {
|
||||
return collection.findOne({userId: user._id}, {sort: {createdAt: -1}});
|
||||
};
|
||||
|
||||
Users.timeSinceLast = function (user, collection){
|
||||
Users.timeSinceLast = function(user, collection) {
|
||||
var now = new Date().getTime();
|
||||
var last = this.findLast(user, collection);
|
||||
if(!last)
|
||||
return 999; // if this is the user's first post or comment ever, stop here
|
||||
return Math.abs(Math.floor((now-last.createdAt)/1000));
|
||||
if (!last) return 999; // if this is the user's first post or comment ever, stop here
|
||||
return Math.abs(Math.floor((now - last.createdAt) / 1000));
|
||||
};
|
||||
|
||||
Users.numberOfItemsInPast24Hours = function (user, collection) {
|
||||
Users.numberOfItemsInPast24Hours = function(user, collection) {
|
||||
var mNow = moment();
|
||||
var items = collection.find({
|
||||
userId: user._id,
|
||||
createdAt: {
|
||||
$gte: mNow.subtract(24, 'hours').toDate()
|
||||
}
|
||||
$gte: mNow.subtract(24, 'hours').toDate(),
|
||||
},
|
||||
});
|
||||
return items.count();
|
||||
};
|
||||
|
||||
Users.getProperty = function (object, property) {
|
||||
Users.getProperty = function(object, property) {
|
||||
// recursive function to get nested properties
|
||||
var array = property.split('.');
|
||||
if(array.length > 1){
|
||||
if (array.length > 1) {
|
||||
var parent = array.shift();
|
||||
// if our property is not at this level, call function again one level deeper if we can go deeper, else return undefined
|
||||
return (typeof object[parent] === 'undefined') ? undefined : this.getProperty(object[parent], array.join('.'));
|
||||
}else{
|
||||
return typeof object[parent] === 'undefined'
|
||||
? undefined
|
||||
: this.getProperty(object[parent], array.join('.'));
|
||||
} else {
|
||||
// else return property
|
||||
return object[array[0]];
|
||||
}
|
||||
|
@ -220,7 +235,6 @@ Users.getProperty = function (object, property) {
|
|||
// Users.update(user._id, modifier);
|
||||
// }
|
||||
|
||||
|
||||
////////////////////
|
||||
// More Helpers //
|
||||
////////////////////
|
||||
|
@ -231,9 +245,9 @@ Users.getProperty = function (object, property) {
|
|||
* @summary @method Users.getRequiredFields
|
||||
* Get a list of all fields required for a profile to be complete.
|
||||
*/
|
||||
Users.getRequiredFields = function () {
|
||||
Users.getRequiredFields = function() {
|
||||
var schema = Users.simpleSchema()._schema;
|
||||
var fields = _.filter(_.keys(schema), function (fieldName) {
|
||||
var fields = _.filter(_.keys(schema), function(fieldName) {
|
||||
var field = schema[fieldName];
|
||||
return !!field.mustComplete;
|
||||
});
|
||||
|
@ -248,6 +262,6 @@ Users.getRequiredFields = function () {
|
|||
// return Meteor.user() ? Users.getEmail(Meteor.user()) : '';
|
||||
// };
|
||||
|
||||
Users.findByEmail = function (email) {
|
||||
return Users.findOne({'email': email});
|
||||
Users.findByEmail = function(email) {
|
||||
return Users.findOne({email: email});
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue