forked from cerc-io/snowballtools-base
Implement GraphQL server setup (#16)
* Set up gql server * Get config data from environment file
This commit is contained in:
committed by
Ashwin Phatak
parent
ea3addfd61
commit
f287929e94
@@ -0,0 +1,4 @@
|
||||
[server]
|
||||
host = "127.0.0.1"
|
||||
port = 8000
|
||||
gqlPath = "/graphql"
|
||||
@@ -4,22 +4,28 @@
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/debug": "^4.1.5",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/node": "^20.11.0",
|
||||
"@types/debug": "^4.1.5",
|
||||
"apollo-server-core": "^3.13.0",
|
||||
"apollo-server-express": "^3.13.0",
|
||||
"express": "^4.18.2",
|
||||
"fs-extra": "^11.2.0",
|
||||
"graphql": "^16.8.1",
|
||||
"reflect-metadata": "^0.2.1",
|
||||
"toml": "^3.0.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typeorm": "^0.3.19",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "DEBUG=snowball:* ts-node ./src/server.ts",
|
||||
"start": "DEBUG=snowball:* ts-node ./src/index.ts",
|
||||
"lint": "eslint .",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@typescript-eslint/eslint-plugin": "^6.18.1",
|
||||
"@typescript-eslint/parser": "^6.18.1",
|
||||
"better-sqlite3": "^9.2.2",
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import 'reflect-metadata';
|
||||
import debug from 'debug';
|
||||
|
||||
import { initializeDatabase } from './database';
|
||||
import { createAndStartServer } from './server';
|
||||
import { createResolvers } from './resolver';
|
||||
import { typeDefs } from './schema';
|
||||
import { getConfig } from './utils';
|
||||
import { Config } from './type';
|
||||
|
||||
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);
|
||||
|
||||
await initializeDatabase();
|
||||
await createAndStartServer(typeDefs, createResolvers, server);
|
||||
};
|
||||
|
||||
main()
|
||||
.then(() => {
|
||||
log('Starting server...');
|
||||
})
|
||||
.catch((err) => {
|
||||
log(err);
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
const user = {
|
||||
id: 2
|
||||
};
|
||||
|
||||
export const createResolvers = async (): Promise<any> => {
|
||||
return {
|
||||
Query: {
|
||||
// TODO: fetch user data from db
|
||||
getUser: () => user
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
export const typeDefs = /* GraphQL */ `
|
||||
type User {
|
||||
id: Int
|
||||
}
|
||||
|
||||
type Query {
|
||||
getUser: User
|
||||
}
|
||||
`;
|
||||
@@ -1,30 +1,59 @@
|
||||
import express, { Request, Response } from 'express';
|
||||
import 'reflect-metadata';
|
||||
import debug from 'debug';
|
||||
import express from 'express';
|
||||
import { ApolloServer } from 'apollo-server-express';
|
||||
import { createServer } from 'http';
|
||||
import {
|
||||
ApolloServerPluginDrainHttpServer,
|
||||
ApolloServerPluginLandingPageLocalDefault
|
||||
} from 'apollo-server-core';
|
||||
|
||||
import { initializeDatabase } from './database';
|
||||
import { TypeSource } from '@graphql-tools/utils';
|
||||
import { makeExecutableSchema } from '@graphql-tools/schema';
|
||||
|
||||
import { ServerConfig } from './type';
|
||||
|
||||
const log = debug('snowball:server');
|
||||
|
||||
export const main = async (): Promise<void> => {
|
||||
await initializeDatabase();
|
||||
const DEFAULT_GQL_PATH = '/graphql';
|
||||
|
||||
export const createAndStartServer = async (
|
||||
typeDefs: TypeSource,
|
||||
resolvers: any,
|
||||
serverConfig: ServerConfig
|
||||
): Promise<ApolloServer> => {
|
||||
const { host, port, gqlPath = DEFAULT_GQL_PATH } = serverConfig;
|
||||
|
||||
const app = express();
|
||||
const port = 8080;
|
||||
|
||||
app.get('/', (req: Request, res: Response) => {
|
||||
res.send('Hello, TypeScript Express Server!');
|
||||
// Create HTTP server
|
||||
const httpServer = createServer(app);
|
||||
|
||||
// Create the schema
|
||||
const schema = makeExecutableSchema({
|
||||
typeDefs,
|
||||
resolvers: await resolvers()
|
||||
});
|
||||
|
||||
app.listen(port, () => {
|
||||
log(`Server is running at http://localhost:${port}`);
|
||||
const server = new ApolloServer({
|
||||
schema,
|
||||
csrfPrevention: true,
|
||||
plugins: [
|
||||
// Proper shutdown for the HTTP server
|
||||
ApolloServerPluginDrainHttpServer({ httpServer }),
|
||||
ApolloServerPluginLandingPageLocalDefault({ embed: true })
|
||||
]
|
||||
});
|
||||
|
||||
await server.start();
|
||||
|
||||
server.applyMiddleware({
|
||||
app,
|
||||
path: gqlPath
|
||||
});
|
||||
|
||||
httpServer.listen(port, host, () => {
|
||||
log(`Server is listening on ${host}:${port}${server.graphqlPath}`);
|
||||
});
|
||||
|
||||
return server;
|
||||
};
|
||||
|
||||
main()
|
||||
.then(() => {
|
||||
log('Starting server...');
|
||||
})
|
||||
.catch((err) => {
|
||||
log(err);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
export interface ServerConfig {
|
||||
host: string;
|
||||
port: number;
|
||||
gqlPath?: string;
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
server: ServerConfig;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import toml from 'toml';
|
||||
import debug from 'debug';
|
||||
|
||||
const log = debug('snowball:utils');
|
||||
|
||||
export const getConfig = async <ConfigType>(
|
||||
configFile: string
|
||||
): Promise<ConfigType> => {
|
||||
const configFilePath = path.resolve(configFile);
|
||||
const fileExists = await fs.pathExists(configFilePath);
|
||||
if (!fileExists) {
|
||||
throw new Error(`Config file not found: ${configFilePath}`);
|
||||
}
|
||||
|
||||
const config = toml.parse(await fs.readFile(configFilePath, 'utf8'));
|
||||
log('config', JSON.stringify(config, null, 2));
|
||||
|
||||
return config;
|
||||
};
|
||||
Reference in New Issue
Block a user