Clean up and autogenerate TS from GQL

This commit is contained in:
Amit Jakubowicz 2019-01-31 13:18:26 +00:00
parent ac4d30ecdf
commit 33b0e8313c
14 changed files with 1093 additions and 292 deletions

11
server/codegen.yml Normal file
View File

@ -0,0 +1,11 @@
schema: src/schema.graphql
overwrite: true
generates:
./src/types.gen.d.ts:
config:
noNamespace: true
fieldResolverNamePrefix: Field
plugins:
- typescript-common
- typescript-server
- typescript-resolvers

View File

@ -1,6 +1,7 @@
{
"name": "functions",
"scripts": {
"codegen": "gql-gen",
"lint": "tslint --project tsconfig.json",
"build": "tsc --version && tsc",
"start": "ts-node src/index.ts"
@ -44,10 +45,14 @@
"@types/joi": "^13.0.8",
"@types/node": "^9.6.1",
"@types/node-fetch": "^2.1.1",
"graphql-code-generator": "^0.16.0",
"graphql-codegen-typescript-common": "^0.16.0",
"graphql-codegen-typescript-resolvers": "^0.16.0",
"graphql-codegen-typescript-server": "^0.16.0",
"ts-jest": "23.10.3",
"ts-node": "^7.0.1",
"tslint": "^5.9.1",
"typescript": "^3.1.1"
"typescript": "^3.2.4"
},
"jest": {
"moduleFileExtensions": [

View File

@ -3,13 +3,6 @@ import {User} from "../types";
import UserManager from "../user";
import SessionManager from "../session";
interface AuthQueryResolvers {
}
interface AuthMutationResolvers {
}
export default class AuthResolvers {
userManager: UserManager
repository: Repository

View File

@ -1,5 +1,4 @@
import {auth} from 'google-auth-library';
import Repository from "../repository";
import {OAuth2Client} from "google-auth-library/build/src/auth/oauth2client";
import {atob} from 'atob';
import {CalendarEvent} from "../types";

View File

@ -1,74 +0,0 @@
import {Request, Response} from "express";
import CalendarManager from './calendar';
import SessionManager from "./session";
import {AuthenticatedRequest, authRequest} from "./authRequest";
import {CalendarEvent} from "./types";
import EventManager from "./event";
let sessionManager: SessionManager, calendarManager: CalendarManager, eventManager: EventManager
export type Dependencies = {
sessionManager: SessionManager
calendarManager: CalendarManager,
eventManager: EventManager,
}
export const setDependencies = (dependencies: Dependencies) => {
sessionManager = dependencies.sessionManager
calendarManager = dependencies.calendarManager
eventManager = dependencies.eventManager
}
export const getEvents = async (req: Request, res: Response) => {
let result
try {
result = await calendarManager.listEvents()
} catch (e) {
console.log('Caught error while listing events', e)
res.status(500)
res.send('Error fetching events')
}
res.send(result)
res.status(200)
}
export const postEvent = async (req: Request, res: Response) => {
await authRequest(sessionManager)(req, res)
const session = (req as AuthenticatedRequest).session
if (!session.isValid) {
res.send('Session expired')
res.sendStatus(401)
}
const eventData = req.body as CalendarEvent
eventData.owner = session.userId
const validationError = eventManager.getValidationErrors({
...req.body,
owner: session.userId,
})
if (!validationError) {
console.log('Validation succeeded for event', eventData)
const dbEvent = await eventManager.createEvent(eventData)
console.log('event created with id', dbEvent.id)
res.send({eventId: dbEvent.id})
res.sendStatus(200)
} else {
console.warn('Bad request coming in', eventData, validationError)
res.status(400)
res.send(validationError)
}
return
}
export const events = async (req: Request, res: Response) => {
let delegationHandler
if (req.method === 'GET') {
delegationHandler = getEvents
} else if (req.method === 'POST') {
delegationHandler = postEvent
} else {
res.sendStatus(400)
return
}
delegationHandler(req, res)
}

View File

@ -1,12 +1,3 @@
import {
setDependencies as setUserHandlerDependencies,
} from './userHandlers'
import {
events as eventsHandler,
setDependencies as setEventsHandlerDependencies
} from './eventHandlers';
import {gcal as gcalConfig, projectId} from "./config";
import UserManager from "./user";
import SessionManager from "./session";
@ -29,13 +20,6 @@ async function start() {
})
const eventManager = new EventManager({calendarManager, eventsRepository})
setUserHandlerDependencies({
userManager, sessionManager
})
setEventsHandlerDependencies({
sessionManager, calendarManager, eventManager
})
const gql = new GraphQLInterface({
repository,
userManager,

View File

@ -3,7 +3,7 @@
const randomstring = require('random-string')
import {sendEmail} from './post_office'
import {domain} from './config'
import { Repository } from './repository'
import Repository from './repository'
import {DBEntity, User} from "./types";
export class SessionAlreadyValidatedError extends Error {}

View File

@ -1,4 +1,4 @@
import Repository from './mongorepo'
import Repository from './repository'
import {User, UserKeys, UserProperties} from './types'
export default class UserManager {

View File

@ -1,150 +0,0 @@
import {parse} from 'url'
import UserManager from './user'
import {Request, Response} from 'express'
import SessionManager, {Session, SessionAlreadyValidatedError, SessionRequest} from './session'
import {UserProperties} from './types'
let userManager, sessionManager
export type Dependencies = {
userManager: UserManager,
sessionManager: SessionManager
}
export const setDependencies = (dependencies) => {
userManager = dependencies.userManager
sessionManager = dependencies.sessionManager
}
export const isUserAvailable = async (req: Request, res: Response) => {
const params = parse(req.url, true).query
const user = await userManager.getUser({
email: params.email as string,
username: params.username as string
})
res.send({
exists: !!user
});
return true
}
const handleSignup = (async (req: Request, res: Response) => {
const {username, email, firstName, lastName} = req.body
const userProperties: UserProperties = {username, email, firstName, lastName}
let newUser
const userKeys = {
username, email, name
}
try {
console.log(`Will try to create new user ${userKeys}`)
newUser = await userManager.createUser(userKeys)
} catch (e) {
console.error('Error creating new user', userKeys, e)
res.status(409)
res.send(e.message)
return
}
if (!newUser) {
res.status(409)
res.send(`Could not create user: ${JSON.stringify(userProperties)}`)
return
}
console.log('User created', JSON.stringify(newUser))
res.status(200)
res.send('User created. Invitation will be sent.')
try {
await sessionManager.inviteUser(newUser)
} catch (e) {
res.status(500)
res.send(`Error sending invitation. ${e.message}`)
console.error('Error sending invitation', e)
}
})
export const signup = async (req: Request, res: Response) => {
try {
await handleSignup(req, res)
} catch (e) {
console.error('Signup handle error', e)
res.send('Signup handle error')
throw e
}
}
const handleSignin = async (req: Request, res: Response) => {
const params = req.body
const ip = req.ip.split('.').map(num => parseInt(num))
console.log('Got sign in request with params', JSON.stringify(params))
let session = null
try {
session = await sessionManager.initiateSession({
hash: params.hash as string,
ipAddress: ip,
userAgent: req.headers['user-agent'],
} as SessionRequest)
} catch (e) {
if (e instanceof SessionAlreadyValidatedError) {
res.status(401)
res.send('Session already validated')
return
}
}
if (!session) {
res.status(403)
res.send('Could not initiate session with the given data')
return
}
console.log('Session initiated', JSON.stringify(session))
res.status(200)
res.setHeader('set-cookie', `__session=${session.hash}; Secure;`)
res.send(`Session initiated: ${JSON.stringify(session)}`)
}
export const signin = async (req: Request, res: Response) => {
try {
console.log('Will handle signin request')
await handleSignin(req, res)
} catch (e) {
console.error('Sign-in handle error', e)
res.send('Sign-in handle error')
res.status(500)
throw e
}
}
const handlePostSession = async (req: Request, res: Response) => {
const { email } = req.body
console.log('Will request new session for email: ', email)
const user = await userManager.getUser({email})
if (!user) {
res.status(404)
res.send('Could not find user')
return
}
await sessionManager.inviteUser(user)
res.status(200)
res.send('Invitation sent to email')
}
export const postSession = async (req: Request, res: Response) => {
try {
await handlePostSession(req, res)
} catch (e) {
console.error('Error in request new session for existing user', e)
res.send('Request session error')
res.status(500)
throw e
}
}

View File

@ -1,6 +1,6 @@
{
"compilerOptions": {
"lib": ["es6", "dom"],
"lib": ["es2015", "esnext.asynciterable"],
"module": "commonjs",
"noImplicitReturns": true,
"outDir": "lib",

View File

@ -107,9 +107,6 @@
// Warns if function overloads could be unified into a single function with optional or rest parameters.
"unified-signatures": {"severity": "warning"},
// Warns if code has an import or variable that is unused.
"no-unused-variable": {"severity": "warning"},
// Prefer const for values that will not change. This better documents code.
"prefer-const": {"severity": "warning"},

View File

@ -10,4 +10,4 @@
"exclude": [
"node_modules"
]
}
}

View File

@ -1,6 +1,6 @@
{
"extends": [
"tslint:recommended",
"tslint:recommended"
],
"linterOptions": {
"exclude": [

1106
yarn.lock

File diff suppressed because it is too large Load Diff