7 | Thanks for joining {{siteName}}, This email is to inform you that you have joined {{siteName}} on {{ date }}, Click Here to verify your account.
8 |
9 |
10 |
11 | Thanks
12 | {{ siteName }} Team.
13 |
14 | `;
15 |
--------------------------------------------------------------------------------
/src/framework/security/createJwtToken.ts:
--------------------------------------------------------------------------------
1 | let moment = require("moment");
2 | let jwt = require("jsonwebtoken");
3 | import { get, has } from "lodash";
4 |
5 | export default async function createJwtToken(data: any) {
6 | if (typeof data !== "object") {
7 | throw "Data must be object";
8 | }
9 | let firstArgument = data;
10 | let secret = process.env.jwtSecret || "asdasdasd";
11 | return await jwt.sign(firstArgument, secret, {expiresIn: data.expiresIn });
12 | }
13 |
--------------------------------------------------------------------------------
/docs/getting-started/installation.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | You can Install wertik with npm or yarn
4 |
5 | npm install wertik-js --save
6 |
7 | or with yarn
8 |
9 | yarn add wertik-js --dev
10 |
11 | After installation you can import Wertik by:
12 |
13 | import wertik from "wertik-js/lib/main";
14 |
15 | or
16 |
17 | const wertik = require("wertik-js/lib/main");
18 |
19 | Great, you have installed wertik, now lets setup the basic app. Please see Configuration part.
20 |
--------------------------------------------------------------------------------
/docs/v2/database.md:
--------------------------------------------------------------------------------
1 | ### Database
2 |
3 | Wertik-js uses Sequelize and supports the database that sequelize support. Database connection can be pass by:
4 |
5 | ```javascript
6 | export default {
7 | name: "Wertik",
8 | // ... Rest of the configuration
9 | database: {
10 | dbDialect: "mysql",
11 | dbUsername: "root",
12 | dbPassword: "pass",
13 | dbName: "graphql",
14 | dbHost: "localhost",
15 | dbPort: "3306",
16 | },
17 | // ... Rest of the configuration
18 | };
19 | ```
20 |
--------------------------------------------------------------------------------
/docs/v2/graphql.md:
--------------------------------------------------------------------------------
1 | #### GraphQL
2 |
3 | **Type:** Object
4 | **Default Value:**
5 | **Description:** Options for graphql. We have used Apollo Graphql.
6 |
7 | ```javascript
8 | {
9 | disable: false,
10 | apolloGraphqlServerOptions: defaultApolloGraphqlOptions
11 | }
12 | ```
13 |
14 | apolloGraphqlServerOptions are the options for apollo graphql. For more details please see: https://www.apollographql.com/docs/apollo-server/api/apollo-server/#options.
15 |
16 | Note: Please donot add these options context, resolvers and typeDefs.
--------------------------------------------------------------------------------
/src/framework/defaults/defaultConfigurations/postgresConfiguration.ts:
--------------------------------------------------------------------------------
1 | import defaultConfiguration from "./defaultConfiguration";
2 |
3 | let configuration = { ...defaultConfiguration };
4 |
5 | configuration.database = {
6 | dbDialect: "postgres",
7 | dbUsername: "wmysixugpufzba",
8 | dbPassword: "7255d55e83deafe26d093306e958b7e50dad5ac02f687249d02c9a53590c120f",
9 | dbName: "d5rsarnju68s4f",
10 | dbHost: "ec2-54-246-89-234.eu-west-1.compute.amazonaws.com",
11 | dbPort: "5432"
12 | };
13 |
14 | export default configuration;
15 |
--------------------------------------------------------------------------------
/src/framework/mailer/email-templates/requestPasswordReset.ts:
--------------------------------------------------------------------------------
1 | export default `
2 |
3 | Hi,
4 |
5 |
6 |
7 | Action taken for resetting {{ email }} password.
8 |
9 |
10 |
11 | Your token is: {{ token }}
12 |
13 |
14 |
15 | You can reset your password Here. This
16 | email is valid for next 30 minutes, The link will expire on {{ nextMinutes}}.
17 |
18 |
19 |
20 | Thanks,
21 | {{siteName}} Team
22 |
23 | `;
24 |
--------------------------------------------------------------------------------
/src/framework/security/getUserWithAccessToken.ts:
--------------------------------------------------------------------------------
1 | let { get } = require("lodash");
2 | export default async function (UserModel: any, token: string) {
3 | try {
4 | let find = await UserModel.findOneByArgs({ access_token: token }, "*");
5 | return get(find, "instance", null);
6 | } catch (errorInstance) {
7 | let modules: any = process.env.builtinModules;
8 | modules = modules.split(",");
9 | modules = modules.filter((c) => c);
10 | if (modules.length == 0) {
11 | return null;
12 | } else {
13 | throw errorInstance;
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/framework/security/isAuthQuery.ts:
--------------------------------------------------------------------------------
1 | let { get } = require("lodash");
2 | let gql = require("graphql-tag");
3 | export default function(query: string) {
4 | let parsed = gql`
5 | ${query}
6 | `;
7 | let queryName = get(parsed, "definitions[0].selectionSet.selections[0].name.value", "");
8 | let auth = [
9 | "signup",
10 | "resetPassword",
11 | "requestPasswordResetToken",
12 | "login",
13 | "activateAccount",
14 | "generalAccessToken",
15 | "twoFactorLogin",
16 | "twoFactorLoginValidate"
17 | ];
18 | return auth.indexOf(queryName) > -1;
19 | }
20 |
--------------------------------------------------------------------------------
/docs/v2/sockets.md:
--------------------------------------------------------------------------------
1 | #### sockets - beta
2 |
3 | **Type:** Object
4 | **Default Value:**
5 | **Description:** For sockets we use Socket.IO.
6 |
7 | ```javascript
8 | {
9 | disable: false,
10 | onClientConnected: function () {
11 | console.log("onClientConnected");
12 | },
13 | onMessageReceived: function () {
14 | console.log("onMessageReceived");
15 | },
16 | onClientDisconnect: function () {
17 | console.log("onClientDisconnect");
18 | },
19 | };
20 | ```
21 |
22 | For please visit https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/socket/index.ts.
--------------------------------------------------------------------------------
/examples/socket-test/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/framework/logger/consoleMessages.ts:
--------------------------------------------------------------------------------
1 | import logSymbols from "log-symbols";
2 | import chalk from "chalk";
3 | const log = console.log;
4 |
5 | export const successMessage = function(message, secondMessage?: string) {
6 | log(
7 | logSymbols.success,
8 | ` [Wertik-js]: `,
9 | chalk.green(message),
10 | secondMessage ? chalk.blue.underline.bold(secondMessage) : ""
11 | );
12 | };
13 |
14 | export const errorMessage = function(message) {
15 | log(logSymbols.error, ` [Wertik-js]:`, chalk.red(message));
16 | };
17 |
18 | export const warningMessage = function() {};
19 |
20 | export const infoMessage = function() {};
21 |
--------------------------------------------------------------------------------
/src/framework/database/helpers/index.ts:
--------------------------------------------------------------------------------
1 | const sequelize = require("sequelize");
2 |
3 | export const convertFieldsIntoSequelizeFields = (fields) => {
4 | let k = Object.keys(fields);
5 | k.forEach((element) => {
6 | let t = fields[element].type;
7 | if (t.toLowerCase() === "number") {
8 | t = "integer";
9 | }
10 | fields[element].type = sequelize[t.toUpperCase()];
11 | fields[element].oldType = t;
12 | });
13 | return fields;
14 | };
15 |
16 | export const deleteModel = () => {};
17 |
18 | export const paginateModel = () => {};
19 |
20 | export const updateModel = () => {};
21 |
22 | export const viewModel = () => {};
23 |
--------------------------------------------------------------------------------
/src/framework/mailer/emailTemplates.ts:
--------------------------------------------------------------------------------
1 | import { get } from "lodash";
2 | import fs from "fs";
3 | import { join } from "path";
4 | import { filesInAFolder } from "./../helpers/index";
5 | export default function(configuration, rootPath) {
6 | let allEmailTemplates = filesInAFolder(`${__dirname}/email-templates`);
7 | let templatesObject = {};
8 | allEmailTemplates.forEach(element => {
9 | let name = element.split(".")[0];
10 | let template = require(`./email-templates/${name}`).default;
11 | templatesObject[name] = template;
12 | });
13 |
14 | return {
15 | ...templatesObject,
16 | ...get(configuration, "email.templates", {})
17 | };
18 | }
19 |
--------------------------------------------------------------------------------
/src/framework/security/getUserRoles.ts:
--------------------------------------------------------------------------------
1 | export default async function(userId, database) {
2 | let sqlQuery = `SELECT r.*, ur.id as ur_id,
3 | ur.name as ur_name,
4 | ur.created_at as ur_created_at,
5 | ur.updated_at as ur_updated_at,
6 | ur.deleted_at as ur_deleted_at,
7 | ur.role as ur_role,
8 | ur.user as ur_user
9 |
10 | from user_role as ur
11 | left JOIN role as r on r.id = ur.role
12 | where ur.user = _________user_ID`;
13 | sqlQuery = sqlQuery.replace(/_________user_ID/g, userId + "");
14 | const roles = await database.query(sqlQuery, { type: database.QueryTypes.SELECT });
15 | return roles;
16 | }
17 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/request_help.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Request Help
3 | about: Any issues while using wertik-js you can use this template for use case of wertik-js
4 | title: ''
5 | labels: 'help support'
6 | assignees: 'ilyaskarim'
7 | ---
8 |
9 | #### Issue having onboarding Wertik? We are here to help.
10 |
11 | **What isue you are having?**
12 |
13 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
14 |
15 | **What you actually you want to do?**
16 |
17 | A clear and concise description of what you want to happen.
18 |
19 |
20 | **Other Remarks**
21 |
22 | Add any other context or screenshots about the feature request here.
23 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/docs/seeds/introduction.md:
--------------------------------------------------------------------------------
1 | ### Seeds
2 |
3 | Seeds allow you to insert some random data to your app, So lets say you want to insert some default Roles into your app, so you can pass seeds by
4 |
5 | ```javascript
6 | let configuration = {
7 | // rest of the configuration
8 | seeds: {
9 | Role: [{ name: "My Role" }, { name: "My Role #2" }],
10 | },
11 | };
12 | ```
13 |
14 | So, you have added, After initializetion of wertik-js you can run seeds by:
15 |
16 | ```javascript
17 | import wertik from "./main";
18 | wertik({ expressApp: app }, defaultConfiguration).then((wertikApp: any) => {
19 | wertikApp.seeds(["Role"]); // Same name goes for module.name
20 | });
21 | ```
22 |
23 | This will insert module seeds.
24 |
--------------------------------------------------------------------------------
/docs/graphql/introduction.md:
--------------------------------------------------------------------------------
1 | ### GraphQL
2 |
3 | Under the hood Wertik-js uses Apollo GraphQL server for Graphql Implementation, we selected Apollo Graphql server due to its popularity and features. Please see this file https://github.com/Uconnect-Technologies/wertik-js/tree/master/src/framework/graphql/index.ts where the GraphQL is added.
4 |
5 | Currently we donot have direct implementation for GraphQL, You can only use GraphQL by using with custom modules, Please see custom modules page for more details.
6 |
7 | If you have any suggestions, bugs or feature request you can create a new issue
8 |
9 | https://github.com/Uconnect-Technologies/wertik-js/issues/new/choose
10 |
11 | We will be happy to assist you with your issue.
--------------------------------------------------------------------------------
/docs/rbac/introduction.md:
--------------------------------------------------------------------------------
1 | ### Role Based Access Control
2 |
3 | Wertik-js provides Role Based Access Control feature. While this can be done through context. Roles and Permissions for a user are passed to context, In GraphQL you can access Roles and Permissions by:
4 |
5 | ```javascript
6 | function (_, args, context,info) {
7 | console.log(context.userRoles); // User Roles
8 | console.log(context.userPermissions) // User Permissions
9 | }
10 | ```
11 |
12 | In RestAPI you can access Roles and Permissions by:
13 |
14 | ```javascript
15 | function (req,res) {
16 | console.log(req.userRoles) // User Roles
17 | console.log(req.userPermissions) // User Permissions
18 | }
19 | ```
20 |
21 | Based on Roles and Permisions, You can decide to continue request.
--------------------------------------------------------------------------------
/src/framework/database/models.ts:
--------------------------------------------------------------------------------
1 | import Model from "./../model/model";
2 | import { IConfiguration } from "../types/configuration";
3 | import { loadModulesFromConfiguration } from "../helpers";
4 | import { get } from "lodash";
5 |
6 | export default function (dbTables, configuration: IConfiguration) {
7 | let modules = loadModulesFromConfiguration(configuration);
8 | let allTables = Object.keys(dbTables);
9 | let models = {};
10 | allTables.forEach((element) => {
11 | let module = modules.filter((c) => c.name == element);
12 | models[element] = Model({
13 | dbTables: dbTables,
14 | tableName: element,
15 | configuration: configuration,
16 | module: get(module, "[0]", {}),
17 | });
18 | });
19 | return models;
20 | }
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - Version [e.g. 22]
28 |
29 | **Additional context**
30 | Add any other context about the problem here.
31 |
--------------------------------------------------------------------------------
/src/framework/helpers/convertConfigurationIntoEnvVariables.ts:
--------------------------------------------------------------------------------
1 | declare var process: any;
2 | import { IConfiguration } from "./../types/configuration";
3 |
4 | export default function(configuration: IConfiguration) {
5 | return new Promise((resolve, reject) => {
6 | try {
7 | let keys = Object.keys(configuration);
8 | // Important ones
9 | process.env.dbDialect = configuration.database.dbDialect;
10 | // Important ones
11 | keys.forEach((key, index) => {
12 | let value = configuration[key];
13 |
14 | process.env[key] = value;
15 | if (index + 1 == keys.length) {
16 | resolve("Added to env.");
17 | }
18 | });
19 | } catch (e) {
20 | reject(e.message);
21 | }
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/src/framework/helpers/validateConfigurationObject.ts:
--------------------------------------------------------------------------------
1 | import checkInstalledPackages from "../initialization/checkInstalledPackages";
2 | import checkModules from "../initialization/checkModules";
3 |
4 | export const requiredFields = {
5 | name: "required",
6 | dialect: "mysql",
7 | db_username: "required",
8 | db_password: "required",
9 | db_name: "required",
10 | db_host: "required",
11 | db_port: "required"
12 | };
13 |
14 | export default function(configuration) {
15 | return new Promise(async (resolve, reject) => {
16 | try {
17 | let responseCheckInstalledPackages = await checkInstalledPackages(configuration);
18 | let responseCheckModules = await checkModules(configuration);
19 | resolve();
20 | } catch (errr) {
21 | reject(errr);
22 | console.log(errr);
23 | }
24 | });
25 | }
26 |
--------------------------------------------------------------------------------
/docs/v2/mailer.md:
--------------------------------------------------------------------------------
1 | #### email
2 |
3 | **Type:** Object
4 | **Default Value:**
5 | **Description:** Wertik uses NodeMailer for emails. The configuration for email handling in Wertik
6 |
7 | ```javascript
8 | {
9 | disable: true;
10 | configuration: NodeMailerConfigurationObject;
11 | }
12 | ```
13 |
14 | By default emailing is disabled in wertik, Assigning false to disable activates the emailing in wertik. You have to provide second arugment which is configuration of Node mailer.
15 |
16 | When pasing mailer. Wertik sends a method called sendEmail to context to send emails. Please see this function for more details: https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/mailer/index.ts#L22. Since its a closure, Main function starts from here: https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/mailer/index.ts#L22.
17 |
--------------------------------------------------------------------------------
/src/framework/graphql/schemaMap.ts:
--------------------------------------------------------------------------------
1 | export default `
2 | type Response {
3 | message: String
4 | version: String
5 | }
6 | type SuccessResponse {
7 | message: String
8 | }
9 | input IDDeleteInput {
10 | id: [Int]
11 | }
12 | [generalSchema__replace]
13 | [modulesSchema__replace]
14 | type Mutation {
15 | response: Response
16 | [mutation__replace]
17 | }
18 | type Query {
19 | response: Response
20 | [query__replace]
21 | }
22 | type Subscription {
23 | response: Response
24 | [subscription__replace]
25 | }
26 | input EmailInput {
27 | email: String!
28 | }
29 | input SignupInput {
30 | email: String!
31 | password: String!
32 | confirmPassword: String!
33 | }
34 | schema {
35 | query: Query
36 | mutation: Mutation
37 | subscription: Subscription
38 | }
39 | `;
40 |
--------------------------------------------------------------------------------
/examples/demo/index.js:
--------------------------------------------------------------------------------
1 | // Import files for database connection and serving wertik.
2 | const { serve, connectDatabase } = require("./../../index");
3 | // import default configuration, remember you have to add .env setup.
4 | const configuration = require("./../../lib/framework/defaults/defaultConfigurations/defaultConfiguration").default;
5 |
6 | // Connect to database.
7 | connectDatabase(configuration.database)
8 | .then((databaseInstance) => {
9 | // Assign database instance to configuration
10 | configuration.databaseInstance = databaseInstance;
11 | // serve app!
12 | serve(configuration).then((wertikApp) => {
13 | if (configuration.database.dbDialect.includes("sql")) {
14 | wertikApp.database.sync();
15 | }
16 | });
17 | })
18 | .catch((e) => {
19 | console.log(`Error connecting with database`);
20 | console.log(e);
21 | });
22 |
--------------------------------------------------------------------------------
/src/devServer.ts:
--------------------------------------------------------------------------------
1 | import { connectDatabase, serve } from "./main";
2 | import { IConfiguration } from "./framework/types/configuration";
3 | const defaultConfiguration: IConfiguration = require("./framework/defaults/defaultConfigurations/defaultConfiguration")
4 | .default;
5 | const postgresConfiguration: IConfiguration = require("./framework/defaults/defaultConfigurations/postgresConfiguration")
6 | .default;
7 |
8 | let configuration = defaultConfiguration;
9 |
10 | connectDatabase(configuration.database)
11 | .then((databaseInstance) => {
12 | configuration.databaseInstance = databaseInstance;
13 | serve(configuration).then((wertikApp: any) => {
14 | if (configuration.database.dbDialect.includes("sql")) {
15 | wertikApp.database.sync();
16 | }
17 | });
18 | })
19 | .catch((e) => {
20 | console.log(`Error connecting with database`);
21 | console.log(e);
22 | });
23 |
--------------------------------------------------------------------------------
/src/framework/initialization/checkModules.ts:
--------------------------------------------------------------------------------
1 | import { IConfiguration } from "../types/configuration";
2 |
3 | export default function(configuration: IConfiguration) {
4 | const { modules } = configuration;
5 | return new Promise((resolve, reject) => {
6 | if (modules.length == 0) {
7 | console.log("[Wertik-js] Starting with no custom modules.")
8 | resolve(true);
9 | }
10 | modules.forEach((element, index) => {
11 | let isLast = index == modules.length - 1;
12 | if (!element || element.constructor !== Object) {
13 | console.error(
14 | `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`
15 | );
16 | process.exit();
17 | }
18 | if (isLast) {
19 | resolve(true);
20 | }
21 | });
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/docs/restApi/introduction.md:
--------------------------------------------------------------------------------
1 |
2 | ### Rest API
3 |
4 | For Rest API wertik-js uses Express-js for rest api feature. Due to its popularity and key features. The rest api is registered in this file: [https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/restApi/index.ts](https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/restApi/index.ts)
5 |
6 | #### Changing Port
7 |
8 | You can change the port by
9 |
10 | ```javascript
11 | let configuration = {
12 | /// Rest of the configuration
13 | restApi: {
14 | port: 7070 // Define your port her
15 | }
16 | }
17 | ```
18 |
19 | #### Disable Rest API
20 |
21 |
22 | You can disable Rest API by:
23 |
24 | ```javascript
25 | let configuration = {
26 | /// Rest of the configuration
27 | restApi: {
28 | disable: true // passing true will disable the Rest API
29 | }
30 | }
31 | ```
32 |
33 |
34 | For adding Rest Api endpoints, Please see custom modules section.
--------------------------------------------------------------------------------
/src/framework/apiDocs/docs/index.ts:
--------------------------------------------------------------------------------
1 | import { IDocServerConfiguration } from "./../../types/configuration";
2 | import express from "express";
3 | import path from "path";
4 | const port = 5200;
5 | const app = express();
6 | import { get } from "lodash";
7 | import { successMessage } from "../../logger/consoleMessages";
8 |
9 | export default function(options: IDocServerConfiguration, cb: Function) {
10 | const { configuration } = options;
11 | const port = get(options, "port", 5200);
12 | app.use(express.static("index"));
13 | app.use(express.static(path.join(__dirname, "/content")));
14 | app.use(async function(req, res, next) {
15 | const ip = req.connection.remoteAddress;
16 | next();
17 | });
18 | app.get("/", function(req, res) {
19 | res.sendFile("./index.html", { root: __dirname });
20 | });
21 | app.listen(port, function() {
22 | successMessage(`Rest API docs running at`,`http://localhost:${port}/`)
23 | cb();
24 | });
25 | }
26 |
--------------------------------------------------------------------------------
/src/framework/builtinModules/me/index.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | name: "Me",
3 | useDatabase: false,
4 | graphql: {
5 | schema: `
6 | type Me {
7 | user: User
8 | name: String
9 | permissions: [Permission]
10 | }
11 | `,
12 | mutation: {
13 | schema: ``,
14 | resolvers: {}
15 | },
16 | query: {
17 | schema: `
18 | me: Me
19 | `,
20 | resolvers: {
21 | me: (_: any, args: any, context: any, info: any) => {
22 | return {
23 | name: "Ilyas",
24 | user: context.user,
25 | permissions: context.permissions.map(element => {
26 | return {
27 | cant: element.permission_cant,
28 | can: element.permission_can,
29 | id: element.permission_id
30 | };
31 | })
32 | };
33 | }
34 | }
35 | }
36 | },
37 | restApi: {}
38 | };
39 |
--------------------------------------------------------------------------------
/docs/storage/introduction.md:
--------------------------------------------------------------------------------
1 | ## Storage - Beta
2 |
3 | Wertik-js allows storing files on your server by using Multer package, Currently storage is only available on Rest Api side. You can find initialization of multer on main.ts file, Please see https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/main.ts#L41. For implementation of storage, You can find storage module here: https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/builtinModules/storage/index.ts.
4 |
5 | After running server you send files to upload on this address: http://localhost:7000/api/v1/storage/upload,
6 |
7 | Method Type: Post
8 |
9 |
10 | Paramter: file
11 |
12 | Depending on status the API will send a response. The Storage feature is in beta, If you can any idea to implement you can write it in a feature request [here][1].
13 |
14 |
15 | [1]: https://github.com/Uconnect-Technologies/wertik-js/issues/new?assignees=&labels=&template=feature_request.md&title=Storage%20feature
16 |
--------------------------------------------------------------------------------
/src/framework/apiDocs/index.ts:
--------------------------------------------------------------------------------
1 | import fs from "fs";
2 | declare var process: any;
3 | import { exists, deleteFile, createEmptyFile, appendToFileSync } from "./../helpers/index";
4 | import { IDocServerConfiguration } from "./../types/configuration";
5 |
6 | const docFileSource = process.env['generateDocumentationPath'];
7 | // const docFileSource = "asd";
8 |
9 | export const addContentsToDoc = async function(doc: string) {
10 | setTimeout(() => {
11 | doc = doc.replace("first________", "/**");
12 | doc = doc.replace("last________", "*/");
13 | appendToFileSync(docFileSource, doc);
14 | }, 600);
15 | };
16 |
17 | export const resetDocFile = async function() {
18 | deleteDocFile(function() {
19 | createEmptyFile(docFileSource, function() {
20 | addContentsToDoc("//empty file");
21 | });
22 | });
23 | };
24 |
25 | export const deleteDocFile = async function(cb: Function) {
26 | if (exists(docFileSource)) {
27 | deleteFile(docFileSource, cb);
28 | } else {
29 | cb();
30 | }
31 | };
--------------------------------------------------------------------------------
/src/framework/types/servers.ts:
--------------------------------------------------------------------------------
1 | import { IConfiguration } from "./configuration";
2 |
3 | export interface IGraphQLInitialize {
4 | sendEmail: Function;
5 | expressApp: any;
6 | configuration: IConfiguration;
7 | dbTables: Array;
8 | models: any;
9 | emailTemplates: Object;
10 | database: any;
11 | WertikEventEmitter: any;
12 | mailerInstance: any;
13 | socketio: any;
14 | logger: any;
15 | }
16 |
17 | export interface IRestApiInitialize {
18 | sendEmail: Function;
19 | configuration: IConfiguration;
20 | mailerInstance: any;
21 | expressApp: any;
22 | dbTables: Array;
23 | emailTemplates: any;
24 | models: any;
25 | database: any;
26 | WertikEventEmitter: any;
27 | multerInstance: any;
28 | socketio: any;
29 | logger: any;
30 | }
31 |
32 | export interface ISocketConfiguration {
33 | onMessageReceived: Function;
34 | onClientConnected: Function;
35 | onClientDisconnect: Function;
36 | disable: Boolean;
37 | options: {
38 | [key: string]: any
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/framework/defaults/loadDefaults.ts:
--------------------------------------------------------------------------------
1 | import defaultConfiguration from "./defaultConfigurations/defaultConfiguration";
2 | import { IConfiguration } from "./../types/configuration";
3 |
4 | export default function(configuration: IConfiguration) {
5 | return new Promise((resolve, reject) => {
6 | try {
7 | let configurationPassesInKeys = Object.keys(configuration);
8 | if (configurationPassesInKeys.length == 0) {
9 | console.warn("[WERTIK-JS] Configuration not passed, using default configuration.");
10 | resolve(defaultConfiguration);
11 | }
12 | let newConfiguration = new Object({ ...defaultConfiguration });
13 | configurationPassesInKeys.forEach((element, index) => {
14 | let isLast = index + 1 == configurationPassesInKeys.length;
15 | newConfiguration[element] = configuration[element];
16 | if (isLast) {
17 | resolve(newConfiguration);
18 | }
19 | });
20 | } catch (err) {
21 | reject(err);
22 | }
23 | });
24 | }
25 |
--------------------------------------------------------------------------------
/src/framework/helpers/replaceFilterOperators.ts:
--------------------------------------------------------------------------------
1 | import { isPlainObject } from "lodash";
2 | import sequelize from "sequelize";
3 | const Op = sequelize.Op;
4 |
5 | const wrap = (operator) => {
6 | return Op[operator.replace("_", "")];
7 | };
8 |
9 | const iterate = (obj) => {
10 | const isObject = isPlainObject(obj);
11 | const isArray = Array.isArray(obj);
12 | if (isObject) {
13 | const keys = Object.keys(obj);
14 | keys.forEach((element) => {
15 | const value = obj[element];
16 | const isArray = Array.isArray(value);
17 | const isObject = isPlainObject(value);
18 | if (element.indexOf("_") === 0) {
19 | const newWrapValue = wrap(element);
20 | obj[newWrapValue] = obj[element];
21 | delete obj[element];
22 | }
23 | if (isArray === true || isObject === true) {
24 | iterate(value);
25 | }
26 | });
27 | return obj;
28 | } else {
29 | obj.forEach((element) => {
30 | iterate(element);
31 | });
32 | }
33 | };
34 |
35 | export default iterate;
36 |
--------------------------------------------------------------------------------
/src/framework/types/models.ts:
--------------------------------------------------------------------------------
1 | export interface IPermission {
2 | id: Number;
3 | name: String;
4 | can: String;
5 | cant: String;
6 | }
7 |
8 | export interface IRole {
9 | name: String;
10 | defaultPermissions: String;
11 | }
12 |
13 | export interface IUser {
14 | id: Number;
15 | name: String;
16 | username: String;
17 | refreshToken: String;
18 | accessToken: String;
19 | isActivated: Boolean;
20 | activatedOn: String;
21 | twoFactorCode: String;
22 | isSuperUser: Boolean;
23 | activationToken: String;
24 | email: String;
25 | gender: String;
26 | referer: String;
27 | }
28 |
29 | export interface IForgetPassword {
30 | id: Number;
31 | name: String;
32 | email: String;
33 | user: any;
34 | token: String;
35 | }
36 |
37 | export interface IRolePermission {
38 | id: Number;
39 | role: any;
40 | permission: any;
41 | }
42 |
43 | export interface IUserPermission {
44 | id: Number;
45 | user: any;
46 | permission: any;
47 | }
48 |
49 | export interface IModelHandlerFunctionProps {
50 | mode: string;
51 | req: any;
52 | }
53 |
--------------------------------------------------------------------------------
/src/framework/cron/index.ts:
--------------------------------------------------------------------------------
1 | import { IConfiguration } from "../types/configuration";
2 | import cron from "node-cron";
3 | import { get } from "lodash";
4 |
5 | export default function (configuration: IConfiguration, context: any) {
6 | return new Promise(async (resolve, reject) => {
7 | let configurationCron = configuration.cron;
8 | configurationCron.cronList.forEach((cronItem) => {
9 | let initializedEvent = get(cronItem, "events.initialized", () => {});
10 | let cronItemOptions = get(cronItem, "options", {});
11 | let cronItemExpression = get(cronItem, "expression", {});
12 | let handler = get(cronItem, "function", () => {});
13 | if (cron.validate(cronItem.expression)) {
14 | let cronScheduleItem = cron.schedule(
15 | cronItemExpression,
16 | () => {
17 | handler(context);
18 | },
19 | cronItemOptions
20 | );
21 | initializedEvent(cronScheduleItem);
22 | } else {
23 | console.log(`Wrong expression: ${cronItem.expression}`);
24 | }
25 | });
26 | });
27 | }
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Ilyas Karim
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/docs/v2/restApi.md:
--------------------------------------------------------------------------------
1 | ### Rest API
2 |
3 | For Rest API wertik-js uses Express-js for rest api feature. Due to its popularity and key features. The rest api is registered in this file: [https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/restApi/index.ts](https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/restApi/index.ts)
4 |
5 | #### Configuration
6 |
7 | ```javascript
8 | let configuration = {
9 | /// Rest of the configuration
10 | restApi: {
11 | showWertik404Page: true, // Show wertik 404 page. If set to false wertik js will not show 404 message.
12 | restApi404Handler: function (req, res) {
13 | res.status(404).json({
14 | message: "Not found",
15 | data: {
16 | message: "Request page didn't found",
17 | },
18 | });
19 | }, // Showing 404 page.
20 | onCustomApiFailure: function ({ path, res, err }) {
21 | res.send("failed at " + path);
22 | }, // On api request fail.
23 | },
24 | };
25 | ```
26 |
27 | For using rest api in modules. Please see [custom modules](http://wapgee.com/wertik-js/custom-modules/introduction) section.
--------------------------------------------------------------------------------
/docs/introduction/motivation.md:
--------------------------------------------------------------------------------
1 |
2 | ### Motivation
3 |
4 | Building SaaS applications backend is not an easy thing, this requires a lot of effort. So wertik-js comes to play here, Wertik-js provides all required features to build a backend. Following things needed to be cared of when building backend api
5 |
6 |
7 | - Database
8 |
9 | - Security
10 |
11 | - Development
12 |
13 | - Seeding
14 |
15 | - Realtime Development
16 |
17 | - Api
18 |
19 | - Email system
20 |
21 | - Events
22 |
23 | - Role based access control
24 |
25 | - Storage
26 |
27 |
28 | #### Why Wertik-js
29 |
30 | Wertik-js comes to play here to build a backend that is powered with all features mentioned above. Wertik-js allows GraphQL and RestAPI in single backend application. The library also provides database that Seqeulize supports. Wertik-js allows sockets integrations. For more you can check this folder to see all Wertik-js features: https://github.com/Uconnect-Technologies/wertik-js/tree/master/src/framework.
31 |
32 | #### Upcoming Features
33 |
34 | These are the upcoming features for Wertik-js:
35 |
36 | - MongoDB Implentation
37 | - Logs with database
38 | - Cron Jobs
39 |
40 |
--------------------------------------------------------------------------------
/src/framework/seeds/index.ts:
--------------------------------------------------------------------------------
1 | export default function(configuration, models) {
2 | return function(modules: Array) {
3 | return new Promise((resolve, reject) => {
4 | if (modules && modules.constructor == Array) {
5 | const seeds = configuration.seeds;
6 | if (modules.length == 0) {
7 | resolve("No Seeds provided.");
8 | return;
9 | }
10 | modules.forEach((currentModule, index) => {
11 | let isEnd = modules.length - 1 == index;
12 | let moduleData = seeds[currentModule];
13 | let model = models[currentModule];
14 | moduleData.forEach((element, indexOfData) => {
15 | model.create(element);
16 | if (isEnd && indexOfData == moduleData.length - 1) {
17 | resolve(`Seeds added for modules: ${modules.join(", ")}`);
18 | }
19 | });
20 | });
21 |
22 | }else {
23 | let message = `[Wertik Seeds]: modules expected in this format: Array, but received: ${modules}`;
24 | console.error(message);
25 | reject(message);
26 | }
27 | });
28 | };
29 | }
--------------------------------------------------------------------------------
/src/framework/logger/index.ts:
--------------------------------------------------------------------------------
1 | export default function () {
2 | return new Promise((resolve, reject) => {
3 | const { createLogger, format, transports } = require("winston");
4 | const { printf, combine, timestamp, label } = format;
5 |
6 | const myFormat = printf(({ level, message, label, timestamp }) => {
7 | // return `${timestamp} [${label}] ${level}: ${message}`;
8 | return JSON.stringify({
9 | timestamp: timestamp,
10 | label: label,
11 | level: level,
12 | message: message && message.constructor == String ? message : message,
13 | });
14 | });
15 |
16 | const logger = createLogger({
17 | format: combine(label({ label: "right meow!" }), timestamp(), myFormat),
18 | transports: [
19 | new transports.Console(),
20 | new transports.File({
21 | filename: "info.log",
22 | level: "info",
23 | }),
24 | new transports.File({
25 | filename: "error.log",
26 | level: "error",
27 | }),
28 | new transports.File({
29 | filename: "warning.log",
30 | level: "warning",
31 | }),
32 | ],
33 | });
34 |
35 | resolve(logger);
36 | });
37 | }
38 |
--------------------------------------------------------------------------------
/src/framework/initialization/checkInstalledPackages.ts:
--------------------------------------------------------------------------------
1 | import { IConfiguration } from "./../types/configuration";
2 | import { errorMessage } from "../logger/consoleMessages";
3 | export function checkIfPackageIsInstalled(packageName: String) {
4 | try {
5 | let version = require(`${packageName}/package.json`).version;
6 | return version;
7 | } catch (e) {
8 | return false;
9 | }
10 | }
11 |
12 | export function check(name: String) {
13 | const isInstalled = checkIfPackageIsInstalled(name);
14 | if (isInstalled) {
15 | return true;
16 | } else {
17 | errorMessage(name + " is not installed, Exiting wertik-js process.");
18 | process.exit();
19 | }
20 | }
21 |
22 | export default function (configuration: IConfiguration) {
23 | return new Promise((resolve, reject) => {
24 | try {
25 | const { dbDialect } = configuration.database;
26 | check("apollo-server");
27 | if (dbDialect == "mysql") {
28 | check("sequelize");
29 | check("mysql2");
30 | }
31 | if (dbDialect == "postgres") {
32 | check("pg");
33 | check("pg-hstore");
34 | check("pg-native");
35 | }
36 | resolve();
37 | } catch (e) {
38 | reject(e);
39 | }
40 | });
41 | }
42 |
--------------------------------------------------------------------------------
/src/framework/socket/index.ts:
--------------------------------------------------------------------------------
1 | import { ISocketConfiguration } from "../types/servers";
2 | import { get } from "lodash";
3 | import { IConfiguration } from "../types/configuration";
4 | import SocketIO from "socket.io";
5 |
6 | export const defaultSocketInstance = (sockets: ISocketConfiguration, context: any) => {
7 | const {disable,options, onMessageReceived, onClientConnected, onClientDisconnect} = sockets;
8 | if (disable === true) {
9 | return null;
10 | }
11 | const { httpServer } = context;
12 | const io = SocketIO(httpServer, options);
13 | io.on("connection", (socket) => {
14 | onClientConnected({
15 | socket,
16 | });
17 | socket.on("message", onMessageReceived);
18 | socket.on("disconnect", onClientDisconnect);
19 | });
20 |
21 | return io;
22 | };
23 |
24 | export default function (options: IConfiguration, context: any) {
25 | let ws = defaultSocketInstance(
26 | {
27 | onClientConnected: get(options,'sockets.onClientConnected', function () {}),
28 | onMessageReceived: get(options,'sockets.onMessageReceived', function () {}),
29 | onClientDisconnect: get(options,'sockets.onClientDisconnect', function () {}),
30 | disable: get(options,'sockets.disable', false),
31 | options: get(options,'sockets.options',{}),
32 | },
33 | context
34 | );
35 | return ws;
36 | }
37 |
--------------------------------------------------------------------------------
/docs/database/introduction.md:
--------------------------------------------------------------------------------
1 | ### Database
2 |
3 | Wertik-js currently provides following database features
4 |
5 | - Mysql
6 | - PostgreSQL
7 |
8 | and other database that sequelize support.
9 |
10 | #### MySQL
11 |
12 | To connect with your MySQL database, You need to share your `Database Name`, `Database Password`, `Database Username` and `Database Host`. Here is how to connect with your MySQL database:
13 |
14 | ```javascript
15 | export default {
16 | name: "Wertik",
17 | // ... Rest of the configuration
18 | database: {
19 | dbDialect: "mysql",
20 | dbUsername: "root",
21 | dbPassword: "pass",
22 | dbName: "graphql",
23 | dbHost: "localhost",
24 | dbPort: "3306",
25 | },
26 | // ... Rest of the configuration
27 | };
28 | ```
29 |
30 | #### PostgreSQL
31 |
32 | To connect with your PostgreSQL database, You need to share your `Database Name`, `Database Password`, `Database Username` and `Database Host` same as MySQL but `dbDialect` must be postgres. Here is how to connect with your PostgreSQL database:
33 |
34 | ```javascript
35 | export default {
36 | name: "Wertik",
37 | // ... Rest of the configuration
38 | database: {
39 | dbDialect: "postgres",
40 | dbUsername: "root",
41 | dbPassword: "pass",
42 | dbName: "graphql",
43 | dbHost: "localhost",
44 | dbPort: "3306",
45 | },
46 | // ... Rest of the configuration
47 | };
48 | ````
49 |
50 |
--------------------------------------------------------------------------------
/docs/v2/cron-jobs.md:
--------------------------------------------------------------------------------
1 | #### sockets - beta
2 |
3 | **Type:** Object
4 | **Default Value:**
5 | **Description:** For sockets we use Socket.IO.
6 |
7 | ```javascript
8 | {
9 | disable: false,
10 | onClientConnected: function () {
11 | console.log("onClientConnected");
12 | },
13 | onMessageReceived: function () {
14 | console.log("onMessageReceived");
15 | },
16 | onClientDisconnect: function () {
17 | console.log("onClientDisconnect");
18 | },
19 | };
20 | ```
21 |
22 | For please visit https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/socket/index.ts.
23 |
24 | #### storage - beta
25 |
26 | **Type:** Object
27 | **Default Value:**
28 |
29 | ```javascript
30 | {
31 | storageDirectory: "./uploads/",
32 | },
33 | ```
34 |
35 | **Description:** Its a module for storage functionality in your app.
36 |
37 | For please visit: https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/builtinModules/storage/index.ts.
38 |
39 | ### Cron - beta
40 |
41 | **Type:** Object
42 | **Default Value:** {}
43 | **Description:** Under the we use node-cron library for cron jobs. Please see https://www.npmjs.com/package/node-cron.
44 |
45 | For more please check [Default Configuration](https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/defaults/defaultConfigurations/defaultConfiguration.ts) to get an idea about cron jobs.
46 |
--------------------------------------------------------------------------------
/docs/v2/custom-modules.md:
--------------------------------------------------------------------------------
1 | ### Custom Modules
2 |
3 | **Type:** Array
4 |
5 | With this guide, you can extend your app with extra modules and functionality. Please refer to this module for getting familiar with modules: https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/builtinModules/forgetPassword/index.ts.
6 |
7 | ### Configuration explained
8 |
9 | ### name
10 |
11 | **Type:** String
12 | **Default Value:** null
13 | **Description:** The name of module.
14 |
15 | ### useDatabase
16 |
17 | **Type:** Boolean
18 | **Default Value:** true
19 | **Description:** Define whether the module uses database or not. If false, database property is not required.
20 |
21 | ### graphql
22 |
23 | **Type:** Object
24 | **Default Value:** {}
25 | **Description:** The graphql will add graphql features to module.
26 |
27 | ### restApi
28 |
29 | **Type:** Object
30 | **Default Value:** {}
31 | **Description:** With this option you can add endpoints to your modules.
32 |
33 | ### database
34 |
35 | **Type:** Object
36 | **Default Value:** {}
37 | **Description:** Defines current module database table. This includes, fields, relationships, which fields to ignore while executing graphql schema. Please visit database section of above shared module: https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/builtinModules/forgetPassword/index.ts#L118.
38 |
--------------------------------------------------------------------------------
/src/framework/restApi/versions/v1/loadAllModules.ts:
--------------------------------------------------------------------------------
1 | import { get, isFunction } from "lodash";
2 | import { IConfiguration } from "src/framework/types/configuration";
3 |
4 | export default async function (expressApp, configuration: IConfiguration, customApi) {
5 | let modules = configuration.builtinModules.split(",");
6 | modules = modules.filter((c) => c);
7 | modules = [...modules, ...get(configuration, "modules", [])];
8 |
9 | const processModule = (module) => {
10 | if (module && module.hasOwnProperty("restApi")) {
11 | const restApi = get(module, "restApi", {});
12 | const restApiEndpoints = get(restApi, "endpoints", []);
13 | restApiEndpoints.forEach((restApiEndpointsElement) => {
14 | customApi(expressApp, restApiEndpointsElement, module, configuration);
15 | });
16 |
17 | const expressAccess = get(module,'restApi.expressAccess', function () {});
18 |
19 | expressAccess(expressApp);
20 | }
21 | };
22 |
23 | modules.forEach(async (element: any) => {
24 | let module;
25 | if (element.constructor === String) {
26 | module = require(`./../../../builtinModules/${element}/index`).default;
27 | } else if (element.constructor === Object || isFunction(element)) {
28 | if (element.constructor == Function) {
29 | module = await element(configuration);
30 | } else {
31 | module = element;
32 | }
33 | }
34 | processModule(module);
35 | });
36 | }
37 |
--------------------------------------------------------------------------------
/docs/sockets/introduction.md:
--------------------------------------------------------------------------------
1 | ### Sockets - Beta
2 |
3 | Wertik-js uses `ws` for SocketIO integration, Please see https://github.com/socketio/socket.io. To see how Sockets is enabled please see https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/socket/index.ts. This file enables SocketIO with Wertik-js.
4 |
5 | By default the socket server runs at port `ws://localhost:2000`. You can detect events for connected, message received and client disconnected by:
6 |
7 | ```javascript
8 | let object = {
9 | // Rest of the configuration
10 | sockets: {
11 | disable: false,
12 | onClientConnected: function () {
13 | console.log("onClientConnected");
14 | },
15 | onMessageReceived: function () {
16 | console.log("onMessageReceived");
17 | },
18 | onClientDisconnect: function () {
19 | console.log("onClientDisconnect");
20 | },
21 | },
22 | };
23 | ```
24 |
25 | #### Sending a message in Rest API handler
26 |
27 | Consider this handler in your rest api handler, SocketIO comes with `req.socketio`, So you can send data,
28 |
29 | ```javascript
30 | async function(req, res) {
31 | req.socketio.send("Test Message"); // This will send test message to all clients
32 | }
33 | ```
34 |
35 | In GraphQL, SocketIO can be accessed by `context.socketio`,
36 |
37 | ```javascript
38 | function (_, args, context,info) {
39 | context.socketio.send("Test Message"); // Tis will send test message to all clients from GraphQL
40 | }
41 | ```
42 |
43 | Currently Web Sockets in wertik-js are in beta, So more features are coming.
44 |
--------------------------------------------------------------------------------
/docs/email/introduction.md:
--------------------------------------------------------------------------------
1 | ### Email - Beta
2 |
3 | Wertik-js also provides email system that allows you to send emails from your own applications. Under the hood, Wertik-js uses nodemailer for sending emails. Please see here how node mailer is initialized https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/mailer/index.ts.
4 |
5 | Wertik-js js allows you to send define your own custom Mailer instance and Email send method. You can check this function that provides mailer instance https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/mailer/index.ts#L52. You have two ways, You can send mailer instance through `configuration.email.defaultMailerInstance` or to extend node mailer you can configuration object for node mailer at `configuration.email.configuration`, The default value for `configuration.email.configuration` is:
6 |
7 | ```javascript
8 | const wertiknodemailerDefaultConfiguration = {
9 | host: "smtp.ethereal.email",
10 | port: 587,
11 | secure: false, // true for 465, false for other ports
12 | auth: {
13 | user: testAccount.user, // generated ethereal user
14 | pass: testAccount.pass, // generated ethereal password
15 | },
16 | };
17 | ```
18 |
19 | **Send Email**
20 |
21 | Wertik-js uses this method to send email by using mailer instance returned from https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/framework/mailer/index.ts#L52. You can define your own custom send email method at `configuration.email.sendEmail`. For more please see https://github.com/Uconnect-Technologies/wertik-js/blob/master/src/main.ts#L33.
22 |
--------------------------------------------------------------------------------
/src/framework/builtinModules/mail/index.ts:
--------------------------------------------------------------------------------
1 | import { get } from "lodash";
2 | export default {
3 | name: "Mail",
4 | useDatabase: false,
5 | graphql: {
6 | schema: `
7 | type EmailResponse {
8 | message: String
9 | }
10 | input SendEmailInput {
11 | template: String!
12 | templateVariablesJSONStringify: String
13 | cc: String
14 | subject: String!
15 | to: String!
16 | bcc: String
17 | }
18 | `,
19 | mutation: {
20 | schema: `
21 | sendEmail(input: SendEmailInput): EmailResponse
22 | `,
23 | resolvers: {
24 | sendEmail: async (_: any, args: any, context: any, info: any) => {
25 | try {
26 | const sendEmail = context.wertik.sendEmail;
27 | const template = args.input.template;
28 | const variables = JSON.stringify(
29 | get(args, "input.templateVariablesJSONStringify", "{}")
30 | );
31 | const transportVariables = {
32 | cc: args.input.cc,
33 | subject: args.input.subject,
34 | bcc: args.input.bcc,
35 | to: args.input.to,
36 | };
37 | await sendEmail(template, variables, transportVariables);
38 | return {
39 | message: "Message Successfully",
40 | };
41 | } catch (e) {
42 | throw new Error(e);
43 | }
44 | },
45 | },
46 | },
47 | query: {
48 | schema: ``,
49 | resolvers: {},
50 | },
51 | },
52 | restApi: {
53 | endpoints: [],
54 | },
55 | };
56 |
--------------------------------------------------------------------------------
/src/framework/graphql/voyager/index.ts:
--------------------------------------------------------------------------------
1 | import { get } from "lodash";
2 | import { defaultPort } from "../../helpers/index";
3 | import { IConfiguration } from "src/framework/types/configuration";
4 | import { successMessage } from "./../../logger/consoleMessages";
5 |
6 | export default function (configuration: IConfiguration) {
7 | const port = get(configuration,'port',defaultPort)
8 | let html = `
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Wertik-js GraphQL voyager
18 |
19 |
20 |