Compare commits

..

No commits in common. "master" and "1.1.3" have entirely different histories.

77 changed files with 479 additions and 1561 deletions

View File

@ -1,25 +0,0 @@
{
"env": {
"es2021": true,
"node": true
},
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"rules": {
"indent": ["error", "tab"],
"linebreak-style": ["error", "unix"],
"quotes": [
"error",
"single",
{
"allowTemplateLiterals": true
}
],
"semi": ["error", "never"]
}
}

View File

@ -1,59 +0,0 @@
#!/bin/bash
# @link https://gist.github.com/mattscilipoti/8424018
#
# Called by "git push" after it has checked the remote status,
# but before anything has been pushed.
#
# If this script exits with a non-zero status nothing will be pushed.
#
# Steps to install, from the root directory of your repo...
# 1. Copy the file into your repo at `.git/hooks/pre-push`
# 2. Set executable permissions, run `chmod +x .git/hooks/pre-push`
# 3. Or, use `rake hooks:pre_push` to install
#
# Try a push to master, you should get a message `*** [Policy] Never push code directly to...`
#
# The commands below will not be allowed...
# `git push origin master`
# `git push --force origin master`
# `git push --delete origin master`
protected_branch='master'
policy="\n\n[Policy] Never push code directly to the "$protected_branch" branch! (Prevented with pre-push hook.)\n\n"
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
push_command=$(ps -ocommand= -p $PPID)
is_destructive='force|delete|\-f'
will_remove_protected_branch=':'$protected_branch
do_exit(){
echo -e $policy
exit 1
}
if [[ $push_command =~ $is_destructive ]] && [ $current_branch = $protected_branch ]; then
do_exit
fi
if [[ $push_command =~ $is_destructive ]] && [[ $push_command =~ $protected_branch ]]; then
do_exit
fi
if [[ $push_command =~ $will_remove_protected_branch ]]; then
do_exit
fi
# Prevent ALL pushes to protected_branch
if [[ $push_command =~ $protected_branch ]] || [ $current_branch = $protected_branch ]; then
do_exit
fi
unset do_exit
exit 0

6
.gitignore vendored
View File

@ -104,8 +104,4 @@ dist
.tern-port .tern-port
# package lock file # package lock file
package-lock.json package-lock.json
_old/
undefined.ts
undefined.ejs

View File

@ -1,4 +0,0 @@
{
"require": ["ts-node/register"],
"watch-files": ["./src/**/*.ts"]
}

View File

View File

@ -1,15 +0,0 @@
{
"tabWidth": 4,
"useTabs": true,
"singleQuote": true,
"semi": false,
"trailingComma": "none",
"jsxSingleQuote": true,
"jsxBracketSameLine": true,
"printWidth": 200,
"bracketSpacing": true,
"vueIndentScriptAndStyle": true,
"arrowParens": "always",
"bracketSameLine": false,
"endOfLine": "lf"
}

View File

