Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/entity/Tomato.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Field, ID, ObjectType } from "type-graphql";
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from "typeorm";
import { autoQueries } from "../modules/dynamic/AutoDecorators";
import { findAll, findOne } from "../modules/dynamic/MyQueries";

@autoQueries([findAll, findOne])
@ObjectType()
@Entity()
export class Tomato extends BaseEntity {
@Field(() => ID)
@PrimaryGeneratedColumn()
id: number;

@Column()
size: number;
}
11 changes: 6 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import "reflect-metadata";
import { ApolloServer } from "apollo-server-express";
import connectRedis from "connect-redis";
import cors from "cors";
import Express from "express";
import session from "express-session";
import "reflect-metadata";
import { formatArgumentValidationError } from "type-graphql";
import { createConnection } from "typeorm";
import session from "express-session";
import connectRedis from "connect-redis";
import cors from "cors";

import { redis } from "./redis";
// @ts-ignore
import { createSchema } from "./utils/createSchema";

const main = async () => {
await createConnection();

// @ts-ignore
const schema = await createSchema();

const apolloServer = new ApolloServer({
Expand Down
18 changes: 18 additions & 0 deletions src/modules/dynamic/AutoDecorators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Query } from "type-graphql";
import { newR } from "./DynamicResolvers";
import { createResolver } from "./ResolversFactory";

// @ts-ignore
export function autoQueries(queries: any[]): any {
return function(target: any) {
const resolverClass = createResolver(
target.name,
target,
class {},
target,
[{ genre: Query, meth: queries }]
);

newR.resolvers = [resolverClass];
};
}
15 changes: 15 additions & 0 deletions src/modules/dynamic/DynamicResolvers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class DynamicResolvers {
private _resolvers: any[] = [];

get resolvers(): any[] {
return this._resolvers;
}

set resolvers(resolver: any[]) {
this._resolvers.push(...resolver);
}

empty() {}
}

export const newR = new DynamicResolvers();
6 changes: 6 additions & 0 deletions src/modules/dynamic/MyMutations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const createM = (data: any) => {
console.log("mutation create data: ", data);
};
export const deleteM = (data: any) => {
console.log("mutation delete data: ", data);
};
6 changes: 6 additions & 0 deletions src/modules/dynamic/MyQueries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export function findAll(data: any) {
console.log("query findAll data: ", data);
}
export function findOne(data: any) {
console.log("query findOne data: ", data);
}
82 changes: 82 additions & 0 deletions src/modules/dynamic/ResolversFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { ClassType, Query, Resolver } from "type-graphql";

// @ts-ignore
export function createResolver<T extends ClassType, X extends ClassType>(
suffix: string,
returnType: T,
// @ts-ignore
inputType: X,
// @ts-ignore
entity: any,
operations: any[]
): any {
function classDecorator(): any {
console.log("classDecorator operations: ", operations);
return function(
target: any,
// @ts-ignore
propertyKey: string,
// @ts-ignore
descriptor: PropertyDescriptor
) {
operations.forEach(oper => {
// @ts-ignore
const deco = oper.genre;
console.log("classDecorator deco: ", deco);
// @ts-ignore
oper.meth.forEach(method => {
target.prototype[method.name] = method;
const targetPrototype = target.prototype;
const methodKey = method.name;
// @ts-ignore
deco(() => returnType, {
name: `${method.name}${suffix}`,
nullable: true
})(
targetPrototype,
// @ts-ignore
methodKey
);
console.log("classDecorator targetPrototype: ", targetPrototype);
});
});
/* console.log("target: ", target);
console.log("propertyKey: ", propertyKey);
console.log("descriptor: ", descriptor); */
};
}

@classDecorator()
@Resolver()
class ResolversFactory {
@Query(() => String, {
nullable: true
})
base() {
return console.log("base query");
}
}

return ResolversFactory;
}

/*
* List of type-graphql decorators and their needed parameters:
* ParameterDecorator: prototype, propertyKey, parameterIndex
* Arg, Args, Ctx, Info, PubSub, Root,
*
* ClassDecorator: target
* ArgsType, InputType, InterfaceType, ObjectType, Resolver,
*
* MethodAndPropDecorator: prototype, propertyKey, descriptor
* Authorized, Field,
*
* MethodDecorator: prototype, propertyKey/methodName
* FieldResolver, Mutation, Query, Subscription,
*
* UseMiddleware can be: MethodAndPropDecorator, MethodDecorator , PropertyDecorator
*
* registerEnumType accepts enumObj and EnumConfig
* createUnionType to be seen better
*
*/
12 changes: 6 additions & 6 deletions src/modules/user/CreateUser.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import {
Resolver,
Mutation,
Arg,
ClassType,
InputType,
Field,
InputType,
Mutation,
Resolver,
UseMiddleware
} from "type-graphql";
import { RegisterInput } from "./register/RegisterInput";
import { User } from "../../entity/User";
import { Product } from "../../entity/Product";
import { Middleware } from "type-graphql/interfaces/Middleware";
import { Product } from "../../entity/Product";
import { User } from "../../entity/User";
import { RegisterInput } from "./register/RegisterInput";

function createResolver<T extends ClassType, X extends ClassType>(
suffix: string,
Expand Down
3 changes: 1 addition & 2 deletions src/modules/user/Login.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Resolver, Mutation, Arg, Ctx } from "type-graphql";
import bcrypt from "bcryptjs";

import { Arg, Ctx, Mutation, Resolver } from "type-graphql";
import { User } from "../../entity/User";
import { MyContext } from "../../types/MyContext";

Expand Down
67 changes: 46 additions & 21 deletions src/utils/createSchema.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,55 @@
import { buildSchema } from "type-graphql";
import { newR } from "../modules/dynamic/DynamicResolvers";
import { ChangePasswordResolver } from "../modules/user/ChangePassword";
import { ConfirmUserResolver } from "../modules/user/ConfirmUser";
import {
CreateProductResolver,
CreateUserResolver
} from "../modules/user/CreateUser";
import { ForgotPasswordResolver } from "../modules/user/ForgotPassword";
import { LoginResolver } from "../modules/user/Login";
import { LogoutResolver } from "../modules/user/Logout";
import { MeResolver } from "../modules/user/Me";
import { RegisterResolver } from "../modules/user/Register";
import {
CreateUserResolver,
CreateProductResolver
} from "../modules/user/CreateUser";

export const createSchema = () =>
buildSchema({
resolvers: [
ChangePasswordResolver,
ConfirmUserResolver,
ForgotPasswordResolver,
LoginResolver,
LogoutResolver,
MeResolver,
RegisterResolver,
CreateUserResolver,
CreateProductResolver
],
authChecker: ({ context: { req } }) => {
return !!req.session.userId;
}
});
let createSchema;
const init = async () => {
// quick and dirty loader. Put here to secure correct call order of the decorators
// but Not sure if needed. needs test
// https://stackoverflow.com/questions/5364928/node-js-require-all-files-in-a-folder
var normalizedPath = require("path").join(__dirname, "../entity");

const fs = require("fs");
await fs
.readdirSync(normalizedPath)
//@ts-ignore
.forEach(function(file) {
import("../entity/" + file);
});
//@ts-ignore
const dynaResolver = newR.resolvers;
//@ts-ignore
const allResolvers = [
ChangePasswordResolver,
ConfirmUserResolver,
ForgotPasswordResolver,
LoginResolver,
LogoutResolver,
MeResolver,
RegisterResolver,
CreateUserResolver,
CreateProductResolver
];
allResolvers.push(...dynaResolver);

createSchema = () =>
buildSchema({
resolvers: allResolvers,
authChecker: ({ context: { req } }) => {
return !!req.session.userId;
}
});
};
init();

export { createSchema };