10 |
11 |
12 | Welcome to React
13 |
14 |
15 | To get started, edit src/App.tsx and save to reload.
16 |
17 |
18 | );
19 | }
20 | }
21 |
22 | export default App;
23 |
--------------------------------------------------------------------------------
/app/connector/projects/blog/comment.ts:
--------------------------------------------------------------------------------
1 | import * as mongoose from 'mongoose';
2 | import { BlogConnection } from '../../../database/connections';
3 | const { Schema } = mongoose;
4 |
5 | const commentSchema = new Schema({
6 | content: String,
7 | authorId: Number,
8 | gmtCreated: Date,
9 | lastModified: Date,
10 | }, {
11 | versionKey: false,
12 | timestamps: { createdAt: 'gmtCreated', updatedAt: 'lastModified' },
13 | toObject: {
14 | virtuals: true,
15 | },
16 | toJSON: {
17 | virtuals: true,
18 | },
19 | collection: 'comment',
20 | });
21 |
22 | export default BlogConnection.getConn().model('BlogComment', commentSchema);
23 |
--------------------------------------------------------------------------------
/app/connector/projects/info/user.ts:
--------------------------------------------------------------------------------
1 | import * as mongoose from 'mongoose';
2 | import { InfoConnection } from '../../../database/connections';
3 | const { Schema } = mongoose;
4 |
5 | const userSchema = new Schema({
6 | userName: String,
7 | mobilePhone: String,
8 | gmtCreated: Date,
9 | lastModified: Date,
10 | lastLoginTime: Date,
11 | lastLoginIp: String,
12 | }, {
13 | versionKey: false,
14 | timestamps: { createdAt: 'gmtCreated', updatedAt: 'lastModified' },
15 | toObject: {
16 | virtuals: true,
17 | },
18 | toJSON: {
19 | virtuals: true,
20 | },
21 | });
22 |
23 | export default InfoConnection.getConn().model('InfoUser', userSchema);
24 |
--------------------------------------------------------------------------------
/app/graphql/projects/comment/resolver.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | Comment: {
3 | author: async ({ authorId }: { authorId: string }, args, context) => {
4 | const result = await context.model.UserModel.findById(authorId);
5 | return result;
6 | },
7 | },
8 | Mutation: {
9 | addComment: async (root, { comment }: { comment: any }, context) => {
10 | const commentResult = await context.model.CommentModel.addComment(comment);
11 | const { articleId } = comment;
12 | const { id } = commentResult;
13 | const result = await context.model.ArticleModel.insertComment(articleId, id);
14 | return result;
15 | },
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/app/graphql/projects/user/schema.gql:
--------------------------------------------------------------------------------
1 | # 用户信息
2 | type User {
3 | # 用户 id
4 | id: String
5 | # 用户名
6 | userName: String
7 | # 用户联系电话
8 | mobilePhone: String
9 | # 创建日期
10 | gmtCreated: Date
11 | # 最近更新日期
12 | lastModified: Date
13 | # 最近登录时间
14 | lastLoginTime: Date
15 | # 最近登录 ip
16 | lastLoginIp: String
17 | }
18 |
19 | input UserInputType {
20 | # 用户名
21 | userName: String
22 | # 用户联系电话
23 | mobilePhone: String
24 | }
25 |
26 | type Query {
27 | # 获取用户列表
28 | users: [User]
29 | # 获取用户信息
30 | user(userName: String): [User]
31 | }
32 |
33 | type Mutation {
34 | ## 添加用户
35 | addUser(user: UserInputType): User
36 | }
37 |
38 |
39 |
--------------------------------------------------------------------------------
/app/connector/projects/blog/article.ts:
--------------------------------------------------------------------------------
1 | import * as mongoose from 'mongoose';
2 | import { BlogConnection } from '../../../database/connections';
3 | const { Schema } = mongoose;
4 |
5 | const articleSchema = new Schema({
6 | title: String,
7 | content: String,
8 | authorId: String,
9 | commentIds: [String],
10 | gmtCreated: Date,
11 | lastModified: Date,
12 | }, {
13 | versionKey: false,
14 | timestamps: { createdAt: 'gmtCreated', updatedAt: 'lastModified' },
15 | toObject: {
16 | virtuals: true,
17 | },
18 | toJSON: {
19 | virtuals: true,
20 | },
21 | collection: 'article',
22 | });
23 |
24 | export default BlogConnection.getConn().model('BlogArticle', articleSchema);
25 |
--------------------------------------------------------------------------------
/app/graphql/projects/article/schema.gql:
--------------------------------------------------------------------------------
1 | # 文章
2 | type Article {
3 | # 文章 id
4 | _id: ID!
5 | # 文章标题
6 | title: String
7 | # 文章内容
8 | content: String
9 | # 作者信息
10 | author: User
11 | # 评论列表
12 | comments: [Comment]
13 | # 创建日期
14 | gmtCreated: Date
15 | # 最近修改日期
16 | lastModified: Date
17 | }
18 |
19 | input ArticleInpuType {
20 | # 文章标题
21 | title: String
22 | # 文章内容
23 | content: String
24 | # 作者信息
25 | authorId: String
26 | }
27 |
28 | type Query {
29 | # 获取文章列表
30 | articles: [Article]
31 | # 获取文章信息
32 | article(title: String): [Article]
33 | }
34 |
35 | type Mutation {
36 | # 添加文章
37 | addArticle(article: ArticleInpuType): Article
38 | }
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/utils/logger.ts:
--------------------------------------------------------------------------------
1 | // const emoji = r equire('node-emoji');
2 | import chalk from 'chalk';
3 | import * as emoji from 'node-emoji';
4 |
5 | const info = chalk.bold.green;
6 | const warn = chalk.bold.yellow;
7 | const error = chalk.bold.red;
8 |
9 | export default {
10 | warn: (...args) => {
11 | console.log(emoji.get('warning'), '-->', warn(...args));
12 | },
13 | info: (...args) => {
14 | console.log(emoji.random().emoji, '-->', info(...args));
15 | },
16 | error: (...args) => {
17 | console.error(emoji.get('x'), '-->', error(...args));
18 | },
19 | log: (emojiSelect: string, color: string, ...args) => {
20 | console.log(emoji.get(emojiSelect), '-->', chalk.keyword(color)(...args));
21 | },
22 | };
23 |
--------------------------------------------------------------------------------
/app/middleware/items/general.ts:
--------------------------------------------------------------------------------
1 | import * as Application from 'koa';
2 | import * as koaBody from 'koa-bodyparser';
3 | import * as compress from 'koa-compress';
4 | import * as logger from 'koa-logger';
5 | import * as serve from 'koa-static';
6 | import * as path from 'path';
7 |
8 | const { resolve } = path;
9 |
10 | const r = (pathstr: string) => resolve(__dirname, pathstr);
11 |
12 | export const addBody = (app: Application) => {
13 | app.use(koaBody());
14 | };
15 |
16 | export const addServe = (app: Application) => {
17 | app.use(serve(r('../../public')));
18 | };
19 |
20 | export const addLogger = (app: Application) => {
21 | app.use(logger());
22 | };
23 |
24 | export const addCompress = (app: Application) => {
25 | app.use(compress());
26 | };
27 |
--------------------------------------------------------------------------------
/front_end/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./src/",
4 | "outDir": "build/dist",
5 | "module": "esnext",
6 | "target": "es5",
7 | "lib": ["es6", "dom"],
8 | "sourceMap": true,
9 | "allowJs": true,
10 | "jsx": "react",
11 | "moduleResolution": "node",
12 | "rootDir": "src",
13 | "forceConsistentCasingInFileNames": true,
14 | "noImplicitReturns": true,
15 | "noImplicitThis": true,
16 | "noImplicitAny": true,
17 | "strictNullChecks": true,
18 | "suppressImplicitAnyIndexErrors": true,
19 | "noUnusedLocals": true
20 | },
21 | "exclude": [
22 | "node_modules",
23 | "build",
24 | "scripts",
25 | "acceptance-tests",
26 | "webpack",
27 | "jest",
28 | "src/setupTests.ts"
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/app/config/development.ts:
--------------------------------------------------------------------------------
1 | export = {
2 | dataSources: {
3 | dbBlog: {
4 | uri: 'mongodb://127.0.0.1:27017/blog',
5 | options: {
6 | autoReconnect: true,
7 | },
8 | },
9 | dbInfo: {
10 | uri: 'mongodb://127.0.0.1:27017/test',
11 | options: {
12 | autoReconnect: true,
13 | },
14 | },
15 | },
16 | mongoClientOptions: {
17 | autoReconnect: true,
18 | reconnectTries: 20,
19 | reconnectInterval: 500,
20 | connectTimeoutMS: 30000,
21 | },
22 | port: 3000,
23 | redis: {
24 | endpoints: [
25 | {
26 | host: '127.0.0.1',
27 | port: 6379,
28 | },
29 | ],
30 | },
31 | base: 'http://localhost:3000',
32 | graphql: {
33 | // remotes: ['https://otherGQService.com/graphql'],
34 | },
35 | };
36 |
--------------------------------------------------------------------------------
/app/middleware/index.ts:
--------------------------------------------------------------------------------
1 | import * as glob from 'glob';
2 | import * as Application from 'koa';
3 | import * as path from 'path';
4 | import * as R from 'ramda';
5 | import Logger from '../utils/logger';
6 | const { resolve } = path;
7 |
8 | export default (app: Application) => {
9 | try {
10 | Logger.info('loading middlewares');
11 | const baseDir = resolve(__dirname, './items/');
12 | const pattern = baseDir + '/**/*.js';
13 | const g = new glob.Glob(pattern, {
14 | mark: true,
15 | sync: true,
16 | });
17 | const load = R.compose(
18 | R.map(R.compose(
19 | R.map((i: (app: Application) => {}) => i(app)),
20 | require,
21 | ),
22 | ),
23 | );
24 | load(g.found);
25 | } catch (error) {
26 | Logger.error(error);
27 | throw error;
28 | }
29 | };
30 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": true,
3 | "compilerOptions": {
4 | // "outDir": "dist",
5 | "allowJs": false,
6 | "allowUnreachableCode": false,
7 | "allowUnusedLabels": false,
8 | "charset": "utf8",
9 | "emitDecoratorMetadata": true,
10 | "experimentalDecorators": true,
11 | "importHelpers": true,
12 | "inlineSourceMap": true,
13 | "module": "commonjs",
14 | "moduleResolution": "node",
15 | "noEmitOnError": false,
16 | "noFallthroughCasesInSwitch": true,
17 | "noImplicitAny": false,
18 | "noUnusedLocals": true,
19 | "noUnusedParameters": false,
20 | "pretty": true,
21 | "skipDefaultLibCheck": true,
22 | "skipLibCheck": true,
23 | "target": "es2017"
24 | },
25 | "include": ["app.ts", "app/**/*.ts", "config/**/*.ts", "test/**/*.ts", "app/**/*.json"]
26 | }
27 |
--------------------------------------------------------------------------------
/app/middleware/items/cache.ts:
--------------------------------------------------------------------------------
1 | import * as Application from 'koa';
2 | import * as session from 'koa-session';
3 | import redis from '../../lib/redis';
4 |
5 | export const clientCache = (app: Application) => {
6 | app.keys = ['sxc_rgb'];
7 | const store = {
8 | get: async (key: string) => {
9 | const res = await redis.get(key);
10 | return JSON.parse(res);
11 | },
12 | set: async (key: string, sess: any) => {
13 | const json = JSON.stringify(sess);
14 | await redis.set(key, json);
15 | },
16 | destroy: async (key: string) => {
17 | await redis.del(key);
18 | },
19 | };
20 | const CONFIG = {
21 | key: 'koa:sess',
22 | maxAge: 86400000,
23 | overwrite: true,
24 | signed: true,
25 | rolling: false,
26 | store,
27 | };
28 |
29 | app.use(session(CONFIG, app));
30 | };
31 |
--------------------------------------------------------------------------------
/front_end/scripts/test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Do this as the first thing so that any code reading it knows the right env.
4 | process.env.BABEL_ENV = 'test';
5 | process.env.NODE_ENV = 'test';
6 | process.env.PUBLIC_URL = '';
7 |
8 | // Makes the script crash on unhandled rejections instead of silently
9 | // ignoring them. In the future, promise rejections that are not handled will
10 | // terminate the Node.js process with a non-zero exit code.
11 | process.on('unhandledRejection', err => {
12 | throw err;
13 | });
14 |
15 | // Ensure environment variables are read.
16 | require('../config/env');
17 |
18 | const jest = require('jest');
19 | const argv = process.argv.slice(2);
20 |
21 | // Watch unless on CI or in coverage mode
22 | if (!process.env.CI && argv.indexOf('--coverage') < 0) {
23 | argv.push('--watch');
24 | }
25 |
26 |
27 | jest.run(argv);
28 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tslint:latest",
3 | "rules": {
4 | "quotemark": [true, "single", "jsx-double"],
5 | "no-console": false,
6 | "space-before-function-paren": false,
7 | "interface-name": [true, "no-prefix"],
8 | "adjacent-overload-signatures": true,
9 | "member-access": [false],
10 | "member-ordering": [
11 | true,
12 | {
13 | "order": "fields-first"
14 | }
15 | ],
16 | "object-literal-sort-keys": false,
17 | "max-classes-per-file": [true, 10],
18 | "variable-name": [true, "allow-leading-underscore"],
19 | "align": [true, "statements"],
20 | "no-reference": false,
21 | "no-this-assignment": [true, {"allowed-names": ["^self$"], "allow-destructuring": true}],
22 | "no-var-requires": false,
23 | "max-line-length": [true, 140],
24 | "no-submodule-imports": false
25 |
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/graphql/remotes/index.ts:
--------------------------------------------------------------------------------
1 | import { createApolloFetch } from 'apollo-fetch';
2 | import * as Promise from 'bluebird';
3 | import {
4 | introspectSchema,
5 | makeRemoteExecutableSchema,
6 | } from 'graphql-tools';
7 | import * as _ from 'lodash';
8 | import config from '../../config';
9 | import logger from '../../utils/logger';
10 |
11 | export default async () => {
12 | if (config.graphql && !_.isEmpty(config.graphql.remotes)) {
13 | const result = Promise.map(config.graphql.remotes, (async (uri: string) => {
14 | logger.info(`loading remote schema from { ${uri} }`);
15 | const fetcher = createApolloFetch({ uri });
16 | const schema = makeRemoteExecutableSchema({
17 | schema: await introspectSchema(fetcher),
18 | fetcher,
19 | });
20 | return schema;
21 | }));
22 | return result;
23 | } else {
24 | return [];
25 | }
26 | };
27 |
--------------------------------------------------------------------------------
/front_end/config/polyfills.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (typeof Promise === 'undefined') {
4 | // Rejection tracking prevents a common issue where React gets into an
5 | // inconsistent state due to an error, but it gets swallowed by a Promise,
6 | // and the user has no idea what causes React's erratic future behavior.
7 | require('promise/lib/rejection-tracking').enable();
8 | window.Promise = require('promise/lib/es6-extensions.js');
9 | }
10 |
11 | // fetch() polyfill for making API calls.
12 | require('whatwg-fetch');
13 |
14 | // Object.assign() is commonly used with React.
15 | // It will use the native implementation if it's present and isn't buggy.
16 | Object.assign = require('object-assign');
17 |
18 | // In tests, polyfill requestAnimationFrame since jsdom doesn't provide it yet.
19 | // We don't polyfill it in the browser--this is user's responsibility.
20 | if (process.env.NODE_ENV === 'test') {
21 | require('raf').polyfill(global);
22 | }
23 |
--------------------------------------------------------------------------------
/app/graphql/projects/article/resolver.ts:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | Query: {
4 | articles: async (root, args, context) => {
5 | const result = await context.model.ArticleModel.findAll();
6 | return result;
7 | },
8 | article: async (root, { title }: { title: string }, context) => {
9 | const result = await context.model.ArticleModel.findByTitle(title);
10 | return result;
11 | },
12 | },
13 | Article: {
14 | author: async ({ authorId }: { authorId: number }, args, context) => {
15 | const result = await context.model.UserModel.findById(authorId);
16 | return result;
17 | },
18 | comments: async ({ commentIds }: { commentIds: [number] }, args, context) => {
19 | const result = await context.model.CommentModel.getByIds(commentIds);
20 | return result;
21 | },
22 | },
23 | Mutation: {
24 | addArticle: async (root, {article}: {article: any}, context) => {
25 | const result = await context.model.ArticleModel.addArticle(article);
26 | return result;
27 | },
28 | },
29 | };
30 |
--------------------------------------------------------------------------------
/app/graphql/common/scalars/JSON.ts:
--------------------------------------------------------------------------------
1 | import { GraphQLScalarType, Kind } from 'graphql';
2 |
3 | function identity(value) {
4 | return value;
5 | }
6 |
7 | function parseLiteral(ast) {
8 | switch (ast.kind) {
9 | case Kind.STRING:
10 | case Kind.BOOLEAN:
11 | return ast.value;
12 | case Kind.INT:
13 | case Kind.FLOAT:
14 | return parseFloat(ast.value);
15 | case Kind.OBJECT: {
16 | const value = Object.create(null);
17 | ast.fields.forEach((field) => {
18 | value[field.name.value] = parseLiteral(field.value);
19 | });
20 |
21 | return value;
22 | }
23 | case Kind.LIST:
24 | return ast.values.map(parseLiteral);
25 | default:
26 | return null;
27 | }
28 | }
29 |
30 | export default new GraphQLScalarType({
31 | name: 'JSON',
32 | description:
33 | 'The `JSON` scalar type represents JSON values as specified by ' +
34 | '[ECMA-404](http://www.ecma-international.org/' +
35 | 'publications/files/ECMA-ST/ECMA-404.pdf).',
36 | serialize: identity,
37 | parseValue: identity,
38 | parseLiteral,
39 | });
40 |
--------------------------------------------------------------------------------
/app/connector/index.ts:
--------------------------------------------------------------------------------
1 |
2 | // import * as fs from 'fs';
3 | // import { Description } from 'graphql-decorators';
4 | import * as glob from 'glob';
5 | import { Context } from 'koa';
6 | import * as path from 'path';
7 | import * as R from 'ramda';
8 | import logger from '../utils/logger';
9 |
10 | const { resolve } = path;
11 | const SYMBOL_CONNECTOR_CLASS = Symbol('Application#Context#connector');
12 |
13 | export const loadConnectors = (context: Context): void => {
14 | try {
15 | logger.info('loading connectors');
16 | const baseDir = resolve(__dirname, './projects/');
17 | const pattern = baseDir + '/**/index.ts';
18 | const g = new glob.Glob(pattern, {
19 | mark: true,
20 | sync: true,
21 | });
22 | Object.defineProperty(context, 'connector', {
23 | get() {
24 | if (!this[SYMBOL_CONNECTOR_CLASS]) {
25 | let connectorsMap: any = {};
26 | R.map(R.compose(
27 | (connectorss: object) => {
28 | connectorsMap = R.merge(connectorsMap, connectorss);
29 | },
30 | require,
31 | ))(g.found);
32 | this[SYMBOL_CONNECTOR_CLASS] = connectorsMap;
33 | }
34 | return this[SYMBOL_CONNECTOR_CLASS];
35 | },
36 | });
37 | } catch (error) {
38 | logger.error(error);
39 | throw error;
40 | }
41 | };
42 |
--------------------------------------------------------------------------------
/app/index.ts:
--------------------------------------------------------------------------------
1 | // import fs from 'fs'
2 | // import * as Koa from 'koa';
3 | import { Context } from 'koa';
4 | import { resolve } from 'path';
5 | import 'reflect-metadata';
6 | import { createKoaServer } from 'routing-controllers';
7 | import conf from './config';
8 | import { loadConnectors } from './connector';
9 | import {
10 | BlogConnection,
11 | InfoConnection,
12 | } from './database/connections';
13 | import { loadSchemasAndModels } from './graphql';
14 | import loadMiddlewares from './middleware';
15 | import Logger from './utils/logger';
16 |
17 | // load routes
18 | const app = createKoaServer({
19 | cors: {},
20 | controllers: [resolve(__dirname, './routes/*.js')],
21 | });
22 |
23 | (async () => {
24 | try {
25 | Logger.info('create db connections');
26 | const dBConnection = new InfoConnection();
27 | await dBConnection.initDB();
28 | const blogConnection = new BlogConnection();
29 | await blogConnection.initDB();
30 | } catch (err) {
31 | Logger.error(err);
32 | throw err;
33 | }
34 |
35 | loadMiddlewares(app);
36 | loadConnectors(app.context);
37 | await loadSchemasAndModels(app.context);
38 | app.use(async (ctx: Context) => {
39 | ctx.status = 200;
40 | });
41 |
42 | // const { errorHandler } = require('./lib/error');
43 |
44 | // app.on('error', errorHandler);
45 | app.listen(conf.port, conf.host);
46 | Logger.log('100', 'green', '服务启动: http://' + conf.host + ':' + conf.port);
47 | })();
48 |
--------------------------------------------------------------------------------
/app/database/connections/blog.ts:
--------------------------------------------------------------------------------
1 | import * as mongoose from 'mongoose';
2 | import config from '../../config';
3 | import Logger from '../../utils/logger';
4 |
5 | require('mongoose').Promise = Promise;
6 |
7 | export default class ConnTrack {
8 | static connInst: ConnTrack = null;
9 |
10 | conn: mongoose.Connection;
11 |
12 | constructor () {
13 | this.conn = mongoose.createConnection(config.dataSources.dbBlog.uri, config.dataSources.dbBlog.options);
14 | }
15 |
16 | static getConn () {
17 | if (ConnTrack.connInst) {
18 | return ConnTrack.connInst.conn;
19 | } else {
20 | ConnTrack.connInst = new ConnTrack();
21 | return ConnTrack.connInst.conn;
22 | }
23 | }
24 |
25 | async initDB () {
26 | return new Promise((resolve, reject) => {
27 | if (!this.conn) {
28 | this.conn = mongoose.createConnection(config.dataSources.dbBlog.uri, config.dataSources.dbBlog.options);
29 | }
30 |
31 | if (config.env === 'development') {
32 | mongoose.set('debug', true);
33 | }
34 |
35 | this.conn.on('disconnected', () => {
36 | mongoose.connect(config.dataSources.dbBlog.uri);
37 | });
38 |
39 | this.conn.on('error', (err) => {
40 | reject(err);
41 | });
42 |
43 | this.conn.on('open', () => {
44 | resolve(this.conn);
45 | });
46 |
47 | this.conn.once('open', () => {
48 | Logger.info('Connected to MongoDB', config.dataSources.dbBlog.uri);
49 | });
50 | });
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/database/connections/info.ts:
--------------------------------------------------------------------------------
1 | import { Connection } from 'mongoose';
2 | import * as mongoose from 'mongoose';
3 | import config from '../../config';
4 | import Logger from '../../utils/logger';
5 |
6 | require('mongoose').Promise = Promise;
7 |
8 | export default class ConnDB {
9 | static connInst: ConnDB = null;
10 |
11 | conn: Connection;
12 |
13 | constructor () {
14 | this.conn = mongoose.createConnection(config.dataSources.dbInfo.uri, config.dataSources.dbInfo.options);
15 | }
16 |
17 | static getConn () {
18 | if (ConnDB.connInst) {
19 | return ConnDB.connInst.conn;
20 | } else {
21 | ConnDB.connInst = new ConnDB();
22 | return ConnDB.connInst.conn;
23 | }
24 | }
25 |
26 | async initDB () {
27 | return new Promise((resolve, reject) => {
28 | if (!this.conn) {
29 | this.conn = mongoose.createConnection(config.dataSources.dbInfo.uri, config.dataSources.dbInfo.options);
30 | }
31 |
32 | if (config.env === 'development') {
33 | mongoose.set('debug', true);
34 | }
35 |
36 | this.conn.on('disconnected', () => {
37 | mongoose.connect(config.dataSources.dbInfo.uri);
38 | });
39 |
40 | this.conn.on('error', (err) => {
41 | reject(err);
42 | });
43 |
44 | this.conn.on('open', () => {
45 | resolve(this.conn);
46 | });
47 |
48 | this.conn.once('open', () => {
49 | Logger.info('Connected to MongoDB', config.dataSources.dbInfo.uri);
50 | });
51 | });
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app/graphql/projects/comment/model.ts:
--------------------------------------------------------------------------------
1 | import { Context } from 'koa';
2 | import BaseModel from '../../base_model';
3 | import DataLoader from '../../data_loader';
4 | export default class CommentModel extends BaseModel {
5 | dataLoader: DataLoader