@ -1,29 +1,22 @@
# Nork # Nork
Simple node.js tool that extends express projects. Simple node.js tool that extends express projects.
- [About](#about) - [About](#about)
- [Installation](#installation) - [Installation](#installation)
- [How to use](#how-to-use) - [How to use](#how-to-use)
## About ## About
The point of this tool is to add to express some feeling of php framework Laravel. Primarily get simply express app into MVC architecture. The point of this tool is to add to express some feeling of php framework Laravel. Primarily get simply express app into MVC architecture.
## Installation ## Installation
``` ```
npm install -g nork npm install -g nork
``` ```
This will install nork globally. If you would like to install nork for only one project, you can also install it locally. For local installation: This will install nork globally. If you would like to install nork for only one project, you can also install it locally. For local installation:
```
npm install nork
``` ```
npm install nork
```
## How to use ## How to use
``` ```
Usage: nork <command> [options] Usage: nork <command> [options]
@ -33,12 +26,11 @@ Options:
Commands: Commands:
create [app-name] create a new project create [app-name] create a new project
create [app-name] -i create a new project in current directory make:controller create a new controller
make controller [name] create a new controller make:middleware create a new middleware
make middleware [name] create a new middleware make:model create a new model
make model [name] create a new model make:route create a new route
make route [name] create a new route make:test create a new test
make test [name] create a new test make:view create a new view
make view [name] create a new view
setup set up an existing project for nork setup set up an existing project for nork
``` ```

View File

@ -1 +0,0 @@
{ "lang": "ts" }

View File

@ -1,60 +1,32 @@
{ {
"name": "nork", "name": "nork",
"version": "3.0.5", "version": "1.1.3",
"description": "The best node.js 'framework' :)", "description": "The best node.js 'framework' :)",
"main": "dist/app.js", "main": "src/app.js",
"bin": "dist/app.js", "bin": "src/app.js",
"types": "dist/app.d.ts", "scripts": {
"scripts": { "start": "node src/app.js"
"start": "npm run start:prod", },
"start:dev": "ts-node src/app.ts", "keywords": [
"start:prod": "node dist/app.js", "node",
"tsc": "tsc -p .", "framework",
"clean": "rimraf dist", "express",
"copy-assets": "ts-node src/utils/copyAssets", "mvc"
"build": "npm-run-all clean tsc copy-assets", ],
"test": "mocha --config .mocharc.json --watch src/**/*.test.ts", "author": "Filip Rojek",
"prepublish": "npm-run-all build", "license": "MIT",
"format": "npx prettier --write ." "dependencies": {
}, "colors": "^1.4.0",
"keywords": [ "fs-extra": "^10.0.0",
"node", "inquirer": "^8.1.2",
"framework", "pad": "^3.2.0"
"express", },
"mvc" "repository": {
], "type": "git",
"author": "Filip Rojek", "url": "git+https://github.com/filiprojek/nork.git"
"license": "MIT", },
"dependencies": { "bugs": {
"colors": "1.4.0", "url": "https://github.com/filiprojek/nork/issues"
"fs-extra": "^10.0.0", },
"inquirer": "^8.1.2", "homepage": "https://github.com/filiprojek/nork/blob/master/README.md"
"pad": "^3.2.0"
},
"devDependencies": {
"@types/chai": "^4.2.22",
"@types/fs-extra": "^9.0.13",
"@types/inquirer": "^8.1.3",
"@types/mocha": "^9.0.0",
"@types/shelljs": "^0.8.11",
"@typescript-eslint/eslint-plugin": "^5.5.0",
"@typescript-eslint/parser": "^5.5.0",
"chai": "^4.3.4",
"eslint": "^8.3.0",
"mocha": "^9.1.3",
"npm-run-all": "^4.1.5",
"prettier": "^2.7.1",
"rimraf": "^3.0.2",
"shelljs": "^0.8.5",
"ts-node": "^10.4.0",
"typescript": "^4.5.2"
},
"repository": {
"type": "git",
"url": "git+https://github.com/filiprojek/nork.git"
},
"bugs": {
"url": "https://github.com/filiprojek/nork/issues"
},
"homepage": "https://github.com/filiprojek/nork/blob/master/README.md"
} }

View File

@ -1,39 +0,0 @@
/_ spell-checker: disable _/
# Todo:
- [ ] auth jwt refresh token based system
- https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/
- [ ] version of nork control
- [ ] upgrade to newer version system
- [ ] updatnout make files (obzvlast modely a rozlisovat modely podle norkconfigu)
- [ ] vyzadovat aktualni verzi 3.#.# pro make commandy (pouzivaly se jiny predtim soubory)
- [ ] moznost vytvorit projekt bez db
### 11-24-2021
- zacal jsem predelavat nork do OOP
- co jsem udelal:
- [x] --help
- [x] --version
- [x] setup
- [x] make
- [x] create
- delam na tom
- je treba dopsat par types a fixnout zbytek erroru
- zatim netestovana funkcnost
### 1-10-2022
- dodelal jsem create a otestoval ho
- [x] create
### 7-30-2022
- norkconfig se generuje lepe a actually ho pouzivam
- pri vytvareni projektu je mozne vybrat si orm (mongoose & sequlize)
- default modely pro db se kopiruji na zaklade parametru db z norkconfigu
- updatnutej ts skeleton
- dropnul jsem support pro js
- version update: 3.0.5

View File

@ -1,5 +0,0 @@
#!/bin/bash
cp .githooks/* .git/hooks
echo "hooks have been copied"

221
src/app.js Normal file
View File

@ -0,0 +1,221 @@
#!/usr/bin/env node
const inquirer = require('inquirer')
const path = require('path')
const fs = require('fs-extra')
const colors = require('colors')
const pad = require('pad')
const langToLanguage = lang => {
switch (lang) {
case 'js':
return 'Javascript'
case 'ts':
return 'Typescript'
default:
return 'Unknown language'
}
}
const logError = errorMsg => {
console.log(colors.bgYellow.red(errorMsg))
return
}
const logSuccess = (msg = false) => {
if (!msg) {
msg = 'Success!'
}
console.log(colors.cyan(msg))
return
}
const logHelp = (specific = false, command = false) => {
let spc = 40
if (specific) {
// log specific help
if (specific == 'make') {
console.log(`Usage: ${specific}:[component]`)
console.log()
console.log(pad(' make:controller', spc), 'create a new controller')
console.log(pad(' make:middleware', spc), 'create a new middleware')
console.log(pad(' make:model', spc), 'create a new model')
console.log(pad(' make:route', spc), 'create a new route')
console.log(pad(' make:test', spc), 'create a new test')
console.log(pad(' make:view', spc), 'create a new view')
return
}
console.log(`Usage: ${specific} [options]`)
return
}
console.log('Usage: nork <command> [options]')
console.log()
console.log('Options:')
console.log(pad(' -v, --version', spc), 'output the version number')
console.log(pad(' -h, --help', spc), 'output usage information')
console.log()
console.log('Commands:')
console.log(pad(' create [app-name]', spc), 'create a new project')
console.log(pad(' make:controller', spc), 'create a new controller')
console.log(pad(' make:middleware', spc), 'create a new middleware')
console.log(pad(' make:model', spc), 'create a new model')
console.log(pad(' make:route', spc), 'create a new route')
console.log(pad(' make:test', spc), 'create a new test')
console.log(pad(' make:view', spc), 'create a new view')
console.log(pad(' setup', spc), 'set up an existing project for nork')
console.log()
console.log(' Run', colors.cyan('nork help <command>'), 'for detailed usage of given command.')
if (command) {
console.log(colors.red('Unknown command'), colors.bold.blue(command))
}
return
}
;(async () => {
if (process.argv[2] == 'create') {
// get info about new project
const data = {}
const questions = [
{
type: 'input',
name: 'project_name',
message: 'Enter project name:',
},
{
type: 'list',
message: "Pick the technology you're using:",
name: 'lang',
choices: [
{ name: 'Typescript', value: 'ts' },
{ name: 'Javascript', value: 'js' },
],
},
{
type: 'input',
name: 'author',
message: 'Enter your name:',
},
]
// remove first question if project name is already known
if (process.argv[3]) {
questions.shift()
}
let answers = await inquirer.prompt(questions)
data.project_name = answers.project_name ? answers.project_name : process.argv[3]
data.lang = answers.lang
data.author = answers.author
// copy skeleton to new project
fs.copySync(path.join(__dirname, './skeletons/express-' + data.lang), process.cwd())
// edit package.json file
const pkgJson = require(path.join(process.cwd(), 'package.json'))
pkgJson.name = data.project_name
pkgJson.author = data.author
fs.writeFile(path.join(process.cwd(), 'package.json'), JSON.stringify(pkgJson, null, 2), err => {
if (err) return logError(err)
})
console.log(colors.yellow('Project settings'))
console.log(colors.yellow('------------------'))
console.log(pad(colors.gray('Project name: '), 30), data.project_name)
console.log(pad(colors.gray('Author: '), 30), data.author)
console.log(pad(colors.gray('Language: '), 30), langToLanguage(data.lang))
return logSuccess(`Project ${data.project_name} created successfully!`)
}
if (process.argv[2] == 'make') {
if (!process.argv[3] || !process.argv[4]) return logHelp('make')
const component = process.argv[3]
const norkcfg = require(path.join(process.cwd(), 'norkconfig.json'))
let tsComponents = ['controller', 'middleware', 'route']
if (tsComponents.includes(component)) {
let src = path.join(__dirname, './make-files/express-' + norkcfg.lang + '/' + component + '.' + norkcfg.lang)
let dest = path.join(process.cwd(), './src/' + component + 's' + '/' + process.argv[4] + '.' + norkcfg.lang)
try {
fs.copySync(src, dest, { overwrite: false, errorOnExist: true })
} catch (err) {
return logError(err.message)
}
return logSuccess()
}
if (component == 'model') {
let src = path.join(__dirname, './make-files/express-' + norkcfg.lang + '/' + component + '.js')
let dest = path.join(process.cwd(), './src/' + component + 's' + '/' + process.argv[4] + '.js')
try {
fs.copySync(src, dest, { overwrite: false, errorOnExist: true })
} catch (err) {
return logError(err.message)
}
return logSuccess()
}
if (component == 'view') {
let src = path.join(__dirname, './make-files/express-' + norkcfg.lang + '/' + component + '.ejs')
let dest = path.join(process.cwd(), './src/' + component + 's' + '/' + process.argv[4] + '.ejs')
try {
fs.copySync(src, dest, { overwrite: false, errorOnExist: true })
} catch (err) {
return logError(err.message)
}
return logSuccess()
}
if (component == 'test') {
let src = path.join(__dirname, './make-files/express-' + norkcfg.lang + '/' + component + '.js')
let dest = path.join(process.cwd(), './src/' + component + 's' + '/' + process.argv[4] + '.test.js')
try {
fs.copySync(src, dest, { overwrite: false, errorOnExist: true })
} catch (err) {
return logError(err.message)
}
return logSuccess()
}
}
if (process.argv[2] == 'setup') {
const questions = {
type: 'list',
message: "Pick the technology you're using:",
name: 'lang',
choices: [
{ name: 'Typescript', value: 'ts' },
{ name: 'Javascript', value: 'js' },
],
}
let answers = await inquirer.prompt(questions)
fs.writeJsonSync(path.join(process.cwd(), './norkconfig.json'), answers)
return logSuccess()
}
if (process.argv[2] == '-v' || process.argv[2] == '--version') {
const pkgJson = require(path.join(__dirname, '../package.json'))
return console.log('nork', pkgJson.version)
}
if (process.argv[2] == 'help' || process.argv[2] == '-h' || process.argv[2] == '--help') {
if (process.argv[3]) {
return logHelp(process.argv[3])
}
return logHelp()
}
process.argv.splice(0, 2)
logHelp(false, process.argv.join(' '))
})()

View File

@ -1,10 +0,0 @@
#!/usr/bin/env node
import Routes from './routes'
export class App {
constructor() {
Routes.router()
}
}
new App()

View File

@ -1,97 +0,0 @@
import pad from 'pad'
import colors from 'colors'
import fs from 'fs-extra'
import path from 'path'
import global from './global'
import { Create as CreateInterface } from './interfaces/CreateInterface'
import inquirer from 'inquirer'
export default class Create {
static async project(projectName: string | boolean = false) {
// get info about new project
let projectPath
const questions = [
{
type: 'input',
name: 'project_name',
message: 'Enter project name:'
},
{
type: 'list',
message: `Pick the technology you're using:`,
name: 'lang',
choices: [
{ name: 'Typescript', value: 'ts' },
{ name: 'Javascript - DEPRECATED', value: 'js' }
]
},
{
type: 'list',
message: `Pick the database & ORM you're using:`,
name: 'db',
choices: [
{ name: 'MongoDB - Mongoose', value: { db: 'mongodb', orm: 'mongoose' } },
{ name: 'MySQL - Sequelize', value: { db: 'mysql', orm: 'sequelize' } },
{ name: 'PostgreSQL - Sequelize', value: { db: 'postgresql', orm: 'sequelize' } }
]
},
{
type: 'input',
name: 'author',
message: 'Enter your name:'
},
{
type: 'input',
name: 'email',
message: 'Enter your email:'
},
{
type: 'input',
name: 'website',
message: 'Enter your website:'
}
]
// remove first question if project name is already known
if (projectName) questions.shift()
const answers = await inquirer.prompt(questions)
const data: CreateInterface = {
project_name: answers.project_name ? answers.project_name : process.argv[3],
lang: answers.lang,
author: answers.author,
database: answers.db,
website: answers.website,
email: answers.email
}
// copy skeleton to new project
process.argv.includes('-i') ? (projectPath = process.cwd()) : (projectPath = path.join(process.cwd(), data.project_name))
fs.copySync(path.join(__dirname, './skeletons/express-' + data.lang), projectPath)
// copy default db models to new project
if (data.database.orm == 'mongoose') fs.copySync(path.join(__dirname, './skeletons/mongoose-models/'), projectPath + '/src/models')
if (data.database.orm == 'sequelize') fs.copySync(path.join(__dirname, './skeletons/sequelize-models/'), projectPath + '/src/models')
// edit package.json file
const pkgJson = fs.readJsonSync(path.join(projectPath, 'package.json'))
pkgJson.name = data.project_name
pkgJson.author = `${data.author} <${data.email}> (${data.website})`
fs.writeFile(path.join(projectPath, 'package.json'), JSON.stringify(pkgJson, null, 2), (err) => {
if (err) return global.logError(err.message)
})
// create norkconfig.json
const norkconfig: any = { ...data }
norkconfig['version'] = require('../package.json').version
fs.writeFileSync(path.join(projectPath, 'norkconfig.json'), JSON.stringify(norkconfig, null, 2))
console.log(colors.yellow('Project settings'))
console.log(colors.yellow('------------------'))
console.log(pad(colors.gray('Project name: '), 30), data.project_name)
console.log(pad(colors.gray('Author: '), 30), pkgJson.author)
console.log(pad(colors.gray('Language: '), 30), global.langToLanguage(String(data.lang)))
console.log(pad(colors.gray('Database: '), 30), global.dbToDatabase(String(data.database.db)))
return global.logSuccess(`Project ${data.project_name} created successfully!`)
}
}

View File

@ -1,40 +0,0 @@
import colors from 'colors'
export default class Global {
static logSuccess = (msg: boolean | string = false): string => {
if (!msg) {
msg = 'Success!'
}
console.log(colors.cyan(String(msg)))
return String(msg)
}
static logError(errorMsg: string) {
console.log(colors.bgYellow.red(errorMsg))
return
}
static langToLanguage(lang: string): string {
switch (lang) {
case 'js':
return 'Javascript'
case 'ts':
return 'Typescript'
default:
return 'Unknown language'
}
}
static dbToDatabase(lang: string): string {
switch (lang) {
case 'mongodb':
return 'MongoDB'
case 'postgresql':
return 'PostgreSQL'
case 'mysql':
return 'MySQL'
default:
return 'Unknown database'
}
}
}

View File

@ -1,66 +0,0 @@
import pad from 'pad'
import colors from 'colors'
export default class Help {
constructor() {
// this.logHelp()
}
// log help & returns status in string for tests
static makeHelp(): string {
const spc = 27
return `
Usage: make:[component]
${pad(' make controller [name]', spc)} create a new controller
${pad(' make middleware [name]', spc)} create a new middleware
${pad(' make model [name]', spc)} create a new model
${pad(' make route [name]', spc)} create a new route
${pad(' make test [name]', spc)} create a new test
${pad(' make view [name]', spc)} create a new view
`
}
static allHelp(): string {
const spc = 27
return `
Usage: nork <command> [options]
Options:
${pad(' -v, --version', spc)} output the version number
${pad(' -h, --help', spc)} output usage information
Commands:
${pad(' create [app-name]', spc)} create a new project
${pad(' create [app-name] -i', spc)} create a new project in current directory
${pad(' make controller [name]', spc)} create a new controller
${pad(' make interface [name]', spc)} create a new interface
${pad(' make middleware [name]', spc)} create a new middleware
${pad(' make model [name]', spc)} create a new model
${pad(' make route [name]', spc)} create a new route
${pad(' make service [name]', spc)} create a new service
${pad(' make test [name]', spc)} create a new test
${pad(' make view [name]', spc)} create a new view
${pad(' setup', spc)} set up an existing project for nork
Run ${colors.cyan('nork help <command>')} for detailed usage of given command.
`
}
static specificHelp(specific: string): string {
return `Usage: ${specific} [options]`
}
static logHelp = (specific: boolean | string = false): string => {
if (specific) {
// log specific help
if (specific == 'make') {
return this.makeHelp()
}
// else return specific help
return this.specificHelp(String(specific))
}
// if nothing return help all
return this.allHelp()
}
}

View File

@ -1,13 +0,0 @@
interface database {
db: string
orm: string
}
export interface Create {
project_name: string
author: string
lang: string
database: database
email: string
website: string
}

View File

@ -1,3 +0,0 @@
export interface Norkcfg {
lang: string
}

View File

@ -1,15 +0,0 @@
export interface Questions {
type: string
message: string
name: string
choices: [
{
name: string
value: string
},
{
name: string
value: string
}
]
}

View File

@ -1,4 +0,0 @@
export interface interfaceName {
hello: string
world: boolean | null | undefined
}

View File

@ -4,5 +4,5 @@ const root_get = (req, res) => {
} }
module.exports = { module.exports = {
root_get root_get,
} }

View File

@ -5,12 +5,12 @@ const modelSchema = new Schema(
{ {
title: { title: {
type: String, type: String,
required: true required: true,
} },
}, },
{ {
timestamps: true timestamps: true,
} },
) )
const ModelName = mongoose.model('ModelName', modelSchema) const ModelName = mongoose.model('ModelName', modelSchema)

View File

@ -1,6 +1,10 @@
import { Request, Response } from 'express' import { Request, Response } from 'express'
export const root_get = (req: Request, res: Response) => { const root_get = (req: Request, res: Response) => {
res.render('home') res.render('home')
return true return true
} }
module.exports = {
root_get,
}

View File

@ -1,4 +0,0 @@
export interface interfaceName {
hello: string
world: boolean | null | undefined
}

View File

@ -1,8 +1,10 @@
import { Router, Request, Response, NextFunction } from 'express' import { Router, Request, Response, NextFunction } from 'express'
export const router = Router() const router = Router()
router.use((req: Request, res: Response, next: NextFunction) => { router.use((req: Request, res: Response, next: NextFunction) => {
console.log('Hi :)') console.log('Hi :)')
next() next()
}) })
module.exports = router

View File

@ -0,0 +1,17 @@
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const modelSchema = new Schema(
{
title: {
type: String,
required: true,
},
},
{
timestamps: true,
},
)
const ModelName = mongoose.model('ModelName', modelSchema)
module.exports = ModelName

View File

@ -1,15 +0,0 @@
import { Schema, model } from 'mongoose'
const modelSchema = new Schema<any>(
{
title: {
type: String,
required: true
}
},
{
timestamps: true
}
)
export default model('ModelName', modelSchema)

View File

@ -1,6 +1,8 @@
import { Router } from 'express' import { Router } from 'express'
import * as rootController from '@/controllers/rootController' const rootController = require('../controllers/rootController')
export const router = Router() const router = Router()
router.get('/', rootController.root_get) router.get('/', rootController.root_get)
module.exports = router

View File

@ -1,3 +0,0 @@
export function helloWorld() {
console.log('hello world')
}

View File

@ -0,0 +1,9 @@
const { getReq, getRes } = require('./modules/reqRes.module.js')
const { root_get } = require('../controllers/rootController.ts')
test('Home page render test', () => {
const req = getReq()
const res = getRes()
expect(root_get(req, res)).toBe(true)
})

View File

@ -1,76 +0,0 @@
import path from 'path'
import fs from 'fs-extra'
import global from './global'
import { Norkcfg } from './interfaces/GlobalInterface'
export default class Make {
static component(component: string) {
// const norkcfg = require(path.join(process.cwd(), 'norkconfig.json'))
const norkcfg: Norkcfg = fs.readJsonSync(path.join(process.cwd(), 'norkconfig.json'))
const tsComponents = ['controller', 'middleware', 'route', 'service']
if (tsComponents.includes(component)) {
const src = path.join(__dirname, './make-files/express-' + norkcfg.lang + '/' + component + '.' + norkcfg.lang)
const dest = path.join(process.cwd(), './src/' + component + 's' + '/' + process.argv[4] + '.' + norkcfg.lang)
try {
fs.copySync(src, dest, { overwrite: false, errorOnExist: true })
} catch (err: any) {
return global.logError(err.message)
}
return global.logSuccess()
}
if (component == 'model') {
const src = path.join(__dirname, './make-files/express-' + norkcfg.lang + '/' + component + '.' + norkcfg.lang)
const dest = path.join(process.cwd(), './src/' + component + 's' + '/' + process.argv[4] + '.' + norkcfg.lang)
try {
fs.copySync(src, dest, { overwrite: false, errorOnExist: true })
} catch (err: any) {
return global.logError(err.message)
}
return global.logSuccess()
}
if (component == 'view') {
const src = path.join(__dirname, './make-files/express-' + norkcfg.lang + '/' + component + '.ejs')
const dest = path.join(process.cwd(), './src/' + component + 's' + '/' + process.argv[4] + '.ejs')
try {
fs.copySync(src, dest, { overwrite: false, errorOnExist: true })
} catch (err: any) {
return global.logError(err.message)
}
return global.logSuccess()
}
if (component == 'test') {
const src = path.join(__dirname, './make-files/express-' + norkcfg.lang + '/' + component + '.js')
const dest = path.join(process.cwd(), './src/' + component + 's' + '/' + process.argv[4] + '.test.js')
try {
fs.copySync(src, dest, { overwrite: false, errorOnExist: true })
} catch (err: any) {
return global.logError(err.message)
}
return global.logSuccess()
}
if (component == 'interface') {
if (norkcfg.lang != 'ts') {
return global.logError('error - this is typescript only component')
}
const src = path.join(__dirname, './make-files/express-' + norkcfg.lang + '/' + component + '.ts')
const dest = path.join(process.cwd(), './src/' + component + 's' + '/' + process.argv[4] + '.ts')
try {
fs.copySync(src, dest, { overwrite: false, errorOnExist: true })
} catch (err: any) {
return global.logError(err.message)
}
return global.logSuccess()
}
return global.logError(`error - unknown component ${component}`)
}
}

View File

@ -1,49 +0,0 @@
import Help from './help'
import Version from './version'
import Setup from './setup'
import Make from './make'
import Create from './create'
export default class Routes {
static router(): string {
if (process.argv[2] == 'help' || process.argv[2] == '-h' || process.argv[2] == '--help') {
if (process.argv[3]) {
console.log(Help.logHelp(process.argv[3]))
return 'specific help'
}
console.log(Help.logHelp())
return 'all help'
}
if (process.argv[2] == '-v' || process.argv[2] == '--version') {
console.log(Version.show())
return 'version'
}
if (process.argv[2] == 'setup') {
if (process.argv[3] != 'test') {
Setup.setup()
}
return 'setup'
}
if (process.argv[2] == 'make') {
if (process.argv[3]) {
if (process.argv[4] != 'test') {
Make.component(process.argv[3])
}
return `make ${process.argv[3]}`
}
}
if (process.argv[2] == 'create') {
if (process.argv[4] != 'test') {
Create.project(process.argv[3])
}
return `create ${process.argv[3]}`
}
console.log(Help.logHelp())
return 'all help'
}
}

View File

@ -1,24 +0,0 @@
import inquirer from 'inquirer'
import fs from 'fs-extra'
import path from 'path'
import Global from './global'
import { Questions } from './interfaces/SetupInterface'
export default class Setup {
static async setup(test = false) {
if (!test) {
const questions: Questions = {
type: 'list',
message: `Pick the technology you're using:`,
name: 'lang',
choices: [
{ name: 'Typescript', value: 'ts' },
{ name: 'Javascript', value: 'js' }
]
}
const answers = await inquirer.prompt(Object(questions))
fs.writeJsonSync(path.join(process.cwd(), './norkconfig.json'), answers)
}
return Global.logSuccess()
}
}

View File

@ -1,3 +1,3 @@
{ {
"lang": "js" "lang": "js"
} }

View File

@ -15,13 +15,13 @@ const app = express()
const dbURI = process.env.DB_URI const dbURI = process.env.DB_URI
mongoose mongoose
.connect(dbURI, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true }) .connect(dbURI, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true })
.then((result) => { .then(result => {
console.log('connected to db') console.log('connected to db')
app.listen(port, () => { app.listen(port, () => {
console.log(`server is running on http://localhost:${port}`) console.log(`server is running on http://localhost:${port}`)
}) })
}) })
.catch((err) => { .catch(err => {
console.log(err) console.log(err)
}) })

View File

@ -4,5 +4,5 @@ const root_get = (req, res) => {
} }
module.exports = { module.exports = {
root_get root_get,
} }

View File

@ -1 +1 @@
# Folder for utils and other config files # Folder for utils and other config files

View File

@ -1,59 +0,0 @@
#!/bin/bash
# @link https://gist.github.com/mattscilipoti/8424018
#
# Called by "git push" after it has checked the remote status,
# but before anything has been pushed.
#
# If this script exits with a non-zero status nothing will be pushed.
#
# Steps to install, from the root directory of your repo...
# 1. Copy the file into your repo at `.git/hooks/pre-push`
# 2. Set executable permissions, run `chmod +x .git/hooks/pre-push`
# 3. Or, use `rake hooks:pre_push` to install
#
# Try a push to master, you should get a message `*** [Policy] Never push code directly to...`
#
# The commands below will not be allowed...
# `git push origin master`
# `git push --force origin master`
# `git push --delete origin master`
protected_branch='master'
policy="\n\n[Policy] Never push code directly to the "$protected_branch" branch! (Prevented with pre-push hook.)\n\n"
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
push_command=$(ps -ocommand= -p $PPID)
is_destructive='force|delete|\-f'
will_remove_protected_branch=':'$protected_branch
do_exit(){
echo -e $policy
exit 1
}
if [[ $push_command =~ $is_destructive ]] && [ $current_branch = $protected_branch ]; then
do_exit
fi
if [[ $push_command =~ $is_destructive ]] && [[ $push_command =~ $protected_branch ]]; then
do_exit
fi
if [[ $push_command =~ $will_remove_protected_branch ]]; then
do_exit
fi
# Prevent ALL pushes to protected_branch
if [[ $push_command =~ $protected_branch ]] || [ $current_branch = $protected_branch ]; then
do_exit
fi
unset do_exit
exit 0

View File

@ -1,5 +1,5 @@
# Logs # Logs
#logs logs
*.log *.log
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*

View File

@ -1,15 +0,0 @@
{
"tabWidth": 4,
"useTabs": true,
"singleQuote": true,
"semi": false,
"trailingComma": "none",
"jsxSingleQuote": true,
"jsxBracketSameLine": true,
"printWidth": 200,
"bracketSpacing": true,
"vueIndentScriptAndStyle": true,
"arrowParens": "always",
"bracketSameLine": false,
"endOfLine": "lf"
}

View File

@ -0,0 +1,5 @@
/** @type {import('@ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};

View File

@ -1,5 +1,3 @@
{ {
"lang": "ts", "lang": "ts"
"db": "", }
"orm": ""
}

View File

@ -2,45 +2,34 @@
"name": "project-name", "name": "project-name",
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"main": "dist/server.js", "main": "app.js",
"private": "true",
"keywords": [],
"author": "",
"repository": "github:username/repo",
"license": "ISC",
"scripts": { "scripts": {
"start": "node dist/server.js", "start": "node dist/app.js",
"start:dev": "nodemon src/server.ts", "dev": "nodemon src/app.ts",
"test": "jest", "test": "jest",
"clean": "rimraf dist/*", "clean": "rimraf dist/*",
"copy-assets": "npx ts-node src/utils/copyAssets", "copy-assets": "ts-node src/utils/copyAssets",
"tsc": "tsc -p .", "tsc": "tsc -p .",
"build": "npm-run-all clean tsc copy-assets", "build": "npm-run-all clean tsc copy-assets"
"format": "npx prettier --write ."
}, },
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": { "dependencies": {
"colors": "1.4.0",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5", "cors": "^2.8.5",
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"ejs": "^3.1.6", "ejs": "^3.1.6",
"express": "^4.17.1", "express": "^4.17.1",
"express-validator": "^6.14.2",
"fs-extra": "^10.0.0",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.12.3", "mongoose": "^5.12.3",
"pg": "^8.7.1", "morgan": "^1.10.0",
"pg-hstore": "^2.3.4", "fs-extra": "^10.0.0"
"sequelize": "^6.15.0"
}, },
"devDependencies": { "devDependencies": {
"@types/cookie-parser": "^1.4.2",
"@types/cors": "^2.8.10", "@types/cors": "^2.8.10",
"@types/ejs": "^3.0.6", "@types/ejs": "^3.0.6",
"@types/express": "^4.17.11", "@types/express": "^4.17.11",
"@types/fs-extra": "^9.0.12", "@types/fs-extra": "^9.0.12",
"@types/jest": "^27.5.2", "@types/jest": "^26.0.24",
"@types/jsonwebtoken": "^8.5.8",
"@types/mongoose": "^5.10.5", "@types/mongoose": "^5.10.5",
"@types/morgan": "^1.9.2", "@types/morgan": "^1.9.2",
"@types/node": "^14.14.41", "@types/node": "^14.14.41",
@ -49,25 +38,8 @@
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"shelljs": "^0.8.4", "shelljs": "^0.8.4",
"ts-jest": "^27.1.5", "ts-jest": "^27.0.4",
"ts-node": "^10.8.1", "ts-node": "^9.1.1",
"typescript": "^4.2.4", "typescript": "^4.2.4"
"morgan": "^1.10.0"
},
"jest": {
"preset": "ts-jest",
"testEnvironment": "node"
},
"nodemonConfig": {
"ignore": [
"**/*.test.ts",
"**/*.spec.ts",
".git",
"node_modules"
],
"watch": [
"src"
],
"ext": "ts, js"
} }
} }

