Application builds with tsc

This commit is contained in:
Amit Jakubowicz 2019-03-08 15:58:35 +01:00
parent 1e45f9fb86
commit 8e260e2e33
28 changed files with 634 additions and 1484 deletions

16
server/ormconfig.ts Normal file
View File

@ -0,0 +1,16 @@
import { ConnectionOptions } from 'typeorm'
const config: ConnectionOptions = {
type: 'postgres',
host: process.env.POSTGRES_HOST || 'localhost',
port: Number(process.env.POSTGRES_PORT || 5432),
username: process.env.POSTGRES_USER || 'admin',
password: process.env.POSTGRES_PASSWORD || 'admin',
database: process.env.POSTGRES_DB || 'gpa',
entities: [
__dirname + '/src/**/*.entity{.ts,.js}',
],
synchronize: true,
}
export default config

View File

@ -1,7 +1,7 @@
{
"name": "functions",
"scripts": {
"codegen": "gql-gen",
"codegen": "gql2ts ./src/schema.graphql -o ./src/@types/index.d.ts",
"lint": "tslint --project tsconfig.json",
"build": "tsc --version && tsc",
"start": "ts-node src/index.ts"
@ -21,12 +21,7 @@
"google-auth-library": "^1.5.0",
"googleapis": "^31.0.2",
"graphql": "^14.0.2",
"graphql-codegen-typescript-mongodb": "^0.16.0",
"graphql-code-generator": "^0.16.0",
"graphql-codegen-add": "^0.16.0",
"graphql-codegen-typescript-common": "^0.16.0",
"graphql-codegen-typescript-resolvers": "^0.16.0",
"graphql-codegen-typescript-server": "^0.16.0",
"graphql-import": "^0.7.1",
"graphql-tag": "^2.10.0",
"graphql-tools": "^4.0.3",
@ -41,6 +36,8 @@
"random-string": "^0.2.0",
"randomstring": "^1.1.5",
"superagent": "^3.8.3",
"typeorm": "^0.2.14",
"uuid": "^3.3.2",
"webpack-node-externals": "^1.7.2"
},
"devDependencies": {
@ -48,9 +45,12 @@
"@types/express": "^4.11.1",
"@types/gapi.client.calendar": "^3.0.0",
"@types/google-cloud__datastore": "^1.3.2",
"@types/jest": "^24.0.9",
"@types/joi": "^13.0.8",
"@types/node": "^9.6.1",
"@types/node-fetch": "^2.1.1",
"@types/uuid": "^3.4.4",
"gql2ts": "^1.10.1",
"ts-jest": "23.10.3",
"ts-node": "^7.0.1",
"tslint": "^5.9.1",

View File

@ -0,0 +1,20 @@
import {Session} from "../Auth/Session.entity"
export interface Context {
url: string
session: Session
req: Express.Request
}
export type GQLResolver = (
parent: any,
args: any,
context: Context,
info: any
) => any
export interface ResolverMap {
[key: string]: {
[key: string]: GQLResolver;
}
}

View File

@ -1,848 +0,0 @@
// tslint:disable
export type Maybe<T> = T | null;
export interface EventsQueryFilter {
limit?: Maybe<number>;
}
export interface SignupInput {
email: string;
username: string;
firstName: string;
lastName?: Maybe<string>;
}
export interface SigninInput {
hash: string;
}
export interface RequestInviteInput {
email: string;
}
export interface CreateEventInput {
owner: string;
time?: Maybe<EventTimeInput>;
info?: Maybe<(Maybe<EventInformationInput>)[]>;
location?: Maybe<EventLocationInput>;
meta?: Maybe<EventMetaInput>;
status: string;
contact: EventContactPersonInput[];
}
export interface EventTimeInput {
timeZone?: Maybe<TimeZone>;
status?: Maybe<EventStatus>;
start?: Maybe<Timestamp>;
end?: Maybe<Timestamp>;
}
export interface EventInformationInput {
language: string;
title: string;
description?: Maybe<string>;
}
export interface EventLocationInput {
address?: Maybe<string>;
name?: Maybe<string>;
coordinate?: Maybe<GeoCoordinateInput>;
}
export interface GeoCoordinateInput {
lat?: Maybe<number>;
lng?: Maybe<number>;
}
export interface EventMetaInput {
tags?: Maybe<(Maybe<string>)[]>;
}
export interface EventContactPersonInput {
name: string;
languages?: Maybe<Language[]>;
contact?: Maybe<Contact>;
}
export interface EventContactInput {
email?: Maybe<string>;
phone?: Maybe<string>;
}
export interface AdditionalEntityFields {
path?: Maybe<string>;
type?: Maybe<string>;
}
/** IANA Timezone e.g. "Europe/Zurich" */
export type TimeZone = any;
/** in RFC3339 e.g. 2002-10-02T10:00:00-05:00 or 2002-10-02T15:00:00Z */
export type Timestamp = any;
/** "confirmed" | "tentative" | "cancelled" */
export type EventStatus = any;
/** e.g. 'de', 'en', etc' */
export type Language = any;
export type Date = any;
// ====================================================
// Scalars
// ====================================================
// ====================================================
// Types
// ====================================================
export interface Query {
/** Auth */
me?: Maybe<User>;
/** Event */
events?: Maybe<(Maybe<CalendarEvent>)[]>;
}
export interface User {
firstName: string;
lastName?: Maybe<string>;
username: string;
email: string;
id: string;
}
export interface CalendarEvent {
id: string;
owner: User;
info: (Maybe<EventInformation>)[];
time: EventTime;
status: EventStatus;
contact: EventContactPerson[];
location: Location;
}
/** Event information for presentation */
export interface EventInformation {
language: string;
title: string;
description?: Maybe<string>;
}
export interface EventTime {
timeZone?: Maybe<TimeZone>;
start?: Maybe<Timestamp>;
end?: Maybe<Timestamp>;
recurrence?: Maybe<string>;
exceptions?: Maybe<string>;
}
export interface EventContactPerson {
name: string;
languages?: Maybe<Language[]>;
contact?: Maybe<Contact>;
}
export interface Contact {
email?: Maybe<string>;
phone?: Maybe<string>;
}
export interface Location {
address?: Maybe<string>;
name?: Maybe<string>;
coordinate?: Maybe<GeoCoordinate>;
}
export interface GeoCoordinate {
lat?: Maybe<number>;
lng?: Maybe<number>;
}
export interface Mutation {
/** Auth */
signup: boolean;
signin: UserSession;
requestInvite: boolean;
/** Event */
createEvent?: Maybe<CalendarEvent>;
}
export interface UserSession {
hash: string;
user: User;
ctime: Date;
isValid: boolean;
}
// ====================================================
// Arguments
// ====================================================
export interface EventsQueryArgs {
filter?: Maybe<EventsQueryFilter>;
}
export interface SignupMutationArgs {
input?: Maybe<SignupInput>;
}
export interface SigninMutationArgs {
input?: Maybe<SigninInput>;
}
export interface RequestInviteMutationArgs {
input?: Maybe<RequestInviteInput>;
}
export interface CreateEventMutationArgs {
input?: Maybe<CreateEventInput>;
foo?: Maybe<string>;
}
import { ObjectID } from "mongodb";
export interface UserDbObject {
firstName: string;
lastName: Maybe<string>;
username: string;
email: string;
_id: ObjectID;
}
export interface CalendarEventDbObject {
_id: ObjectID;
owner: ObjectID;
info: (Maybe<EventInformationDbObject>)[];
time: EventTime;
status: EventStatus;
contact: EventContactPersonDbObject[];
location: LocationDbObject;
}
export interface EventInformationDbObject {
language: string;
title: string;
description: Maybe<string>;
}
export interface EventContactPersonDbObject {
name: string;
languages: Maybe<LanguageDbObject[]>;
contact: Maybe<Contact>;
}
export interface UserSessionDbObject {
hash: string;
user: ObjectID;
ctime: Date;
isValid: boolean;
}
import {
GraphQLResolveInfo,
GraphQLScalarType,
GraphQLScalarTypeConfig
} from "graphql";
export type Resolver<Result, Parent = {}, Context = {}, Args = {}> = (
parent: Parent,
args: Args,
context: Context,
info: GraphQLResolveInfo
) => Promise<Result> | Result;
export interface ISubscriptionResolverObject<Result, Parent, Context, Args> {
subscribe<R = Result, P = Parent>(
parent: P,
args: Args,
context: Context,
info: GraphQLResolveInfo
): AsyncIterator<R | Result> | Promise<AsyncIterator<R | Result>>;
resolve?<R = Result, P = Parent>(
parent: P,
args: Args,
context: Context,
info: GraphQLResolveInfo
): R | Result | Promise<R | Result>;
}
export type SubscriptionResolver<
Result,
Parent = {},
Context = {},
Args = {}
> =
| ((
...args: any[]
) => ISubscriptionResolverObject<Result, Parent, Context, Args>)
| ISubscriptionResolverObject<Result, Parent, Context, Args>;
export type TypeResolveFn<Types, Parent = {}, Context = {}> = (
parent: Parent,
context: Context,
info: GraphQLResolveInfo
) => Maybe<Types>;
export type NextResolverFn<T> = () => Promise<T>;
export type DirectiveResolverFn<TResult, TArgs = {}, TContext = {}> = (
next: NextResolverFn<TResult>,
source: any,
args: TArgs,
context: TContext,
info: GraphQLResolveInfo
) => TResult | Promise<TResult>;
export namespace QueryResolvers {
export interface Resolvers<Context = {}, TypeParent = {}> {
/** Auth */
me?: MeResolver<Maybe<User>, TypeParent, Context>;
/** Event */
events?: EventsResolver<
Maybe<(Maybe<CalendarEvent>)[]>,
TypeParent,
Context
>;
}
export type MeResolver<R = Maybe<User>, Parent = {}, Context = {}> = Resolver<
R,
Parent,
Context
>;
export type EventsResolver<
R = Maybe<(Maybe<CalendarEvent>)[]>,
Parent = {},
Context = {}
> = Resolver<R, Parent, Context, EventsArgs>;
export interface EventsArgs {
filter?: Maybe<EventsQueryFilter>;
}
}
export namespace UserResolvers {
export interface Resolvers<Context = {}, TypeParent = User> {
firstName?: FirstNameResolver<string, TypeParent, Context>;
lastName?: LastNameResolver<Maybe<string>, TypeParent, Context>;
username?: UsernameResolver<string, TypeParent, Context>;
email?: EmailResolver<string, TypeParent, Context>;
id?: IdResolver<string, TypeParent, Context>;
}
export type FirstNameResolver<
R = string,
Parent = User,
Context = {}
> = Resolver<R, Parent, Context>;
export type LastNameResolver<
R = Maybe<string>,
Parent = User,
Context = {}
> = Resolver<R, Parent, Context>;
export type UsernameResolver<
R = string,
Parent = User,
Context = {}
> = Resolver<R, Parent, Context>;
export type EmailResolver<R = string, Parent = User, Context = {}> = Resolver<
R,
Parent,
Context
>;
export type IdResolver<R = string, Parent = User, Context = {}> = Resolver<
R,
Parent,
Context
>;
}
export namespace CalendarEventResolvers {
export interface Resolvers<Context = {}, TypeParent = CalendarEvent> {
id?: IdResolver<string, TypeParent, Context>;
owner?: OwnerResolver<User, TypeParent, Context>;
info?: InfoResolver<(Maybe<EventInformation>)[], TypeParent, Context>;
time?: TimeResolver<EventTime, TypeParent, Context>;
status?: StatusResolver<EventStatus, TypeParent, Context>;
contact?: ContactResolver<EventContactPerson[], TypeParent, Context>;
location?: LocationResolver<Location, TypeParent, Context>;
}
export type IdResolver<
R = string,
Parent = CalendarEvent,
Context = {}
> = Resolver<R, Parent, Context>;
export type OwnerResolver<
R = User,
Parent = CalendarEvent,
Context = {}
> = Resolver<R, Parent, Context>;
export type InfoResolver<
R = (Maybe<EventInformation>)[],
Parent = CalendarEvent,
Context = {}
> = Resolver<R, Parent, Context>;
export type TimeResolver<
R = EventTime,
Parent = CalendarEvent,
Context = {}
> = Resolver<R, Parent, Context>;
export type StatusResolver<
R = EventStatus,
Parent = CalendarEvent,
Context = {}
> = Resolver<R, Parent, Context>;
export type ContactResolver<
R = EventContactPerson[],
Parent = CalendarEvent,
Context = {}
> = Resolver<R, Parent, Context>;
export type LocationResolver<
R = Location,
Parent = CalendarEvent,
Context = {}
> = Resolver<R, Parent, Context>;
}
/** Event information for presentation */
export namespace EventInformationResolvers {
export interface Resolvers<Context = {}, TypeParent = EventInformation> {
language?: LanguageResolver<string, TypeParent, Context>;
title?: TitleResolver<string, TypeParent, Context>;
description?: DescriptionResolver<Maybe<string>, TypeParent, Context>;
}
export type LanguageResolver<
R = string,
Parent = EventInformation,
Context = {}
> = Resolver<R, Parent, Context>;
export type TitleResolver<
R = string,
Parent = EventInformation,
Context = {}
> = Resolver<R, Parent, Context>;
export type DescriptionResolver<
R = Maybe<string>,
Parent = EventInformation,
Context = {}
> = Resolver<R, Parent, Context>;
}
export namespace EventTimeResolvers {
export interface Resolvers<Context = {}, TypeParent = EventTime> {
timeZone?: TimeZoneResolver<Maybe<TimeZone>, TypeParent, Context>;
start?: StartResolver<Maybe<Timestamp>, TypeParent, Context>;
end?: EndResolver<Maybe<Timestamp>, TypeParent, Context>;
recurrence?: RecurrenceResolver<Maybe<string>, TypeParent, Context>;
exceptions?: ExceptionsResolver<Maybe<string>, TypeParent, Context>;
}
export type TimeZoneResolver<
R = Maybe<TimeZone>,
Parent = EventTime,
Context = {}
> = Resolver<R, Parent, Context>;
export type StartResolver<
R = Maybe<Timestamp>,
Parent = EventTime,
Context = {}
> = Resolver<R, Parent, Context>;
export type EndResolver<
R = Maybe<Timestamp>,
Parent = EventTime,
Context = {}
> = Resolver<R, Parent, Context>;
export type RecurrenceResolver<
R = Maybe<string>,
Parent = EventTime,
Context = {}
> = Resolver<R, Parent, Context>;
export type ExceptionsResolver<
R = Maybe<string>,
Parent = EventTime,
Context = {}
> = Resolver<R, Parent, Context>;
}
export namespace EventContactPersonResolvers {
export interface Resolvers<Context = {}, TypeParent = EventContactPerson> {
name?: NameResolver<string, TypeParent, Context>;
languages?: LanguagesResolver<Maybe<Language[]>, TypeParent, Context>;
contact?: ContactResolver<Maybe<Contact>, TypeParent, Context>;
}
export type NameResolver<
R = string,
Parent = EventContactPerson,
Context = {}
> = Resolver<R, Parent, Context>;
export type LanguagesResolver<
R = Maybe<Language[]>,
Parent = EventContactPerson,
Context = {}
> = Resolver<R, Parent, Context>;
export type ContactResolver<
R = Maybe<Contact>,
Parent = EventContactPerson,
Context = {}
> = Resolver<R, Parent, Context>;
}
export namespace ContactResolvers {
export interface Resolvers<Context = {}, TypeParent = Contact> {
email?: EmailResolver<Maybe<string>, TypeParent, Context>;
phone?: PhoneResolver<Maybe<string>, TypeParent, Context>;
}
export type EmailResolver<
R = Maybe<string>,
Parent = Contact,
Context = {}
> = Resolver<R, Parent, Context>;
export type PhoneResolver<
R = Maybe<string>,
Parent = Contact,
Context = {}
> = Resolver<R, Parent, Context>;
}
export namespace LocationResolvers {
export interface Resolvers<Context = {}, TypeParent = Location> {
address?: AddressResolver<Maybe<string>, TypeParent, Context>;
name?: NameResolver<Maybe<string>, TypeParent, Context>;
coordinate?: CoordinateResolver<Maybe<GeoCoordinate>, TypeParent, Context>;
}
export type AddressResolver<
R = Maybe<string>,
Parent = Location,
Context = {}
> = Resolver<R, Parent, Context>;
export type NameResolver<
R = Maybe<string>,
Parent = Location,
Context = {}
> = Resolver<R, Parent, Context>;
export type CoordinateResolver<
R = Maybe<GeoCoordinate>,
Parent = Location,
Context = {}
> = Resolver<R, Parent, Context>;
}
export namespace GeoCoordinateResolvers {
export interface Resolvers<Context = {}, TypeParent = GeoCoordinate> {
lat?: LatResolver<Maybe<number>, TypeParent, Context>;
lng?: LngResolver<Maybe<number>, TypeParent, Context>;
}
export type LatResolver<
R = Maybe<number>,
Parent = GeoCoordinate,
Context = {}
> = Resolver<R, Parent, Context>;
export type LngResolver<
R = Maybe<number>,
Parent = GeoCoordinate,
Context = {}
> = Resolver<R, Parent, Context>;
}
export namespace MutationResolvers {
export interface Resolvers<Context = {}, TypeParent = {}> {
/** Auth */
signup?: SignupResolver<boolean, TypeParent, Context>;
signin?: SigninResolver<UserSession, TypeParent, Context>;
requestInvite?: RequestInviteResolver<boolean, TypeParent, Context>;
/** Event */
createEvent?: CreateEventResolver<
Maybe<CalendarEvent>,
TypeParent,
Context
>;
}
export type SignupResolver<R = boolean, Parent = {}, Context = {}> = Resolver<
R,
Parent,
Context,
SignupArgs
>;
export interface SignupArgs {
input?: Maybe<SignupInput>;
}
export type SigninResolver<
R = UserSession,
Parent = {},
Context = {}
> = Resolver<R, Parent, Context, SigninArgs>;
export interface SigninArgs {
input?: Maybe<SigninInput>;
}
export type RequestInviteResolver<
R = boolean,
Parent = {},
Context = {}
> = Resolver<R, Parent, Context, RequestInviteArgs>;
export interface RequestInviteArgs {
input?: Maybe<RequestInviteInput>;
}
export type CreateEventResolver<
R = Maybe<CalendarEvent>,
Parent = {},
Context = {}
> = Resolver<R, Parent, Context, CreateEventArgs>;
export interface CreateEventArgs {
input?: Maybe<CreateEventInput>;
foo?: Maybe<string>;
}
}
export namespace UserSessionResolvers {
export interface Resolvers<Context = {}, TypeParent = UserSession> {
hash?: HashResolver<string, TypeParent, Context>;
user?: UserResolver<User, TypeParent, Context>;
ctime?: CtimeResolver<Date, TypeParent, Context>;
isValid?: IsValidResolver<boolean, TypeParent, Context>;
}
export type HashResolver<
R = string,
Parent = UserSession,
Context = {}
> = Resolver<R, Parent, Context>;
export type UserResolver<
R = User,
Parent = UserSession,
Context = {}
> = Resolver<R, Parent, Context>;
export type CtimeResolver<
R = Date,
Parent = UserSession,
Context = {}
> = Resolver<R, Parent, Context>;
export type IsValidResolver<
R = boolean,
Parent = UserSession,
Context = {}
> = Resolver<R, Parent, Context>;
}
export type UnionDirectiveResolver<Result> = DirectiveResolverFn<
Result,
UnionDirectiveArgs,
{}
>;
export interface UnionDirectiveArgs {
discriminatorField?: Maybe<string>;
}
export type AbstractEntityDirectiveResolver<Result> = DirectiveResolverFn<
Result,
AbstractEntityDirectiveArgs,
{}
>;
export interface AbstractEntityDirectiveArgs {
discriminatorField: string;
}
export type EntityDirectiveResolver<Result> = DirectiveResolverFn<
Result,
EntityDirectiveArgs,
{}
>;
export interface EntityDirectiveArgs {
embedded?: Maybe<boolean>;
additionalFields?: Maybe<(Maybe<AdditionalEntityFields>)[]>;
}
export type ColumnDirectiveResolver<Result> = DirectiveResolverFn<
Result,
ColumnDirectiveArgs,
{}
>;
export interface ColumnDirectiveArgs {
name?: Maybe<string>;
overrideType?: Maybe<string>;
overrideIsArray?: Maybe<boolean>;
}
export type IdDirectiveResolver<Result> = DirectiveResolverFn<Result, {}, {}>;
export type LinkDirectiveResolver<Result> = DirectiveResolverFn<Result, {}, {}>;
export type EmbeddedDirectiveResolver<Result> = DirectiveResolverFn<
Result,
{},
{}
>;
export type MapDirectiveResolver<Result> = DirectiveResolverFn<
Result,
MapDirectiveArgs,
{}
>;
export interface MapDirectiveArgs {
path: string;
}
/** Directs the executor to skip this field or fragment when the `if` argument is true. */
export type SkipDirectiveResolver<Result> = DirectiveResolverFn<
Result,
SkipDirectiveArgs,
{}
>;
export interface SkipDirectiveArgs {
/** Skipped when true. */
if: boolean;
}
/** Directs the executor to include this field or fragment only when the `if` argument is true. */
export type IncludeDirectiveResolver<Result> = DirectiveResolverFn<
Result,
IncludeDirectiveArgs,
{}
>;
export interface IncludeDirectiveArgs {
/** Included when true. */
if: boolean;
}
/** Marks an element of a GraphQL schema as no longer supported. */
export type DeprecatedDirectiveResolver<Result> = DirectiveResolverFn<
Result,
DeprecatedDirectiveArgs,
{}
>;
export interface DeprecatedDirectiveArgs {
/** Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted using the Markdown syntax (as specified by [CommonMark](https://commonmark.org/). */
reason?: string;
}
export interface TimeZoneScalarConfig
extends GraphQLScalarTypeConfig<TimeZone, any> {
name: "TimeZone";
}
export interface TimestampScalarConfig
extends GraphQLScalarTypeConfig<Timestamp, any> {
name: "Timestamp";
}
export interface EventStatusScalarConfig
extends GraphQLScalarTypeConfig<EventStatus, any> {
name: "EventStatus";
}
export interface LanguageScalarConfig
extends GraphQLScalarTypeConfig<Language, any> {
name: "Language";
}
export interface DateScalarConfig extends GraphQLScalarTypeConfig<Date, any> {
name: "Date";
}
export interface IResolvers<Context = {}> {
Query?: QueryResolvers.Resolvers<Context>;
User?: UserResolvers.Resolvers<Context>;
CalendarEvent?: CalendarEventResolvers.Resolvers<Context>;
EventInformation?: EventInformationResolvers.Resolvers<Context>;
EventTime?: EventTimeResolvers.Resolvers<Context>;
EventContactPerson?: EventContactPersonResolvers.Resolvers<Context>;
Contact?: ContactResolvers.Resolvers<Context>;
Location?: LocationResolvers.Resolvers<Context>;
GeoCoordinate?: GeoCoordinateResolvers.Resolvers<Context>;
Mutation?: MutationResolvers.Resolvers<Context>;
UserSession?: UserSessionResolvers.Resolvers<Context>;
TimeZone?: GraphQLScalarType;
Timestamp?: GraphQLScalarType;
EventStatus?: GraphQLScalarType;
Language?: GraphQLScalarType;
Date?: GraphQLScalarType;
}
export interface IDirectiveResolvers<Result> {
union?: UnionDirectiveResolver<Result>;
abstractEntity?: AbstractEntityDirectiveResolver<Result>;
entity?: EntityDirectiveResolver<Result>;
column?: ColumnDirectiveResolver<Result>;
id?: IdDirectiveResolver<Result>;
link?: LinkDirectiveResolver<Result>;
embedded?: EmbeddedDirectiveResolver<Result>;
map?: MapDirectiveResolver<Result>;
skip?: SkipDirectiveResolver<Result>;
include?: IncludeDirectiveResolver<Result>;
deprecated?: DeprecatedDirectiveResolver<Result>;
}

View File

@ -1,131 +0,0 @@
import Repository, {transformId, OIDable, Collections} from "../repository";
import {SessionInvite} from "./SessionManager";
import {Collection, ObjectID} from "mongodb";
import {SignupInput, User, UserDbObject, UserSession, UserSessionDbObject} from "../@types";
interface UserKeys {
username?: string
email?: string
}
type Insertable<T> = T & {
_id?: ObjectID
}
interface AuthCollections {
users: Collection<UserDbObject>,
sessions: Collection<UserSessionDbObject>,
sessionInvites: Collection<SessionInvite>
}
class AuthRepository {
repository: Repository
c: AuthCollections
constructor({repository}) {
this.repository = repository
this.c = {
users: this.repository.db.collection<UserDbObject>('users'),
sessions: this.repository.db.collection<UserSessionDbObject>('sessions'),
sessionInvites: this.repository.db.collection<SessionInvite>('session_invites'),
}
}
async createUser(userProperties: SignupInput): Promise<UserDbObject> {
if (!(userProperties.username && userProperties.email)) {
const message = `Cannot create user without username and email: ${JSON.stringify(userProperties)}`
console.error(message)
return Promise.reject(new Error(message))
}
const dbSession = await this.repository.client.startSession()
dbSession.startTransaction()
let excpetionToThrowBack: Error | null = null
try {
const existingUser = await this.c.users.findOne({
$or: [
{email: userProperties.email},
{username: userProperties.username}
]
})
if (existingUser) {
await dbSession.abortTransaction()
const message = 'Error creating new user: already exists'
excpetionToThrowBack = new Error(message)
throw excpetionToThrowBack
}
const insertResult = await this.c.users.insertOne(userProperties as UserDbObject)
if (insertResult.result.ok !== 1) {
await dbSession.abortTransaction()
excpetionToThrowBack = new Error(`Error inserting user ${userProperties}`)
} else {
await dbSession.commitTransaction()
}
} finally {
if (dbSession.inTransaction()) {
dbSession.abortTransaction()
}
}
if (excpetionToThrowBack) {
throw excpetionToThrowBack
}
return this.c.users.findOne({username: userProperties.username, email: userProperties.email})
}
async saveSessionInvite(invite: SessionInvite) {
const result = await this.c.sessionInvites.insertOne(invite)
if (result.result.ok !== 1) {
throw Error(`Error saving session invite: ${JSON.stringify(result)}`)
}
}
async getSessionInvite(hash: string): Promise<SessionInvite | null> {
const result: OIDable<SessionInvite> = await this.c.sessionInvites.findOne({hash})
return transformId(result) as unknown as SessionInvite
}
async createSession(session: UserSessionDbObject): Promise<UserSessionDbObject> {
const dbSession = await this.repository.client.startSession()
dbSession.startTransaction()
const existingSession = await this.c.sessions.findOne({hash: session.hash})
if (existingSession) {
dbSession.abortTransaction()
throw new Error(`Session already exists and cannot be reinitiated`)
} else {
const insertResult = await this.c.sessions.insertOne(session)
if (insertResult.result.ok !== 1) {
dbSession.abortTransaction()
throw new Error(`Error inserting session ${session}`)
} else {
await dbSession.commitTransaction()
}
}
return this.c.sessions.findOne({hash: session.hash});
}
async getSession(hash: string): Promise<UserSessionDbObject> {
return this.c.sessions.findOne({hash})
}
async getUser(userKeys: UserKeys): Promise<UserDbObject> {
return this.c.users.findOne({
$or: [
{id: userKeys.email},
{id: userKeys.username},
]
})
}
async getUserById(id: string): Promise<UserDbObject> {
return this.c.users.findOne({_id: new ObjectID(id)})
}
}
export default AuthRepository;

View File

@ -0,0 +1,33 @@
import {BaseEntity, Column, Entity, ManyToOne, PrimaryColumn, PrimaryGeneratedColumn} from 'typeorm'
import {User} from "./User.entity"
import * as uuid4 from 'uuid/v4'
@Entity()
export class Session extends BaseEntity {
@ManyToOne(type => User, (user: User) => user.sessionInvites)
user: User
@Column()
isValid: boolean
@Column()
hash: string
}
@Entity()
export class SessionInvite extends BaseEntity {
@PrimaryGeneratedColumn()
id: string
@ManyToOne(type => User, (user: User) => user.sessionInvites)
user: User
@Column()
hash: string
@Column({nullable: true})
timeValidated?: Date
}

View File

@ -1,12 +1,11 @@
// Free API to get location from IP: http://freegeoip.net/json/149.11.144.50
import {User, UserDbObject, UserSession, UserSessionDbObject} from "../@types";
import {User} from "./User.entity"
import * as uuid from 'uuid/v4'
const randomstring = require('random-string')
import {sendEmail} from '../post_office'
import {domain} from '../config'
import {ObjectID} from "mongodb";
import AuthRepository from "./AuthRepository";
import {Session, SessionInvite} from "./Session.entity"
export class SessionAlreadyValidatedError extends Error {}
@ -16,45 +15,32 @@ const generateHash = () => randomstring({
special: false
})
export class SessionInvite {
hash: string
userId: string
timeValidated?: number
constructor(user: User) {
this.hash = generateHash()
this.userId = user.id
this.timeValidated = null
const generateUniqueInviteHash = () => {
const hash = generateHash()
const existingSession = SessionInvite.findOne({hash: hash})
if (existingSession) {
return generateUniqueInviteHash()
} else {
return hash
}
}
const generateUniqueSessionHash = () => {
const hash = generateHash()
const existingSession = Session.findOne({hash: hash})
if (existingSession) {
return generateUniqueInviteHash()
} else {
return hash
}
}
export default class SessionManager {
authRepository: AuthRepository
constructor(authRepository: AuthRepository) {
this.authRepository = authRepository
}
inviteUser = async (email: string): Promise<SessionInvite> => {
const user = await this.authRepository.getUser({ email });
if (!user) {
throw new Error('Could not find user for this email');
}
const { _id, ...userProps } = user;
const invite = new SessionInvite({
id: _id.toString(),
...userProps
});
try {
const persistedInvite = await this.authRepository.saveSessionInvite(invite)
console.log(`Invite persisted for user ${user.username}`, persistedInvite)
} catch (e) {
console.error('Failed to save invite', invite)
throw e;
}
inviteUser = async (user: User): Promise<SessionInvite> => {
const invite = new SessionInvite()
invite.user = user
invite.hash = await generateUniqueInviteHash()
await invite.save()
return new Promise(async (resolve: (SessionInvite) => void, reject)=>{
try {
@ -75,36 +61,21 @@ export default class SessionManager {
}
initiateSession = async (inviteHash: string): Promise<UserSessionDbObject> => {
const sessionInvite: SessionInvite = await this.authRepository.getSessionInvite(inviteHash)
initiateSession = async (inviteHash: string): Promise<Session> => {
const sessionInvite: SessionInvite = await SessionInvite.findOne({hash: inviteHash})
if (!sessionInvite) {
throw new Error(`Could not find invite with hash ${inviteHash}`)
}
if (sessionInvite.timeValidated) {
throw new SessionAlreadyValidatedError()
}
const matchingUser: UserDbObject = await this.authRepository.getUserById(sessionInvite.userId)
if (!matchingUser) {
console.error(`Invite hash ${inviteHash} could not find related userId ${sessionInvite.userId}`)
throw new Error('Cannot find related user to this invite')
}
if (matchingUser._id.equals(sessionInvite.userId)) {
const session: UserSessionDbObject = {
user: matchingUser._id,
ctime: Date.now(),
isValid: true,
hash: generateHash(),
}
const persistedSession = await this.authRepository.createSession(session)
return Promise.resolve(persistedSession)
} else {
console.warn(`user ids didn't match. userId: ${matchingUser._id}. sessionUserId: ${sessionInvite.userId}`)
return Promise.resolve(null)
}
}
const session = new Session()
session.user = sessionInvite.user
session.isValid = true
session.hash = generateUniqueSessionHash()
await session.save()
getSession = async(sessionHash: string): Promise<UserSessionDbObject> => {
return await this.authRepository.getSession(sessionHash)
return session
}
}

View File

@ -0,0 +1,36 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
BaseEntity,
OneToMany
} from "typeorm"
import { Event } from "../Calendar/Event.entity"
import {SessionInvite} from "./Session.entity"
@Entity()
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: string
@Column()
firstName: string
@Column()
lastName: string
@Column()
username: string
@Column()
email: string
@Column()
age: number
@OneToMany(type => Event, event => event.owner)
events: Event[]
@OneToMany(type => SessionInvite, invite => invite.user)
sessionInvites: SessionInvite[]
}

View File

@ -1,19 +1,12 @@
import Repository from "../repository";
import UserManager from "../user";
import SessionManager from "./SessionManager";
import {MutationResolvers, User, UserDbObject} from "../@types";
import SignupArgs = MutationResolvers.SignupArgs;
import SigninArgs = MutationResolvers.SigninArgs;
import RequestInviteArgs = MutationResolvers.RequestInviteArgs;
import SessionManager from "./SessionManager"
import {User} from "./User.entity"
export default class AuthResolvers {
userManager: UserManager
repository: Repository
sessionManager: SessionManager
constructor({repository, userManager, sessionManager}) {
this.userManager = repository;
this.sessionManager = sessionManager;
constructor({sessionManager}) {
this.sessionManager = sessionManager
}
Query = {
@ -21,32 +14,57 @@ export default class AuthResolvers {
}
Mutation = {
signup: async (_, args: SignupArgs, context, info) => {
const newUser = await this.userManager.createUser(args.input)
if (!newUser) {
throw new Error("New user was not created for request" + JSON.stringify(args))
signup: async (_, args: GQL.ISignupOnMutationArguments, context, info) => {
const errors = []
if (await User.findOne({email: args.input.email})) {
errors.push({
path: "email",
message: "Email taken"
})
}
if (await User.findOne({username: args.input.username})) {
errors.push({
path: "username",
message: "Username taken"
})
}
if (errors.length) {
return errors
}
const newUser = new User()
newUser.firstName = args.input.firstName
newUser.lastName = args.input.lastName
newUser.email = args.input.email
newUser.username = args.input.username
await newUser.save()
if (!newUser.id) {
throw new Error("Could not create user")
}
try {
await this.sessionManager.inviteUser(newUser.email)
await this.sessionManager.inviteUser(newUser)
} catch (e) {
console.error('Error sending invitation', e)
}
return !!newUser
return null
},
signin: async (_, req: SigninArgs, context, info) => {
const session = await this.sessionManager.initiateSession(req.input.hash);
signin: async (_, req, context, info) => {
const session = await this.sessionManager.initiateSession(req.input.hash)
if (!session || !session.isValid) {
throw new Error('Could not find session invite')
}
return session;
return session
},
requestInvite: async (_, req: RequestInviteArgs, context, info) => {
const invite = await this.sessionManager.inviteUser(req.input.email)
if (!invite) {
throw new Error('Invitation failed')
requestInvite: async (_, req: GQL.IRequestInviteOnMutationArguments, context, info) => {
const user = await User.findOne({email: req.input.email})
if (user) {
this.sessionManager.inviteUser(user)
}
return true
},
}

View File

@ -1,8 +1,7 @@
import {auth} from 'google-auth-library';
import {OAuth2Client} from "google-auth-library/build/src/auth/oauth2client";
import {atob} from 'atob';
import {EventsRepository} from "../Events/EventsRepository";
import {CalendarEvent} from "../@types";
import {auth} from 'google-auth-library'
import {OAuth2Client} from "google-auth-library/build/src/auth/oauth2client"
import {atob} from 'atob'
import { Event } from './Event.entity'
type GCalConfig = {
calendarId: string
@ -10,15 +9,12 @@ type GCalConfig = {
clientEmail: string
}
export default class CalendarManager {
eventsRepository: EventsRepository
gcalConfig: GCalConfig
gcalBaseURL: string
constructor(options: {
eventsRepository: EventsRepository,
gcalConfig: GCalConfig,
}) {
this.eventsRepository = options.eventsRepository
this.gcalConfig = options.gcalConfig
this.gcalBaseURL = `https://www.googleapis.com/calendar/v3/calendars/${options.gcalConfig.calendarId}`
}
@ -27,11 +23,11 @@ export default class CalendarManager {
const client: any = auth.fromJSON({
private_key: atob(this.gcalConfig.privateKeyBase64),
client_email: this.gcalConfig.clientEmail
});
})
client.scopes = ['https://www.googleapis.com/auth/calendar'];
client.scopes = ['https://www.googleapis.com/auth/calendar']
await client.authorize()
return client as OAuth2Client;
return client as OAuth2Client
}
createPrimaryCalendar = async () => {
@ -42,7 +38,7 @@ export default class CalendarManager {
data: {
summary: 'primary events calendar'
}
});
})
return res.data
}
@ -50,8 +46,8 @@ export default class CalendarManager {
const client = await this.getClient()
const res = await client.request({
url: 'https://www.googleapis.com/calendar/v3/users/me/calendarList'
});
return (res.data as any).items;
})
return (res.data as any).items
}
listEvents = async () => {
@ -64,7 +60,7 @@ export default class CalendarManager {
})
} catch (e) {
console.error('Error fetching events', e)
throw e;
throw e
}
@ -72,16 +68,16 @@ export default class CalendarManager {
const dbIdToGCalEvents = {}
eventsResponse.data.items.forEach(gCalEvent => {
const dbId = gCalEvent.extendedProperties.private.eventId;
const dbId = gCalEvent.extendedProperties.private.eventId
dbIdToGCalEvents[dbId] = gCalEvent
eventsDBPromises.push(
this.eventsRepository.getEvent(dbId)
Event.findOne(dbId)
.catch(e => {
console.warn(`Error fetching DB event ${dbId}, will skip this one`, e)
return null;
return null
})
)
});
})
const allEvents = await Promise.all(eventsDBPromises)
const result = allEvents.filter(Boolean).map(dbEvent => ({
@ -92,7 +88,7 @@ export default class CalendarManager {
return result
}
createEvent = async (event: CalendarEvent): Promise<String> => {
createEvent = async (event: Event): Promise<String> => {
if (!event.id) {
throw new Error('Event doesn\'t have id')
}

View File

@ -0,0 +1,67 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
BaseEntity,
OneToMany,
OneToOne,
ManyToOne,
CreateDateColumn
} from "typeorm"
import {User} from "../Auth/User.entity"
@Entity()
class EventLocation extends BaseEntity {
}
@Entity()
class EventContactPerson extends BaseEntity {
}
export class EventTime extends BaseEntity {
@CreateDateColumn()
timeZone: string
@Column({type: "datetime"})
start: Date
@Column()
end: Date
@Column()
recurrence: String
@Column()
exceptions: String
}
export class EventInformation {
@Column()
title: string
@Column()
description: string
}
@Entity()
export class Event extends BaseEntity {
@PrimaryGeneratedColumn()
id: number
@ManyToOne(type => User, user => user.events)
owner: User
@Column(type => EventInformation)
info: EventInformation
@Column(type => EventTime)
time: EventTime
@Column()
status: string
@Column(type => EventContactPerson)
contact: EventContactPerson[]
@Column(type => EventLocation)
location: EventLocation
}

View File

@ -1,45 +0,0 @@
import {EventsRepository} from './EventsRepository'
import CalendarManager from "../Calendar/CalendarManager";
import {CalendarEvent, CalendarEventDbObject, CreateEventInput} from "../@types";
export interface EventsListFilter {
tags?: {
include?: string[]
exclude?: string[]
}
earliest?: Date
latest?: Date
limit?: number
skip?: number
}
export default class EventManager {
eventsRepository: EventsRepository
calendarManager: CalendarManager
constructor({eventsRepository, calendarManager}: { eventsRepository: EventsRepository, calendarManager: CalendarManager }) {
this.eventsRepository = eventsRepository;
this.calendarManager = calendarManager;
}
async createEvent(eventDetails: CreateEventInput): Promise<CalendarEvent> {
let dbEvent
try {
dbEvent = await this.eventsRepository.createEvent(eventDetails)
console.log('Event created on the db', JSON.stringify(dbEvent))
} catch (e) {
console.error('Error while persisting new event:', e)
}
if (!(dbEvent && dbEvent.id)) {
console.error('Could not get persisted event from the database')
return null
}
return dbEvent;
}
async listEvents(filter: EventsListFilter): Promise<CalendarEventDbObject[]> {
return this.eventsRepository.getEvents(filter)
}
}

View File

@ -1,46 +0,0 @@
import Repository, {transformId, OIDable, Collections} from "../repository";
import {CalendarEvent, CalendarEventDbObject, CreateEventInput} from "../@types";
import {EventsListFilter} from "./EventManager";
class EventsRepository {
repository: Repository
c: Collections
constructor({repository}) {
this.repository = repository
this.c = repository.c;
}
async createEvent(event: CreateEventInput): Promise<CalendarEventDbObject> {
const insertResult = await this.c.events.insertOne(event as any as CalendarEventDbObject)
if (insertResult.result.ok !== 1) {
throw new Error(`Could new insert event ${JSON.stringify(event)}`)
}
return this.c.events.findOne({
_id: insertResult.insertedId
})
}
async updateEvent(event: CalendarEvent): Promise<CalendarEventDbObject> {
const {id, owner, ...strippedFromId} = event;
const updateResult = await this.c.events.updateOne({
_id: event.id
}, strippedFromId as CalendarEventDbObject)
if (updateResult.result.ok !== 1) {
throw new Error(`Error updating event ${event.id}`)
}
return this.c.events.findOne({_id: event.id})
}
async getEvent(id: string): Promise<CalendarEvent> {
return this.c.events.findOne({_id: id})
}
async getEvents(filter: EventsListFilter): Promise<CalendarEventDbObject[]> {
return this.c.events.find({}).limit(filter.limit).toArray()
}
}
export { EventsRepository };

View File

@ -1,37 +1,29 @@
import EventManager from './EventManager'
import CalendarManager from "../Calendar/CalendarManager";
import CreateEventResolver = MutationResolvers.CreateEventResolver;
import {CalendarEventResolvers, MutationResolvers} from "../@types";
import CreateEventArgs = MutationResolvers.CreateEventArgs;
import {Event} from "../Calendar/Event.entity"
import {ResolverMap} from "../@types/graphql-utils"
export default class EventsResolvers {
eventManager: EventManager
calendarManager: CalendarManager
const resolvers: ResolverMap = {
constructor({eventManager, calendarManager}: {eventManager: EventManager, calendarManager: CalendarManager}) {
this.eventManager = eventManager;
this.calendarManager = calendarManager;
}
Query = {
events: async (req) => {
return this.eventManager.listEvents({})
Query: {
events: async (_, req: GQL.IEventsOnQueryArguments, context, info) => {
return Event.find({
take: req.filter.limit
})
},
}
Event = {
owner: async (event, args, context, info) => {
},
Event: {
owner: async (event: Event, args, context, info) => {
return event.owner
}
}
},
Mutation: {
createEvent: CreateEventResolver
} = {
createEvent: async (_, args: CreateEventArgs, context, info) => {
console.warn('To Do: Event owner is not verified!')
const event = await this.eventManager.createEvent(args.input)
return event
createEvent: async (_, { input }: GQL.ICreateEventOnMutationArguments, context, info) => {
const event = new Event()
event.owner = context.session.user
return null
}
}
},
}
export default resolvers

View File

@ -1,6 +1,4 @@
import {CalendarEventRequest} from "../types";
const event: CalendarEventRequest = {
const event = {
"contactPhone": "+34655700372",
"contactEmail": "rastro@example.copm",
"locationAddress": "By the river",

View File

@ -1,34 +0,0 @@
import SessionManager, {Session} from "./session";
import {Request, Response} from 'express';
import * as cookie from 'cookie'
export type AuthenticatedRequest = Request & {
session: Session
}
export const authRequest = (sessionManager: SessionManager) => async (req: Request, res: Response) => {
// const eventData: CalendarEvent = req.body;
let sessionHash, session: Session
try {
const cookiesHeader = req.headers.cookie
console.log('allHeaders', req.headers)
console.log('cookiesHeader', cookiesHeader)
sessionHash = cookie.parse(req.headers.cookie).__session
if (!sessionHash) {
throw new Error('Session cookie required')
}
session = await sessionManager.getSession(sessionHash)
} catch (e) {
console.log('Exception getting session', e)
res.status(401)
res.send('Authentication required to post an event')
return
}
if (!session || !session.isValid) {
res.status(401)
res.send('Could not find active session. Please log in.')
return
}
(req as AuthenticatedRequest).session = session
}

View File

@ -1,81 +1,58 @@
import Repository from "./repository";
import UserManager from "./user";
import SessionManager from "./auth/SessionManager";
import CalendarManager from "./Calendar/CalendarManager";
import EventManager from "./Events/EventManager";
import {ApolloServer} from 'apollo-server';
import {makeExecutableSchema} from "graphql-tools";
import SessionManager from "./auth/SessionManager"
import CalendarManager from "./Calendar/CalendarManager"
import {ApolloServer} from 'apollo-server'
import {makeExecutableSchema} from "graphql-tools"
import EventsResolvers from './Events/eventsResolvers'
import {importSchema} from 'graphql-import';
import AuthResolvers from "./Auth/authResolvers";
import { DIRECTIVES } from 'graphql-codegen-typescript-mongodb';
import {readFileSync} from "fs";
import {importSchema} from 'graphql-import'
import AuthResolvers from "./Auth/authResolvers"
interface Dependencies {
repository: Repository,
userManager: UserManager,
sessionManager: SessionManager,
calendarManager: CalendarManager,
eventManager: EventManager
}
export default class GraphQLInterface {
repository: Repository
userManager: UserManager
sessionManager: SessionManager
calendarManager: CalendarManager
eventManager: EventManager
constructor(dependencies: Dependencies) {
this.repository = dependencies.repository
this.userManager = dependencies.userManager
this.sessionManager = dependencies.sessionManager
this.calendarManager = dependencies.calendarManager
this.eventManager = dependencies.eventManager
}
start = () => {
const eventsResolvers = new EventsResolvers({
eventManager: this.eventManager,
calendarManager: this.calendarManager
})
const authResolvers = new AuthResolvers({
repository: this.repository,
sessionManager: this.sessionManager,
userManager: this.userManager
})
const typeDefs = readFileSync(__dirname + '/schema.graphql', 'utf8');
const typeDefs = importSchema(__dirname + '/schema.graphql')
const schema = makeExecutableSchema({
typeDefs: [
DIRECTIVES,
typeDefs
],
resolvers: {
Query: {
...this.resolvers.Query,
...eventsResolvers.Query,
...EventsResolvers.Query,
...authResolvers.Query
},
Mutation: {
...this.resolvers.Mutation,
...eventsResolvers.Mutation,
...EventsResolvers.Mutation,
...authResolvers.Mutation
}
},
});
})
const server = new ApolloServer({schema});
const server = new ApolloServer({schema})
server.listen().then(({url}) => {
console.log(`🚀 Server ready at ${url}`);
});
console.log(`🚀 Server ready at ${url}`)
})
}
resolvers = {
Query: {},
Mutation: {}
};
}
}

View File

@ -1,35 +1,10 @@
import {gcal as gcalConfig, projectId} from "./config";
import UserManager from "./user";
import SessionManager from "./Auth/SessionManager";
import Repository from './repository'
import Calendar from "./Calendar/CalendarManager";
import EventManager from "./Events/EventManager";
import GraphQLInterface from "./graphql";
import {EventsRepository} from "./Events/EventsRepository";
import AuthRepository from "./Auth/AuthRepository";
import GraphQLInterface from "./graphql"
import SessionManager from "./Auth/SessionManager"
async function start() {
const repository = new Repository(projectId)
await repository.connect()
const authRepository = new AuthRepository({repository})
const userManager = new UserManager(authRepository)
const sessionManager = new SessionManager(authRepository)
const eventsRepository = new EventsRepository({repository})
const calendarManager = new Calendar({
eventsRepository: eventsRepository,
gcalConfig: gcalConfig
})
const eventManager = new EventManager({calendarManager, eventsRepository})
const gql = new GraphQLInterface({
repository,
userManager,
sessionManager,
calendarManager,
eventManager,
});
sessionManager: new SessionManager()
})
gql.start()
}

View File

@ -1,42 +0,0 @@
import {MongoClient, Db, Collection, ObjectID} from 'mongodb';
import {CalendarEventDbObject, UserDbObject, UserSessionDbObject} from "./@types";
export interface MongoEntity<T> extends OIDable<T> {
}
export function transformId<T extends {_id: ObjectID}>(mongoInstance?: MongoEntity<T>): T {
if (!mongoInstance) {
return null
}
const {_id, ...entityProps} = mongoInstance
return {...entityProps, id: _id.toString()} as unknown as T;
}
export interface OIDable<T> {
_id?: ObjectID
}
export interface Collections {
events: Collection<CalendarEventDbObject>
}
export default class Repository {
client: MongoClient
dbName: string
db: Db
public c: Collections
constructor(projectId: string) {
this.dbName = projectId
}
async connect() {
console.log('Will connect to mongo db')
this.client = await MongoClient.connect('mongodb://localhost', {useNewUrlParser: true})
this.db = this.client.db(this.dbName)
this.c = {
events: this.db.collection<CalendarEventDbObject>('events'),
}
console.log('Mongo connected and collections set up')
}
}

View File

@ -1,18 +1,18 @@
type User @entity {
firstName: String! @column
lastName: String @column
username: String! @column
email: String! @column
id: ID! @id
type User {
firstName: String!
lastName: String
username: String!
email: String!
id: ID!
}
scalar Date
type UserSession @entity {
hash: String! @column
user: User! @link
ctime: Date! @column
isValid: Boolean! @column
type UserSession {
hash: String!
user: User!
ctime: Date!
isValid: Boolean!
}
input SignupInput {
@ -35,14 +35,14 @@ input RequestInviteInput {
# ------
type CalendarEvent @entity {
id: ID! @id
owner: User! @link
info: [EventInformation]! @embedded
time: EventTime! @column
status: EventStatus! @column
contact: [EventContactPerson!]! @embedded
location: Location! @embedded
type CalendarEvent {
id: ID!
owner: User!
info: [EventInformation]!
time: EventTime!
status: EventStatus!
contact: [EventContactPerson!]!
location: Location!
}
type Location {
@ -77,16 +77,16 @@ scalar EventStatus
scalar Language
# Event information for presentation
type EventInformation @entity {
language: String! @column
title: String! @column
description: String @column
type EventInformation {
language: String!
title: String!
description: String
}
type EventContactPerson @entity {
name: String! @column
languages: [Language!] @embedded
contact: Contact @column
type EventContactPerson {
name: String!
languages: [Language!]
contact: Contact
}
type Contact {

View File

@ -1,21 +0,0 @@
import Repository from './repository'
import {SignupInput, User, UserDbObject} from "./@types";
import AuthRepository from "./Auth/AuthRepository";
export default class UserManager {
authRepository: AuthRepository
constructor(authRepository: AuthRepository) {
this.authRepository = authRepository
}
getUser = async (keys) => {
return await this.authRepository.getUser(keys)
}
createUser = async (user: SignupInput): Promise<UserDbObject> => {
return this.authRepository.createUser(user)
}
}

View File

@ -8,7 +8,9 @@
"sourceMap": true,
"target": "es6",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true
},
"compileOnSave": true,
"include": [
@ -18,5 +20,5 @@
"./src/@types/index.d.ts"
],
"exclude": [
"**/*.spec.ts"
"**/*.spec.ts", "node_modules", "__tests__"
]}

View File

@ -17,6 +17,7 @@
// Force the use of ES6-style imports instead of /// <reference path=> imports.
"no-reference": true,
"semicolon": [true, "never"],
// Do not allow type assertions that do nothing. This is a big warning that the developer may not understand the
// code currently being edited (they may be incorrectly handling a different type case that does not exist).

View File

@ -1,13 +0,0 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "lib/"
},
"lib": [
"es2015"
],
"exclude": [
"node_modules"
]
}

View File

@ -15,6 +15,7 @@
"no-console": false,
"interface-name" : false,
"no-empty-interface" : false,
"max-classes-per-file" : false
"max-classes-per-file" : false,
"semicolon": [true, "never"]
}
}

355
yarn.lock
View File

@ -740,6 +740,36 @@
lodash "^4.17.10"
to-fast-properties "^2.0.0"
"@gql2ts/from-query@^1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@gql2ts/from-query/-/from-query-1.9.0.tgz#ae92a4fa3df005df57eb835b371d7964644b9beb"
integrity sha512-hfH2Oq3ikHu+zKE4b9kdGbzEqFiX+VxIg0nhgpY5iUgl975cAtTFhAdwfzr/jKdZhC9Ad5dE1CPrjEA+G7hzMg==
dependencies:
"@gql2ts/language-typescript" "^1.9.0"
"@gql2ts/util" "^1.9.0"
"@gql2ts/from-schema@^1.10.1":
version "1.10.1"
resolved "https://registry.yarnpkg.com/@gql2ts/from-schema/-/from-schema-1.10.1.tgz#f8bb1f9525d5731163b16f5bcf300f87ef560273"
integrity sha512-atYXxY8WBBfK39fEbdwx3CgqRYYUR10a1hGPIwVcvEuNYIlAnIUR1drVbmC3higwMbAyHGkMxDPJ9Us7tnNz6w==
dependencies:
"@gql2ts/language-typescript" "^1.9.0"
"@gql2ts/util" "^1.9.0"
dedent "^0.7.0"
"@gql2ts/language-typescript@^1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@gql2ts/language-typescript/-/language-typescript-1.9.0.tgz#c521e800817d1341552e9c684bca6b64b0abb46f"
integrity sha512-d3OlIFMjKoXH+VukXD7+pQRLgrP3NkXDQbCWSGonIl5mpRQ5aO5I8Fo53cMZQ9xCjj1Y5Vg24wtZOuY8spc6Ag==
dependencies:
"@gql2ts/util" "^1.9.0"
humps "^2.0.0"
"@gql2ts/util@^1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@gql2ts/util/-/util-1.9.0.tgz#d07a54832757d2f2d1fc9891e5b0e3e3b4886c6a"
integrity sha512-mkHar7AdyShUFJE6Mlke1tUbb+lPCK1EozZeAhCuRrhQ5aCCBAG6RxzNUYX1Q2jeGeyU0WRAtQu1oE/GoIsNXA==
"@graphql-modules/epoxy@0.2.18":
version "0.2.18"
resolved "https://registry.yarnpkg.com/@graphql-modules/epoxy/-/epoxy-0.2.18.tgz#58ea584e57e0573d804ee39e34ee2fad604ba63a"
@ -1014,11 +1044,23 @@
resolved "https://registry.yarnpkg.com/@types/is-glob/-/is-glob-4.0.0.tgz#fb8a2bff539025d4dcd6d5efe7689e03341b876d"
integrity sha512-zC/2EmD8scdsGIeE+Xg7kP7oi9VP90zgMQtm9Cr25av4V+a+k8slQyiT60qSw8KORYrOKlPXfHwoa1bQbRzskQ==
"@types/jest-diff@*":
version "20.0.1"
resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89"
integrity sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==
"@types/jest@^23.3.1":
version "23.3.10"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-23.3.10.tgz#4897974cc317bf99d4fe6af1efa15957fa9c94de"
integrity sha512-DC8xTuW/6TYgvEg3HEXS7cu9OijFqprVDXXiOcdOKZCU/5PJNLZU37VVvmZHdtMiGOa8wAA/We+JzbdxFzQTRQ==
"@types/jest@^24.0.9":
version "24.0.9"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.9.tgz#74ce9cf337f25e189aa18f76ab3d65e8669b55f2"
integrity sha512-k3OOeevcBYLR5pdsOv5g3OP94h3mrJmLPHFEPWgbbVy2tGv0TZ/TlygiC848ogXhK8NL0I5up7YYtwpCp8xCJA==
dependencies:
"@types/jest-diff" "*"
"@types/joi@^13.0.8", "@types/joi@^13.6.0":
version "13.6.3"
resolved "https://registry.yarnpkg.com/@types/joi/-/joi-13.6.3.tgz#79364839a9cc2c6d4d915ef8822e1f703e28648f"
@ -1154,6 +1196,13 @@
dependencies:
source-map "^0.6.1"
"@types/uuid@^3.4.4":
version "3.4.4"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.4.tgz#7af69360fa65ef0decb41fd150bf4ca5c0cefdf5"
integrity sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw==
dependencies:
"@types/node" "*"
"@types/valid-url@1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@types/valid-url/-/valid-url-1.0.2.tgz#60fa435ce24bfd5ba107b8d2a80796aeaf3a8f45"
@ -1463,6 +1512,11 @@ any-observable@^0.3.0:
resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b"
integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==
any-promise@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
integrity sha1-q8av7tzqUugJzcA3au0845Y10X8=
anymatch@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
@ -1617,6 +1671,11 @@ apollo-utilities@^1.0.0, apollo-utilities@^1.0.1:
dependencies:
fast-json-stable-stringify "^2.0.0"
app-root-path@^2.0.1:
version "2.1.0"
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.1.0.tgz#98bf6599327ecea199309866e8140368fd2e646a"
integrity sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo=
aproba@^1.0.3, aproba@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@ -2140,7 +2199,7 @@ buffer@^4.3.0:
ieee754 "^1.1.4"
isarray "^1.0.0"
buffer@^5.0.3:
buffer@^5.0.3, buffer@^5.1.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6"
integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==
@ -2234,7 +2293,7 @@ caseless@~0.12.0:
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
chalk@2.4.2, chalk@^2.0.1:
chalk@2.4.2, chalk@^2.0.1, chalk@^2.3.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@ -2243,7 +2302,7 @@ chalk@2.4.2, chalk@^2.0.1:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@^1.0.0, chalk@^1.1.3:
chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
@ -2366,6 +2425,17 @@ cli-cursor@^2.0.0, cli-cursor@^2.1.0:
dependencies:
restore-cursor "^2.0.0"
cli-highlight@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/cli-highlight/-/cli-highlight-1.2.3.tgz#b200f97ed0e43d24633e89de0f489a48bb87d2bf"
integrity sha512-cmc4Y2kJuEpT2KZd9pgWWskpDMMfJu2roIcY1Ya/aIItufF5FKsV/NtA6vvdhSUllR8KJfvQDNmIcskU+MKLDg==
dependencies:
chalk "^2.3.0"
highlight.js "^9.6.0"
mz "^2.4.0"
parse5 "^3.0.3"
yargs "^10.0.3"
cli-truncate@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574"
@ -2469,7 +2539,7 @@ commander@2.17.x, commander@~2.17.1:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
commander@2.19.0, commander@^2.12.1:
commander@2.19.0, commander@^2.12.1, commander@^2.9.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
@ -2678,6 +2748,15 @@ cross-fetch@2.2.2:
node-fetch "2.1.2"
whatwg-fetch "2.0.4"
cross-spawn@^5.0.1:
version "5.1.0"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=
dependencies:
lru-cache "^4.0.1"
shebang-command "^1.2.0"
which "^1.2.9"
cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
@ -2812,7 +2891,7 @@ debug@^4.1.0:
dependencies:
ms "^2.1.1"
decamelize@^1.2.0:
decamelize@^1.1.1, decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
@ -2829,6 +2908,11 @@ decode-uri-component@^0.2.0:
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
dedent@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=
deep-equal@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
@ -3082,6 +3166,11 @@ dot-case@^2.1.0:
dependencies:
no-case "^2.2.0"
dotenv@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef"
integrity sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==
duplexify@^3.4.2, duplexify@^3.6.0:
version "3.6.1"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.6.1.tgz#b1a7a29c4abfd639585efaecce80d666b1e34125"
@ -3331,6 +3420,19 @@ execa@^0.10.0:
signal-exit "^3.0.0"
strip-eof "^1.0.0"
execa@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=
dependencies:
cross-spawn "^5.0.1"
get-stream "^3.0.0"
is-stream "^1.1.0"
npm-run-path "^2.0.0"
p-finally "^1.0.0"
signal-exit "^3.0.0"
strip-eof "^1.0.0"
expand-brackets@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
@ -3500,6 +3602,11 @@ figgy-pudding@^3.1.0, figgy-pudding@^3.5.1:
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
figlet@^1.1.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/figlet/-/figlet-1.2.1.tgz#48d35df9d9b10b1b3888302e6e57904a0b00509c"
integrity sha512-qc8gycfnnfOmfvPl7Fi3JeTbcvdmbZkckyUVGGAM02je7Ookvu+bBfKy1I4FKqTsQHCs3ARJ76ip/k98r+OQuQ==
figures@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
@ -3845,6 +3952,17 @@ googleapis@^31.0.2:
url-template "^2.0.8"
uuid "^3.2.1"
gql2ts@^1.10.1:
version "1.10.1"
resolved "https://registry.yarnpkg.com/gql2ts/-/gql2ts-1.10.1.tgz#aae1a1312744f7c9b36abf78437413ea317f6a71"
integrity sha512-Kwa1Db1e3qGediBi1A5wX98UBKmvUklsQgfLwk7J8bj9RQ4AkAwTToFvUmKhflKTZndAtQbdOJWwm5cmgXsLYA==
dependencies:
"@gql2ts/from-query" "^1.9.0"
"@gql2ts/from-schema" "^1.10.1"
"@gql2ts/util" "^1.9.0"
commander "^2.9.0"
graphql ">= 0.10 <15"
graceful-fs@^4.1.11, graceful-fs@^4.1.2:
version "4.1.15"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
@ -3885,13 +4003,6 @@ graphql-code-generator@^0.16.0:
request "2.88.0"
valid-url "1.0.9"
graphql-codegen-add@^0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/graphql-codegen-add/-/graphql-codegen-add-0.16.0.tgz#f1c19166d12a4174c597719b42facb7502b04fc8"
integrity sha512-6Zi993CXlfyLmqS8dqmlCbSbCAFzEoS7rN5PPvDgwyxiJ6SAdzGN+TjCRJUSWS9BuaI4rSgM1nGyRYG0erkeGg==
dependencies:
graphql-codegen-core "0.16.0"
graphql-codegen-core@0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/graphql-codegen-core/-/graphql-codegen-core-0.16.0.tgz#04f19e231fcf27fb9911a192620f8567322bbf69"
@ -3905,48 +4016,6 @@ graphql-codegen-core@0.16.0:
ts-log "2.1.4"
winston "3.1.0"
graphql-codegen-plugin-helpers@0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/graphql-codegen-plugin-helpers/-/graphql-codegen-plugin-helpers-0.16.0.tgz#1b662df373b393d021499247e650f12bb22c1878"
integrity sha512-cigkirFkhe5aa/dFR90kpKvuGBwvltTRpgo+ZQSEIgkM86jeJS4Vju9XsynqgsjVZpdsJlj/sfrWH4xB3UzsWQ==
dependencies:
graphql-codegen-core "0.16.0"
import-from "2.1.0"
graphql-codegen-typescript-common@0.16.0, graphql-codegen-typescript-common@^0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/graphql-codegen-typescript-common/-/graphql-codegen-typescript-common-0.16.0.tgz#7f13060b2071e4d8e25ee9ffe85db075e3a5a13d"
integrity sha512-tZxIzSl3UgoLSTlQaobFrLq1ovYN6ALYjAZReJJcvkz1/ACZbw7rX6OMR0hakpp93kkH5J8Em7Cx6uzKSvsTlA==
dependencies:
change-case "3.1.0"
common-tags "1.8.0"
graphql-codegen-core "0.16.0"
graphql-codegen-plugin-helpers "0.16.0"
graphql-codegen-typescript-mongodb@^0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/graphql-codegen-typescript-mongodb/-/graphql-codegen-typescript-mongodb-0.16.0.tgz#3e0a2ac468ff74743fb03c037cedcc3f3b7c99ef"
integrity sha512-u0HR1qVxBXL4KOLO8fsHGpVC2/upnknaCId132ujbJes0TJN9guibcis4RiExOJ2P+rX/2tCTyeAMl5ONJRplw==
dependencies:
graphql-codegen-core "0.16.0"
graphql-codegen-plugin-helpers "0.16.0"
graphql-codegen-typescript-common "0.16.0"
graphql-codegen-typescript-resolvers@^0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/graphql-codegen-typescript-resolvers/-/graphql-codegen-typescript-resolvers-0.16.0.tgz#e38c8a2bd867d93c554f07ff4a37ae037d17dc32"
integrity sha512-uaEs7/KH+IPgg8tuRXlkbIAedCn013BBk8qxsbT1ITr0XAzojM80fkpMWtA0oicLOxWbjoxRVQVpeVVYZrhQMQ==
dependencies:
graphql-codegen-plugin-helpers "0.16.0"
graphql-codegen-typescript-common "0.16.0"
graphql-codegen-typescript-server@^0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/graphql-codegen-typescript-server/-/graphql-codegen-typescript-server-0.16.0.tgz#e747ce0e670374884d797d389288c8a52ced1997"
integrity sha512-sIhNi7LJM9F6FHPA6Zh4R8JhcGgda324ToIYX9gcU1dHBcHJRyVgzN7jsgOcDnpzIJwPnEa6LzX6MpSssygH5g==
dependencies:
graphql-codegen-typescript-common "0.16.0"
graphql-config@2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/graphql-config/-/graphql-config-2.2.1.tgz#5fd0ec77ac7428ca5fb2026cf131be10151a0cb2"
@ -4026,6 +4095,13 @@ graphql-tools@4.0.3, graphql-tools@^4.0.0, graphql-tools@^4.0.3:
iterall "^1.1.3"
uuid "^3.1.0"
"graphql@>= 0.10 <15":
version "14.1.1"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.1.1.tgz#d5d77df4b19ef41538d7215d1e7a28834619fac0"
integrity sha512-C5zDzLqvfPAgTtP8AUPIt9keDabrdRAqSWjj2OPRKrKxI9Fb65I36s1uCs1UUBFnSWTdO7hyHi7z1ZbwKMKF6Q==
dependencies:
iterall "^1.2.2"
graphql@^14.0.2:
version "14.0.2"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.0.2.tgz#7dded337a4c3fd2d075692323384034b357f5650"
@ -4161,6 +4237,11 @@ header-case@^1.0.0:
no-case "^2.2.0"
upper-case "^1.1.3"
highlight.js@^9.6.0:
version "9.15.6"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.6.tgz#72d4d8d779ec066af9a17cb14360c3def0aa57c4"
integrity sha512-zozTAWM1D6sozHo8kqhfYgsac+B+q0PmsjXeyDrYIHHcBN0zTVT66+s2GW1GZv7DbyaROdLXKdabwS/WqPyIdQ==
history@^4.7.2:
version "4.7.2"
resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b"
@ -4352,6 +4433,11 @@ https-proxy-agent@^2.2.1:
agent-base "^4.1.0"
debug "^3.1.0"
humps@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/humps/-/humps-2.0.1.tgz#dd02ea6081bd0568dc5d073184463957ba9ef9aa"
integrity sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao=
hyphenate-style-name@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b"
@ -4388,13 +4474,6 @@ ignore-walk@^3.0.1:
dependencies:
minimatch "^3.0.4"
import-from@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1"
integrity sha1-M1238qev/VOqpHHUuAId7ja387E=
dependencies:
resolve-from "^3.0.0"
import-local@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d"
@ -4497,6 +4576,11 @@ invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.4:
dependencies:
loose-envify "^1.0.0"
invert-kv@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY=
invert-kv@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
@ -4860,6 +4944,14 @@ js-yaml@3.12.1, js-yaml@^3.10.0:
argparse "^1.0.7"
esprima "^4.0.0"
js-yaml@^3.11.0:
version "3.12.2"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.2.tgz#ef1d067c5a9d9cb65bd72f285b5d8105c77f14fc"
integrity sha512-QHn/Lh/7HhZ/Twc7vJYQTkjuCa0kaCcDcjK5Zlk2rvnUpy7DxMJ23+Jc2dcyvltwQVg1nygAVlB2oRDFHoRS5Q==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
js-yaml@^3.7.0:
version "3.12.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1"
@ -5068,6 +5160,13 @@ kuler@1.0.x:
dependencies:
colornames "^1.1.1"
lcid@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=
dependencies:
invert-kv "^1.0.0"
lcid@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
@ -5280,7 +5379,7 @@ lower-case@^1.1.0, lower-case@^1.1.1, lower-case@^1.1.2:
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
lru-cache@^4.1.3:
lru-cache@^4.0.1, lru-cache@^4.1.3:
version "4.1.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
@ -5360,6 +5459,13 @@ media-typer@0.3.0:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
mem@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76"
integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=
dependencies:
mimic-fn "^1.0.0"
mem@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/mem/-/mem-4.0.0.tgz#6437690d9471678f6cc83659c00cbafcd6b0cdaf"
@ -5602,6 +5708,15 @@ mute-stream@0.0.7:
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
mz@^2.4.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
dependencies:
any-promise "^1.0.0"
object-assign "^4.0.1"
thenify-all "^1.0.0"
nan@^2.9.2:
version "2.11.1"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766"
@ -5941,6 +6056,15 @@ os-homedir@^1.0.0:
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
os-locale@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2"
integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==
dependencies:
execa "^0.7.0"
lcid "^1.0.0"
mem "^1.1.0"
os-locale@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.0.1.tgz#3b014fbf01d87f60a1e5348d80fe870dc82c4620"
@ -6072,6 +6196,11 @@ param-case@2.1.x, param-case@^2.1.0:
dependencies:
no-case "^2.2.0"
parent-require@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/parent-require/-/parent-require-1.0.0.tgz#746a167638083a860b0eef6732cb27ed46c32977"
integrity sha1-dGoWdjgIOoYLDu9nMssn7UbDKXc=
parse-asn1@^5.0.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8"
@ -6083,6 +6212,13 @@ parse-asn1@^5.0.0:
evp_bytestokey "^1.0.0"
pbkdf2 "^3.0.3"
parse5@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c"
integrity sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==
dependencies:
"@types/node" "*"
parseurl@~1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
@ -6660,6 +6796,11 @@ redbox-react@^1.2.5:
prop-types "^15.5.4"
sourcemapped-stacktrace "^1.1.6"
reflect-metadata@^0.1.12:
version "0.1.13"
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==
regenerate-unicode-properties@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c"
@ -6933,7 +7074,7 @@ saslprep@^1.0.0:
dependencies:
sparse-bitfield "^3.0.3"
sax@^1.2.4:
sax@>=0.6.0, sax@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
@ -7598,6 +7739,20 @@ text-hex@1.0.x:
resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"
integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==
thenify-all@^1.0.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=
dependencies:
thenify ">= 3.1.0 < 4"
"thenify@>= 3.1.0 < 4":
version "3.3.0"
resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839"
integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=
dependencies:
any-promise "^1.0.0"
through2@^2.0.0:
version "2.0.5"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
@ -7830,6 +7985,26 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
typeorm@^0.2.14:
version "0.2.14"
resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.14.tgz#5bd39de1306977e7ccdb31c3915018374415e9ff"
integrity sha512-kPV8nX7g7hvFpuzdLKGxqkVRHEJe9AK6csgWJJPaCFU3NrLmUG6a2Q0FxY/Z0Qy/2gqt5VG3t3FyFpw360XSvg==
dependencies:
app-root-path "^2.0.1"
buffer "^5.1.0"
chalk "^2.3.2"
cli-highlight "^1.2.3"
debug "^3.1.0"
dotenv "^5.0.1"
glob "^7.1.2"
js-yaml "^3.11.0"
mkdirp "^0.5.1"
reflect-metadata "^0.1.12"
tslib "^1.9.0"
xml2js "^0.4.17"
yargonaut "^1.1.2"
yargs "^12.0.5"
typescript@^3.1.1:
version "3.2.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.2.2.tgz#fe8101c46aa123f8353523ebdcf5730c2ae493e5"
@ -8304,6 +8479,19 @@ ws@^6.0.0:
dependencies:
async-limiter "~1.0.0"
xml2js@^0.4.17:
version "0.4.19"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7"
integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==
dependencies:
sax ">=0.6.0"
xmlbuilder "~9.0.1"
xmlbuilder@~9.0.1:
version "9.0.7"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=
xregexp@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943"
@ -8319,6 +8507,11 @@ xtend@^4.0.0, xtend@~4.0.1:
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
y18n@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
@ -8334,6 +8527,15 @@ yallist@^3.0.0, yallist@^3.0.2:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==
yargonaut@^1.1.2:
version "1.1.4"
resolved "https://registry.yarnpkg.com/yargonaut/-/yargonaut-1.1.4.tgz#c64f56432c7465271221f53f5cc517890c3d6e0c"
integrity sha512-rHgFmbgXAAzl+1nngqOcwEljqHGG9uUZoPjsdZEs1w5JW9RXYzrSvH/u70C1JE5qFi0qjsdhnUX/dJRpWqitSA==
dependencies:
chalk "^1.1.1"
figlet "^1.1.1"
parent-require "^1.0.0"
yargs-parser@10.x, yargs-parser@^10.1.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
@ -8349,6 +8551,13 @@ yargs-parser@^11.1.1:
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs-parser@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950"
integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==
dependencies:
camelcase "^4.1.0"
yargs@12.0.2:
version "12.0.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.2.tgz#fe58234369392af33ecbef53819171eff0f5aadc"
@ -8367,7 +8576,25 @@ yargs@12.0.2:
y18n "^3.2.1 || ^4.0.0"
yargs-parser "^10.1.0"
yargs@^12.0.2:
yargs@^10.0.3:
version "10.1.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5"
integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==
dependencies:
cliui "^4.0.0"
decamelize "^1.1.1"
find-up "^2.1.0"
get-caller-file "^1.0.1"
os-locale "^2.0.0"
require-directory "^2.1.1"
require-main-filename "^1.0.1"
set-blocking "^2.0.0"
string-width "^2.0.0"
which-module "^2.0.0"
y18n "^3.2.1"
yargs-parser "^8.1.0"
yargs@^12.0.2, yargs@^12.0.5:
version "12.0.5"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==