diff --git a/package.json b/package.json index f6f01fdc..128f958f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,8 @@ { "name": "wertik-js", - "version": "3.0.8-beta", + "version": "3.1.0-beta", "main": "lib/main.js", + "types": "lib/types.d.ts", "repository": "https://github.com/Uconnect-Technologies/wertik-js.git", "keywords": [ "mysql", @@ -36,7 +37,7 @@ "prettier" ], "dependencies": { - "apollo-server": "^2.8.2", + "apollo-server": "^3.5.0", "apollo-server-express": "^2.9.4", "aws-sdk": "^2.820.0", "bcryptjs": "^2.4.3", @@ -45,11 +46,10 @@ "cors": "^2.8.5", "dropbox": "^8.2.0", "express": "^4.17.1", - "graphql": "^14.1.1", + "graphql": "^15.7.2", "graphql-fields": "^2.0.3", "graphql-type-json": "^0.3.2", "handlebars": "^4.5.3", - "jsonwebtoken": "^8.4.0", "lodash": "^4.17.15", "log-symbols": "^3.0.0", "moment": "^2.23.0", @@ -59,11 +59,7 @@ "mysqldump": "^3.2.0", "node-cron": "^2.0.3", "nodemailer": ">=6.4.16", - "pg": "^7.18.2", - "pg-hstore": "^2.3.3", - "request-ip": "^2.1.3", "sequelize": "^6.3.5", - "shelljs": "^0.8.3", "socket.io": "^4.1.3", "winston": "^3.1.0", "ws": "^8.0.0" @@ -74,7 +70,6 @@ "@types/dotenv": "^4.0.3", "@types/express": "^4.16.0", "@types/http-codes": "^1.0.1", - "@types/jsonwebtoken": "^7.2.8", "@types/knex": "^0.14.19", "@types/morgan": "^1.7.35", "@types/node": "^9.6.55", @@ -82,10 +77,8 @@ "@types/winston": "^2.4.4", "concurrently": "^3.6.1", "dotenv": "^6.2.0", - "module-alias": "^2.1.0", "nodemon": "^1.18.9", "prettier": "^2.3.2", - "sequelize-cli": "^5.4.0", "tslint": "^5.17.0", "typescript": "^3.5.1" } diff --git a/src/framework/builtinModules/auth/handlers/index.ts b/src/framework/builtinModules/auth/handlers/index.ts deleted file mode 100644 index 99162484..00000000 --- a/src/framework/builtinModules/auth/handlers/index.ts +++ /dev/null @@ -1,243 +0,0 @@ -import moment from "moment"; -import createJwtToken from "./../../../../framework/security/createJwtToken"; -import { ApolloError } from "apollo-server"; -import { - verifyPassword, - generateHashPassword, -} from "./../../../../framework/helpers/auth"; -import { get } from "lodash"; - -export const signup = async function (obj) { - const { userModel, data, emailTemplates, sendEmail, configuration } = obj; - const { sendEmailOnSignup } = get( - configuration, - "email.sendEmailOnSignup", - true - ); - let { email, password, confirmPassword, ...restData } = data; - if (password !== confirmPassword) - throw new ApolloError("Passwords doesn't match."); - let user = await userModel.findOne({ - where: { - email: email, - }, - }); - if (user) throw new ApolloError("Email is already used"); - var hash = generateHashPassword(password); - let newUser = await userModel.create({ - email: email, - referer: get(data, "referer", ""), - superUser: false, - name: get(data, "name", ""), - accessToken: await createJwtToken({ - email: email, - for: "authentication", - expiresIn: moment().add(5, "days").unix(), - }), - refreshToken: await createJwtToken({ - email: email, - for: "refreshToken", - expiresIn: moment().add(5, "days").unix(), - }), - isActivated: false, - isSuperUser: get(data, "isSuperUser", false), - activationToken: - Math.random().toString(36).substring(2) + - Math.random().toString(36).substring(2) + - Math.random().toString(36).substring(2), - password: hash, - ...restData, - }); - let userInstance = newUser; - if (sendEmailOnSignup) { - await sendEmail( - emailTemplates.welcome, - { - email: newUser.email, - username: newUser.email, - date: moment().format("dddd, MMMM Do YYYY, h:mm:ss a"), - siteName: process.env.name, - activationUrl: `${process.env.frontendAppUrl}/activate-account/`, - activationToken: newUser.activationToken, - }, - { - from: process.env.mailerServiceUsername, - to: newUser.email, - subject: `Welcome to ${process.env.name}`, - } - ); - } - return { - message: "Signup Completed", - returning: userInstance, - }; -}; -export const login = async function ( - obj, - NoUserFoundMessage: string = '"No User found with such email"' -) { - const { userModel, data } = obj; - const { email, password } = data; - const restArgs = get(data, "restArgs", {}); - let user = await userModel.findOne({ - where: { - email: email, - ...restArgs, - }, - }); - if (!user) { - throw new ApolloError(NoUserFoundMessage); - } - let comparePassword = await verifyPassword(password, user.password); - if (!comparePassword) { - throw new ApolloError("Incorrect Password"); - } - let token = await createJwtToken({ - email: email, - for: "authentication", - expiresIn: moment().add(5, "days").unix(), - }); - user = await user.update({ - accessToken: token, - }); - return { - message: "Login Completed", - returning: user, - }; -}; -export const twoFactorLogin = async function (obj) { - const { userModel, emailTemplates, sendEmail, data } = obj; - const { email } = data; - let user = await userModel.findOne({ - where: { - email: email, - }, - }); - if (!user) { - throw new ApolloError("Incorrect email."); - } - const twoFactorCode = `Code-` + Math.floor(Math.random() * 60000 + 5000); - user = await user.update({ - twoFactorCode: twoFactorCode, - }); - let userInstance = user; - await sendEmail( - emailTemplates.twoFactorLogin, - { - username: user.email, - siteName: process.env.name, - twoFactorCode: twoFactorCode, - }, - { - from: process.env.mailerServiceUsername, - to: user.email, - subject: `${twoFactorCode} is your authentication number - ${process.env.name}`, - } - ); - return { - message: `A code has been sent to your email which is ${userInstance.email}`, - }; -}; -export const twoFactorLoginValidate = async function (obj) { - const { userModel, data } = obj; - const { twoFactorCode } = data; - let user = await userModel.findOne({ - where: { - twoFactorCode: twoFactorCode, - }, - }); - if (!user) { - throw new ApolloError("Incorrect twoFactorCode or already used."); - } - user = await user.update({ - twoFactorCode: "", - accessToken: await createJwtToken({ - email: user.email, - for: "authentication", - }), - refreshToken: await createJwtToken({ - email: user.email, - for: "authentication", - }), - }); - return user; -}; -export const loginWithAccessToken = async function (obj) { - const { userModel, data } = obj; - const { accessToken } = data; - let user = await userModel.findOne({ - where: { - accessToken: accessToken, - }, - }); - if (!user) { - throw new ApolloError("Access token is missing."); - } - user = await user.update({ - accessToken: await createJwtToken({ - email: user.email, - for: "authentication", - }), - refreshToken: await createJwtToken({ - email: user.email, - for: "authentication", - }), - }); - return user; -}; -export const activateAccount = async function (obj) { - const { userModel, emailTemplates, sendEmail, data } = obj; - const { activationToken } = data; - let user = await userModel.findOne({ - where: { - activation_token: activationToken, - }, - }); - if (!user) { - throw new ApolloError("No User found or account is already is activated."); - } - user = await user.update({ - is_activated: true, - activation_token: "", - }); - let userInstance = user; - (await sendEmail) && - sendEmail( - emailTemplates.accountActivated, - { - username: user.email, - siteName: process.env.name, - }, - { - from: process.env.mailerServiceUsername, - to: user.email, - subject: `Account activated ${process.env.name}`, - } - ); - return { - message: "Account activated", - }; -}; -export const refreshTokenHandler = async function (obj) { - const { userModel, data } = obj; - const { refreshToken } = data; - let user = await userModel.findOne({ - where: { - refreshToken: refreshToken, - }, - }); - if (!user) { - throw new ApolloError("Unauthorized, Missing refresh token."); - } - user = await user.update({ - accessToken: await createJwtToken({ - email: user.email, - for: "authentication", - }), - refreshToken: await createJwtToken({ - email: user.email, - for: "authentication", - }), - }); - return user; -}; diff --git a/src/framework/builtinModules/auth/index.ts b/src/framework/builtinModules/auth/index.ts deleted file mode 100644 index 67556003..00000000 --- a/src/framework/builtinModules/auth/index.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { - login, - signup, - loginWithAccessToken, - activateAccount, - refreshTokenHandler, - twoFactorLogin, - twoFactorLoginValidate, -} from "./handlers/index"; - -export default { - name: "Auth", - useDatabase: false, - graphql: { - schema: ` - input TwoFactorCodeInput { - twoFactorCode: String! - } - input AccessTokenInput { - accessToken: String! - } - input ActivationTokenInput { - activationToken: String! - } - input RefreshTokenInput { - refreshToken: String! - } - input loginInput { - email: String! - password: String! - } - type AuthResponse { - message: String - returning: User - } - `, - mutation: { - schema: ` - twoFactorLogin(input: EmailInputFP): SuccessResponse - twoFactorLoginValidate(input: TwoFactorCodeInput): User - loginWithAccessToken(input: AccessTokenInput): User - activateAccount(input: ActivationTokenInput): SuccessResponse - signup(input: SignupInput): AuthResponse - login(input: loginInput): AuthResponse - refreshToken(input: RefreshTokenInput): User - `, - resolvers: { - twoFactorLogin: async (_: any, args: any, context: any, info: any) => { - return await twoFactorLogin({ - userModel: context.wertik.models["User"], - emailTemplates: context.wertik.emailTemplates, - sendEmail: context.wertik.sendEmail, - data: args.input, - }); - }, - twoFactorLoginValidate: async ( - _: any, - args: any, - context: any, - info: any - ) => { - return await twoFactorLoginValidate({ - userModel: context.wertik.models["User"], - data: args.input, - }); - }, - loginWithAccessToken: async ( - _: any, - args: any, - context: any, - info: any - ) => { - return await loginWithAccessToken({ - userModel: context.wertik.models["User"], - data: args.input, - }); - }, - activateAccount: async (_: any, args: any, context: any, info: any) => { - return await activateAccount({ - userModel: context.wertik.models["User"], - emailTemplates: context.wertik.emailTemplates, - sendEmail: context.wertik.sendEmail, - data: args.input, - }); - }, - signup: async (_: any, args: any, context: any, info: any) => { - return await signup({ - userModel: context.wertik.models["User"], - emailTemplates: context.wertik.emailTemplates, - sendEmail: context.wertik.sendEmail, - data: args.input, - configuration: context.wertik.configuration, - }); - }, - login: async (_: any, args: any, context: any, info: any) => { - return await login({ - userModel: context.wertik.models["User"], - data: args.input, - }); - }, - refreshToken: async (_: any, args: any, context: any, info: any) => { - return await refreshTokenHandler({ - userModel: context.wertik.models["User"], - data: args.input, - }); - }, - }, - }, - query: { - schema: ``, - resolvers: {}, - }, - }, - restApi: { - endpoints: [], - }, -}; diff --git a/src/framework/builtinModules/forgetPassword/handlers/index.ts b/src/framework/builtinModules/forgetPassword/handlers/index.ts deleted file mode 100644 index c97a0d5b..00000000 --- a/src/framework/builtinModules/forgetPassword/handlers/index.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { ApolloError } from "apollo-server"; -import createJwtToken from "./../../../security/createJwtToken"; -import { randomString } from "./../../../helpers/index"; -import moment from "moment"; -import { generateHashPassword } from "../../../helpers/auth"; - -export const requestPasswordResetHandler = async function (obj) { - const { userModel, forgetPasswordModel, data, emailTemplates, sendEmail } = - obj; - let user = await userModel.findOne({ - where: { - email: data.email, - }, - }); - if (!user.instance) throw new ApolloError("No User found with such email."); - let forgetPassword = await forgetPasswordModel.findOne({ - where: { - email: data.email, - }, - }); - if (forgetPassword.instance) { - await forgetPassword.delete(); - } - let token = randomString(24, "MYNAMEISILYASKARIMANDIVETHESENUMBERS123456789"); - await forgetPasswordModel.create({ - token: token, - email: user.instance.email, - user: user.instance.id, - expiresIn: moment().add(30, "m").unix(), - }); - await sendEmail( - emailTemplates.requestPasswordReset, - { - email: user.instance.email, - nextMinutes: moment().add(30, "m").format("LLLL"), - token: token, - siteName: process.env.name, - frontendAppPasswordResetUrl: process.env.frontendAppPasswordResetUrl, - }, - { - from: process.env.mailerServiceUsername, - to: user.instance.email, - subject: `Reset Password`, - } - ); - return { - message: "Please check your email", - }; -}; - -export const resetPasswordHandler = async function (obj) { - const { userModel, forgetPasswordModel, data } = obj; - const { token, password, confirmPassword } = data; - let forgetPassword = await forgetPasswordModel.findOne({ - where: { - token: token, - }, - }); - if (!forgetPassword.instance) - throw new ApolloError("Token mismatch or already used."); - let user = await userModel.findOne({ - where: { - email: forgetPassword.instance.email, - }, - }); - if (!user.instance) throw new ApolloError("User not found"); - const hash = generateHashPassword(password); - await user.update({ - password: hash, - }); - await forgetPassword.delete(); - return { - message: "Password changed", - }; -}; diff --git a/src/framework/builtinModules/forgetPassword/index.ts b/src/framework/builtinModules/forgetPassword/index.ts deleted file mode 100644 index e0082e2e..00000000 --- a/src/framework/builtinModules/forgetPassword/index.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { requestPasswordResetHandler, resetPasswordHandler } from "./handlers"; -import getRequestedFieldsFromResolverInfo from "./../../helpers/getRequestedFieldsFromResolverInfo"; - -export default { - name: "ForgetPassword", - graphql: { - schema: ` - type ForgetPassword { - id: Int - name: String - email: String - user: User - user_id: Int - token: String - created_at: String - updated_at: String - } - input requestPasswordResetInput { - email: String! - } - input resetPasswordInput { - token: String! - password: String! - confirmPassword: String! - } - input ForgetPasswordInput { - id: Int - name: String - email: String - user_id: Int - token: String - } - `, - customResolvers: {}, - mutation: { - schema: ` - requestPasswordReset(input: requestPasswordResetInput): SuccessResponse - resetPassword(input: resetPasswordInput): SuccessResponse - `, - resolvers: { - requestPasswordReset: async ( - _: any, - args: any, - context: any, - info: any - ) => { - return await requestPasswordResetHandler({ - userModel: context.wertik.models.User, - forgetPasswordModel: context.wertik.models.ForgetPassword, - data: args.input, - emailTemplates: context.wertik.emailTemplates, - sendEmail: context.wertik.sendEmail, - }); - }, - resetPassword: async (_: any, args: any, context: any, info: any) => { - return await resetPasswordHandler({ - userModel: context.wertik.models.User, - forgetPasswordModel: context.wertik.models.ForgetPassword, - data: args.input, - }); - }, - }, - }, - query: { - schema: ``, - resolvers: {}, - }, - }, - restApi: { - endpoints: [ - { - path: "/request-password-reset", - methodType: "post", - handler: async function (req, res) { - try { - let response = await requestPasswordResetHandler({ - userModel: req.wertik.models.User, - forgetPasswordModel: req.wertik.models.ForgetPassword, - data: req.body.input, - emailTemplates: req.wertik.emailTemplates, - sendEmail: req.wertik.sendEmail, - }); - res.json({ - message: response, - }); - } catch (e) { - res.json({ - success: false, - message: e.message, - result: {}, - }); - } - }, - }, - { - path: "/reset-password", - methodType: "post", - handler: async function (req, res) { - try { - let response = await resetPasswordHandler({ - userModel: req.wertik.models.User, - forgetPasswordModel: req.wertik.models.ForgetPassword, - data: req.body.input, - }); - res.json({ - message: response, - }); - } catch (e) { - res.json({ - success: false, - message: e.message, - result: {}, - }); - } - }, - }, - ], - }, - database: { - selectIgnoreFields: ["user"], - relationships: { - oneToOne: { - User: { - sourceKey: "user_id", - as: "user", - foreignKey: "id", - }, - }, - }, - sql: { - tableName: "forgetPassword", - fields: { - name: { - type: "String", - }, - email: { - type: "String", - }, - user_id: { - type: "Integer", - }, - token: { - type: "String", - }, - is_deleted: { - type: "INTEGER", - }, - }, - }, - }, -}; diff --git a/src/framework/builtinModules/permission/index.ts b/src/framework/builtinModules/permission/index.ts deleted file mode 100644 index 97b76983..00000000 --- a/src/framework/builtinModules/permission/index.ts +++ /dev/null @@ -1,79 +0,0 @@ -export default { - name: "Permission", - graphql: { - schema: ` - type Permission { - id: Int - name: String - cant: String - can: String - created_by: User - created_by_id: Int - created_at: String - updated_at: String - user_permissions: UserPermissionList - role_permissions: RolePermissionList - } - input PermissionInput { - id: Int - name: String - cant: String - can: String - created_by_id: Int - } - - `, - mutation: { - schema: ``, - resolvers: {}, - }, - query: { - schema: ``, - resolvers: {}, - }, - }, - restApi: {}, - database: { - selectIgnoreFields: ["user_permissions", "role_permissions", "created_by"], - relationships: { - oneToMany: { - UserPermission: { - as: "user_permissions", - foreignKey: "permission_id", - }, - RolePermission: { - as: "role_permissions", - foreignKey: "permission_id", - }, - }, - oneToOne: { - User: { - as: "created_by", - foreignKey: "id", - sourceKey: "created_by_id", - }, - }, - }, - sql: { - tableName: "permission", - fields: { - name: { - type: "STRING", - unique: true, - }, - cant: { - type: "STRING", - }, - can: { - type: "STRING", - }, - is_deleted: { - type: "INTEGER", - }, - created_by_id: { - type: "INTEGER", - }, - }, - }, - }, -}; diff --git a/src/framework/builtinModules/role/index.ts b/src/framework/builtinModules/role/index.ts deleted file mode 100644 index 6b676827..00000000 --- a/src/framework/builtinModules/role/index.ts +++ /dev/null @@ -1,74 +0,0 @@ -export default { - name: "Role", - graphql: { - schema: ` - type Role { - id: Int - name: String - default_permissions: String - created_by: User - created_by_id: Int - is_deleted: Boolean - created_at: String - updated_at: String - user_roles: UserRoleList - role_permissions: RolePermissionList - } - input RoleInput { - id: Int - default_permissions: String - created_by_id: Int - name: String - } - `, - mutation: { - schema: ``, - resolvers: {}, - }, - query: { - schema: ``, - resolvers: {}, - }, - }, - restApi: {}, - database: { - selectIgnoreFields: ["user_roles", "role_permissions", "created_by"], - relationships: { - oneToMany: { - UserRole: { - as: "user_roles", - foreignKey: "role_id", - }, - RolePermission: { - as: "role_permissions", - foreignKey: "role_id", - }, - }, - oneToOne: { - User: { - as: "created_by", - foreignKey: "id", - sourceKey: "created_by_id", - }, - }, - }, - sql: { - tableName: "role", - fields: { - name: { - type: "STRING", - unique: true, - }, - default_permissions: { - type: "STRING", - }, - is_deleted: { - type: "INTEGER", - }, - created_by_id: { - type: "INTEGER", - }, - }, - }, - }, -}; diff --git a/src/framework/builtinModules/rolePermission/index.ts b/src/framework/builtinModules/rolePermission/index.ts deleted file mode 100644 index 1952e5a9..00000000 --- a/src/framework/builtinModules/rolePermission/index.ts +++ /dev/null @@ -1,80 +0,0 @@ -export default { - name: "RolePermission", - graphql: { - schema: ` - type RolePermission { - id: Int - name: String - role: Role - role_id: Int - permission: Permission - permission_id: Int - created_by: User - created_by_id: Int - created_at: String - updated_at: String - } - input RolePermissionInput { - id: Int - name: String - role_id: Int - permission_id: Int - created_by_id: Int - } - `, - customResolvers: {}, - mutation: { - schema: ``, - resolvers: {}, - }, - query: { - schema: ``, - resolvers: {}, - }, - }, - restApi: {}, - database: { - selectIgnoreFields: ["permission", "role", "created_by"], - relationships: { - belongsTo: { - Permission: { - sourceKey: "permission_id", - as: "permission", - foreignKey: "id", - }, - Role: { - sourceKey: "role_id", - as: "role", - foreignKey: "id", - }, - }, - oneToOne: { - User: { - as: "created_by", - foreignKey: "id", - sourceKey: "created_by_id", - }, - }, - }, - sql: { - tableName: "rolePermission", - fields: { - name: { - type: "STRING", - }, - role_id: { - type: "INTEGER", - }, - permission_id: { - type: "INTEGER", - }, - is_deleted: { - type: "INTEGER", - }, - created_by_id: { - type: "INTEGER", - }, - }, - }, - }, -}; diff --git a/src/framework/builtinModules/user/index.ts b/src/framework/builtinModules/user/index.ts index 58ee9971..4a8a63a3 100644 --- a/src/framework/builtinModules/user/index.ts +++ b/src/framework/builtinModules/user/index.ts @@ -18,8 +18,6 @@ export default { referer: String created_at: String updated_at: String - user_roles: UserRoleList - user_permissions: UserPermissionList } input UserInput { id: Int @@ -54,18 +52,9 @@ export default { }, restApi: {}, database: { - selectIgnoreFields: ["user_permissions", "user_roles"], + selectIgnoreFields: [], relationships: { - oneToMany: { - UserRole: { - as: "user_roles", - foreignKey: "user_id", - }, - UserPermission: { - as: "user_permissions", - foreignKey: "user_id", - }, - }, + oneToMany: {}, }, sql: { tableName: "user", diff --git a/src/framework/builtinModules/userPermission/index.ts b/src/framework/builtinModules/userPermission/index.ts deleted file mode 100644 index a43dd73e..00000000 --- a/src/framework/builtinModules/userPermission/index.ts +++ /dev/null @@ -1,81 +0,0 @@ -export default { - name: "UserPermission", - graphql: { - schema: ` - type UserPermission { - id: Int - name: String - user: User - user_id: Int - permission: Permission - permission_id: Int - created_by: User - created_by_id: Int - created_at: String - updated_at: String - } - input UserPermissionInput { - id: Int - name: String - user_id: Int - permission_id: Int - } - `, - customResolvers: {}, - mutation: { - schema: ``, - resolvers: {}, - }, - query: { - schema: ``, - resolvers: {}, - }, - }, - restApi: {}, - database: { - selectIgnoreFields: ["user", "permission", "created_by"], - relationships: { - belongsTo: { - Permission: { - sourceKey: "permission_id", - as: "permission", - foreignKey: "id", - }, - }, - oneToOne: { - User: [ - { - sourceKey: "created_by_id", - as: "created_by", - foreignKey: "id", - }, - { - sourceKey: "user_id", - as: "user", - foreignKey: "id", - }, - ], - }, - }, - sql: { - tableName: "userPermission", - fields: { - name: { - type: "STRING", - }, - user_id: { - type: "INTEGER", - }, - permission_id: { - type: "INTEGER", - }, - is_deleted: { - type: "INTEGER", - }, - created_by_id: { - type: "INTEGER", - }, - }, - }, - }, -}; diff --git a/src/framework/builtinModules/userRole/index.ts b/src/framework/builtinModules/userRole/index.ts deleted file mode 100644 index 0f9fe9e3..00000000 --- a/src/framework/builtinModules/userRole/index.ts +++ /dev/null @@ -1,83 +0,0 @@ -export default { - name: "UserRole", - graphql: { - schema: ` - type UserRole { - id: Int - name: String - user: User - user_id: Int - role: Role - role_id: Int - created_by: User - created_by_id: Int - created_at: String - updated_at: String - } - input UserRoleInput { - id: Int - name: String - user_id: Int - role_id: Int - created_by_id: Int - } - `, - customResolvers: {}, - mutation: { - schema: ``, - resolvers: {}, - }, - query: { - schema: ``, - resolvers: {}, - }, - }, - - restApi: {}, - database: { - selectIgnoreFields: ["user", "role", "created_by"], - relationships: { - belongsTo: { - Role: { - sourceKey: "role_id", - as: "role", - foreignKey: "id", - }, - }, - oneToOne: { - User: [ - { - sourceKey: "user_id", - as: "user", - foreignKey: "id", - }, - { - sourceKey: "created_by_id", - as: "created_by", - foreignKey: "id", - }, - ], - }, - }, - sql: { - tableName: "userRole", - fields: { - name: { - type: "STRING", - }, - user_id: { - type: "INTEGER", - }, - role_id: { - type: "INTEGER", - }, - is_deleted: { - type: "INTEGER", - }, - created_by_id: { - type: "INTEGER", - }, - }, - }, - }, -}; diff --git a/src/framework/database/helpers/index.ts b/src/framework/database/helpers/index.ts index fd7f4ae9..d9884ab3 100644 --- a/src/framework/database/helpers/index.ts +++ b/src/framework/database/helpers/index.ts @@ -12,11 +12,3 @@ export const convertFieldsIntoSequelizeFields = (fields) => { }); return fields; }; - -export const deleteModel = () => {}; - -export const paginateModel = () => {}; - -export const updateModel = () => {}; - -export const viewModel = () => {}; diff --git a/src/framework/database/helpers/stats.ts b/src/framework/database/helpers/stats.ts deleted file mode 100644 index 1190594e..00000000 --- a/src/framework/database/helpers/stats.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { - getQueryForLast7Days, - getQueryForLastYear, - getQueryForThisYear, - getQueryForThisMonth, - getQueryForLastMonth, - getQueryForThisWeek, - getQueryForToday, - getQueryForLast90Days, -} from "../../reporting/index"; -import { get } from "lodash"; - -export default function (database, model) { - return function (requestedReports) { - return new Promise(async (resolve, reject) => { - try { - let statsInfo = { - total_count: null, - total_created_today: null, - total_created_this_week: null, - total_created_last_7_days: null, - total_created_this_month: null, - total_created_last_month: null, - total_created_last_90_days: null, - total_created_last_year: null, - total_created_this_year: null, - }; - let count, - countLast7Days, - countToday, - countLastYear, - countThisYear, - countThisMonth, - countThisweek, - countLastMonth, - countLast90Days; - let selectOptions = { - type: database.QueryTypes.SELECT, - }; - if (requestedReports.includes("total_count")) { - count = await database.query( - `select count(*) as total_count from ${model.getTableName()}`, - selectOptions - ); - } - if (requestedReports.includes("total_created_last_7_days")) { - countLast7Days = await database.query( - getQueryForLast7Days(model.getTableName()), - selectOptions - ); - } - if (requestedReports.includes("total_created_today")) { - countToday = await database.query( - getQueryForToday(model.getTableName()), - selectOptions - ); - } - if (requestedReports.includes("total_created_last_year")) { - countLastYear = await database.query( - getQueryForLastYear(model.getTableName()), - selectOptions - ); - } - if (requestedReports.includes("total_created_this_year")) { - countThisYear = await database.query( - getQueryForThisYear(model.getTableName()), - selectOptions - ); - } - if (requestedReports.includes("total_created_this_month")) { - countThisMonth = await database.query( - getQueryForThisMonth(model.getTableName()), - selectOptions - ); - } - if (requestedReports.includes("total_created_this_week")) { - countThisweek = await database.query( - getQueryForThisWeek(model.getTableName()), - selectOptions - ); - } - if (requestedReports.includes("total_created_last_month")) { - countLastMonth = await database.query( - getQueryForLastMonth(model.getTableName()), - selectOptions - ); - } - if (requestedReports.includes("total_created_last_90_days")) { - countLast90Days = await database.query( - getQueryForLast90Days(model.getTableName()), - selectOptions - ); - } - - statsInfo.total_count = get(count, "[0].total_count", 0); - statsInfo.total_created_this_month = get( - countThisMonth, - "[0].total_created_this_month", - 0 - ); - statsInfo.total_created_this_week = get( - countThisweek, - "[0].total_created_this_week", - 0 - ); - statsInfo.total_created_last_7_days = get( - countLast7Days, - "[0].total_created_last_7_days", - 0 - ); - statsInfo.total_created_today = get( - countToday, - "[0].total_created_today", - 0 - ); - statsInfo.total_created_last_month = get( - countLastMonth, - "[0].total_created_last_month", - 0 - ); - statsInfo.total_created_last_90_days = get( - countLast90Days, - "[0].total_created_last_90_days", - 0 - ); - statsInfo.total_created_last_year = get( - countLastYear, - "[0].total_created_last_year", - 0 - ); - statsInfo.total_created_this_year = get( - countThisYear, - "[0].total_created_this_year", - 0 - ); - - resolve(statsInfo); - } catch (error) { - reject(error); - } - }); - }; -} diff --git a/src/framework/database/loadTables.ts b/src/framework/database/loadTables.ts index 495504f8..40ed40fe 100644 --- a/src/framework/database/loadTables.ts +++ b/src/framework/database/loadTables.ts @@ -9,7 +9,6 @@ import { IConfiguration, } from "../types/configuration"; import { applyRelationshipSql } from "../moduleRelationships/database"; -import stats from "./helpers/stats"; import paginate from "./helpers/paginate"; const checkDatabaseOptions = (moduleName, tableName) => { @@ -92,7 +91,6 @@ export default function (connection, configuration: IConfiguration) { }); Object.keys(tables).forEach(async (table) => { - tables[table].stats = await stats(connection, tables[table]); tables[table].paginate = await paginate(tables[table]); }); diff --git a/src/framework/defaults/defaultConfigurations/defaultConfiguration.ts b/src/framework/defaults/defaultConfigurations/defaultConfiguration.ts index 422c7801..a6f8229d 100644 --- a/src/framework/defaults/defaultConfigurations/defaultConfiguration.ts +++ b/src/framework/defaults/defaultConfigurations/defaultConfiguration.ts @@ -1,7 +1,7 @@ export default { name: "Wertik", builtinModules: - "user,auth,forgetPassword,permission,role,rolePermission,userPermission,userRole,storage,email,backup", + "user,permission,role,rolePermission,userPermission,userRole,storage,email,backup", database: { dbDialect: process.env.dbDialect, dbUsername: process.env.dbUsername, @@ -95,65 +95,7 @@ export default { }, }, restApi: { - endpoints: [ - { - path: "/relations", - methodType: "get", - handler: async function (req, res) { - const models = req.wertik.models; - const { UserPermission, User, Permission, UserRole, Role } = - models; - const All = await User.findOne({ - where: { - id: 1, - }, - attributes: ["id", "email"], - include: [ - { - model: UserRole, - as: "user_roles", - attributes: ["id", "user_id", "role_id"], - include: [ - { - model: Role, - as: "role", - attributes: ["id", "name"], - }, - { - model: User, - as: "user", - attributes: ["id", "email"], - }, - ], - }, - { - model: UserPermission, - as: "user_permissions", - attributes: ["id", "user_id", "permission_id"], - include: [ - { - model: User, - as: "user", - attributes: ["id", "email"], - }, - { - model: Permission, - as: "permission", - attributes: ["id", "can", "cant"], - }, - ], - }, - ], - }); - res.json({ - message: true, - data: { - user: All, - }, - }); - }, - }, - ], + endpoints: [], }, database: { sql: { diff --git a/src/framework/defaults/options/index.ts b/src/framework/defaults/options/index.ts index 18303f82..22466113 100644 --- a/src/framework/defaults/options/index.ts +++ b/src/framework/defaults/options/index.ts @@ -56,14 +56,6 @@ export const defaultSocketOptions = { }, }; -export const defaultApolloGraphqlOptions = { - cacheControl: { - defaultMaxAge: 0, - }, - tracing: true, - subscriptions: { - path: "/subscriptions", - }, -}; +export const defaultApolloGraphqlOptions = {}; export const defaultPort = 7000; diff --git a/src/framework/graphql/crudGenerator.ts b/src/framework/graphql/crudGenerator.ts index 54c57663..fb0e3b61 100644 --- a/src/framework/graphql/crudGenerator.ts +++ b/src/framework/graphql/crudGenerator.ts @@ -19,7 +19,7 @@ export const generateQueriesCrudSchema = (moduleName: String) => { moduleName )}(filters: [FilterInput]): ${moduleName}`; const viewString = `view${moduleName}(${identityColumn}: ${identityColumnGraphQLType}): ${moduleName}`; - const listString = `list${moduleName}(cache: CacheOptionsInput, pagination: PaginationInput, filters: ${moduleName}FilterInput, sorting: [SortingInput]): ${moduleName}List`; + const listString = `list${moduleName}(pagination: PaginationInput, filters: ${moduleName}FilterInput, sorting: [SortingInput]): ${moduleName}List`; const countString = `count${moduleName}(filters: ${moduleName}FilterInput): Int`; string = ` ${viewString} @@ -30,42 +30,6 @@ export const generateQueriesCrudSchema = (moduleName: String) => { return string; }; -export const generateMutationsCrudSubscriptionSchema = (moduleName: String) => { - return ` - ${moduleName}Deleted: SuccessResponse - ${moduleName}BulkCreated: [${moduleName}] - ${moduleName}BulkUpdated: [${moduleName}] - `; -}; - -export const getSubscriptionConstants = (moduleName: String) => { - return { - deletedModule: `${moduleName}Deleted`, - bulkCreatedModule: `${moduleName}BulkCreated`, - bulkUpdatedModule: `${moduleName}BulkUpdated`, - }; -}; - -export const generateSubscriptionsCrudResolvers = ( - moduleName: String, - pubsub: any -) => { - const { deletedModule, bulkCreatedModule, bulkUpdatedModule } = - getSubscriptionConstants(moduleName); - let object = { - [deletedModule]: { - subscribe: () => pubsub.asyncIterator([deletedModule]), - }, - [bulkCreatedModule]: { - subscribe: () => pubsub.asyncIterator([bulkCreatedModule]), - }, - [bulkUpdatedModule]: { - subscribe: () => pubsub.asyncIterator([bulkUpdatedModule]), - }, - }; - return object; -}; - export const generateMutationsCrudSchema = (moduleName: String) => { const bulkUpdateString = `bulkUpdate${moduleName}(input: [${moduleName}Input]): ${moduleName}BulkMutationResponse`; const bulkCreateString = `bulkCreate${moduleName}(input: [${moduleName}Input]): ${moduleName}BulkMutationResponse`; @@ -79,7 +43,6 @@ export const generateMutationsCrudSchema = (moduleName: String) => { export const generateCrudResolvers = ( module: IConfigurationCustomModule, - pubsub, configuration: IConfiguration ) => { const overrideMutationBulkCreate = get( @@ -162,10 +125,6 @@ export const generateCrudResolvers = ( null ); - const { bulkCreatedModule, bulkUpdatedModule } = getSubscriptionConstants( - module.name - ); - let object = { mutations: { [`bulkDelete${module.name}`]: async ( @@ -228,9 +187,6 @@ export const generateCrudResolvers = ( : args; let model = context.wertik.models[module.name]; let result = await model.bulkCreate(finalArgs.input); - pubsub.publish(bulkCreatedModule, { - [bulkCreatedModule]: result, - }); if (isFunction(afterBulkCreate)) { afterBulkCreate({ mode: "graphql", @@ -281,9 +237,6 @@ export const generateCrudResolvers = ( result.push(a); } } - pubsub.publish(bulkUpdatedModule, { - [bulkUpdatedModule]: result, - }); if (isFunction(afterBulkUpdate)) { afterBulkUpdate({ mode: "graphql", @@ -360,32 +313,20 @@ export const generateCrudResolvers = ( params: { _, args, context, info }, }) : args; - const cacheWith = (args.cache && args.cache.name) || ""; - const cacheValue = context.wertik.cache.get(cacheWith); - if (cacheWith && cacheValue) { - response = cacheValue; - } else { - let model = context.wertik.models[module.name]; - let requestedFields = getRequestedFieldsFromResolverInfo(info); - response = await model.paginate( - finalArgs, - Object.keys(requestedFields.list) - ); - } + let model = context.wertik.models[module.name]; + let requestedFields = getRequestedFieldsFromResolverInfo(info); + response = await model.paginate( + finalArgs, + Object.keys(requestedFields.list) + ); + if (isFunction(afterList)) { afterList({ mode: "graphql", params: { _, args, context, info, instance: response }, }); } - if (cacheWith) { - context.wertik.cache.set( - cacheWith, - response, - (args.cache && args.cache.expiry) || 0 - ); - } return response; }, }, diff --git a/src/framework/graphql/generalSchema.ts b/src/framework/graphql/generalSchema.ts index 3ba8c88e..e979c960 100644 --- a/src/framework/graphql/generalSchema.ts +++ b/src/framework/graphql/generalSchema.ts @@ -48,17 +48,6 @@ export default ` _ne: Boolean } - type ModuleStats { - total_count: Int - total_created_this_month: Int - total_created_this_week: Int - total_created_last_7_days: Int - total_created_today: Int - total_created_last_month: Int - total_created_last_90_days: Int - total_created_last_year: Int - total_created_this_year: Int - } type Sorting { column: String type: String @@ -93,8 +82,4 @@ export default ` previousPage: Int hasMore: Boolean } - input CacheOptionsInput { - name: String - expiry: Int - } `; diff --git a/src/framework/graphql/index.ts b/src/framework/graphql/index.ts index 69386502..0a5fec2a 100644 --- a/src/framework/graphql/index.ts +++ b/src/framework/graphql/index.ts @@ -1,15 +1,12 @@ -// let { ApolloServer } = require("apollo-server"); import loadAllModules from "./loadAllModules"; import { IGraphQLInitialize } from "./../types/servers"; import { get } from "lodash"; import voyager from "./voyager/index"; import { defaultApolloGraphqlOptions } from "../defaults/options/index"; import GraphQLJSON, { GraphQLJSONObject } from "graphql-type-json"; -const { ApolloServer } = require("apollo-server-express"); +import { ApolloServer } from "apollo-server-express"; import * as auth from "./../helpers/auth"; -//expressApp,configuration,models,emailTemplates,sendEmail,database,WertikEventEmitter - export default async function (options: IGraphQLInitialize) { const { mailerInstance, diff --git a/src/framework/graphql/loadAllModules.ts b/src/framework/graphql/loadAllModules.ts index 963210db..b525b49c 100644 --- a/src/framework/graphql/loadAllModules.ts +++ b/src/framework/graphql/loadAllModules.ts @@ -4,18 +4,14 @@ import { get, isFunction } from "lodash"; import generalSchema from "./generalSchema"; import { - generateSubscriptionsCrudResolvers, generateQueriesCrudSchema, generateListTypeForModule, - generateMutationsCrudSubscriptionSchema, generateMutationsCrudSchema, generateCrudResolvers, } from "./crudGenerator"; -import { PubSub } from "apollo-server"; import { IConfiguration } from "../types/configuration"; import { GraphQLModuleRelationMapper } from "../moduleRelationships/graphql"; import self from "./self"; -const pubsub = new PubSub(); export default async function (configuration: IConfiguration) { let modulesSchema = ` @@ -118,7 +114,6 @@ export default async function (configuration: IConfiguration) { const crudResolvers = generateCrudResolvers( currentModule, - pubsub, configuration ); @@ -129,13 +124,6 @@ export default async function (configuration: IConfiguration) { const crudQuerySchema = generateQueriesCrudSchema(currentModuleName); const crudQueryResolvers = crudResolvers.queries; - const crudSubscriptionSchema = - generateMutationsCrudSubscriptionSchema(currentModuleName); - const crudSubscriptionResolvers = generateSubscriptionsCrudResolvers( - currentModuleName, - pubsub - ); - modulesQuerySchema = `${modulesQuerySchema} ${crudQuerySchema} `; @@ -153,12 +141,8 @@ export default async function (configuration: IConfiguration) { ...crudMutationResolvers, }; - modulesSubscriptionSchema = - modulesSubscriptionSchema + crudSubscriptionSchema; - appSubscriptions = { ...appSubscriptions, - ...crudSubscriptionResolvers, }; } diff --git a/src/framework/helpers/replaceFilterOperators.ts b/src/framework/helpers/replaceFilterOperators.ts index 2e38645c..92ca8b13 100644 --- a/src/framework/helpers/replaceFilterOperators.ts +++ b/src/framework/helpers/replaceFilterOperators.ts @@ -11,11 +11,11 @@ const iterate = (obj) => { const isArray = Array.isArray(obj); if (isObject) { const keys = Object.keys(obj); - keys.forEach((element) => { + keys.forEach((element: string) => { const value = obj[element]; const isArray = Array.isArray(value); const isObject = isPlainObject(value); - if (element.indexOf("_") === 0) { + if (element.startsWith("_")) { const newWrapValue = wrap(element); obj[newWrapValue] = obj[element]; delete obj[element]; diff --git a/src/framework/helpers/validateConfigurationObject.ts b/src/framework/helpers/validateConfigurationObject.ts index 483fa308..4715baa5 100644 --- a/src/framework/helpers/validateConfigurationObject.ts +++ b/src/framework/helpers/validateConfigurationObject.ts @@ -14,11 +14,9 @@ export const requiredFields = { export default function (configuration) { return new Promise(async (resolve, reject) => { try { - let responseCheckInstalledPackages = await checkInstalledPackages( - configuration - ); - let responseCheckModules = await checkModules(configuration); - resolve(); + await checkInstalledPackages(configuration); + await checkModules(configuration); + resolve(true); } catch (errr) { reject(errr); console.log(errr); diff --git a/src/framework/initialization/checkInstalledPackages.ts b/src/framework/initialization/checkInstalledPackages.ts index 69e74fff..2ca27da7 100644 --- a/src/framework/initialization/checkInstalledPackages.ts +++ b/src/framework/initialization/checkInstalledPackages.ts @@ -33,7 +33,7 @@ export default function (configuration: IConfiguration) { check("pg-hstore"); check("pg-native"); } - resolve(); + resolve(true); } catch (e) { reject(e); } diff --git a/src/framework/initialization/checkModules.ts b/src/framework/initialization/checkModules.ts index f4997980..ed800769 100644 --- a/src/framework/initialization/checkModules.ts +++ b/src/framework/initialization/checkModules.ts @@ -3,21 +3,25 @@ import { IConfiguration } from "../types/configuration"; export default function (configuration: IConfiguration) { const { modules } = configuration; return new Promise((resolve, reject) => { - if (modules.length == 0) { - console.log("[Wertik-js] Starting with no custom modules."); - resolve(true); - } - modules.forEach((element, index) => { - let isLast = index == modules.length - 1; - if (!element || element.constructor !== Object) { - console.error( - `You have passed unsupported modules at index: ${index}, received: ${element.constructor} \n Closing process. Please see: http://www.wapgee.com/wertik-js/getting-started/custom-modules` - ); - process.exit(); - } - if (isLast) { + try { + if (modules.length == 0) { + console.log("[Wertik-js] Starting with no custom modules."); resolve(true); } - }); + modules.forEach((element, index) => { + let isLast = index == modules.length - 1; + if (!element || element.constructor !== Object) { + console.error( + `You have passed unsupported modules at index: ${index}, received: ${element.constructor} \n Closing process. Please see: http://www.wapgee.com/wertik-js/getting-started/custom-modules` + ); + process.exit(); + } + if (isLast) { + resolve(true); + } + }); + } catch (e) { + reject(e); + } }); } diff --git a/src/framework/initialization/startServers.ts b/src/framework/initialization/startServers.ts index 51b33e80..eccf2e5a 100644 --- a/src/framework/initialization/startServers.ts +++ b/src/framework/initialization/startServers.ts @@ -65,16 +65,16 @@ export default function (configuration: IConfiguration, servers: any) { restApi.get("*", restApi404Handler); } httpServer.listen(expressAppPort, () => { + successMessage( + `Express Server Started`, + `http://localhost:${expressAppPort}` + ); if (disableSockets === false) { successMessage( `Socket.IO server running at`, `http://localhost:${expressAppPort}` ); } - successMessage( - `Rest API server started at`, - `http://localhost:${expressAppPort}` - ); if (disableGraphqlVoyager === false) { successMessage( `GraphQL Voyager running at`, @@ -86,10 +86,6 @@ export default function (configuration: IConfiguration, servers: any) { "GraphQL Server started at", `http://localhost:${expressAppPort}${graphql.graphqlPath}` ); - successMessage( - "GraphQL Subscriptions are running at", - `ws://localhost:${expressAppPort}${graphql.subscriptionsPath}` - ); } }); } diff --git a/src/framework/reporting/index.ts b/src/framework/reporting/index.ts deleted file mode 100644 index f4380eb0..00000000 --- a/src/framework/reporting/index.ts +++ /dev/null @@ -1,122 +0,0 @@ -import moment from "moment"; -import { resolve } from "url"; - -export const getYear = (mm = null) => { - return mm ? mm.year() : moment().year(); -}; - -export const getMonth = (mm = null) => { - return mm ? mm.month() + 1 : moment().month() + 1; -}; - -export const getDate = (mm = null) => { - return mm ? mm.date() : moment().date(); -}; - -export const substractDays = (num) => { - return moment().subtract(num, "d"); -}; - -export const getQueryForLast7Days = function (tableName: String) { - return ` - SELECT count(*) as total_created_last_7_days FROM ${tableName} - WHERE DATE(created_at) - BETWEEN - '${getYear(substractDays(7))}-${ - substractDays(7).month() + 1 - }-${substractDays(7).date()}' - AND - '${getYear(substractDays(7))}-${ - moment().month() + 1 - }-${moment().date()}' - `; -}; - -export const getQueryForToday = function (tableName: String) { - return ` - SELECT count(*) as total_created_today FROM ${tableName} - WHERE DATE(created_at) - BETWEEN - '${getYear()}-${getMonth()}-${getDate()} 00:00:00' - AND - '${getYear()}-${getMonth()}-${getDate()} 23:59:59' - `; -}; - -export const getQueryForThisYear = function (tableName: String) { - return ` - SELECT count(*) as total_created_this_year FROM ${tableName} - WHERE DATE(created_at) - BETWEEN - '${getYear()}-1-1' - AND - '${getYear()}-12-31' - `; -}; - -export const getQueryForThisMonth = function (tableName: String) { - return ` - SELECT count(*) as total_created_this_month FROM ${tableName} - WHERE DATE(created_at) - BETWEEN - '${getYear()}-${moment().month() + 1}-${moment().startOf("month").date()}' - AND - '${getYear()}-${moment().month() + 1}-${moment().endOf("month").date()}' - `; -}; - -export const getQueryForThisWeek = function (tableName: String) { - return ` - SELECT count(*) as total_created_this_week FROM ${tableName} - WHERE DATE(created_at) - BETWEEN - '${getYear(moment().startOf("isoWeek"))}-${ - moment().startOf("isoWeek").month() + 1 - }-${moment().startOf("isoWeek").date()}' - AND - '${getYear(moment().endOf("isoWeek"))}-${ - moment().endOf("isoWeek").month() + 1 - }-${moment().endOf("isoWeek").date()}' - `; -}; - -export const getQueryForLastMonth = function (tableName: String) { - return ` - SELECT count(*) as total_created_last_month FROM ${tableName} - WHERE DATE(created_at) - BETWEEN - '${moment().subtract(1, "months").year()}-${ - moment().subtract(1, "months").month() + 1 - }-${moment().subtract(1, "months").startOf("month").date()}' - AND - '${moment().subtract(1, "months").year()}-${ - moment().subtract(1, "months").month() + 1 - }-${moment().subtract(1, "months").endOf("month").date()}' - `; -}; - -export const getQueryForLast90Days = function (tableName: String) { - return ` - SELECT count(*) as total_created_last_90_days FROM ${tableName} - WHERE DATE(created_at) - BETWEEN - '${moment().subtract(90, "days").year()}-${ - moment().subtract(90, "days").month() + 1 - }-${moment().subtract(90, "days").startOf("month").date()}' - AND - '${moment().year()}-${moment().month() + 1}-${moment() - .endOf("month") - .date()}' - `; -}; - -export const getQueryForLastYear = function (tableName: String) { - return ` - SELECT count(*) as total_created_last_year FROM ${tableName} - WHERE DATE(created_at) - BETWEEN - '${getYear() - 1}-1-1' - AND - '${getYear() - 1}-12-31' - `; -}; diff --git a/src/framework/security/createJwtToken.ts b/src/framework/security/createJwtToken.ts deleted file mode 100644 index 4892ae56..00000000 --- a/src/framework/security/createJwtToken.ts +++ /dev/null @@ -1,12 +0,0 @@ -let moment = require("moment"); -let jwt = require("jsonwebtoken"); -import { get, has } from "lodash"; - -export default async function createJwtToken(data: any) { - if (typeof data !== "object") { - throw "Data must be object"; - } - let firstArgument = data; - let secret = process.env.jwtSecret || "asdasdasd"; - return await jwt.sign(firstArgument, secret, { expiresIn: data.expiresIn }); -} diff --git a/src/framework/security/getUserAllPermissions.ts b/src/framework/security/getUserAllPermissions.ts deleted file mode 100644 index bd650c54..00000000 --- a/src/framework/security/getUserAllPermissions.ts +++ /dev/null @@ -1,37 +0,0 @@ -export default async function (userId, database) { - let sqlQuery = ` - SELECT permissionTable.id AS permission_id, - permissionTable.NAME AS permission_name, - permissionTable.can AS permission_can, - permissionTable.cant AS permission_cant, - role_permissionTable.id AS rolepermission_id, - role_permissionTable.role AS rolepermission_role, - role_permissionTable.permission AS rolepermission_permission, - role_permissionTable.NAME AS rolepermission_name, - userpermissionTable.id AS userpermission_id, - userpermissionTable.USER AS userpermission_user, - userpermissionTable.permission AS userpermission_permission, - roleTable.id AS role_id, - roleTable.NAME AS role_name, - userroleTable.id AS userrole_id, - userroleTable.NAME AS userrole_name, - userroleTable.USER AS userrole_user, - userroleTable.role AS userrole_role - FROM permission AS permissionTable - LEFT JOIN role_permission AS role_permissionTable - ON permissionTable.id = role_permissionTable.permission - LEFT JOIN user_permission AS userpermissionTable - ON permissionTable.id = userpermissionTable.permission - LEFT JOIN role AS roleTable - ON role_permissionTable.role = roleTable.id - LEFT JOIN user_role AS userroleTable - ON userroleTable.id = role_permissionTable.role - WHERE userroleTable.USER = _________user_ID - OR userpermissionTable.USER = _________user_ID - `; - sqlQuery = sqlQuery.replace(/_________user_ID/g, userId + ""); - const permissions = await database.query(sqlQuery, { - type: database.QueryTypes.SELECT, - }); - return permissions; -} diff --git a/src/framework/security/getUserRoles.ts b/src/framework/security/getUserRoles.ts deleted file mode 100644 index 80c51071..00000000 --- a/src/framework/security/getUserRoles.ts +++ /dev/null @@ -1,18 +0,0 @@ -export default async function (userId, database) { - let sqlQuery = `SELECT r.*, ur.id as ur_id, - ur.name as ur_name, - ur.created_at as ur_created_at, - ur.updated_at as ur_updated_at, - ur.deleted_at as ur_deleted_at, - ur.role as ur_role, - ur.user as ur_user - - from user_role as ur - left JOIN role as r on r.id = ur.role - where ur.user = _________user_ID`; - sqlQuery = sqlQuery.replace(/_________user_ID/g, userId + ""); - const roles = await database.query(sqlQuery, { - type: database.QueryTypes.SELECT, - }); - return roles; -} diff --git a/src/framework/security/getUserWithAccessToken.ts b/src/framework/security/getUserWithAccessToken.ts deleted file mode 100644 index 8ee0021d..00000000 --- a/src/framework/security/getUserWithAccessToken.ts +++ /dev/null @@ -1,21 +0,0 @@ -let { get } = require("lodash"); -export default async function (UserModel: any, token: string) { - try { - let find = await UserModel.findOne({ - where: { - access_token: token, - }, - include: "*", - }); - return get(find, "instance", null); - } catch (errorInstance) { - let modules: any = process.env.builtinModules; - modules = modules.split(","); - modules = modules.filter((c) => c); - if (modules.length == 0) { - return null; - } else { - throw errorInstance; - } - } -} diff --git a/src/framework/security/isAccessTokenValid.ts b/src/framework/security/isAccessTokenValid.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/framework/security/isAuthQuery.ts b/src/framework/security/isAuthQuery.ts deleted file mode 100644 index 8f8c93f3..00000000 --- a/src/framework/security/isAuthQuery.ts +++ /dev/null @@ -1,23 +0,0 @@ -let { get } = require("lodash"); -let gql = require("graphql-tag"); -export default function (query: string) { - let parsed = gql` - ${query} - `; - let queryName = get( - parsed, - "definitions[0].selectionSet.selections[0].name.value", - "" - ); - let auth = [ - "signup", - "resetPassword", - "requestPasswordResetToken", - "login", - "activateAccount", - "generalAccessToken", - "twoFactorLogin", - "twoFactorLoginValidate", - ]; - return auth.indexOf(queryName) > -1; -} diff --git a/src/framework/security/validateAccessToken.ts b/src/framework/security/validateAccessToken.ts deleted file mode 100644 index b6639c8e..00000000 --- a/src/framework/security/validateAccessToken.ts +++ /dev/null @@ -1,11 +0,0 @@ -import getUserWithAccessToken from "./getUserWithAccessToken"; - -export default async function (userModel, accessToken) { - const token = accessToken.replace("bearer ", ""); - const user = await getUserWithAccessToken(userModel, token); - if (user) { - return user; - } else { - throw new Error("Access token expired"); - } -} diff --git a/src/framework/types/models.ts b/src/framework/types/models.ts index 51c8d5af..13988a59 100644 --- a/src/framework/types/models.ts +++ b/src/framework/types/models.ts @@ -26,14 +26,6 @@ export interface IUser { referer: String; } -export interface IForgetPassword { - id: Number; - name: String; - email: String; - user: any; - token: String; -} - export interface IRolePermission { id: Number; role: any; diff --git a/src/framework/types/override.ts b/src/framework/types/override.ts index ef2c3f01..fba2cba0 100644 --- a/src/framework/types/override.ts +++ b/src/framework/types/override.ts @@ -49,21 +49,8 @@ export interface IBuiltinModuleOverrideAuth { refreshToken: Function; }; } -export interface IBuiltinModuleOverrideForgetPassword { - graphql: { - mutation: { - requestPasswordReset: Function; - resetPassword: Function; - }; - }; - restApi: { - requestPasswordReset: Function; - resetPassword: Function; - }; -} export interface IConfigurationOverride { - ForgetPassword: IBuiltinModuleOverrideForgetPassword; Role: IBuiltinModuleOverride; UserPermission: IBuiltinModuleOverride; Permission: IBuiltinModuleOverride; diff --git a/src/next/cronJobs/index.ts b/src/next/cronJobs/index.ts index 3b9739f3..3feee7e3 100644 --- a/src/next/cronJobs/index.ts +++ b/src/next/cronJobs/index.ts @@ -1,24 +1,24 @@ import { get } from "lodash"; import nodeCron from "node-cron"; +import { WertikApp } from "../types/types"; +import { + iObject, + useCronJobsProps, + WertikConfiguration, +} from "../types/types.v2"; -export const useCronJob = (obj) => { - return obj; +export const useCronJob = (cron: useCronJobsProps) => { + return ({ + configuration, + wertikApp, + }: { + configuration: WertikConfiguration; + wertikApp: WertikApp; + }) => { + return nodeCron.schedule(cron.expression, () => { + get(cron, "beforeRun", () => {})(wertikApp); + cron.handler(wertikApp); + get(cron, "afterRun", () => {})(wertikApp); + }) as iObject; + }; }; - -const fn = function () {}; - -export default function (app, wertikApp) { - Object.keys(app.cronJobs).forEach((element) => { - const cron = app.cronJobs[element]; - if (cron) { - app.cronJobs[element] = wertikApp.cronJobs[element] = nodeCron.schedule( - cron.expression, - () => { - get(cron, "beforeRun", fn)(app); - cron.handler(app); - get(cron, "afterRun", fn)(app); - } - ); - } - }); -} diff --git a/src/next/crud/index.ts b/src/next/crud/index.ts index e7a3998b..cd257b1c 100644 --- a/src/next/crud/index.ts +++ b/src/next/crud/index.ts @@ -62,12 +62,50 @@ export default function (module, schemaInformation, store) { update${module.name}(input: update${module.name}Input,where: ${module.name}FilterInput!): ${module.name}BulkMutationResponse create${module.name}(input: [create${module.name}Input]): ${module.name}BulkMutationResponse delete${module.name}(where: ${module.name}FilterInput!): SuccessResponse + createOrUpdate${module.name}(id: Int, input: create${module.name}Input): ${module.name} } `; }, generateCrudResolvers() { return { Mutation: { + [`createOrUpdate${module.name}`]: get( + module, + "graphql.mutations.createOrUpdate", + async (_, args, context, info) => { + const argsFromEvent = await get( + module, + "events.beforeCreateOrUpdate", + function () {} + )(_, args, context, info); + args = argsFromEvent ? argsFromEvent : args; + const id = args.id; + let ___find: any; + if (id) { + ___find = await schemaInformation.tableInstance.findOne({ + where: { + id: id, + }, + }); + + if (!___find) { + throw new Error(`${module.name} Not found`); + } + + await schemaInformation.tableInstance.update(args.input, { + where: { id: id }, + }); + + return await schemaInformation.tableInstance.findOne({ + where: { id: id }, + }); + } else { + return await schemaInformation.tableInstance.create( + args.input + ); + } + } + ), [`update${module.name}`]: get( module, "graphql.mutations.update", diff --git a/src/next/database.ts b/src/next/database.ts index 9a90b302..de037465 100644 --- a/src/next/database.ts +++ b/src/next/database.ts @@ -2,6 +2,8 @@ import { Sequelize } from "sequelize"; import { databaseDefaultOptions } from "../framework/defaults/options"; import { get } from "lodash"; import { paginate } from "./crud/index"; +import { Store, UseDatabaseProps } from "./types/types.v2"; +import { WertikApp } from "./types/types.v2"; export const getAllRelationships = (dbName: String) => { return ` @@ -14,33 +16,33 @@ export const getAllRelationships = (dbName: String) => { `; }; -export const useDatabase = function (obj: any) { - return () => - new Promise(async (resolve, reject) => { - let sequelize = new Sequelize(obj.name, obj.username, obj.password, { - host: obj.host, - dialect: "mysql", - logging: false, - ...get(obj, "options", {}), - ...(databaseDefaultOptions as any).sql.dbInitializeOptions, - }); - try { - await sequelize.authenticate(); - (sequelize as any).relationships = await sequelize.query( - getAllRelationships(obj.name) - ); - console.log(`[DB] Succcessfully connected to database ${obj.name}`); - resolve({ - credentials: obj, - instance: sequelize, - }); - } catch (e) { - reject(`${e.message} \n [DB] Error connecting to database ${obj.name}`); - } +export const useDatabase = function (obj: UseDatabaseProps) { + return async () => { + let sequelize = new Sequelize(obj.name, obj.username, obj.password, { + host: obj.host, + dialect: "mysql", + logging: false, + ...get(obj, "options", {}), + ...(databaseDefaultOptions as any).sql.dbInitializeOptions, }); + await sequelize.authenticate().catch((err) => { + throw new Error(err); + }); + (sequelize as any).relationships = await sequelize.query( + getAllRelationships(obj.name) + ); + console.log(`[DB] Succcessfully connected to database ${obj.name}`); + return { + credentials: obj, + instance: sequelize, + }; + }; }; -export const applyRelationshipsFromStoreToDatabase = async (store, app) => { +export const applyRelationshipsFromStoreToDatabase = async ( + store: Store, + app: WertikApp +) => { store.database.relationships.forEach((element) => { const currentTable = app.modules[element.currentModule].tableInstance; const referencedTable = app.modules[element.referencedModule].tableInstance; @@ -49,7 +51,10 @@ export const applyRelationshipsFromStoreToDatabase = async (store, app) => { }); }; -export const applyRelationshipsFromStoreToGraphql = async (store, app) => { +export const applyRelationshipsFromStoreToGraphql = async ( + store: Store, + _app: WertikApp +) => { store.database.relationships.forEach((element) => { const oldResolvers = get( store, diff --git a/src/next/devServer.ts b/src/next/devServer.ts index 1e76683d..1b694aaf 100644 --- a/src/next/devServer.ts +++ b/src/next/devServer.ts @@ -1,16 +1,58 @@ +import { useCronJob } from "./cronJobs"; import { useDatabase } from "./database"; import { useGraphql } from "./graphql"; -import wertik, { useModule } from "./index"; +import wertik from "./index"; +import { useModule, useWebSockets } from "./index"; +import { useMailer } from "./mailer"; +import { useStorage } from "./storage"; (async () => { wertik({ port: 1200, - graphql: useGraphql(), - cronJobs: {}, - email: {}, - storage: {}, - sockets: {}, - database: {}, - modules: {}, + graphql: useGraphql({ + applyMiddlewareOptions: { + path: "/graphql", + }, + }), + database: { + jscontainer: useDatabase({ + name: "jscontainer", + password: "pass", + host: "localhost", + port: 3306, + username: "root", + }), + }, + sockets: { + mySockets: useWebSockets({ + path: "/sockets.wo", + }), + }, + storage: { + dropbox: useStorage({ + for: "dropbox", + dropboxOptions: { + accessToken: "asda", + }, + }), + }, + cronJobs: { + aCronJobName: useCronJob({ + name: "Send emails to people every 1 minute", + handler: () => console.log(1), + expression: "*/10 * * * * *", + }), + }, + mailer: { + mail: useMailer(), + }, + modules: { + containers: useModule({ + table: "containers", + database: "jscontainer", + name: "containers", + useDatabase: true, + }), + }, }); })(); diff --git a/src/next/graphql/index.ts b/src/next/graphql/index.ts index 9de85cb9..eff1524b 100644 --- a/src/next/graphql/index.ts +++ b/src/next/graphql/index.ts @@ -1,44 +1,61 @@ import { get, omit } from "lodash"; import { defaultApolloGraphqlOptions } from "../../framework/defaults/options"; import { ApolloServer } from "apollo-server-express"; - -export const useGraphql = (obj = {}) => obj; - -export default function ({ wertikApp, app, store, configuration }) { - store.graphql.typeDefs = store.graphql.typeDefs.concat( - get(configuration, "graphql.typeDefs", "") - ); - - store.graphql.resolvers.Query = { - ...store.graphql.resolvers.Query, - ...get(configuration, "graphql.resolvers.Query", {}), +import { + GraphqlInitializeProps, + iObject, + useGraphqlProps, +} from "../types/types.v2"; + +export const useGraphql = (props: useGraphqlProps) => { + return ({ + wertikApp, + expressApp, + store, + configuration, + }: GraphqlInitializeProps) => { + store.graphql.typeDefs = store.graphql.typeDefs.concat( + get(configuration, "graphql.typeDefs", "") + ); + + store.graphql.resolvers.Query = { + ...store.graphql.resolvers.Query, + ...get(configuration, "graphql.resolvers.Query", {}), + }; + + store.graphql.resolvers.Mutation = { + ...store.graphql.resolvers.Mutation, + ...get(configuration, "graphql.resolvers.Mutation", {}), + }; + + const options = { ...get(configuration, "graphql.options", {}) }; + + const GraphqlApolloServer = new ApolloServer({ + typeDefs: store.graphql.typeDefs, + resolvers: { + ...store.graphql.resolvers, + }, + ...defaultApolloGraphqlOptions, + ...omit(options, ["context"]), + context: async () => { + let contextFromOptions = await get( + options, + "context", + function () {} + )(); + + return { + wertik: wertikApp, + ...contextFromOptions, + }; + }, + }); + + GraphqlApolloServer.applyMiddleware({ + app: expressApp, + ...(props?.applyMiddlewareOptions ?? {}), + }); + + return GraphqlApolloServer; }; - - store.graphql.resolvers.Mutation = { - ...store.graphql.resolvers.Mutation, - ...get(configuration, "graphql.resolvers.Mutation", {}), - }; - - const options = { ...get(configuration, "graphql.options", {}) }; - - const GraphqlApolloServer = new ApolloServer({ - typeDefs: store.graphql.typeDefs, - resolvers: { - ...store.graphql.resolvers, - }, - ...defaultApolloGraphqlOptions, - ...omit(options, ["context"]), - context: async () => { - let contextFromOptions = await get(options, "context", function () {})(); - - return { - wertik: wertikApp, - ...contextFromOptions, - }; - }, - }); - - GraphqlApolloServer.applyMiddleware({ app }); - - return GraphqlApolloServer; -} +}; diff --git a/src/next/index.ts b/src/next/index.ts index c850b852..16a2fabc 100644 --- a/src/next/index.ts +++ b/src/next/index.ts @@ -1,16 +1,14 @@ import { get } from "lodash"; import express from "express"; -import graphql from "./graphql/index"; import store from "./store"; import { applyRelationshipsFromStoreToDatabase, applyRelationshipsFromStoreToGraphql, } from "./database"; import { emailSender } from "./mailer/index"; -import cronJobs from "./cronJobs"; -import storage from "./storage/index"; -import sockets from "./sockets"; import http from "http"; +import { WertikConfiguration } from "./types/types.v2"; +import { WertikApp } from "./types/types.v2"; export * from "./database"; export * from "./modules/modules"; @@ -21,93 +19,123 @@ export * from "./storage"; export * from "./helpers/modules/backup"; export * from "./sockets"; -export default async function (configuration: any = {}) { +const Wertik: (configuration: WertikConfiguration) => Promise = ( + configuration: WertikConfiguration +) => { return new Promise(async (resolve, reject) => { try { - const wertikApp: { [key: string]: any } = { - email: { - sendEmail: () => {}, - }, + const wertikApp: WertikApp = { modules: {}, + database: {}, + mailer: {}, + graphql: {}, + sockets: {}, cronJobs: {}, storage: {}, - database: {}, }; const port = get(configuration, "port", 5050); const skip = get(configuration, "skip", false); - const app = get(configuration, "express", express()); - const server = http.createServer(app); - - wertikApp.server = server; - wertikApp.express = app; - wertikApp.email = { - sendEmail: emailSender(configuration), - ...get(configuration, "email", {}), - }; + const expressApp = get(configuration, "express", express()); + const httpServer = http.createServer(expressApp); + + wertikApp.httpServer = httpServer; + wertikApp.express = expressApp; + + for (const mailName of Object.keys(configuration.mailer || {})) { + wertikApp.mailer[mailName] = await configuration.mailer[mailName](); + } + + if (configuration.storage) { + for (const storageName of Object.keys(configuration.storage || {})) { + wertikApp.storage[storageName] = configuration.storage[storageName]({ + configuration: configuration, + wertikApp: wertikApp, + }); + } + } + + if (configuration.cronJobs) { + for (const cronName of Object.keys(configuration.cronJobs || {})) { + wertikApp.cronJobs[cronName] = configuration.cronJobs[cronName]({ + configuration: configuration, + wertikApp: wertikApp, + }); + } + } + + if (configuration.sockets) { + for (const socketName of Object.keys(configuration.sockets || {})) { + wertikApp.sockets[socketName] = configuration.sockets[socketName]({ + configuration: configuration, + wertikApp: wertikApp, + }); + } + } if (configuration.database) { - for (const databaseName of Object.keys(configuration.database)) { + for (const databaseName of Object.keys(configuration.database || {})) { try { - configuration.database[databaseName] = wertikApp.database[ + wertikApp.database[databaseName] = await configuration.database[ databaseName - ] = await configuration.database[databaseName](); + ](); } catch (e) { throw new Error(e); } } } + applyRelationshipsFromStoreToDatabase(store, wertikApp); + applyRelationshipsFromStoreToGraphql(store, wertikApp); + if (configuration.modules) { - for (const moduleName of Object.keys(configuration.modules)) { - configuration.modules[moduleName] = wertikApp.modules[moduleName] = - await configuration.modules[moduleName]( - configuration, - store, - wertikApp - ); + for (const moduleName of Object.keys(configuration.modules || {})) { + wertikApp.modules[moduleName] = await configuration.modules[ + moduleName + ]({ + store: store, + configuration: configuration, + app: wertikApp, + }); } } - applyRelationshipsFromStoreToDatabase(store, wertikApp); - applyRelationshipsFromStoreToGraphql(store, wertikApp); - - app.get("/w/info", function (req, res) { + expressApp.get("/w/info", function (req, res) { res.json({ - message: "You are running wertik-js", + message: "You are running wertik-js v3", version: require("./../../package.json").version, }); }); - configuration.cronJobs && cronJobs(configuration, wertikApp); - configuration.storage && storage(configuration, wertikApp); - configuration.sockets && sockets(configuration, wertikApp); + wertikApp.sendEmail = emailSender(wertikApp); if (configuration.graphql) { - configuration.graphql = wertikApp.graphql = graphql({ - wertikApp, - app, - store, - configuration, + wertikApp.graphql = configuration.graphql({ + wertikApp: wertikApp, + store: store, + configuration: configuration, + expressApp: expressApp, }); } - app.use(async function (req, res, next) { + expressApp.use(async function (req, _res, next) { req.wertik = wertikApp; next(); }); setTimeout(async () => { if (skip === false) { - server.listen(port, () => { + httpServer.listen(port, () => { console.log(`Wertik JS app listening at http://localhost:${port}`); }); } - resolve(app); + resolve(wertikApp); }, 500); } catch (e) { console.error(e); reject(e); } }); -} +}; + +export default Wertik; diff --git a/src/next/mailer/index.ts b/src/next/mailer/index.ts index 635f6189..2b270659 100644 --- a/src/next/mailer/index.ts +++ b/src/next/mailer/index.ts @@ -1,66 +1,57 @@ import nodemailer from "nodemailer"; import handlebars from "handlebars"; +import { emailSendProps, iObject, WertikApp } from "../types/types.v2"; -export const useMailer = async () => { - return new Promise(async (resolve, reject) => { - try { - let testAccount = await nodemailer.createTestAccount(); - const wertiknodemailerDefaultConfiguration = { - host: "smtp.ethereal.email", - port: 587, - secure: false, - auth: { - user: testAccount.user, - pass: testAccount.pass, - }, - }; - let transporter = nodemailer.createTransport( - wertiknodemailerDefaultConfiguration - ); - resolve(transporter); - } catch (e) { - console.log( - `Something went wrong while setting up email system: ${e.message}` - ); - reject(e); - } - }); +export const useMailer = (props?: iObject) => { + return async () => { + let testAccount = props ? null : await nodemailer.createTestAccount(); + + const wertiknodemailerDefaultConfiguration = props + ? props + : { + host: "smtp.ethereal.email", + port: 587, + secure: false, + auth: { + user: testAccount?.user, + pass: testAccount?.pass, + }, + }; + + return nodemailer.createTransport(wertiknodemailerDefaultConfiguration); + }; }; -export const emailSender = (app) => { - return (mailer, options) => { - return new Promise(async (resolve, reject) => { - try { - let transporter = app.email[mailer]; +export const emailSender = (app: WertikApp) => { + const fn = (props: { mailer: string; options: emailSendProps }) => { + return async () => { + let transporter = app.mailer[props.mailer]; - if (!transporter) { - throw new Error( - `Email integration ${mailer} not found. Please check the typo.` - ); - } + if (!transporter) { + throw new Error( + `Email integration ${props.mailer} not found. Please check the typo.` + ); + } - let compiled = handlebars.compile(options.template); - let resultTemplate = compiled(options.variables); - let emailInstance = await transporter.sendMail({ - from: options.from, - to: options.to, - html: resultTemplate, - subject: options.subject, - }); - if (emailInstance && emailInstance.messageId) { - console.log("Message sent: %s", emailInstance.messageId); - } - if (nodemailer && nodemailer.getTestMessageUrl) { - console.log( - "Preview URL: %s", - nodemailer.getTestMessageUrl(emailInstance) - ); - } - resolve(true); - } catch (e) { - console.error(e); - reject(e); + let compiled = handlebars.compile(props.options.template); + let resultTemplate = compiled(props.options.variables); + let emailInstance = await transporter.sendMail({ + from: props.options.from, + to: props.options.to, + html: resultTemplate, + subject: props.options.subject, + }); + if (emailInstance && emailInstance.messageId) { + console.log("Message sent: %s", emailInstance.messageId); + } + if (nodemailer && nodemailer.getTestMessageUrl) { + console.log( + "Preview URL: %s", + nodemailer.getTestMessageUrl(emailInstance) + ); } - }); + return emailInstance; + }; }; + return fn; }; diff --git a/src/next/modules/modules.ts b/src/next/modules/modules.ts index 06e83126..166352fb 100644 --- a/src/next/modules/modules.ts +++ b/src/next/modules/modules.ts @@ -1,4 +1,4 @@ -import { get, isFunction } from "lodash"; +import { get } from "lodash"; import crud from "../crud"; import { databaseDefaultOptions } from "../../framework/defaults/options"; import { RelationParams, useModuleProps } from "../types/types"; @@ -107,7 +107,7 @@ const getCreateSchema = (props, tableInformation) => { }; export const useModule = (props: useModuleProps) => { - return async (wertik: any, store: any, wertikApp: any) => { + return async ({ store, configuration, app }: any) => { let tableInstance; let graphqlSchema = []; @@ -139,7 +139,7 @@ export const useModule = (props: useModuleProps) => { const useExpress = (fn = (express) => {}) => { setTimeout(() => { - fn(wertikApp.express); + fn(app.express); }, 2500); }; @@ -148,7 +148,7 @@ export const useModule = (props: useModuleProps) => { if (useDatabase) { var createSchema = []; var updateSchema = []; - const connection = wertik.database[props.database]; + const connection = app.database[props.database]; const describe = await connection.instance.query( `describe ${props.table}` ); @@ -195,6 +195,7 @@ export const useModule = (props: useModuleProps) => { tableInformation.forEach((element, _index) => { if ( element.Type.includes("timestamp") || + element.Type.includes("datetime") || element.Type.includes("varchar") || element.Type.includes("text") ) { diff --git a/src/next/sockets/index.ts b/src/next/sockets/index.ts index d8f67d0f..d4b761c4 100644 --- a/src/next/sockets/index.ts +++ b/src/next/sockets/index.ts @@ -1,35 +1,64 @@ -import { isFunction } from "lodash"; -import { Server } from "socket.io"; -import { Server as WebSocketServer } from "ws"; +import { Server as SocketIOServer } from "socket.io"; +import { + Server as WebSocketServer, + ServerOptions as WebSocketServerOptions, +} from "ws"; +import { WertikApp } from "../types/types"; +import { WertikConfiguration } from "../types/types.v2"; -export const useWebSockets = (configuration) => { - return (props, app) => { +export const useWebSockets = (props: WebSocketServerOptions = {}) => { + return ({ + configuration, + wertikApp, + }: { + configuration: WertikConfiguration; + wertikApp: WertikApp; + }) => { + if (!props.path) { + throw new Error("Path must be passed for useWebSockets"); + } + console.log( + `Web Sockets server starting at ws://localhost:${configuration.port}${props.path}` + ); return new WebSocketServer({ - server: app.server, - ...configuration, + server: wertikApp.httpServer, + ...props, }); }; }; -export const useIndependentWebSocketsServer = (configuration) => { - return (props, app) => { +export const useIndependentWebSocketsServer = ( + props: WebSocketServerOptions = {} +) => { + return ({ + configuration, + wertikApp, + }: { + configuration: WertikConfiguration; + wertikApp: WertikApp; + }) => { + console.log( + `Web Sockets server starting at ws://localhost:${configuration.port}${props.path}` + ); return new WebSocketServer({ - ...configuration, + ...props, }); }; }; -export const useSocketIO = (configuration) => { - return (props) => { - return new Server(props.server, { - ...configuration, - }); +export const useSocketIO = (props: any = {}) => { + return ({ + configuration, + wertikApp, + }: { + configuration: WertikConfiguration; + wertikApp: WertikApp; + }) => { + console.log( + `Socket.IO server starting at http://localhost:${configuration.port}${ + props.path ?? "/socket.io" + }` + ); + return new SocketIOServer(wertikApp.httpServer, props); }; }; - -export default function (props, app) { - Object.keys(props.sockets).forEach((element) => { - const socket = props.sockets[element]; - if (isFunction(socket)) socket(props, app); - }); -} diff --git a/src/next/storage/index.ts b/src/next/storage/index.ts index d024bc29..d95dea58 100644 --- a/src/next/storage/index.ts +++ b/src/next/storage/index.ts @@ -1,14 +1,19 @@ -export const useStorage = (obj) => obj; +import { WertikApp } from "../types/types"; +import { useStorageProps, WertikConfiguration } from "../types/types.v2"; const DIGITAL_OCEAN = "digitalocean"; const DROPBOX = "dropbox"; -export default function (props, wertikApp) { - Object.keys(props.storage).forEach((element) => { - const storageItem = props.storage[element]; - +export const useStorage = (storageItem: useStorageProps) => { + return ({ + configuration, + wertikApp, + }: { + configuration: WertikConfiguration; + wertikApp: WertikApp; + }) => { if (storageItem.for === DIGITAL_OCEAN) { - const digitalOceanSpacesDetails = storageItem.options; + const digitalOceanSpacesDetails = storageItem.digitalOceanOptions; const aws = require("aws-sdk"); @@ -25,20 +30,24 @@ export default function (props, wertikApp) { endpoint: spacesEndpoint, }); - props.storage[element] = wertikApp.storage[element] = { + return { spacesEndpoint, s3, }; } else if (storageItem.for === DROPBOX) { - const dropdboxDetails = storageItem.options; + const dropdboxDetails = storageItem.dropboxOptions; const { Dropbox } = require("dropbox"); const dropboxInstance = new Dropbox({ accessToken: dropdboxDetails.accessToken, }); - props.storage[element] = wertikApp.storage[element] = { + return { dropbox: dropboxInstance, }; } - }); + }; +}; + +export default function (props, wertikApp) { + Object.keys(props.storage).forEach((element) => {}); } diff --git a/src/next/types/types.ts b/src/next/types/types.ts index 5bfa8b4e..815cfc7e 100644 --- a/src/next/types/types.ts +++ b/src/next/types/types.ts @@ -1,11 +1,34 @@ +import { httpstatus } from "aws-sdk/clients/glacier"; import { Express } from "express"; -import { Http2Server } from "http2"; -import { Sequelize } from "sequelize/types"; +import { Server } from "http"; +import { Model, Sequelize } from "sequelize/types"; +import { iObject } from "./types.v2"; + +export interface NextConfigurationProps { + port?: number; + skip?: any; + express?: any; + database?: { + [key: string]: (props: useDatabaseProps) => Function; + }; + modules?: { + [key: string]: (props: useModuleProps) => Function; + }; + cronJobs?: any; + sockets?: { + [key: string]: (props: any) => Function; + }; + graphql?: (props: useGraphqlProps) => { [key: string]: any }; + email?: { + [key: string]: (props: useMailerProps) => Function; + }; + storage?: any; +} export interface WertikApp { express?: Express; - server?: Http2Server; - port: number | string; + httpServer?: Server; + port?: number | string; skip: boolean; email: {}; database: { @@ -21,7 +44,9 @@ export interface WertikDatabase { credentials: WertikDatabaseCredentials; instance: Sequelize; } -export interface WertikModule {} +export interface WertikModule { + tableInstance: Model; +} export interface WertikDatabaseCredentials { port: number; password: string; @@ -30,28 +55,52 @@ export interface WertikDatabaseCredentials { name: string; } export interface WertikStorage {} - -export interface useGraphqlProps {} +export interface useGraphqlProps { + options?: { + [key: string]: any; + }; + resolvers?: { + Mutation: {}; + Query: {}; + }; + typeDefs?: string; +} export interface useCronJobsProps {} export interface useMailerProps {} export interface useIndependentWebSocketsServerProps {} export interface useWebSocketsProps {} export interface useSocketIOProps {} -export interface useDatabaseProps {} +export interface useDatabaseProps { + name: string; + username: string; + password: string; + host: number; + options: { + [key: string]: any; + }; +} export interface useModuleProps { name: string; useDatabase: boolean; table?: string; database?: string; - tableOptions?: any; + tableOptions?: iObject; graphql?: { schema?: string; + updateSchema?: string; + createSchema: string; + mutations?: { + update?: Function; + delete?: Function; + create?: Function; + createOrUpdate?: Function; + }; }; on?: (obj: { useQuery: (props: useQueryProps) => {} | void; useMutation: (props: useMutationProps) => {} | void; - useExpress: (props: useExpressProps) => {} | void; + useExpress: (express: any) => void; hasOne: (props: RelationParams) => {} | void; belongsTo: (props: RelationParams) => {} | void; belongsToMany: (props: RelationParams) => {} | void; @@ -65,6 +114,7 @@ export interface useModuleProps { beforeCreate?: Function; beforeDelete?: Function; beforeUpdate?: Function; + beforeCreateOrUpdate?: Function; }; } export interface useQueryProps { diff --git a/src/next/types/types.v2.ts b/src/next/types/types.v2.ts new file mode 100644 index 00000000..b9e7755a --- /dev/null +++ b/src/next/types/types.v2.ts @@ -0,0 +1,152 @@ +import { ApolloServer, GetMiddlewareOptions } from "apollo-server-express"; +import { Sequelize } from "sequelize/types"; +import { useDatabaseProps, WertikDatabase } from "./types"; + +export interface GetMiddlewareOptionsGraphql extends GetMiddlewareOptions { + path: string; +} + +export type iObject = { [key: string]: any }; + +export interface ModuleProps { + name: string; + useDatabase: false; + table: string; + database: string; +} + +export interface Store { + graphql: { + typeDefs: String; + resolvers: { + Query: { + [key: string]: Function; + }; + Mutation: { + [key: string]: Function; + }; + }; + }; + database: { + relationships: Array; + }; +} + +export interface useStorageProps { + for: "dropbox" | "digitalocean"; + dropboxOptions?: { + accessToken: string; + }; + digitalOceanOptions?: { + accessKeyId: string; + secretAccessKey: string; + spacesEndpoint: string; + }; +} + +export interface UseDatabaseProps { + name: string; + username: string; + password: string; + host: string; + port: number; + options?: iObject; +} + +export interface WertikConfiguration { + port: number; + express?: any; + httpServer?: iObject; + skip?: boolean; + database?: { + [key: string]: () => Promise<{ + credentials: UseDatabaseProps; + instance: Sequelize; + }>; + }; + modules?: { + [key: string]: ({ + store: Store, + configuration: WertikConfiguration, + app: WertikApp, + }) => iObject; + }; + storage?: { + [key: string]: ({ + configuration: WertikConfiguration, + wertikApp: WertikApp, + }) => { + spacesEndpoint?: iObject; + s3?: iObject; + dropbox?: iObject; + }; + }; + mailer?: { + [key: string]: () => Promise; + }; + sockets?: { + [key: string]: ({ + configuration: WertikConfiguration, + wertikApp: WertikApp, + }) => iObject; + }; + graphql?: ({ + store: Store, + configuration: WertikConfiguration, + wertikApp: WertikApp, + expressApp: any, + }) => iObject; + cronJobs?: { + [key: string]: ({ + configuration: WertikConfiguration, + wertikApp: WertikApp, + }) => iObject; + }; +} + +export interface useCronJobsProps { + expression: string; + name: string; + beforeRun?: (app: WertikApp) => void | any; + afterRun?: (app: WertikApp) => void | any; + handler: (app: WertikApp) => void | any; +} + +export interface emailSendProps { + template: string; + variables: { + [key: string]: any; + }; + from: string; + to: string; + subject: string; + [key: string]: any; +} + +export interface useGraphqlProps { + options?: { + [key: string]: any; + }; + applyMiddlewareOptions?: GetMiddlewareOptionsGraphql; + resolvers?: { + Mutation: {}; + Query: {}; + }; + typeDefs?: string; +} + +export interface userMailerProps {} + +export interface WertikApp { + sendEmail?: ( + app: WertikApp + ) => ({ mailer: string, options: emailSendProps }) => iObject; + [key: string]: any; +} + +export interface GraphqlInitializeProps { + wertikApp: WertikApp; + store: Store; + configuration: WertikConfiguration; + expressApp: any; +} diff --git a/tsconfig.json b/tsconfig.json index 193dc844..d7a4c2d8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,19 +1,17 @@ { - "compilerOptions": { - "module": "commonjs", - "esModuleInterop": true, - "target": "es2015", - "noImplicitAny": false, - "moduleResolution": "node", - "sourceMap": true, - "outDir": "lib", - "baseUrl": "./", - "lib": ["es6", "esnext.asynciterable"], - "types": [ - "node" - ] - }, - "include": [ - "src/**/*" - ] -} \ No newline at end of file + "compilerOptions": { + "module": "commonjs", + "esModuleInterop": true, + "target": "es2015", + "noImplicitAny": false, + "moduleResolution": "node", + "sourceMap": true, + "outDir": "lib", + "baseUrl": "./", + "lib": ["es6", "esnext.asynciterable"], + "types": ["node"], + "skipLibCheck": true, + "declaration": true + }, + "include": ["src/**/*"] +}