View File

@ -1,5 +0,0 @@
#!/bin/bash
cp .githooks/* .git/hooks
echo "hooks have been copied"

View File

@ -1,26 +1,2 @@
# General APP_PORT = 8080
APP_PORT = 6060
APP_HOSTNAME = 'localhost'
APP_HOST = 'http://localhost:8080' # frontend url
# Timezone
TZ = 'Europe/Prague'
CORS_WHITELIST = http://172.15.46.21:8080;http://192.168.0.1:8080
JWT_SECRET = ''
# MongoDB
DB_URI = 'mongodb://username:password@localhost:27017/database?authSource=admin' DB_URI = 'mongodb://username:password@localhost:27017/database?authSource=admin'
# PostgreSQL
DB_PORT = 5432
DB_HOST = '127.0.0.1'
DB_USERNAME = ''
DB_PASSWORD = ''
DB_DATABASE = ''
# SMTP
SMTP_HOST = ''
SMTP_USER = ''
SMTP_PASS = ''
SMTP_FROM = ''

View File

@ -1,42 +1,43 @@
import express from 'express' import express from 'express'
import morgan from 'morgan' import morgan from 'morgan'
import mongoose from 'mongoose'
import path from 'path' import path from 'path'
import cors from 'cors' import cors from 'cors'
import cookieParser from 'cookie-parser'
import { router as routes } from './routes'
import { router as middlewares } from './middlewares'
import env from './config/environment'
export let corsWhitelist: Array<string> const config = require('./utils/environment')
if (env.CORS_WHITELIST != 'undefined') { const routes = require('./routes')
corsWhitelist = [...['http://localhost:8080', 'http://localhost:6040'], ...env.CORS_WHITELIST.split(';')] const middlewares = require('./middlewares')
} else {
corsWhitelist = ['http://localhost:8080', 'http://localhost:6040']
}
const corsOptions = {
origin: function (origin: any, callback: any) {
if (!origin || corsWhitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
},
optionsSuccessStatus: 200,
credentials: true
}
export const app = express() const port: Number = config.APP_PORT || 8080
const app = express()
// MongoDB
const dbURI: string = config.DB_URI
mongoose
.connect(dbURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(result => {
console.log('connected to db')
app.listen(port, () => {
console.log(`Server is listening on http://localhost:${port}`)
})
})
.catch(err => {
console.log(err)
})
// Middlewares // Middlewares
app.use(middlewares) app.use(middlewares)
app.set('view engine', 'ejs') app.set('view engine', 'ejs')
app.set('views', path.join(__dirname, 'views')) app.set('views', path.join(__dirname, 'views'))
app.use(cors(corsOptions)) app.use(cors())
app.use(morgan('dev')) app.use(morgan('dev'))
app.use(express.urlencoded({ extended: true })) app.use(express.urlencoded({ extended: true }))
app.use(express.json()) app.use(express.json())
app.use(express.static(path.join(__dirname, 'public'))) app.use(express.static(path.join(__dirname, 'public')))
app.use(cookieParser())
// Routes // Routes
app.use(routes) app.use(routes)

View File

@ -1,49 +0,0 @@
import mongoose from 'mongoose'
import env from './environment'
import { Err, Succ } from '../services/globalService'
import db from './sequelize.config'
// MongoDB
const dbURI: string = env.DB_URI
function connect() {
if (!env.NORK.database) {
new Err(500, 'no database is in norkcfg.json')
return false
}
if (env.NORK.database.orm == 'mongoose') {
mongoose
.connect(dbURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
})
.then(() => {
new Succ(200, 'connected to db')
return true
})
.catch((err: any) => {
new Err(500, err)
return false
})
}
if (env.NORK.database.orm == 'sequelize') {
db.sync()
.then(() => {
new Succ(200, 'connected to db')
return true
})
.catch((err: any) => {
new Err(500, `Can't connect to db\n${err}`)
return false
})
}
if (env.NORK.database.db.length > 0) {
new Err(500, `unsupported database ${env.NORK.database.db}`)
return false
}
}
export default connect

View File

@ -1,59 +0,0 @@
import path from 'path'
import fs from 'fs-extra'
import { Err } from '../services/globalService'
import dotenv from 'dotenv'
const env_path = process.env.NODE_ENV ? `../.env.${process.env.NODE_ENV}` : '../.env'
dotenv.config({ path: path.join(__dirname, env_path) })
const norkcfg = fs.readJSONSync(path.join(__dirname, '../../norkconfig.json'))
if (norkcfg.database) {
if (norkcfg.database.db == 'postgresql') {
if (!process.env.DB_PORT) {
process.env.DB_PORT = '5432'
}
if (!process.env.DB_HOST) {
process.env.DB_HOST = '127.0.0.1'
}
if (!process.env.DB_USERNAME || !process.env.DB_PASSWORD || !process.env.DB_DATABASE) {
new Err(500, 'missing DB parameters in .env file')
process.exit(1)
}
}
}
if (!fs.existsSync(path.join(__dirname, env_path))) {
console.log('$env_path = ', env_path)
console.log('$__dirname = ', __dirname)
new Err(500, `.env file for ${process.env.NODE_ENV ? process.env.NODE_ENV : ''} environment does not exists`)
process.exit()
}
if (process.env.JWT_SECRET === undefined || process.env.JWT_SECRET == '') {
new Err(500, 'JWT_SECRET is not set!')
process.exit()
}
export default {
// General
APP_PORT: Number(process.env.APP_PORT),
APP_HOST: String(process.env.APP_HOST),
APP_HOSTNAME: process.env.APP_HOSTNAME !== undefined ? String(process.env.APP_HOSTNAME) : null,
CORS_WHITELIST: String(process.env.CORS_WHITELIST),
JWT_SECRET: String(process.env.JWT_SECRET),
// MongoDB
DB_URI: String(process.env.DB_URI),
// PostgreSQL
DB_PORT: Number(process.env.DB_PORT),
DB_HOST: String(process.env.DB_HOST),
DB_USERNAME: String(process.env.DB_USERNAME),
DB_PASSWORD: String(process.env.DB_PASSWORD),
DB_DATABASE: String(process.env.DB_DATABASE),
// Nork
NORK: norkcfg,
// SMTP
SMTP_HOST: String(process.env.SMTP_HOST),
SMTP_USER: String(process.env.SMTP_USER),
SMTP_PASS: String(process.env.SMTP_PASS),
SMTP_FROM: String(process.env.SMTP_FROM)
}

View File

@ -1,10 +0,0 @@
import { Sequelize } from 'sequelize'
import env from './environment'
const db = new Sequelize(env.DB_DATABASE, env.DB_USERNAME, env.DB_PASSWORD, {
host: env.DB_HOST,
dialect: 'postgres',
logging: false
})
export default db

View File

@ -1,6 +1,10 @@
import { Request, Response } from 'express' import { Request, Response } from 'express'
export function root_get(req: Request, res: Response) { const root_get = (req: Request, res: Response) => {
res.render('home') res.render('home')
return true return true
} }
module.exports = {
root_get,
}

View File

@ -1,4 +0,0 @@
export interface ErrType {
code: number
message: string
}

View File

@ -1 +0,0 @@
*.log

View File

@ -1,63 +0,0 @@
import { Request, Response, NextFunction } from 'express'
import jwt from 'jsonwebtoken'
import env from '../config/environment'
import { Err, Succ } from '../services/globalService'
import User from '../models/User' // uncomment this
export function requireAuth(req: Request, res: Response, next: NextFunction) {
const token = req.cookies.jwt
new Err(500, 'uncomment code in authMiddleware before using!')
if (token) {
jwt.verify(token, env.JWT_SECRET, async (err: any, decodedToken: any) => {
if (err) {
// console.error(err.message)
res.status(401).json(new Err(401, 'user is not authenticated'))
}
if (!err) {
const user = (async () => {
if (env.NORK.db.orm) {
if (env.NORK.db.orm == 'sequelize') {
return await User.findByPk(decodedToken.id)
}
if (env.NORK.db.orm == 'mongoose') {
return await User.findById(decodedToken.id)
}
} else {
return null
}
})()
if (user === null) {
res.status(401).json(new Err(401, 'user is not authenticated'))
return
}
res.locals.user = user
new Succ(100, 'user is authenticated')
next()
}
})
}
if (!token) {
res.status(401).json(new Err(401, 'user is not authenticated'))
}
}
export function requireVerified(req: Request, res: Response, next: NextFunction) {
if (res.locals.user._id) {
if (res.locals.user.verified) {
new Succ(100, 'user is verified')
next()
return
}
res.status(403).json(new Err(403, 'user is not verified'))
return
}
if (!res.locals.user._id) {
res.status(401).json(new Err(401, 'user is not authenticated'))
return
}
}

View File

@ -1,16 +0,0 @@
import { Request, Response, NextFunction } from 'express'
import { validationResult } from 'express-validator'
import { Err } from '../services/globalService'
class Middleware {
handleValidationError(req: Request, res: Response, next: NextFunction) {
const error = validationResult(req)
if (!error.isEmpty()) {
new Err(400, error)
return res.status(400).json(new Err(400, 'validation error', error.array()[0]))
}
next()
}
}
export default new Middleware()

View File

@ -1,6 +1,8 @@
import { Router } from 'express' import { Router } from 'express'
import { router as sayHiMiddleware } from '../middlewares/sayHiMiddleware' const sayHiMiddleware = require('./sayHiMiddleware')
export const router = Router() const router = Router()
// router.use(sayHiMiddleware) router.use(sayHiMiddleware)
module.exports = router

View File

@ -1,9 +1,11 @@
import { Router, Request, Response, NextFunction } from 'express' import { Router, Request, Response, NextFunction } from 'express'
export const router = Router() const router = Router()
router.use((req: Request, res: Response, next: NextFunction) => { router.use((req: Request, res: Response, next: NextFunction) => {
console.log('Hi :)') console.log('Hi :)')
next() next()
}) })
module.exports = router

View File

@ -1,11 +1,13 @@
import { Request, Response, Router } from 'express' import { Router } from 'express'
import { router as rootRoutes } from './rootRoutes' const rootRoutes = require('./rootRoutes')
export const router = Router() const router = Router()
router.use(rootRoutes) router.use(rootRoutes)
// 404 // 404
router.use((req: Request, res: Response) => { router.use((req, res) => {
res.status(404).send('E404') res.status(404).send('E404')
}) })
module.exports = router

View File

@ -1,9 +1,8 @@
import { Router } from 'express' import { Router } from 'express'
import * as rootController from '../controllers/rootController' const rootController = require('../controllers/rootController')
import rootValidator from '../validators/rootValidator'
import handleValidation from '../middlewares/handleValidation'
export const router = Router() const router = Router()
const mws = [handleValidation.handleValidationError]
router.get('/', rootValidator.checkRootGet(), mws, rootController.root_get) router.get('/', rootController.root_get)
module.exports = router

View File

@ -1,24 +0,0 @@
import http from 'http'
import { app } from './app'
import env from './config/environment'
import { Succ } from './services/globalService'
import database from './config/database'
const port: number = env.APP_PORT || 8080
const hostname: string = env.APP_HOSTNAME || 'localhost'
export const server = http.createServer(app)
// Server
export function runServer(): void {
server.listen(port, hostname, () => {
new Succ(200, `Server is listening on http://${hostname}:${port}`)
})
}
if (!env.NORK.database) {
runServer()
} else {
const db_connection = database()
if (db_connection) {
runServer()
}
}

View File

@ -1,173 +0,0 @@
import colors from 'colors'
import fs from 'fs'
import path from 'path'
export interface ErrType {
code: number
message: string
data?: any
}
export class Err implements ErrType {
code: number
message: string
data: any
constructor(code: number, message: string | object, data: any = null) {
this.code = code
typeof message === 'object' ? (this.message = JSON.stringify(message)) : (this.message = message)
data ? (this.data = data) : false
// typeof data === 'object' ? (this.data = JSON.stringify(data)) : (this.data = data)
this.drop()
}
drop() {
if (this.data) {
console.log(colors.bgRed(`${this.code}`) + colors.bgBlack.red(` ${this.message}`) + this.data)
Log.make('Err', this.code, this.message, this.data)
return {
code: this.code,
message: this.message,
data: this.data
}
}
console.log(colors.bgRed(`${this.code}`) + colors.bgBlack.red(` ${this.message}`))
Log.make('Err', this.code, this.message)
return {
code: this.code,
message: this.message
}
}
}
export class Succ {
code: number
message: string
data?: any
constructor(code: number, message: string, data: any = null) {
this.code = code
this.message = message
data ? (this.data = data) : false
this.drop()
}
drop() {
if (this.data) {
console.log(colors.bgGreen.black(`${this.code}`) + colors.green.bgBlack(` ${this.message}`) + this.data)
return {
code: this.code,
message: this.message,
data: this.data
}
}
console.log(colors.bgGreen.black(`${this.code}`) + colors.green.bgBlack(` ${this.message}`))
return {
code: this.code,
message: this.message
}
}
}
export interface LogType {
type: 'Err' | 'Succ' | 'Info'
code?: number
message?: string
data?: any
logFile?: string
}
export class Log implements LogType {
type: 'Err' | 'Succ' | 'Info'
code?: number
message?: string
data?: any
logFile?: string
/**
* @param type
* - Type of log
* - Err | Succ | Info
* @param code
* - not required
* - HTTP status code
* @param message
* - could be anything
* @param data
* - could be anything
* @param logFile
* - name of logFile
* - default is log type file
*/
constructor(type: 'Err' | 'Succ' | 'Info', code?: number, message?: string, data?: any, logFile?: string) {
this.type = type
this.code = code
this.message = message
this.data = data
this.logFile = logFile
if (!this.logFile) {
this.logFile = `${type}.global.log`
} else {
this.logFile = this.logFile + '.log'
}
this.logFile = path.join(__dirname, this.logFile)
}
static pathMake(type: string, name?: string) {
let logName
if (!name) {
logName = `${type}.global.log`
} else {
logName = name + '.log'
}
return path.join(__dirname, '../logs/' + logName)
}
/**
* returns current date in my custom format
*/
static dateNow(): string {
/**
* @param num: number
*
* receives number and returns two digits number
* example:
* input num = 9 => returns string 09
*/
function add0(num: number): string {
if (num.toString().length <= 1) {
return '0' + String(num)
}
return String(num)
}
const d = new Date()
return `${d.getFullYear()}-${add0(d.getMonth() + 1)}-${add0(d.getDate())} ${add0(d.getHours())}:${add0(d.getMinutes())}:${add0(d.getSeconds())}`
}
static make(type: 'Err' | 'Succ' | 'Info', code?: number, message?: string, data?: any, logFile?: string) {
let realPath = Log.pathMake(type, logFile)
let formattedData = `Date: "${Log.dateNow()}" Type: "${type}"`
code ? (formattedData += ` Code: "${code}"`) : false
message ? (formattedData += ` Message: "${message}"`) : false
if (data) {
if (typeof data === 'object') {
data = JSON.stringify(data)
}
formattedData += ` Data: "${data}"`
}
formattedData += '\n'
if (fs.existsSync(realPath)) {
fs.appendFileSync(realPath, formattedData)
} else {
fs.writeFileSync(realPath, formattedData)
}
}
}

