Browse Source

Merge pull request #7 from codefeathers/develop

`up v. 0.2.0` Alpha release
tags/v0.2.0 v0.2.0
Muthu Kumar 7 years ago
committed by GitHub
parent
commit
803977783a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 45
      .eslintrc.json
  2. 5
      .vscode/settings.json
  3. 46
      CODE_OF_CONDUCT.md
  4. 13
      Changelog.md
  5. 21
      LICENSE
  6. 29
      README.md
  7. 31
      actions/createProxyServer.js
  8. 48
      actions/createStaticServer.js
  9. 38
      actions/killALL.js
  10. 18
      actions/killAllConfirm.js
  11. 16
      actions/killServer.js
  12. 16
      actions/listServers.js
  13. 1542
      assets/tlds.txt
  14. 136
      build/defaultNginx.conf
  15. 8
      build/fetchTLDS.js
  16. 94
      index.js
  17. 1534
      package-lock.json
  18. 14
      package.json
  19. 63
      utils/isFQDN.js
  20. 10
      utils/isIP.js
  21. 56
      utils/listFile.js
  22. 7
      utils/nginxConf.js
  23. 43
      utils/nginxPath.js
  24. 6
      utils/nginxReload.js
  25. 9
      utils/parseToInt.js
  26. 16
      utils/removeFromArray.js
  27. 33
      utils/requirements.js
  28. 63
      utils/validate.js

45
.eslintrc.json

@ -1,21 +1,28 @@
{
"env": {
"node": true
},
"extends": "eslint:recommended",
"rules": {
"no-console": "off",
"indent": [
"error",
"tab"
],
"linebreak-style": [
"error",
"unix"
],
"semi": [
"error",
"always"
]
}
"env": {
"node": true,
"es6": true
},
"extends": "eslint:recommended",
"rules": {
"no-console": "off",
"indent": [
"error",
"tab"
],
"linebreak-style": [
"error",
"unix"
],
"semi": [
"error",
"always"
],
"prefer-const": "error",
"prefer-destructuring": "error",
"no-var": "error",
"strict": "error",
"eol-last": "error",
"max-len": "error"
}
}

5
.vscode/settings.json

@ -0,0 +1,5 @@
{
"editor.insertSpaces": false,
"editor.tabSize": 4,
"files.eol": "\n"
}

46
CODE_OF_CONDUCT.md

@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@thefeathers.in. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

13
Changelog.md

@ -0,0 +1,13 @@
# Changelog / Version history
## `up` v. 0.2.0
Changelog:
- Under the hood BREAKING changes. Working directories change.
- `/var/www/` to `/etc/up-serve/static/`
- `/etc/nginx/sites-available/` to `/etc/nginx/conf.d`
- `up static|proxy <domain>` adds the server to `/etc/up-serve/servers.up` list.
- `up kill <domain>` removes server from `servers.up` list.
- `up list` lists available servers from /etc/up-serve/servers.up!
- `up kill-all` destroys all servers and places a `default.conf` in `/etc/nginx/sites-enabled`.

21
LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Anu Rahul Nandhan a.k.a Muthu Kumar & CodeFeathers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

29
README.md

