This commit is contained in:
Wyatt Johnson
2018-06-21 10:44:36 -06:00
parent a3e3d93607
commit 6f80a2458c
48 changed files with 1234 additions and 1243 deletions
+8 -2
View File
@@ -2,8 +2,14 @@ root = true
[*]
indent_style = space
indent_size = 4
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
trim_trailing_whitespace = true
insert_final_newline = true
[*.json]
insert_final_newline = false
[*.ts]
max_line_length = 80
-1
View File
@@ -1,4 +1,3 @@
{
"singleQuote": true,
"trailingComma": "es5"
}
+1 -1
View File
@@ -6,7 +6,7 @@
"start": "node dist/index.js",
"build": "tsc",
"watch": "nodemon --config .nodemonrc.json src/index.ts",
"lint": "prettier --write src/**/*.ts"
"lint": "prettier --write \"src/**/*.ts\""
},
"author": "",
"license": "Apache-2.0",
+1 -1
View File
@@ -1,4 +1,4 @@
import Server, { ServerOptions } from './server';
import Server, { ServerOptions } from "./server";
/**
* Create a Talk Server.
+12 -12
View File
@@ -1,18 +1,18 @@
import { Express } from 'express';
import { Db } from 'mongodb';
import http from 'http';
import { Redis } from 'ioredis';
import { Express } from "express";
import { Db } from "mongodb";
import http from "http";
import { Redis } from "ioredis";
import { Config } from 'talk-server/config';
import { Schemas } from 'talk-server/graph/schemas';
import { handleSubscriptions } from 'talk-server/graph/common/subscriptions/middleware';
import { Config } from "talk-server/config";
import { Schemas } from "talk-server/graph/schemas";
import { handleSubscriptions } from "talk-server/graph/common/subscriptions/middleware";
import { createRouter } from './router';
import serveStatic from './middleware/serveStatic';
import { createRouter } from "./router";
import serveStatic from "./middleware/serveStatic";
import {
access as accessLogger,
error as errorLogger,
} from './middleware/logging';
} from "./middleware/logging";
export interface AppOptions {
parent: Express;
@@ -73,12 +73,12 @@ export async function attachSubscriptionHandlers(
// Setup the Management Subscription endpoint.
handleSubscriptions(server, {
schema: schemas.management,
path: '/api/management/live',
path: "/api/management/live",
});
// Setup the Tenant Subscription endpoint.
handleSubscriptions(server, {
schema: schemas.tenant,
path: '/api/tenant/live',
path: "/api/tenant/live",
});
}
+7 -7
View File
@@ -1,6 +1,6 @@
import { RequestHandler, ErrorRequestHandler } from 'express';
import logger from '../../logger';
import now from 'performance-now';
import { RequestHandler, ErrorRequestHandler } from "express";
import logger from "../../logger";
import now from "performance-now";
export const access: RequestHandler = (req, res, next) => {
const startTime = now();
@@ -10,11 +10,11 @@ export const access: RequestHandler = (req, res, next) => {
const responseTime = Math.round(now() - startTime);
// Get some extra goodies from the request.
const userAgent = req.get('User-Agent');
const userAgent = req.get("User-Agent");
// Reattach the old end, and finish.
res.end = end;
if (typeof encodingOrCb === 'function') {
if (typeof encodingOrCb === "function") {
res.end(chunk, encodingOrCb);
} else {
res.end(chunk, encodingOrCb, cb);
@@ -30,7 +30,7 @@ export const access: RequestHandler = (req, res, next) => {
userAgent,
responseTime,
},
'http request'
"http request"
);
};
@@ -38,6 +38,6 @@ export const access: RequestHandler = (req, res, next) => {
};
export const error: ErrorRequestHandler = (err, req, res, next) => {
logger.error({ err }, 'http error');
logger.error({ err }, "http error");
next(err);
};
+2 -2
View File
@@ -1,4 +1,4 @@
import { MiddlewareOptions } from 'graphql-playground-html';
import playground from 'graphql-playground-middleware-express';
import { MiddlewareOptions } from "graphql-playground-html";
import playground from "graphql-playground-middleware-express";
export default (options: MiddlewareOptions) => playground(options);
@@ -1,4 +1,4 @@
import serveStatic from 'express-static-gzip';
import path from 'path';
import serveStatic from "express-static-gzip";
import path from "path";
export default serveStatic(path.join(__dirname, '..', '..', 'dist'), {});
export default serveStatic(path.join(__dirname, "..", "..", "dist"), {});
+19 -23
View File
@@ -1,28 +1,28 @@
import express, { Router } from 'express';
import express, { Router } from "express";
import tenantGraphMiddleware from 'talk-server/graph/tenant/middleware';
import managementGraphMiddleware from 'talk-server/graph/management/middleware';
import tenantGraphMiddleware from "talk-server/graph/tenant/middleware";
import managementGraphMiddleware from "talk-server/graph/management/middleware";
import { AppOptions } from './index';
import playground from './middleware/playground';
import { AppOptions } from "./index";
import playground from "./middleware/playground";
async function createManagementRouter(opts: AppOptions) {
const router = express.Router();
if (opts.config.get('env') === 'development') {
if (opts.config.get("env") === "development") {
// GraphiQL
router.get(
'/graphiql',
"/graphiql",
playground({
endpoint: '/api/management/graphql',
subscriptionEndpoint: '/api/management/live',
endpoint: "/api/management/graphql",
subscriptionEndpoint: "/api/management/live",
})
);
}
// Management API
router.use(
'/graphql',
"/graphql",
express.json(),
await managementGraphMiddleware(
opts.schemas.management,
@@ -37,26 +37,22 @@ async function createManagementRouter(opts: AppOptions) {
async function createTenantRouter(opts: AppOptions) {
const router = express.Router();
if (opts.config.get('env') === 'development') {
if (opts.config.get("env") === "development") {
// GraphiQL
router.get(
'/graphiql',
"/graphiql",
playground({
endpoint: '/api/tenant/graphql',
subscriptionEndpoint: '/api/tenant/live',
endpoint: "/api/tenant/graphql",
subscriptionEndpoint: "/api/tenant/live",
})
);
}
// Tenant API
router.use(
'/graphql',
"/graphql",
express.json(),
await tenantGraphMiddleware(
opts.schemas.tenant,
opts.config,
opts.mongo
)
await tenantGraphMiddleware(opts.schemas.tenant, opts.config, opts.mongo)
);
return router;
@@ -67,10 +63,10 @@ async function createAPIRouter(opts: AppOptions) {
const router = express.Router();
// Configure the tenant routes.
router.use('/tenant', await createTenantRouter(opts));
router.use("/tenant", await createTenantRouter(opts));
// Configure the management routes.
router.use('/management', await createManagementRouter(opts));
router.use("/management", await createManagementRouter(opts));
return router;
}
@@ -79,7 +75,7 @@ export async function createRouter(opts: AppOptions) {
// Create a router.
const router = express.Router();
router.use('/api', await createAPIRouter(opts));
router.use("/api", await createAPIRouter(opts));
return router;
}
+34 -34
View File
@@ -1,6 +1,6 @@
import Joi from 'joi';
import convict from 'convict';
import dotenv from 'dotenv';
import Joi from "joi";
import convict from "convict";
import dotenv from "dotenv";
// Apply all the configuration provided in the .env file if it isn't already in
// the environment.
@@ -8,12 +8,12 @@ dotenv.config();
// Add custom format for the mongo uri scheme.
convict.addFormat({
name: 'mongo-uri',
name: "mongo-uri",
validate: (url: string) => {
Joi.assert(
url,
Joi.string().uri({
scheme: ['mongodb'],
scheme: ["mongodb"],
})
);
},
@@ -21,12 +21,12 @@ convict.addFormat({
// Add custom format for the redis uri scheme.
convict.addFormat({
name: 'redis-uri',
name: "redis-uri",
validate: (url: string) => {
Joi.assert(
url,
Joi.string().uri({
scheme: ['redis'],
scheme: ["redis"],
})
);
},
@@ -34,45 +34,45 @@ convict.addFormat({
const config = convict({
env: {
doc: 'The application environment.',
format: ['production', 'development', 'test'],
default: 'development',
env: 'NODE_ENV',
doc: "The application environment.",
format: ["production", "development", "test"],
default: "development",
env: "NODE_ENV",
},
port: {
doc: 'The port to bind.',
format: 'port',
doc: "The port to bind.",
format: "port",
default: 3000,
env: 'PORT',
arg: 'port',
env: "PORT",
arg: "port",
},
mongodb: {
doc: 'The MongoDB database to connect to.',
format: 'mongo-uri',
default: 'mongodb://localhost/talk',
env: 'MONGODB',
arg: 'mongodb',
doc: "The MongoDB database to connect to.",
format: "mongo-uri",
default: "mongodb://localhost/talk",
env: "MONGODB",
arg: "mongodb",
},
redis: {
doc: 'The Redis database to connect to.',
format: 'redis-uri',
default: 'redis://localhost:6379',
env: 'REDIS',
arg: 'redis',
doc: "The Redis database to connect to.",
format: "redis-uri",
default: "redis://localhost:6379",
env: "REDIS",
arg: "redis",
},
secret: {
doc: 'The secret used to sign and verify JWTs',
format: '*',
doc: "The secret used to sign and verify JWTs",
format: "*",
default: null,
env: 'SECRET',
arg: 'secret',
env: "SECRET",
arg: "secret",
},
logging_level: {
doc: 'The logging level to print to the console',
format: ['fatal', 'error', 'warn', 'info', 'debug', 'trace'],
default: 'info',
env: 'LOGGING_LEVEL',
arg: 'logging',
doc: "The logging level to print to the console",
format: ["fatal", "error", "warn", "info", "debug", "trace"],
default: "info",
env: "LOGGING_LEVEL",
arg: "logging",
},
});
@@ -2,18 +2,18 @@ import {
graphqlExpress,
ExpressGraphQLOptionsFunction,
GraphQLOptions,
} from 'apollo-server-express';
import { GraphQLError, FieldDefinitionNode, ValidationContext } from 'graphql';
import { resolveGraphqlOptions } from 'apollo-server-core';
import { Config } from 'talk-server/config';
} from "apollo-server-express";
import { GraphQLError, FieldDefinitionNode, ValidationContext } from "graphql";
import { resolveGraphqlOptions } from "apollo-server-core";
import { Config } from "talk-server/config";
// Sourced from: https://github.com/apollographql/apollo-server/blob/958846887598491fadea57b3f9373d129300f250/packages/apollo-server-core/src/ApolloServer.ts#L46-L57
const NoIntrospection = (context: ValidationContext) => ({
Field(node: FieldDefinitionNode) {
if (node.name.value === '__schema' || node.name.value === '__type') {
if (node.name.value === "__schema" || node.name.value === "__type") {
context.reportError(
new GraphQLError(
'GraphQL introspection is not allowed in production, but the query contained __schema or __type.',
"GraphQL introspection is not allowed in production, but the query contained __schema or __type.",
[node]
)
);
@@ -28,7 +28,7 @@ export const graphqlMiddleware = (
// Generate the validation rules.
const validationRules: Array<(context: ValidationContext) => any> = [];
if (config.get('env') !== 'production') {
if (config.get("env") !== "production") {
// Disable introspection in production.
validationRules.push(NoIntrospection);
}
@@ -36,11 +36,7 @@ export const graphqlMiddleware = (
// Generate the actual middleware.
return graphqlExpress(async (req, res) => {
// Resolve the base options.
const requestOptions = await resolveGraphqlOptions(
baseOptions,
req,
res
);
const requestOptions = await resolveGraphqlOptions(baseOptions, req, res);
// Apply the validators, sourced from: https://github.com/apollographql/apollo-server/blob/958846887598491fadea57b3f9373d129300f250/packages/apollo-server-core/src/ApolloServer.ts#L104-L107
requestOptions.validationRules = requestOptions.validationRules
+11 -11
View File
@@ -1,7 +1,7 @@
import { DateTime } from 'luxon';
import { GraphQLScalarType } from 'graphql';
import { Kind } from 'graphql/language';
import { Cursor } from 'talk-server/models/connection';
import { DateTime } from "luxon";
import { GraphQLScalarType } from "graphql";
import { Kind } from "graphql/language";
import { Cursor } from "talk-server/models/connection";
function parseIntegerCursor(value: string): number {
try {
@@ -14,7 +14,7 @@ function parseIntegerCursor(value: string): number {
}
function parseCursor(value: string): Cursor {
if (value.endsWith('Z')) {
if (value.endsWith("Z")) {
const date = DateTime.fromISO(value, {});
if (!date.isValid) {
return parseIntegerCursor(value);
@@ -27,11 +27,11 @@ function parseCursor(value: string): Cursor {
}
export default new GraphQLScalarType({
name: 'Cursor',
description: 'Cursor represents a paginating cursor.',
name: "Cursor",
description: "Cursor represents a paginating cursor.",
serialize(value) {
switch (typeof value) {
case 'object':
case "object":
if (value instanceof Date) {
return value.toISOString();
} else if (value instanceof DateTime) {
@@ -39,16 +39,16 @@ export default new GraphQLScalarType({
}
return null;
case 'number':
case "number":
return value.toString();
case 'string':
case "string":
return value;
default:
return null;
}
},
parseValue(value) {
if (typeof value === 'string') {
if (typeof value === "string") {
return parseCursor(value);
}
+2 -2
View File
@@ -1,5 +1,5 @@
import { addResolveFunctionsToSchema, IResolvers } from 'graphql-tools';
import { getGraphQLProjectConfig } from 'graphql-config';
import { addResolveFunctionsToSchema, IResolvers } from "graphql-tools";
import { getGraphQLProjectConfig } from "graphql-config";
export default function loadSchema(projectName: string, resolvers: IResolvers) {
// Load the configuration from the provided `.graphqlconfig` file.
@@ -1,6 +1,6 @@
import http from 'http';
import { SubscriptionServer } from 'subscriptions-transport-ws';
import { GraphQLSchema, execute, subscribe } from 'graphql';
import http from "http";
import { SubscriptionServer } from "subscriptions-transport-ws";
import { GraphQLSchema, execute, subscribe } from "graphql";
export interface SubscriptionMiddlewareOptions {
schema: GraphQLSchema;
@@ -1,6 +1,6 @@
import { RedisPubSub } from 'graphql-redis-subscriptions';
import { createRedisClient } from 'talk-server/services/redis';
import { Config } from 'talk-server/config';
import { RedisPubSub } from "graphql-redis-subscriptions";
import { createRedisClient } from "talk-server/services/redis";
import { Config } from "talk-server/config";
export async function createPubSub(config: Config): Promise<RedisPubSub> {
// Create the Redis clients for the PubSub server.
+1 -1
View File
@@ -1,4 +1,4 @@
import { Db } from 'mongodb';
import { Db } from "mongodb";
export interface ManagementContextOptions {
db: Db;
@@ -1,10 +1,10 @@
import { Db } from 'mongodb';
import { GraphQLSchema } from 'graphql';
import { Db } from "mongodb";
import { GraphQLSchema } from "graphql";
import { graphqlMiddleware } from 'talk-server/graph/common/middleware';
import { Config } from 'talk-server/config';
import { graphqlMiddleware } from "talk-server/graph/common/middleware";
import { Config } from "talk-server/config";
import Context from './context';
import Context from "./context";
export default (schema: GraphQLSchema, config: Config, db: Db) =>
graphqlMiddleware(config, async () => ({
@@ -1,4 +1,4 @@
import Cursor from '../../common/scalars/cursor';
import Cursor from "../../common/scalars/cursor";
export default {
Cursor,
@@ -1,6 +1,6 @@
import loadSchema from 'talk-server/graph/common/schema';
import resolvers from 'talk-server/graph/management/resolvers';
import loadSchema from "talk-server/graph/common/schema";
import resolvers from "talk-server/graph/management/resolvers";
export default function getManagementSchema() {
return loadSchema('management', resolvers);
return loadSchema("management", resolvers);
}
+1 -1
View File
@@ -1,4 +1,4 @@
import { GraphQLSchema } from 'graphql';
import { GraphQLSchema } from "graphql";
export interface Schemas {
management: GraphQLSchema;
+3 -3
View File
@@ -1,6 +1,6 @@
import loaders from './loaders';
import { Db } from 'mongodb';
import { Tenant } from 'talk-server/models/tenant';
import loaders from "./loaders";
import { Db } from "mongodb";
import { Tenant } from "talk-server/models/tenant";
export interface TenantContextOptions {
tenant?: Tenant;
@@ -1,9 +1,9 @@
import DataLoader from 'dataloader';
import DataLoader from "dataloader";
import {
Asset,
retrieveMany as retrieveManyAssets,
} from 'talk-server/models/asset';
import Context from 'talk-server/graph/tenant/context';
} from "talk-server/models/asset";
import Context from "talk-server/graph/tenant/context";
export default (ctx: Context) => ({
asset: new DataLoader<string, Asset>(ids =>
@@ -1,12 +1,12 @@
import DataLoader from 'dataloader';
import DataLoader from "dataloader";
import {
Comment,
retrieveMany,
retrieveAssetConnection,
ConnectionInput,
retrieveRepliesConnection,
} from 'talk-server/models/comment';
import Context from 'talk-server/graph/tenant/context';
} from "talk-server/models/comment";
import Context from "talk-server/graph/tenant/context";
export default (ctx: Context) => ({
comment: new DataLoader((ids: string[]) =>
@@ -15,11 +15,5 @@ export default (ctx: Context) => ({
forAsset: (assetID: string, input: ConnectionInput) =>
retrieveAssetConnection(ctx.db, ctx.tenant.id, assetID, input),
forParent: (assetID: string, parentID: string, input: ConnectionInput) =>
retrieveRepliesConnection(
ctx.db,
ctx.tenant.id,
assetID,
parentID,
input
),
retrieveRepliesConnection(ctx.db, ctx.tenant.id, assetID, parentID, input),
});
@@ -1,7 +1,7 @@
import Assets from './assets';
import Comments from './comments';
import Users from './users';
import Context from 'talk-server/graph/tenant/context';
import Assets from "./assets";
import Comments from "./comments";
import Users from "./users";
import Context from "talk-server/graph/tenant/context";
export default (ctx: Context) => ({
Assets: Assets(ctx),
@@ -1,6 +1,6 @@
import DataLoader from 'dataloader';
import { User, retrieveMany } from 'talk-server/models/user';
import Context from 'talk-server/graph/tenant/context';
import DataLoader from "dataloader";
import { User, retrieveMany } from "talk-server/models/user";
import Context from "talk-server/graph/tenant/context";
export default (ctx: Context) => ({
user: new DataLoader<string, User>(ids =>
+7 -7
View File
@@ -1,12 +1,12 @@
import { Db } from 'mongodb';
import { GraphQLSchema } from 'graphql';
import { Db } from "mongodb";
import { GraphQLSchema } from "graphql";
import { retrieveByDomain } from 'talk-server/models/tenant';
import { createPubSub } from 'talk-server/graph/common/subscriptions/pubsub';
import { Config } from 'talk-server/config';
import { graphqlMiddleware } from 'talk-server/graph/common/middleware';
import { retrieveByDomain } from "talk-server/models/tenant";
import { createPubSub } from "talk-server/graph/common/subscriptions/pubsub";
import { Config } from "talk-server/config";
import { graphqlMiddleware } from "talk-server/graph/common/middleware";
import TenantContext from './context';
import TenantContext from "./context";
export default async (schema: GraphQLSchema, config: Config, db: Db) => {
// Configure the PubSub broker.
@@ -1,6 +1,6 @@
import { Asset } from 'talk-server/models/asset';
import Context from 'talk-server/graph/tenant/context';
import { ConnectionInput } from 'talk-server/models/comment';
import { Asset } from "talk-server/models/asset";
import Context from "talk-server/graph/tenant/context";
import { ConnectionInput } from "talk-server/models/comment";
export default {
comments: async (asset: Asset, input: ConnectionInput, ctx: Context) =>
@@ -1,5 +1,5 @@
import { Comment, ConnectionInput } from 'talk-server/models/comment';
import Context from 'talk-server/graph/tenant/context';
import { Comment, ConnectionInput } from "talk-server/models/comment";
import Context from "talk-server/graph/tenant/context";
export default {
author: async (comment: Comment, _: any, ctx: Context) =>
@@ -1,7 +1,7 @@
import Asset from './asset';
import Comment from './comment';
import Cursor from '../../common/scalars/cursor';
import Query from './query';
import Asset from "./asset";
import Comment from "./comment";
import Cursor from "../../common/scalars/cursor";
import Query from "./query";
export default {
Asset,
@@ -1,5 +1,5 @@
import TenantContext from 'talk-server/graph/tenant/context';
import { Asset } from 'talk-server/models/asset';
import TenantContext from "talk-server/graph/tenant/context";
import { Asset } from "talk-server/models/asset";
export default {
asset: async (
+3 -3
View File
@@ -1,6 +1,6 @@
import loadSchema from 'talk-server/graph/common/schema';
import resolvers from 'talk-server/graph/tenant/resolvers';
import loadSchema from "talk-server/graph/common/schema";
import resolvers from "talk-server/graph/tenant/resolvers";
export default function getTenantSchema() {
return loadSchema('tenant', resolvers);
return loadSchema("tenant", resolvers);
}
+13 -13
View File
@@ -1,14 +1,14 @@
import express, { Express } from 'express';
import http from 'http';
import express, { Express } from "express";
import http from "http";
import config, { Config } from './config';
import { createApp, listenAndServe, attachSubscriptionHandlers } from './app';
import logger from './logger';
import { createMongoDB } from './services/mongodb';
import { createRedisClient } from './services/redis';
import getManagementSchema from 'talk-server/graph/management/schema';
import getTenantSchema from 'talk-server/graph/tenant/schema';
import { Schemas } from 'talk-server/graph/schemas';
import config, { Config } from "./config";
import { createApp, listenAndServe, attachSubscriptionHandlers } from "./app";
import logger from "./logger";
import { createMongoDB } from "./services/mongodb";
import { createRedisClient } from "./services/redis";
import getManagementSchema from "talk-server/graph/management/schema";
import getTenantSchema from "talk-server/graph/tenant/schema";
import { Schemas } from "talk-server/graph/schemas";
export interface ServerOptions {
config?: Config;
@@ -36,7 +36,7 @@ class Server {
this.parentApp = express();
this.config = config
.load(options.config || {})
.validate({ allowed: 'strict' });
.validate({ allowed: "strict" });
// Load the graph schemas.
this.schemas = {
@@ -52,7 +52,7 @@ class Server {
* @param parent the optional express application to bind the server to.
*/
public async start(parent?: Express) {
const port = this.config.get('port');
const port = this.config.get("port");
// Ensure we have an app to bind to.
parent = parent ? parent : this.parentApp;
@@ -78,7 +78,7 @@ class Server {
// Setup the websocket servers on the new http.Server.
attachSubscriptionHandlers(this.schemas, this.httpServer);
logger.info({ port }, 'now listening');
logger.info({ port }, "now listening");
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
import bunyan from 'bunyan';
import bunyan from "bunyan";
const logger = bunyan.createLogger({ name: 'talk' });
const logger = bunyan.createLogger({ name: "talk" });
export default logger;
+14 -14
View File
@@ -1,13 +1,13 @@
import { Db, Collection } from 'mongodb';
import Query, { FilterQuery } from './query';
import { defaults } from 'lodash';
import uuid from 'uuid';
import { Omit } from 'talk-common/types';
import dotize from 'dotize';
import { TenantResource } from 'talk-server/models/tenant';
import { Db, Collection } from "mongodb";
import Query, { FilterQuery } from "./query";
import { defaults } from "lodash";
import uuid from "uuid";
import { Omit } from "talk-common/types";
import dotize from "dotize";
import { TenantResource } from "talk-server/models/tenant";
function collection(db: Db): Collection<Asset> {
return db.collection<Asset>('assets');
return db.collection<Asset>("assets");
}
export interface Asset extends TenantResource {
@@ -27,7 +27,7 @@ export interface Asset extends TenantResource {
created_at: Date;
}
export type CreateAssetInput = Pick<Asset, 'id' | 'url'>;
export type CreateAssetInput = Pick<Asset, "id" | "url">;
export async function create(
db: Db,
@@ -57,7 +57,7 @@ export async function create(
// Perform the upsert operation.
const result = await db
.collection<Asset>('assets')
.collection<Asset>("assets")
.findOneAndUpdate(query.filter, update, {
// Create the object if it doesn't already exist.
upsert: true,
@@ -75,7 +75,7 @@ export async function retrieve(
id: string
): Promise<Asset> {
return await db
.collection<Asset>('assets')
.collection<Asset>("assets")
.findOne({ id, tenant_id: tenantID });
}
@@ -85,7 +85,7 @@ export async function retrieveMany(
ids: string[]
): Promise<Array<Asset>> {
const cursor = await db
.collection<Asset>('assets')
.collection<Asset>("assets")
.find({ id: { $in: ids }, tenant_id: tenantID });
const assets = await cursor.toArray();
@@ -95,7 +95,7 @@ export async function retrieveMany(
export type UpdateAssetInput = Omit<
Partial<Asset>,
'id' | 'tenant_id' | 'url' | 'created_at'
"id" | "tenant_id" | "url" | "created_at"
>;
export async function update(
@@ -104,7 +104,7 @@ export async function update(
id: string,
update: UpdateAssetInput
): Promise<Readonly<Asset>> {
const result = await db.collection<Asset>('assets').findOneAndUpdate(
const result = await db.collection<Asset>("assets").findOneAndUpdate(
{ id, tenant_id: tenantID },
// Only update fields that have been updated.
{ $set: dotize(update) },
+25 -25
View File
@@ -1,14 +1,14 @@
import { Db, Collection } from 'mongodb';
import { Omit, Sub } from 'talk-common/types';
import { merge } from 'lodash';
import uuid from 'uuid';
import { Connection, Edge, Cursor } from 'talk-server/models/connection';
import Query from 'talk-server/models/query';
import { ActionCounts } from 'talk-server/models/actions';
import { TenantResource } from 'talk-server/models/tenant';
import { Db, Collection } from "mongodb";
import { Omit, Sub } from "talk-common/types";
import { merge } from "lodash";
import uuid from "uuid";
import { Connection, Edge, Cursor } from "talk-server/models/connection";
import Query from "talk-server/models/query";
import { ActionCounts } from "talk-server/models/actions";
import { TenantResource } from "talk-server/models/tenant";
function collection(db: Db): Collection<Comment> {
return db.collection<Comment>('comments');
return db.collection<Comment>("comments");
}
export interface BodyHistoryItem {
@@ -23,11 +23,11 @@ export interface StatusHistoryItem {
}
export enum CommentStatus {
ACCEPTED = 'ACCEPTED',
REJECTED = 'REJECTED',
PREMOD = 'PREMOD',
SYSTEM_WITHHELD = 'SYSTEM_WITHHELD',
NONE = 'NONE',
ACCEPTED = "ACCEPTED",
REJECTED = "REJECTED",
PREMOD = "PREMOD",
SYSTEM_WITHHELD = "SYSTEM_WITHHELD",
NONE = "NONE",
}
export interface Comment extends TenantResource {
@@ -50,12 +50,12 @@ export interface Comment extends TenantResource {
export type CreateCommentInput = Omit<
Comment,
| 'id'
| 'tenant_id'
| 'created_at'
| 'reply_count'
| 'body_history'
| 'status_history'
| "id"
| "tenant_id"
| "created_at"
| "reply_count"
| "body_history"
| "status_history"
>;
export async function create(
@@ -130,10 +130,10 @@ export async function retrieveMany(
}
export enum CommentSort {
CREATED_AT_DESC = 'CREATED_AT_DESC',
CREATED_AT_ASC = 'CREATED_AT_ASC',
REPLIES_DESC = 'REPLIES_DESC',
RESPECT_DESC = 'RESPECT_DESC',
CREATED_AT_DESC = "CREATED_AT_DESC",
CREATED_AT_ASC = "CREATED_AT_ASC",
REPLIES_DESC = "REPLIES_DESC",
RESPECT_DESC = "RESPECT_DESC",
}
export interface ConnectionInput {
@@ -256,7 +256,7 @@ async function retrieveConnection(
}
break;
case CommentSort.RESPECT_DESC:
query.orderBy({ 'action_counts.respect': -1, created_at: -1 });
query.orderBy({ "action_counts.respect": -1, created_at: -1 });
if (input.after) {
query.after(input.after as number);
}
+4 -4
View File
@@ -1,7 +1,7 @@
import { merge } from 'lodash';
import { Collection, Cursor } from 'mongodb';
import { FilterQuery as MongoFilterQuery } from 'mongodb';
import { Writeable } from '../../common/types';
import { merge } from "lodash";
import { Collection, Cursor } from "mongodb";
import { FilterQuery as MongoFilterQuery } from "mongodb";
import { Writeable } from "../../common/types";
/**
* FilterQuery<T> ensures that given the type T, that the FilterQuery will be a
+9 -9
View File
@@ -1,11 +1,11 @@
import { Db, Collection } from 'mongodb';
import { merge } from 'lodash';
import dotize from 'dotize';
import uuid from 'uuid';
import { Omit, Sub } from 'talk-common/types';
import { Db, Collection } from "mongodb";
import { merge } from "lodash";
import dotize from "dotize";
import uuid from "uuid";
import { Omit, Sub } from "talk-common/types";
function collection(db: Db): Collection<Tenant> {
return db.collection<Tenant>('tenants');
return db.collection<Tenant>("tenants");
}
export interface TenantResource {
@@ -18,8 +18,8 @@ export interface Wordlist {
}
export enum Moderation {
PRE = 'PRE',
POST = 'POST',
PRE = "PRE",
POST = "POST",
}
export interface Tenant {
@@ -66,7 +66,7 @@ export interface Tenant {
*/
export type CreateTenantInput = Pick<
Tenant,
'domain' | 'organizationName' | 'organizationContactEmail' | 'domains'
"domain" | "organizationName" | "organizationContactEmail" | "domains"
>;
/**
+24 -24
View File
@@ -1,12 +1,12 @@
import { ActionCounts } from 'talk-server/models/actions';
import { Db, Collection } from 'mongodb';
import uuid from 'uuid';
import { Omit, Sub } from 'talk-common/types';
import { merge } from 'lodash';
import { TenantResource } from 'talk-server/models/tenant';
import { ActionCounts } from "talk-server/models/actions";
import { Db, Collection } from "mongodb";
import uuid from "uuid";
import { Omit, Sub } from "talk-common/types";
import { merge } from "lodash";
import { TenantResource } from "talk-server/models/tenant";
function collection(db: Db): Collection<User> {
return db.collection<User>('users');
return db.collection<User>("users");
}
export interface Profile {
@@ -25,31 +25,31 @@ export enum UserUsernameStatus {
// require moderator action to become active. This can be used when the user
// signs up with a social login and has the option of setting their own
// username.
UNSET = 'UNSET',
UNSET = "UNSET",
// SET is used when the username has been set for the first time, but cannot
// change without the username being rejected by a moderator and that moderator
// agreeing that the username should be allowed to change.
SET = 'SET',
SET = "SET",
// APPROVED is used when the username was changed, and subsequently approved by
// said moderator.
APPROVED = 'APPROVED',
APPROVED = "APPROVED",
// REJECTED is used when the username was changed, and subsequently rejected by
// said moderator.
REJECTED = 'REJECTED',
REJECTED = "REJECTED",
// CHANGED is used after a user has changed their username after it was
// rejected.
CHANGED = 'CHANGED',
CHANGED = "CHANGED",
}
export enum UserRole {
ADMIN = 'ADMIN',
MODERATOR = 'MODERATOR',
STAFF = 'STAFF',
COMMENTER = 'COMMENTER',
ADMIN = "ADMIN",
MODERATOR = "MODERATOR",
STAFF = "STAFF",
COMMENTER = "COMMENTER",
}
export interface UserStatusHistory<T> {
@@ -85,14 +85,14 @@ export interface User extends TenantResource {
export type CreateUserInput = Omit<
User,
| 'id'
| 'tenant_id'
| 'tokens'
| 'status'
| 'role'
| 'action_counts'
| 'ignored_users'
| 'created_at'
| "id"
| "tenant_id"
| "tokens"
| "status"
| "role"
| "action_counts"
| "ignored_users"
| "created_at"
>;
export async function create(
+2 -2
View File
@@ -1,5 +1,5 @@
import { Db } from 'mongodb';
import { Comment } from 'talk-server/models/comment';
import { Db } from "mongodb";
import { Comment } from "talk-server/models/comment";
export async function create(db: Db): Promise<Comment> {
return null;
+3 -3
View File
@@ -1,5 +1,5 @@
import { MongoClient, Db } from 'mongodb';
import { Config } from 'talk-server/config';
import { MongoClient, Db } from "mongodb";
import { Config } from "talk-server/config";
/**
* create will connect to the MongoDB instance identified in the configuration.
@@ -8,7 +8,7 @@ import { Config } from 'talk-server/config';
*/
export async function createMongoDB(config: Config): Promise<Db> {
// Connect and create a client for MongoDB.
const client = await MongoClient.connect(config.get('mongodb'));
const client = await MongoClient.connect(config.get("mongodb"));
// Return the database handle, which defaults to the database name provided
// in the config connection string.
+3 -3
View File
@@ -1,5 +1,5 @@
import RedisClient, { Redis } from 'ioredis';
import { Config } from 'talk-server/config';
import RedisClient, { Redis } from "ioredis";
import { Config } from "talk-server/config";
/**
* create will connect to the Redis instance identified in the configuration.
@@ -7,5 +7,5 @@ import { Config } from 'talk-server/config';
* @param config application configuration.
*/
export async function createRedisClient(config: Config): Promise<Redis> {
return new RedisClient(config.get('redis'), {});
return new RedisClient(config.get("redis"), {});
}
+6 -6
View File
@@ -1,10 +1,10 @@
import { Db } from 'mongodb';
import { Redis } from 'ioredis';
import DataLoader from 'dataloader';
import { Db } from "mongodb";
import { Redis } from "ioredis";
import DataLoader from "dataloader";
import { Tenant, retrieveAll, retrieveMany } from 'talk-server/models/tenant';
import { Tenant, retrieveAll, retrieveMany } from "talk-server/models/tenant";
const CacheUpdateChannel = 'tenant';
const CacheUpdateChannel = "tenant";
// Cache provides an interface for retrieving tenant stored in local memory
// rather than grabbing it from the database every single call.
@@ -25,7 +25,7 @@ export default class Cache {
// Attach to messages on this connection so we can receive updates when
// the tenant are changed.
subscriber.on('message', this.onMessage);
subscriber.on("message", this.onMessage);
}
/**
+2 -2
View File
@@ -1,5 +1,5 @@
import createTalk from './core';
import express from 'express';
import createTalk from "./core";
import express from "express";
// Create the app that will serve as the mounting point for the Talk Server.
const app = express();
+1 -1
View File
@@ -1,4 +1,4 @@
declare module 'dotize' {
declare module "dotize" {
export = dotize;
function dotize(obj: any): { [_: string]: any };
+1 -1
View File
@@ -1,4 +1,4 @@
declare module 'express-static-gzip' {
declare module "express-static-gzip" {
export = express_static_gzip;
function express_static_gzip(rootFolder: any, options: any): any;