View File

@ -1,3 +0,0 @@
export const helloWorld = () => {
console.log('hello world')
}

View File

@ -0,0 +1,9 @@
const { getReq, getRes } = require('./modules/reqRes.module.js')
const { root_get } = require('../controllers/rootController.ts')
test('Home page render test', () => {
const req = getReq()
const res = getRes()
expect(root_get(req, res)).toBe(true)
})

View File

@ -0,0 +1,16 @@
module.exports.getReq = () => {
const req = {}
req.body = {}
return req
}
module.exports.getRes = () => {
const res = {}
res.locals = {}
res.status = () => res
res.json = () => res
res.send = () => res
res.render = () => res
return res
}

View File

@ -3,5 +3,4 @@ import * as shell from 'shelljs'
// Copy all the view templates // Copy all the view templates
shell.cp('-R', 'src/views', 'dist/') shell.cp('-R', 'src/views', 'dist/')
shell.cp('-R', 'src/public', 'dist/') shell.cp('-R', 'src/public', 'dist/')
shell.cp('-R', 'src/models', 'dist/')
shell.cp('-u', 'src/.env', 'dist/') shell.cp('-u', 'src/.env', 'dist/')

View File

@ -0,0 +1,7 @@
import path from 'path'
require('dotenv').config({ path: path.join(__dirname, '../.env') })
module.exports = {
APP_PORT: process.env.APP_PORT,
DB_URI: process.env.DB_URI,
}

