Refactor database setup and add user context to GQL requests (#17)
* Add context to each request * Implement get user db query * Move constants to a separate file * Refactor database init method
This commit is contained in:
parent
4d00cfb8f0
commit
e4c099f8c3
@ -2,3 +2,6 @@
|
||||
host = "127.0.0.1"
|
||||
port = 8000
|
||||
gqlPath = "/graphql"
|
||||
|
||||
[database]
|
||||
dbPath = "db/snowball"
|
||||
|
@ -4,6 +4,11 @@ export interface ServerConfig {
|
||||
gqlPath?: string;
|
||||
}
|
||||
|
||||
export interface DatabaseConfig {
|
||||
dbPath: string;
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
server: ServerConfig;
|
||||
database: DatabaseConfig;
|
||||
}
|
4
packages/backend/src/constants.ts
Normal file
4
packages/backend/src/constants.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export const DEFAULT_GQL_PATH = '/graphql';
|
||||
|
||||
// Note: temporary hardcoded user, later to be derived from auth token
|
||||
export const USER_ID = 1;
|
@ -2,23 +2,35 @@ import { DataSource } from 'typeorm';
|
||||
import path from 'path';
|
||||
import debug from 'debug';
|
||||
|
||||
const log = debug('snowball:server');
|
||||
import { User } from './entity/User';
|
||||
import { DatabaseConfig } from './config';
|
||||
|
||||
export const initializeDatabase = async (
|
||||
database: string = 'db/snowball'
|
||||
): Promise<void> => {
|
||||
try {
|
||||
const AppDataSource = new DataSource({
|
||||
const log = debug('snowball:database');
|
||||
|
||||
export class Database {
|
||||
private dataSource: DataSource;
|
||||
|
||||
constructor ({ dbPath }: DatabaseConfig) {
|
||||
this.dataSource = new DataSource({
|
||||
type: 'better-sqlite3',
|
||||
database,
|
||||
database: dbPath,
|
||||
entities: [path.join(__dirname, '/entity/*')],
|
||||
synchronize: true,
|
||||
logging: false
|
||||
});
|
||||
|
||||
await AppDataSource.initialize();
|
||||
log('database initialized');
|
||||
} catch (error) {
|
||||
log(error);
|
||||
}
|
||||
};
|
||||
|
||||
async init () : Promise<void> {
|
||||
await this.dataSource.initialize();
|
||||
log('database initialized');
|
||||
}
|
||||
|
||||
async getUser (userId: number) : Promise<User | null> {
|
||||
const userRepository = this.dataSource.getRepository(User);
|
||||
const user = await userRepository.findOneBy({
|
||||
id: userId
|
||||
});
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
|
@ -3,22 +3,26 @@ import debug from 'debug';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import { initializeDatabase } from './database';
|
||||
import { Database } from './database';
|
||||
import { createAndStartServer } from './server';
|
||||
import { createResolvers } from './resolvers';
|
||||
import { getConfig } from './utils';
|
||||
import { Config } from './type';
|
||||
import { Config } from './config';
|
||||
|
||||
const log = debug('snowball:server');
|
||||
const configFilePath = 'environments/local.toml';
|
||||
|
||||
export const main = async (): Promise<void> => {
|
||||
// TODO: get config path using cli
|
||||
const { server } = await getConfig<Config>(configFilePath);
|
||||
const { server, database } = await getConfig<Config>(configFilePath);
|
||||
|
||||
const db = new Database(database);
|
||||
await db.init();
|
||||
|
||||
await initializeDatabase();
|
||||
const typeDefs = fs.readFileSync(path.join(__dirname, 'schema.gql')).toString();
|
||||
await createAndStartServer(typeDefs, createResolvers, server);
|
||||
const resolvers = await createResolvers(db);
|
||||
|
||||
await createAndStartServer(typeDefs, resolvers, server);
|
||||
};
|
||||
|
||||
main()
|
||||
|
@ -1,12 +1,16 @@
|
||||
const user = {
|
||||
id: 2
|
||||
};
|
||||
import { Database } from './database';
|
||||
|
||||
export const createResolvers = async (): Promise<any> => {
|
||||
export const createResolvers = async (db: Database): Promise<any> => {
|
||||
return {
|
||||
Query: {
|
||||
// TODO: fetch user data from db
|
||||
user: () => user
|
||||
user: (
|
||||
_: any,
|
||||
__: any,
|
||||
// TODO: add custom type for context
|
||||
context: any
|
||||
) => {
|
||||
return db.getUser(context.userId);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -10,12 +10,11 @@ import {
|
||||
import { TypeSource } from '@graphql-tools/utils';
|
||||
import { makeExecutableSchema } from '@graphql-tools/schema';
|
||||
|
||||
import { ServerConfig } from './type';
|
||||
import { ServerConfig } from './config';
|
||||
import { DEFAULT_GQL_PATH, USER_ID } from './constants';
|
||||
|
||||
const log = debug('snowball:server');
|
||||
|
||||
const DEFAULT_GQL_PATH = '/graphql';
|
||||
|
||||
export const createAndStartServer = async (
|
||||
typeDefs: TypeSource,
|
||||
resolvers: any,
|
||||
@ -31,12 +30,16 @@ export const createAndStartServer = async (
|
||||
// Create the schema
|
||||
const schema = makeExecutableSchema({
|
||||
typeDefs,
|
||||
resolvers: await resolvers()
|
||||
resolvers
|
||||
});
|
||||
|
||||
const server = new ApolloServer({
|
||||
schema,
|
||||
csrfPrevention: true,
|
||||
context: () => {
|
||||
// TODO: Use userId derived from auth token
|
||||
return { userId: USER_ID };
|
||||
},
|
||||
plugins: [
|
||||
// Proper shutdown for the HTTP server
|
||||
ApolloServerPluginDrainHttpServer({ httpServer }),
|
||||
|
Loading…
Reference in New Issue
Block a user