forked from cerc-io/snowballtools-base
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"
|
host = "127.0.0.1"
|
||||||
port = 8000
|
port = 8000
|
||||||
gqlPath = "/graphql"
|
gqlPath = "/graphql"
|
||||||
|
|
||||||
|
[database]
|
||||||
|
dbPath = "db/snowball"
|
||||||
|
@ -4,6 +4,11 @@ export interface ServerConfig {
|
|||||||
gqlPath?: string;
|
gqlPath?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DatabaseConfig {
|
||||||
|
dbPath: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Config {
|
export interface Config {
|
||||||
server: ServerConfig;
|
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 path from 'path';
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
|
|
||||||
const log = debug('snowball:server');
|
import { User } from './entity/User';
|
||||||
|
import { DatabaseConfig } from './config';
|
||||||
|
|
||||||
export const initializeDatabase = async (
|
const log = debug('snowball:database');
|
||||||
database: string = 'db/snowball'
|
|
||||||
): Promise<void> => {
|
export class Database {
|
||||||
try {
|
private dataSource: DataSource;
|
||||||
const AppDataSource = new DataSource({
|
|
||||||
|
constructor ({ dbPath }: DatabaseConfig) {
|
||||||
|
this.dataSource = new DataSource({
|
||||||
type: 'better-sqlite3',
|
type: 'better-sqlite3',
|
||||||
database,
|
database: dbPath,
|
||||||
entities: [path.join(__dirname, '/entity/*')],
|
entities: [path.join(__dirname, '/entity/*')],
|
||||||
synchronize: true,
|
synchronize: true,
|
||||||
logging: false
|
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 fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
import { initializeDatabase } from './database';
|
import { Database } from './database';
|
||||||
import { createAndStartServer } from './server';
|
import { createAndStartServer } from './server';
|
||||||
import { createResolvers } from './resolvers';
|
import { createResolvers } from './resolvers';
|
||||||
import { getConfig } from './utils';
|
import { getConfig } from './utils';
|
||||||
import { Config } from './type';
|
import { Config } from './config';
|
||||||
|
|
||||||
const log = debug('snowball:server');
|
const log = debug('snowball:server');
|
||||||
const configFilePath = 'environments/local.toml';
|
const configFilePath = 'environments/local.toml';
|
||||||
|
|
||||||
export const main = async (): Promise<void> => {
|
export const main = async (): Promise<void> => {
|
||||||
// TODO: get config path using cli
|
// 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();
|
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()
|
main()
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
const user = {
|
import { Database } from './database';
|
||||||
id: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createResolvers = async (): Promise<any> => {
|
export const createResolvers = async (db: Database): Promise<any> => {
|
||||||
return {
|
return {
|
||||||
Query: {
|
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 { TypeSource } from '@graphql-tools/utils';
|
||||||
import { makeExecutableSchema } from '@graphql-tools/schema';
|
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 log = debug('snowball:server');
|
||||||
|
|
||||||
const DEFAULT_GQL_PATH = '/graphql';
|
|
||||||
|
|
||||||
export const createAndStartServer = async (
|
export const createAndStartServer = async (
|
||||||
typeDefs: TypeSource,
|
typeDefs: TypeSource,
|
||||||
resolvers: any,
|
resolvers: any,
|
||||||
@ -31,12 +30,16 @@ export const createAndStartServer = async (
|
|||||||
// Create the schema
|
// Create the schema
|
||||||
const schema = makeExecutableSchema({
|
const schema = makeExecutableSchema({
|
||||||
typeDefs,
|
typeDefs,
|
||||||
resolvers: await resolvers()
|
resolvers
|
||||||
});
|
});
|
||||||
|
|
||||||
const server = new ApolloServer({
|
const server = new ApolloServer({
|
||||||
schema,
|
schema,
|
||||||
csrfPrevention: true,
|
csrfPrevention: true,
|
||||||
|
context: () => {
|
||||||
|
// TODO: Use userId derived from auth token
|
||||||
|
return { userId: USER_ID };
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
// Proper shutdown for the HTTP server
|
// Proper shutdown for the HTTP server
|
||||||
ApolloServerPluginDrainHttpServer({ httpServer }),
|
ApolloServerPluginDrainHttpServer({ httpServer }),
|
||||||
|
Loading…
Reference in New Issue
Block a user