View File

@ -1,9 +0,0 @@
import { body, param, query } from 'express-validator'
class rootValidator {
checkRootGet() {
return []
}
}
export default new rootValidator()

View File

@ -1,63 +1,71 @@
{ {
"compilerOptions": { "compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */ /* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */ /* Basic Options */
// "incremental": true, /* Enable incremental compilation */ // "incremental": true, /* Enable incremental compilation */
"target": "es6", "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
// "lib": [], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./dist", /* Redirect output structure to the directory. */
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ /* Strict Type-Checking Options */
"module": "commonjs", "strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ /* Additional Checks */
// "lib": [], /* Specify library files to be included in the compilation. */ // "noUnusedLocals": true, /* Report errors on unused locals. */
// "allowJs": true, /* Allow javascript files to be compiled. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */
// "checkJs": true, /* Report errors in .js files. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */ // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./dist",
/* Redirect output structure to the directory. */ /* Module Resolution Options */
"rootDir": "./src", // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
/* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "composite": true, /* Enable project compilation */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "removeComments": true, /* Do not emit comments to output. */ // "typeRoots": [], /* List of folders to include type definitions from. */
// "noEmit": true, /* Do not emit outputs. */ // "types": [], /* Type declaration files to be included in compilation. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Strict Type-Checking Options */ /* Source Map Options */
"strict": true, // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
/* Enable all strict type-checking options. */ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "strictNullChecks": true, /* Enable strict null checks. */ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
"baseUrl": "./", /* Experimental Options */
"esModuleInterop": true, // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
/* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
"resolveJsonModule": true,
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ /* Advanced Options */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ "skipLibCheck": true, /* Skip type checking of declaration files. */
/* Experimental Options */ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
"experimentalDecorators": true, }
/* Enables experimental support for ES7 decorators. */
"emitDecoratorMetadata": true,
/* Enables experimental support for emitting type metadata for decorators. */
/* Advanced Options */
"skipLibCheck": true,
/* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true
/* Disallow inconsistently-cased references to the same file. */
},
"exclude": ["src/tests"]
} }