@ -8,17 +8,17 @@
# up
> Current version: `up v.0.1.5 (Pre-Alpha)`
> Current version: `up v.0.2.0 (Alpha)`
> Notes: `up` has landed in pre-alpha! 🎉 Changelog will be added from `up v.0.2.0` [(Alpha/MVP)](Roadmap.md)\
> ⚠️ ❌ `up` is still not ready for use yet! Do not attempt to use this in development or production until alpha!
> Notes: `up` is now in Alpha! 🎉 [(Changelog)](Changelog.md)\
> ⚠️ ❌ `up` is pretty useable so far. If you're testing `up` on a development server, do give us feedback.
**`up`** is a command line application that creates nginx server blocks quickly with a single command.
## Installation
As of now, `up` only supports Debian and Ubuntu based distros. Support for more distros will come soon. Add an issue to bump this process.
`up` currently supports nginx mainline and nginx stable on Linux based distros. Support for more distros will come soon. Add an issue to bump this process.
You will need to have [_node JS_](https://nodejs.org) and [_nginx_](https://nginx.org) installed.
@ -28,23 +28,20 @@ Install `up` from npm:
> `up` is now available as a command.
## Commands
## Basic Commands
`up static <domain>` - Create new static server at current folder.
Format: `up command <required> [optional]`
`up proxy <domain> <port>` - Create new proxy server listening at said port.
`up list` - List currently available servers. (Doesn't work yet)
`up kill <domain>` - Kill the server for this domain.
- `up static <domain> [outbound port]` - Create new static server at current folder.
- `up proxy <domain> <inbound port> [outbound port]` - Create new proxy server listening at said port.
- `up list` - List currently available servers.
- `up kill <domain>` - Kill the server for this domain.
## Examples
`up static example.com` will serve a static website from current folder.
`up proxy example.com 8081` will create a reverse proxy listening at port 8081.
`up kill example.com`
- `up static example.com` will serve a static website from current folder.
- `up proxy example.com 8081` will create a reverse proxy listening at port 8081.
- `up kill example.com`
## Contributors, Collaborators, and Guides

31
actions/createProxyServer.js

@ -1,14 +1,20 @@
var fs = require('fs-extra');
var shell = require('shelljs');
'use strict';
var npath = require('../utils/nginxPath');
var conf = require('../utils/nginxConf');
var nginxReload = require('../utils/nginxReload');
const fs = require('fs-extra');
const shell = require('shelljs');
var EOL = require('os').EOL; // \n if used on Linux, \r\n if used on Windows.
const npath = require('../utils/nginxPath');
const conf = require('../utils/nginxConf');
const nginxReload = require('../utils/nginxReload');
const { appendToList } = require('../utils/listFile');
const { EOL } = require('os'); // \n if used on Linux, \r\n if used on Windows.
function createProxyServer(domain, inPort, outPort) {
fs.outputFileSync((conf(npath.availableSites(), domain, outPort)),
outPort = outPort || 80;
shell.mkdir('-p', npath.confD());
fs.outputFileSync((conf(npath.confD(), domain, outPort)),
"server {" + EOL +
" listen " + outPort + ";" + EOL +
" listen [::]:" + outPort + ";" + EOL +
@ -25,10 +31,15 @@ function createProxyServer(domain, inPort, outPort) {
" }" + EOL +
"}"
);
shell.mkdir('-p', npath.enabledSites()); // Creates directory if doesn't exist
shell.ln('-sf', conf(npath.availableSites(), domain, outPort), conf(npath.enabledSites(), domain, outPort)); // Symlink the conf file from sites-available to sites-enabled
shell.mkdir('-p', npath.confD());
shell.mkdir('-p', npath.enabledSites());
// Creates directories if doesn't exist
shell.ln('-sf', conf(npath.confD(), domain, outPort),
conf(npath.enabledSites(), domain, outPort));
// Symlink the conf file from sites-available to sites-enabled
appendToList(domain, outPort, inPort);
nginxReload();
}
module.exports = createProxyServer;
module.exports = createProxyServer;

48
actions/createStaticServer.js

@ -1,21 +1,27 @@
var fs = require('fs-extra');
var shell = require('shelljs');
var path = require('path');
'use strict';
var npath = require('../utils/nginxPath');
var conf = require('../utils/nginxConf');
var nginxReload = require('../utils/nginxReload');
const fs = require('fs-extra');
const shell = require('shelljs');
const path = require('path');
var currentPath = path.normalize(process.cwd());
var EOL = require('os').EOL; // \n if used on Linux, \r\n if used on Windows.
const npath = require('../utils/nginxPath');
const conf = require('../utils/nginxConf');
const nginxReload = require('../utils/nginxReload');
const { appendToList } = require('../utils/listFile');
const currentPath = path.normalize(process.cwd());
const { EOL } = require('os'); // \n if used on Linux, \r\n if used on Windows.
function createStaticServer(domain, outPort) {
outPort = outPort || 80;
fs.outputFileSync((conf(npath.availableSites(), domain, outPort)), // Gets nginx's paths from nginxPath.js
shell.mkdir('-p', npath.confD());
fs.outputFileSync((conf(npath.confD(), domain, outPort)),
// Gets nginx's paths from nginxPath.js
"server {" + EOL +
" listen " + outPort + ";" + EOL +
" listen [::]:" + outPort + ";" + EOL +
" root " + npath.webRoot() + domain + ";" + EOL +
" root " + npath.webRoot() + domain + "." + outPort + ";" + EOL +
" index index.html index.htm;" + EOL +
"" + EOL +
" server_name " + domain + ";" + EOL +
@ -24,14 +30,22 @@ function createStaticServer(domain, outPort) {
" }" + EOL +
"}"
);
shell.mkdir('-p', npath.enabledSites()); // Creates directory if doesn't exist
shell.rm('-rf', conf(npath.enabledSites(), domain, outPort)); // Removes domain from sites-enabled if exists
shell.ln('-sf', conf(npath.availableSites(), domain, outPort), conf(npath.enabledSites(), domain, outPort)); // Symlink the conf file from sites-available to sites-enabled
shell.rm('-rf', npath.webRootDomain(domain, outPort)); // Removes domain from webroot if exists
shell.mkdir('-p', npath.webRoot()); // Creating the nginx www path if it doesn't exist so symlink doesn't fail
shell.ln('-sf', currentPath, npath.webRootDomain(domain, outPort)); // Symlink current directory to nginx's web root
shell.mkdir('-p', npath.enabledSites());
// Creates directories if doesn't exist
shell.rm('-rf', conf(npath.enabledSites(), domain, outPort));
// Removes domain from sites-enabled if exists
shell.ln('-sf', conf(npath.confD(), domain, outPort),
conf(npath.enabledSites(), domain, outPort));
// Symlink the conf file from confD to sites-enabled
shell.rm('-rf', npath.webRootDomain(domain, outPort));
// Removes domain from webroot if exists
shell.mkdir('-p', npath.webRoot());
// Creating the nginx www path if it doesn't exist so symlink doesn't fail
shell.ln('-sf', currentPath, npath.webRootDomain(domain, outPort));
// Symlink current directory to nginx's web root
appendToList(domain, outPort);
nginxReload();
}
module.exports = createStaticServer;
module.exports = createStaticServer;

38
actions/killALL.js

@ -0,0 +1,38 @@
'use strict';
const shell = require('shelljs');
const { EOL } = require('os');
const npath = require('../utils/nginxPath');
const conf = require('../utils/nginxConf');
function killALL () {
shell.rm('-Rf', npath.serversBakUp);
shell.mv(npath.serversUp(), npath.serversBakUp());
shell.rm('-Rf', npath() + "sites-available");
shell.rm('-Rf', npath.confD());
shell.rm('-Rf', npath.enabledSites());
shell.rm('-Rf', npath.webRoot());
shell.mkdir('-p', npath.confD());
shell.mkdir('-p', npath.enabledSites());
shell.mkdir('-p', npath.webRoot());
shell.cp('./build/defaultNginx.conf', conf(npath.confD()));
// Create the default.conf file
shell.ln('-sf', npath.confD() + "default.conf",
npath.enabledSites() + "default.conf");
// Symlink the default.conf file from confD to sites-enabled
console.log("All servers were killed and reverted to default.");
console.log(EOL + [
"A backup of your old servers.up is " +
"saved in /etc/up-serve/servers.bak.up.",
"Check this if you need to."
].join(EOL) + EOL);
}
function noKill () {
console.log("\nkill-all was interrupted by user.");
}
module.exports.kill = killALL;
module.exports.noKill = noKill;

18
actions/killAllConfirm.js

@ -0,0 +1,18 @@
'use strict';
const readlineSync = require('readline-sync');
const killALL = require('./killALL').kill;
const { noKill } = require('./killALL');
function killAllConfirm() {
console.log("\nThis action will destroy all nginx servers and return "
+ "to default configuration.");
if (readlineSync.keyInYN("Are you sure you want to do this?")) {
killALL();
}
else {
noKill();
}
}
module.exports = killAllConfirm;

16
actions/killServer.js

@ -1,15 +1,19 @@
var shell = require('shelljs');
'use strict';
var npath = require('../utils/nginxPath');
var conf = require('../utils/nginxConf');
var nginxReload = require('../utils/nginxReload');
const shell = require('shelljs');
const npath = require('../utils/nginxPath');
const conf = require('../utils/nginxConf');
const nginxReload = require('../utils/nginxReload');
const { removeFromList } = require('../utils/listFile');
function killServer(domain, outPort) {
shell.rm('-rf', conf(npath.enabledSites(), domain, outPort));
shell.rm('-rf', conf(npath.availableSites(), domain, outPort));
shell.rm('-rf', conf(npath.confD(), domain, outPort));
shell.rm('-rf', npath.webRootDomain(domain, outPort));
removeFromList(domain, outPort);
nginxReload();
}
module.exports = killServer;
module.exports = killServer;

16
actions/listServers.js

@ -0,0 +1,16 @@
'use strict';
const { readServers } = require('../utils/listFile');
const prettyjson = require('prettyjson');
const { EOL } = require('os');
function listServers() {
const serversList = readServers();
if(serversList) console.log(EOL + prettyjson.render(serversList) + EOL);
else console.log(EOL +
"No servers were found! Create some using `up`!" +
EOL);
}
module.exports = listServers;

1542
assets/tlds.txt

File diff suppressed because it is too large

136
build/defaultNginx.conf

@ -0,0 +1,136 @@
#user nobody;
#Defines which Linux system user will own and run the Nginx server
worker_processes 1;
#Referes to single threaded process. Generally set to be equal to the number of CPUs or cores.
#error_log logs/error.log; #error_log logs/error.log notice;
#Specifies the file where server logs.
#pid logs/nginx.pid;
#nginx will write its master process ID(PID).
events {
worker_connections 1024;
# worker_processes and worker_connections allows you to calculate maxclients value:
# max_clients = worker_processes * worker_connections
}
http {
include mime.types;
# anything written in /opt/nginx/conf/mime.types is interpreted as if written inside the http { } block
default_type application/octet-stream;
#
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
# If serving locally stored static files, sendfile is essential to speed up the server,
# But if using as reverse proxy one can deactivate it
#tcp_nopush on;
# works opposite to tcp_nodelay. Instead of optimizing delays, it optimizes the amount of data sent at once.
#keepalive_timeout 0;
keepalive_timeout 65;
# timeout during which a keep-alive client connection will stay open.
#gzip on;
# tells the server to use on-the-fly gzip compression.
server {
# You would want to make a separate file with its own server block for each virtual domain
# on your server and then include them.
listen 80;
#tells Nginx the hostname and the TCP port where it should listen for HTTP connections.
# listen 80; is equivalent to listen *:80;
server_name localhost;
# lets you doname-based virtual hosting
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
#The location setting lets you configure how nginx responds to requests for resources within the server.
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}

8
build/fetchTLDS.js

@ -0,0 +1,8 @@
'use strict';
const https = require('https');
const fs = require('fs-extra');
const file = fs.createWriteStream("./assets/tlds.txt");
https.get("https://data.iana.org/TLD/tlds-alpha-by-domain.txt",response =>
response.pipe(file));

94
index.js

@ -1,66 +1,104 @@
#!/usr/bin/env node
'use strict';
const { EOL } = require('os');
// Requiring npm modules
var program = require('commander');
var chalk = require('chalk');
const program = require('commander');
const chalk = require('chalk');
//var fs = require('fs-extra');
// Requiring Actions
const createProxyServer = require('./actions/createProxyServer');
const createStaticServer = require('./actions/createStaticServer');
const killServer = require('./actions/killServer');
const listServers = require('./actions/listServers');
const killAllConfirm = require('./actions/killAllConfirm');
// Requiring utils
var validate = require('./utils/validate');
var requirements = require('./utils/requirements');
const validate = require('./utils/validate');
const requirements = require('./utils/requirements');
// Requiring Actions
var createProxyServer = require('./actions/createProxyServer');
var createStaticServer = require('./actions/createStaticServer');
var killServer = require('./actions/killServer');
// Check for requirements such as OS version and nginx install.
// Throw and exit if requirements not found.
// #Roadmap: Add ability to satisfy any possible requirements.
// Check for requirements such as OS version and nginx install. Throw and exit if requirements not found. #Roadmap: Add ability to satisfy any possible requirements.
requirements(); // Comment in development and uncomment this line in production. This should check whether the OS is compatible with this version of `up`
requirements(); // Comment in development and uncomment this line in production.
// This should check whether the OS is compatible with this version of `up`
program
.version('0.1.5');
.version('0.2.0');
program
.command('static <domain> [outPort]')
.description('Create a static server at this folder.')
.action(function (domain, outPort) { //If outport is not given, 80 is set as default. Later, change this default to reflect nginx's settings.
outPort = outPort || "80"; // This is a string because regex needs to validate it.
if (!validate(domain, outPort)) return; //Validates domain and outport, and if invalid, throws and returns.
.action(function (domain, outPort) {
// If outport is not given, 80 is set as default.
// Later, change this default to reflect nginx's settings.
outPort = outPort || "80";
// This is a string because regex needs to validate it.
if (!validate(domain, outPort)) return;
// Validates domain and outport, and if invalid, throws and returns.
createStaticServer(domain, outPort);
if (outPort != "80" || "443") domain = domain + ":" + outPort;
console.log("Done! Your static server has been set up!\nPoint your domain to this server and check " + chalk.cyan(domain) + " to verify!");
console.log(EOL + [
"Done! Your static server has been set up!",
"Point your domain to this server and check " +
chalk.cyan(domain) +
" to verify!"
].join(EOL));
});
program
.command('proxy <domain> <inPort> [outPort]')
.description('Create a proxy server, listening at port number.')
.action(function (domain, inPort, outPort) { //Inbound port is necessary, but outbound is set to 80 by default. Again, will change this to reflect nginx's settings.
outPort = outPort || "80"; // This is a string because regex needs to validate it.
.action(function (domain, inPort, outPort) {
// Inbound port is necessary, but outbound is set to 80 by default.
// Again, will change this to reflect nginx's settings.
outPort = outPort || "80";
// This is a string because regex needs to validate it.
if (!validate(domain, inPort, outPort)) return;
createProxyServer(domain, inPort, outPort);
if (outPort != "80" || "443") domain = domain + ":" + outPort;
console.log("Done! Your reverse proxy server has been set up!\nPoint your domain to this server and check " + chalk.cyan(domain) + " to verify!");
console.log(EOL + [
"Done! Your reverse proxy server has been set up!",
"Point your domain to this server and check " +
chalk.cyan(domain) +
" to verify!"
].join(EOL));
});
program
.command('list')
.description('List all available servers.')
.action(function () {
// Stuff happens here
listServers();
});
program
.command('kill <domain> [ourPort]')
.description('Kill a server.')
.action(function (domain, outPort) {
outPort = outPort || "80"; // This is a string because regex needs to validate it.
outPort = outPort || "80";
// This is a string because regex needs to validate it.
killServer(domain, outPort);
console.log("\nDone! Your server has been killed!\n");
console.log(EOL + "Done! Your server has been killed!"+ EOL);
});
program
.command('kill-all')
.description('Warning! Will completely kill all servers and reset nginx')
.action(function() {
//new Promise(resolve => killed\killAllConfirm();
killAllConfirm();
});
program
.command('*') // This should pick invalid commands, but it doesn't, yet.
.action(function () {
console.log("Invalid command. Type " + chalk.cyan('up --help') + " for help.");
console.log(EOL + "Invalid command. Type " +
chalk.cyan('up --help') + " for help." + EOL);
});
// Adds custom help text to the automatically generated help.
@ -68,13 +106,19 @@ program.on('--help', function () {
console.log('');
console.log(' Usage:');
console.log('');
console.log(' ', chalk.yellow('$ up'), chalk.cyan('static'), chalk.blue('domain-name'));
console.log(' ',
chalk.yellow('$ up'),
chalk.cyan('static'),
chalk.blue('domain-name'));
console.log(' Set up a static server at domain-name');
console.log('');
console.log(' ', chalk.yellow('$ up'), chalk.cyan('proxy'), chalk.blue('domain-name port-number'));
console.log(' ',
chalk.yellow('$ up'),
chalk.cyan('proxy'),
chalk.blue('domain-name port-number'));
console.log(' Set up a proxy server listening at port-number');
console.log('');
});
// Parses commands passed to `up` and chooses one of the above commands.
program.parse(process.argv);
program.parse(process.argv);

1534
package-lock.json

File diff suppressed because it is too large

14
package.json

@ -1,10 +1,11 @@
{
"name": "up-serve",
"version": "0.1.5",
"version": "0.2.0",
"description": "A cli tool to quickly create and manage nginx server blocks.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \"Error: no test specified\" && exit 1",
"build": "node ./build/fetchTLDS"
},
"repository": {
"type": "git",
@ -30,7 +31,12 @@
"chalk": "^2.3.0",
"commander": "^2.11.0",
"fs-extra": "^4.0.2",
"shelljs": "^0.7.8",
"validator": "^9.1.1"
"prettyjson": "^1.2.1",
"prompt": "^1.0.0",
"readline-sync": "^1.4.7",
"shelljs": "^0.7.8"
},
"devDependencies": {
"eslint": "^4.10.0"
}
}

63
utils/isFQDN.js

@ -0,0 +1,63 @@
// Module courtesy of TRGWII
// Original: https://github.com/trgwii/isFQDN
'use strict';
const fs = require('fs-extra');
const path = require('path');
// Official list of TLDs should be fetched from:
// https://data.iana.org/TLD/tlds-alpha-by-domain.txt
// You must have received a copy of the list along with `up`
// Run `npm run build` to update the cached list
function isFQDN(domain) {
// Importing and parsing `tlds.txt` file
const tldspath = path.join(__dirname, '/../assets/tlds.txt');
const tlds = fs.readFileSync(tldspath, 'utf8')
.split(/[\r\n]+/)
.filter(x => !x.startsWith('#'));
if (domain.length > 253) {
return false;
}
const labels = domain.split('.').reverse();
if (labels.length < 2) {
return false;
}
const [ tld ] = labels;
if (!tlds.includes(tld.toUpperCase())) {
return false;
}
for (const label of labels) {
const len = label.length;
if (len > 63 || len === 0) {
return false;
}
for (let i = 0; i < len; i++) {
const char = label[i];
if ((i === 0 || i === len - 1) && char === '-') {
return false;
}
if (!char.match(/^[a-zA-Z0-9-]$/)) {
return false;
}
}
}
return true;
}
module.exports = isFQDN;

10
utils/isIP.js

@ -1,14 +1,16 @@
'use strict';
// Parses a string, and returns true if it is an IP Address.
function isIP(str) {
var segments = str
const segments = str
.split(".")
.map(Number);
if (!segments.length === 4) {
return false;
}
for(var i = 0; i < segments.length; i++) {
var segment = segments[i];
for(let i = 0; i < segments.length; i++) {
const segment = segments[i];
if (Number.isNaN(segment)) {
return false;
}
@ -22,4 +24,4 @@ function isIP(str) {
return true;
}
module.exports = isIP;
module.exports = isIP;

56
utils/listFile.js

@ -0,0 +1,56 @@
'use strict';
const { EOL } = require('os');
const fs = require('fs-extra');
const removeFromArray = require('./removeFromArray');
const listFilePath = require('./nginxPath').serversUp;
function appendToList(domain, outPort, inPort) {
inPort = inPort || undefined;
let jsonFile = { "domains": [] };
const domBlock = {
"domain": domain,
"outPort": outPort
};
if (!inPort) {
domBlock.type = "static";
} else {
domBlock.type = "proxy";
domBlock.inPort = inPort;
}
if (fs.existsSync(listFilePath())) {
const jsonBuffer = JSON.parse(fs.readFileSync(listFilePath()));
jsonFile.domains = removeFromArray(jsonBuffer.domains, domain, outPort);
}
jsonFile.domains.push(domBlock);
jsonFile = JSON.stringify(jsonFile, null, '\t');
fs.writeFileSync(listFilePath(), jsonFile);
}
function removeFromList (domain, outPort) {
if (fs.existsSync(listFilePath())) {
let jsonFile = { "domains": [] };
const jsonBuffer = JSON.parse(fs.readFileSync(listFilePath()));
jsonFile.domains = removeFromArray(jsonBuffer.domains, domain, outPort);
jsonFile = JSON.stringify(jsonBuffer, null, '\t');
fs.writeFileSync(listFilePath(), jsonFile);
}
else console.log(EOL + "No servers were created using `up` yet." + EOL);
}
function readServers () {
const serversList = JSON.parse(fs.readFileSync(listFilePath()));
if(!serversList.domains[0]) return undefined;
return serversList;
}
module.exports.appendToList = appendToList;
module.exports.readServers = readServers;
module.exports.removeFromList = removeFromList;

7
utils/nginxConf.js

@ -1,7 +1,10 @@
// Simple function that takes a path and domain name, concatenates them with ".conf" and returns it.
'use strict';
// Simple function that takes a path and domain name,
// concatenates them with ".conf" and returns it.
function conf(path, domain, outPort) {
return (path + domain + "." + outPort + ".conf");
}
module.exports = conf;
module.exports = conf;

43
utils/nginxPath.js

@ -1,27 +1,50 @@
// These functions just return paths. Later, these should be modified to poll from nginx's config.
'use strict';
var available = "/etc/nginx/sites-available/";
var enabled = "/etc/nginx/sites-enabled/";
var wwwRoot = "/var/www/";
// These functions just return paths.
// Later, these should be modified to poll from nginx's config.
function availableSites() {
return available;
const npath = "/etc/nginx/";
const enabled = npath + "sites-enabled/";
const confDpath = npath + "conf.d/";
const upPath = "/etc/up-serve/";
const wwwRoot = upPath + "static/";
const serverListPath = upPath + "servers";
function nginxPath() {
return npath;
}
function enabledSites() {
return enabled;
}
function confD() {
return confDpath;
}
function webRoot() {
return wwwRoot;
}
function webRootDomain(domain, outPort) {
var rootWithDomain = wwwRoot + domain + "." + outPort;
return rootWithDomain;
const path = wwwRoot + domain + "." + outPort;
return path;
}
function serversUp() {
const path = serverListPath + ".up";
return path;
}
function serversBakUp() {
const path = serverListPath + ".bak.up";
return path;
}
module.exports.availableSites = availableSites;
module.exports = nginxPath;
module.exports.confD = confD;
module.exports.enabledSites = enabledSites;
module.exports.webRoot = webRoot;
module.exports.webRootDomain = webRootDomain;
module.exports.webRootDomain = webRootDomain;
module.exports.serversUp = serversUp;
module.exports.serversBakUp = serversBakUp;

6
utils/nginxReload.js

@ -1,4 +1,6 @@
var execSync = require('child_process').execSync;
'use strict';
const { execSync } = require('child_process');
function nginxReload() {
execSync('service nginx reload', function (error, stdout, stderr) {
@ -11,4 +13,4 @@ function nginxReload() {
});
}
module.exports = nginxReload;
module.exports = nginxReload;

9
utils/parseToInt.js

@ -1,8 +1,11 @@
// Parse an input string and return a number if it is an integer. If it's a float, string, or array, return undefined.
'use strict';
// Parse an input string and return a number if it is an integer.
// If it's a float, string, or array, return undefined.
function parseToInt(inputString) {
var parsing = /^\d+$/.exec(inputString);
const parsing = /^\d+$/.exec(inputString);
return (parsing || [])[0];
}
module.exports = parseToInt;
module.exports = parseToInt;

16
utils/removeFromArray.js

@ -0,0 +1,16 @@
'use strict';
function removeFromArray (arr, dom, port) {
let shouldDelete = [];
for(let i = 0; i < arr.length; i++)
if((arr[i].domain == dom) && (arr[i].outPort == port))
shouldDelete = [true, i];
if (shouldDelete[0]) {
arr.splice(shouldDelete[1], 1);
}
return arr;
}
module.exports = removeFromArray;

33
utils/requirements.js

@ -1,23 +1,40 @@
var shell = require('shelljs');
var chalk = require('chalk');
'use strict';
const { EOL } = require('os');
const shell = require('shelljs');
const chalk = require('chalk');
function requirements() {
// Detect Linux or BSD
var isLin = /^linux|^bsd/.test(process.platform);
const isLin = /^linux|^bsd/.test(process.platform);
// Throw if OS is not Linux or BSD. This should be changed to throw if not Debian based distro. Eventually, we can add more exceptions as `up` handles more cases.
// Throw if OS is not Linux or BSD.
// This should be changed to throw if not Debian based distro.
// Eventually, we can add more exceptions as `up` handles more cases.
if(!isLin) {
shell.echo("\nThis is not a Linux or freeBSD distribution. This tool not written for this distro. Please raise an issue at " + chalk.cyan("https://github.com/codefeathers/up-serve") + " if you want `up` to be ported for your distro");
shell.echo(EOL +
"This is not a Linux or freeBSD distribution. " +
"This tool not written for this distro. " +
"Please raise an issue at " +
chalk.cyan("https://github.com/codefeathers/up-serve") +
" if you want `up` to be ported for your distro");
shell.exit(1);
}
// Check if sudo
if (process.getuid() != 0) {
console.log("`up` requires root privileges to work. Please use `sudo up <command>`");
shell.exit(1);
}
// Throw if Nginx is not found
if (!shell.which('nginx')) {
shell.echo('I need nginx to work. Install nginx first. https://nginx.org/');
shell.echo(
'I need nginx to work. Install nginx first. https://nginx.org/');
shell.exit(1);
}
}
module.exports = requirements;
module.exports = requirements;

63
utils/validate.js

@ -1,9 +1,12 @@
var validator = require('validator');
var parseToInt = require('./parseToInt');
var isIP = require('./isIP');
'use strict';
const { EOL } = require('os');
const parseToInt = require('./parseToInt');
const isIP = require('./isIP');
// Using Validator
var isDomain = validator.isFQDN;
const isDomain = require('./isFQDN');
function validate(domain, inPort, outPort) {
//
@ -11,15 +14,27 @@ function validate(domain, inPort, outPort) {
outPort = outPort || 80;
// Error messages
var domainInvalidMsg = ["\nPlease use a domain name instead of an IP address.", "\nDomain is not valid. Please use a valid domain name."];
var portInvalidMsg = ["\nPort should be a number.", "\nPort should be a number from 1 and 65535."];
const domainInvalidMsg = [
EOL + "Please use a domain name instead of an IP address.",
EOL + "Domain is not valid. Please use a valid domain name."
];
const portInvalidMsg = [
EOL + "Port should be a number.",
EOL + "Port should be a number from 1 and 65535."
];
// ARGV returns a string as input. Port numbers should be parsed to int to validate them. If validation fails, these will return undefined and will fail the subsequent test.
var validInPort = parseToInt(inPort);
var validOutPort = parseToInt(outPort);
// ARGV returns a string as input.
// Port numbers should be parsed to int to validate them.
// If validation fails, these will return undefined and
// will fail the subsequent test.
const validInPort = parseToInt(inPort);
const validOutPort = parseToInt(outPort);
// The value of isInvalid will be returned back. If none of the `if`s are true, the default value `true` is returned `domain`, `inPort` and `outPort` are considered validated.
var isValid = true;
// The value of isInvalid will be returned back.
// If none of the `if`s are true, the default
// value `true` is returned `domain`, `inPort` and `outPort` are considered
// validated.
let isValid = true;
// Throw if IP is given instead of domain name.
if (isIP(domain)) {
@ -33,32 +48,42 @@ function validate(domain, inPort, outPort) {
return isValid = false;
}
// Enter if `inPort` is not defined. This happens for `up static` where no inbound ports are required.
// Enter if `inPort` is not defined.
// This happens for `up static` where no inbound ports are required.
if (typeof inPort == undefined) {
if (!validOutPort) {
console.log(portInvalidMsg[0]); // `outPort` is not an integer.
return isValid = false;
}
if (!(validOutPort > 0 && validOutPort <= 65535)) {
console.log(portInvalidMsg[1]); // `outPort` is not within port range.
console.log(portInvalidMsg[1]);
// `outPort` is not within port range.
return isValid = false;
}
}
// Enter if `inPort` is defined. This happens for `up proxy` where inbound port is required.
// Enter if `inPort` is defined. This happens for `up proxy` where
// inbound port is required.
if (typeof inPort !== undefined) {
if (!validInPort || !validOutPort) {
console.log(portInvalidMsg[0]); // Either `inPort` or `outPort` is not an integer.
console.log(portInvalidMsg[0]);
// Either `inPort` or `outPort` is not an integer.
return isValid = false;
}
if (typeof outPort !== undefined) {
if (!((validInPort > 0 && validInPort <= 65535) && (validOutPort > 0 && validOutPort <= 65535))) {
console.log(portInvalidMsg[1]); // Either `inPort` or `outPort` are not within port range.
if (!(
(validInPort > 0 && validInPort <= 65535) &&
(validOutPort > 0 && validOutPort <= 65535)
)) {
console.log(portInvalidMsg[1]);
// Either `inPort` or `outPort` are not within port range.
return isValid = false;
}
}
return isValid; // If any of the `if`s were true, `isInvalid = false`. If not, `isInvalid = true`.
return isValid;
// If any of the `if`s were true, `isInvalid = false`.
// If not, `isInvalid = true`.
}
}
module.exports = validate;
module.exports = validate;

Loading…
Cancel
Save