View File

@ -1,40 +0,0 @@
import path from 'path'
import { Schema, model } from 'mongoose'
export const schemaName = path.basename(__filename).split('.')[0]
const schema = new Schema(
{
username: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
domains: [
{
role: Number,
domain_id: String
}
],
verification_code: {
type: Number,
length: 6
},
verified: {
type: Boolean,
default: false
}
},
{
timestamps: true
}
)
export default model(path.basename(__filename).split('.')[0], schema)

View File

@ -1,35 +0,0 @@
import { DataTypes, Model } from 'sequelize'
import path from 'path'
import db from '../config/sequelize.config.ts'
class Instance extends Model {}
Instance.init(
{
_id: {
type: DataTypes.UUID,
primaryKey: true,
allowNull: false,
unique: true
},
username: {
type: DataTypes.STRING,
allowNull: false
},
password: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true
}
},
{
sequelize: db,
tableName: path.basename(__filename).split('.')[0].toLowerCase()
}
)
export default Instance

View File

@ -1,23 +0,0 @@
import { assert } from 'chai'
import Help from '../help'
import pad from 'pad'
describe('should return help', () => {
it('returns all help', () => {
const help = Help.logHelp()
const correct = Help.allHelp()
assert.equal(help, correct)
})
it('returns make help', () => {
const help = Help.logHelp('make')
const correct = Help.makeHelp()
assert.equal(help, correct)
})
it('returns specific help', () => {
const help = Help.logHelp('setup')
const correct = Help.specificHelp('setup')
assert.equal(help, correct)
})
})

View File

@ -1,68 +0,0 @@
import { assert } from 'chai'
import Routes from '../routes'
describe('should return help', () => {
process.argv = []
it('return all help', () => {
const options = ['-h', '--help']
for (let i = 0; i < options.length; i++) {
process.argv[2] = options[i]
process.argv[3] = ''
const routes = Routes.router()
assert.equal(routes, 'all help')
}
})
it('return specific help', () => {
const options = ['-h', '--help']
for (let i = 0; i < options.length; i++) {
process.argv[2] = options[i]
process.argv[3] = 'make'
const routes = Routes.router()
assert.equal(routes, 'specific help')
}
})
})
describe('should return version', () => {
it('return version', () => {
const options = ['-v', '--version']
for (let i = 0; i < options.length; i++) {
process.argv[2] = options[i]
const routes = Routes.router()
assert.equal(routes, 'version')
}
})
})
describe('should return setup', () => {
it('return setup', () => {
process.argv[2] = 'setup'
process.argv[3] = 'test'
const routes = Routes.router()
assert.equal(routes, 'setup')
})
})
describe('should return make', () => {
const options = ['controller', 'middleware', 'route', 'service', 'model', 'view', 'test', 'interface']
for (let i = 0; i < options.length; i++) {
it(`return make ${options[i]}`, () => {
process.argv[2] = 'make'
process.argv[3] = options[i]
process.argv[4] = 'test'
const routes = Routes.router()
assert.equal(routes, `make ${options[i]}`)
})
}
})
describe('should return create', () => {
it('return create testProject', () => {
process.argv[2] = 'create'
process.argv[3] = 'testProject'
process.argv[4] = 'test'
const routes = Routes.router()
assert.equal(routes, 'create testProject')
})
})

View File

@ -1,11 +0,0 @@
import { assert } from 'chai'
import Setup from '../setup'
import Global from '../global'
describe('should setup project', () => {
it('setup project', async () => {
const correct: string = Global.logSuccess()
const setup = await Setup.setup(true)
assert.equal(setup, correct)
})
})

View File

@ -1,20 +0,0 @@
import { assert } from 'chai'
import { App } from '../app'
// Describe tests
describe('some demo tests', () => {
// Create tests
it('adds two number together', () => {
assert(2 + 3 === 5)
})
it('should return Hello plus my name', () => {
assert.equal(App.sayHello('Filip'), 'Hello Filip')
assert.notEqual(App.sayHello('Adam'), 'Hello Filip')
})
it('should return Hello plus my name within instance', () => {
const app = new App('Filip')
assert.equal(app.pozdrav(), 'Hello Filip')
})
})

View File

@ -1,11 +0,0 @@
import { assert } from 'chai'
import Version from '../version'
import path from 'path'
describe('should return version', () => {
it('return version', () => {
const pkgJson = require(path.join(__dirname, '../../package'))
const actualVersion = pkgJson.version
assert.equal(Version.show(), `nork ${actualVersion}`)
})
})

View File

@ -1,7 +0,0 @@
import * as shell from 'shelljs'
shell.cp('-R', 'src/skeletons', 'dist/')
shell.cp('-R', 'src/interfaces', 'dist/')
shell.cp('-R', 'src/make-files', 'dist/')
shell.chmod('+x', 'dist/app.js')

View File

@ -1,10 +0,0 @@
import fs from 'fs-extra'
import path from 'path'
export default class Version {
static show(): string {
const pkgJson = fs.readJsonSync(path.join(__dirname, '../package.json'))
const log = `nork ${pkgJson.version}`
return log
}
}

View File

@ -1,15 +0,0 @@
{
"compilerOptions": {
"target": "es6" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"module": "commonjs" /* Specify what module code is generated. */,
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
"rootDir": "./src" /* Specify the root folder within your source files. */,
"strict": true /* Enable all strict type-checking options. */,
"baseUrl": "./" /* Base directory to resolve non-absolute module names. */,
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
"skipLibCheck": true /* Skip type checking all .d.ts files. */,
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
"declaration": true
},
"exclude": ["_old", "node_modules", "src/make-files", "src/skeletons", "src/tests", "src/interfaces", "src/utils"]
}