deploy.sh 1.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +36 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +105 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +56 -0
- package/.github/workflows/ci.yml +29 -0
- package/.github/workflows/pages.yml +48 -0
- package/.oxfmtrc.json +7 -0
- package/.oxlintrc.json +11 -0
- package/LICENSE +183 -183
- package/README.md +99 -11
- package/app/actions/deployments.ts +82 -0
- package/app/actions/metrics.ts +13 -0
- package/app/root.tsx +60 -0
- package/app/routes/dashboard/detail/history.tsx +73 -0
- package/app/routes/dashboard/detail/layout.tsx +125 -0
- package/app/routes/dashboard/detail/logs.tsx +85 -0
- package/app/routes/dashboard/detail/overview.tsx +119 -0
- package/app/routes/dashboard/detail/requests.tsx +163 -0
- package/app/routes/dashboard/detail/resources.tsx +268 -0
- package/app/routes/dashboard/detail/shared.tsx +59 -0
- package/app/routes/dashboard/index.tsx +360 -0
- package/app/routes/dashboard/layout.tsx +30 -0
- package/app/routes/docs/architecture.tsx +155 -0
- package/app/routes/docs/cli.tsx +122 -0
- package/app/routes/docs/deploying.tsx +105 -0
- package/app/routes/docs/index.tsx +104 -0
- package/app/routes/docs/layout.tsx +58 -0
- package/app/routes/home.tsx +134 -0
- package/app/routes/root.client.tsx +46 -0
- package/app/routes.ts +21 -0
- package/app/styles.css +15 -0
- package/app/theme.css +134 -0
- package/bin/deploy.js +360 -110
- package/docs-site/404.html +33 -0
- package/docs-site/home.tsx +130 -0
- package/docs-site/index.html +35 -0
- package/docs-site/layout.tsx +57 -0
- package/docs-site/main.tsx +41 -0
- package/docs-site/shell.tsx +34 -0
- package/docs-site/styles.css +4 -0
- package/drizzle.config.js +8 -0
- package/examples/docker/Dockerfile +5 -0
- package/examples/docker/server.js +18 -0
- package/examples/node/package.json +7 -0
- package/examples/node/pnpm-lock.yaml +9 -0
- package/examples/node/server.js +12 -0
- package/examples/static/index.html +48 -0
- package/package.json +41 -55
- package/public/favicon.ico +0 -0
- package/react-router-vite/entry.browser.tsx +49 -0
- package/react-router-vite/entry.rsc.single.tsx +7 -0
- package/react-router-vite/entry.rsc.tsx +36 -0
- package/react-router-vite/entry.ssr.tsx +29 -0
- package/react-router-vite/plugin.ts +114 -0
- package/react-router-vite/types.d.ts +11 -0
- package/react-router.config.ts +5 -0
- package/server/api.test.ts +344 -0
- package/server/api.ts +445 -0
- package/server/docker.ts +268 -0
- package/server/index.ts +17 -0
- package/server/metrics-collector.ts +29 -0
- package/server/schema.ts +56 -0
- package/server/store.test.ts +278 -0
- package/server/store.ts +398 -0
- package/tsconfig.json +21 -0
- package/vite.config.ts +45 -0
- package/vite.docs.config.ts +31 -0
- package/.eslintignore +0 -5
- package/.eslintrc +0 -23
- package/.travis.yml +0 -9
- package/.tryitout +0 -48
- package/CHANGELOG.md +0 -56
- package/bin/deploy-delete.js +0 -11
- package/bin/deploy-deploy.js +0 -31
- package/bin/deploy-list.js +0 -32
- package/bin/deploy-login.js +0 -39
- package/bin/deploy-logout.js +0 -12
- package/bin/deploy-logs.js +0 -19
- package/bin/deploy-open.js +0 -19
- package/bin/deploy-register.js +0 -40
- package/bin/deploy-server.js +0 -5
- package/bin/deploy-whoami.js +0 -12
- package/docs/code/CLI.html +0 -2901
- package/docs/code/Deployment.html +0 -2469
- package/docs/code/Request.html +0 -906
- package/docs/code/User.html +0 -1219
- package/docs/code/classifier.js.html +0 -121
- package/docs/code/deploy.js.html +0 -122
- package/docs/code/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-Bold-webfont.svg +0 -1830
- package/docs/code/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
- package/docs/code/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-Italic-webfont.svg +0 -1830
- package/docs/code/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-Light-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-Light-webfont.svg +0 -1831
- package/docs/code/fonts/OpenSans-Light-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
- package/docs/code/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-Regular-webfont.svg +0 -1831
- package/docs/code/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-Semibold-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-Semibold-webfont.svg +0 -1830
- package/docs/code/fonts/OpenSans-Semibold-webfont.ttf +0 -0
- package/docs/code/fonts/OpenSans-Semibold-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-SemiboldItalic-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-SemiboldItalic-webfont.svg +0 -1830
- package/docs/code/fonts/OpenSans-SemiboldItalic-webfont.ttf +0 -0
- package/docs/code/fonts/OpenSans-SemiboldItalic-webfont.woff +0 -0
- package/docs/code/helpers_cli.js.html +0 -315
- package/docs/code/helpers_util.js.html +0 -194
- package/docs/code/index.html +0 -66
- package/docs/code/models_deployment.js.html +0 -515
- package/docs/code/models_request.js.html +0 -158
- package/docs/code/models_user.js.html +0 -198
- package/docs/code/module-lib_classifier.html +0 -246
- package/docs/code/module-lib_deploy.html +0 -350
- package/docs/code/module-lib_helpers_util.html +0 -707
- package/docs/code/scripts/linenumber.js +0 -25
- package/docs/code/scripts/prettify/Apache-License-2.0.txt +0 -202
- package/docs/code/scripts/prettify/lang-css.js +0 -2
- package/docs/code/scripts/prettify/prettify.js +0 -28
- package/docs/code/styles/jsdoc-default.css +0 -692
- package/docs/code/styles/prettify-jsdoc.css +0 -111
- package/docs/code/styles/prettify-tomorrow.css +0 -132
- package/docs/example.gif +0 -0
- package/docs/example.mov +0 -0
- package/docs/index.html +0 -4463
- package/docs/logo.png +0 -0
- package/docs/logo.pxm +0 -0
- package/docs/logo@2x.png +0 -0
- package/docs/main.css +0 -162
- package/docs/main.js +0 -53
- package/index.js +0 -55
- package/jsdoc.json +0 -27
- package/lib/classifier.js +0 -61
- package/lib/deploy.js +0 -62
- package/lib/helpers/cli.js +0 -255
- package/lib/helpers/util.js +0 -134
- package/lib/models/deployment.js +0 -455
- package/lib/models/request.js +0 -98
- package/lib/models/user.js +0 -138
- package/lib/server.js +0 -165
- package/lib/static/not-found.html +0 -30
- package/lib/static/page-could-not-load.html +0 -30
- package/lib/static/static-server.js +0 -69
- package/test/fixtures/docker/Dockerfile +0 -5
- package/test/fixtures/docker/index.js +0 -12
- package/test/fixtures/node/index.js +0 -8
- package/test/fixtures/node/package.json +0 -15
- package/test/fixtures/static/index.html +0 -14
- package/test/fixtures/static/main.css +0 -7
- package/test/fixtures/static/out.gifcd +0 -0
- package/test/fixtures/unknown/.gitkeep +0 -0
- package/test/lib/classifier.js +0 -51
- package/test/lib/helpers/util.js +0 -47
package/lib/models/user.js
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
const mongoose = require('mongoose');
|
|
2
|
-
const crypto = require('crypto');
|
|
3
|
-
|
|
4
|
-
const Schema = mongoose.Schema;
|
|
5
|
-
|
|
6
|
-
const UserSchema = new Schema({
|
|
7
|
-
_id: String,
|
|
8
|
-
username: String,
|
|
9
|
-
password: String,
|
|
10
|
-
token: String
|
|
11
|
-
}, {
|
|
12
|
-
minimize: false,
|
|
13
|
-
timestamps: {
|
|
14
|
-
createdAt: 'created_at',
|
|
15
|
-
updatedAt: 'updated_at'
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const UserModel = mongoose.model('User', UserSchema);
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* User definition
|
|
23
|
-
* @class User
|
|
24
|
-
* @property {String} username - a string that defines the user's accounts
|
|
25
|
-
* @property {String} password - a password for the user
|
|
26
|
-
* @property {String=} token - an access token
|
|
27
|
-
*/
|
|
28
|
-
class User {
|
|
29
|
-
/**
|
|
30
|
-
* middleware to verify the username and token are valid, will then set the user to req.user
|
|
31
|
-
* @function authenticateMiddleware
|
|
32
|
-
* @memberof User
|
|
33
|
-
* @param {Object} req - express request
|
|
34
|
-
* @param {Object} res - express response
|
|
35
|
-
* @param {Function} next - callback to go to next middleware
|
|
36
|
-
*/
|
|
37
|
-
static async authenticateMiddleware(req, res, next) {
|
|
38
|
-
const username = req.headers['x-deploy-username'];
|
|
39
|
-
const token = req.headers['x-deploy-token'];
|
|
40
|
-
|
|
41
|
-
if(!username && !token) {
|
|
42
|
-
res.status(500).send({ error: 'authentication necessary' });
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
req.user = await User.authenticate(username, token);
|
|
46
|
-
|
|
47
|
-
next();
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* verify the username and token are valid
|
|
51
|
-
* @method authenticate
|
|
52
|
-
* @memberof User
|
|
53
|
-
* @param {String} token - the token associated with the username
|
|
54
|
-
* @param {String} username - the username of the user
|
|
55
|
-
* @return {Promise}
|
|
56
|
-
*/
|
|
57
|
-
static async authenticate(username, token) {
|
|
58
|
-
let user = await UserModel.findOne({
|
|
59
|
-
_id: username,
|
|
60
|
-
token
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
if(!user) throw new Error('not authenticated');
|
|
64
|
-
|
|
65
|
-
return {
|
|
66
|
-
username: user.username,
|
|
67
|
-
token: user.token
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* logs out a user by deleting their token
|
|
72
|
-
* @method logout
|
|
73
|
-
* @memberof User
|
|
74
|
-
* @param {String} token - the token associated with the username
|
|
75
|
-
* @param {String} username - the username of the user
|
|
76
|
-
* @return {Promise}
|
|
77
|
-
*/
|
|
78
|
-
static async logout({ token, username }) {
|
|
79
|
-
let user = await UserModel.findOne({
|
|
80
|
-
_id: username,
|
|
81
|
-
token
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
if(!user) throw new Error('token and username not valid');
|
|
85
|
-
|
|
86
|
-
user.token = '';
|
|
87
|
-
|
|
88
|
-
return await user.save();
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* logs in a user and returns
|
|
92
|
-
* @method login
|
|
93
|
-
* @memberof User
|
|
94
|
-
* @param {String} username - the username of the user who is logging in
|
|
95
|
-
* @param {String} password - the password associated with the user
|
|
96
|
-
* @return {Promise}
|
|
97
|
-
*/
|
|
98
|
-
static async login({ username, password }) {
|
|
99
|
-
let user = await UserModel.findOne({
|
|
100
|
-
_id: username,
|
|
101
|
-
password: crypto.createHash('sha256').update(password).digest('hex')
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
if(!user) throw new Error('password username combination not correct');
|
|
105
|
-
|
|
106
|
-
user.token = crypto.createHash('sha256').update(Date.now() + password + username).digest('hex');
|
|
107
|
-
await user.save();
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
username: user.username,
|
|
111
|
-
token: user.token
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* registers a user
|
|
116
|
-
* @method register
|
|
117
|
-
* @memberof User
|
|
118
|
-
* @param {String} username - the username of the user who is logging in
|
|
119
|
-
* @param {String} password - the password associated with the user
|
|
120
|
-
* @return {Promise}
|
|
121
|
-
*/
|
|
122
|
-
static async register({ username, password }) {
|
|
123
|
-
let user = await UserModel.create({
|
|
124
|
-
_id: username,
|
|
125
|
-
username,
|
|
126
|
-
password: crypto.createHash('sha256').update(password).digest('hex'),
|
|
127
|
-
token: crypto.createHash('sha256').update(Date.now() + password + username).digest('hex')
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
return {
|
|
131
|
-
username: user.username,
|
|
132
|
-
token: user.token,
|
|
133
|
-
depoyments: user.deployments
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
module.exports = User;
|
package/lib/server.js
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
const express = require('express');
|
|
2
|
-
const formidable = require('formidable');
|
|
3
|
-
const bodyParser = require('body-parser');
|
|
4
|
-
|
|
5
|
-
const app = express();
|
|
6
|
-
|
|
7
|
-
const deploy = require('./deploy');
|
|
8
|
-
const { authenticateMiddleware, register, logout, login } = require('./models/user');
|
|
9
|
-
const { del, logs, get, getAll, proxy } = require('./models/deployment');
|
|
10
|
-
const { log } = require('./models/request');
|
|
11
|
-
|
|
12
|
-
const port = process.env.PORT || 5000;
|
|
13
|
-
|
|
14
|
-
app.use(bodyParser.urlencoded({ extended: false }));
|
|
15
|
-
app.use(bodyParser.json());
|
|
16
|
-
|
|
17
|
-
const asyncMiddleware = (fn) => {
|
|
18
|
-
return (req, res, next) => {
|
|
19
|
-
Promise.resolve(fn(req, res, next)).catch(next);
|
|
20
|
-
};
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const formidablePromise = (req, opts) => {
|
|
24
|
-
return new Promise(function (resolve, reject) {
|
|
25
|
-
var form = new formidable.IncomingForm(opts);
|
|
26
|
-
form.parse(req, function (err, fields, files) {
|
|
27
|
-
if (err) return reject(err);
|
|
28
|
-
resolve({ fields: fields, files: files });
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
app.post('/register', asyncMiddleware(async (req, res) => {
|
|
34
|
-
const { username, password } = req.body;
|
|
35
|
-
if(!username || !password) return res.status(500).send({ error: 'please provide username and password'});
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
const user = await register({ username, password });
|
|
39
|
-
res.status(200).send(user);
|
|
40
|
-
} catch(error) {
|
|
41
|
-
res.status(500).send({ error: 'something went wrong' });
|
|
42
|
-
}
|
|
43
|
-
}));
|
|
44
|
-
|
|
45
|
-
app.post('/login', asyncMiddleware(async (req, res) => {
|
|
46
|
-
const { username, password } = req.body;
|
|
47
|
-
|
|
48
|
-
if(!username || !password) return res.status(500).send({ error: 'please provide username and password'});
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
const user = await login({ username, password });
|
|
52
|
-
res.status(200).send(user);
|
|
53
|
-
} catch(error) {
|
|
54
|
-
res.status(500).send({ error });
|
|
55
|
-
}
|
|
56
|
-
}));
|
|
57
|
-
|
|
58
|
-
app.post('/upload', authenticateMiddleware, asyncMiddleware(async (req, res) => {
|
|
59
|
-
try {
|
|
60
|
-
const { user } = req;
|
|
61
|
-
const { username, token } = user;
|
|
62
|
-
|
|
63
|
-
const { fields, files } = await formidablePromise(req, {
|
|
64
|
-
type: true
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
const { name } = fields;
|
|
68
|
-
const { bundle } = files;
|
|
69
|
-
const deployment = await deploy({
|
|
70
|
-
name,
|
|
71
|
-
bundlePath: bundle.path,
|
|
72
|
-
token,
|
|
73
|
-
username
|
|
74
|
-
});
|
|
75
|
-
res.status(200).send({ success: `application ${name} deployed successfully`, deployment });
|
|
76
|
-
} catch(ex) {
|
|
77
|
-
res.status(500).send({ error: ex.stack });
|
|
78
|
-
}
|
|
79
|
-
}));
|
|
80
|
-
|
|
81
|
-
app.get('/api/deployments/:name/logs', authenticateMiddleware, asyncMiddleware(async (req, res) => {
|
|
82
|
-
const { name } = req.params;
|
|
83
|
-
const { token, username } = req.user;
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
const _logs = await logs({
|
|
87
|
-
name,
|
|
88
|
-
username,
|
|
89
|
-
token
|
|
90
|
-
});
|
|
91
|
-
res.status(200).send({ logs: _logs });
|
|
92
|
-
} catch(ex) {
|
|
93
|
-
res.status(500).send({ ex });
|
|
94
|
-
}
|
|
95
|
-
}));
|
|
96
|
-
|
|
97
|
-
app.get('/api/deployments', authenticateMiddleware, asyncMiddleware(async (req, res) => {
|
|
98
|
-
const { token, username } = req.user;
|
|
99
|
-
|
|
100
|
-
try {
|
|
101
|
-
const deployments = await getAll({
|
|
102
|
-
username,
|
|
103
|
-
token
|
|
104
|
-
});
|
|
105
|
-
res.status(200).send({ deployments });
|
|
106
|
-
} catch(error) {
|
|
107
|
-
res.status(500).send({ error });
|
|
108
|
-
}
|
|
109
|
-
}));
|
|
110
|
-
|
|
111
|
-
app.delete('/api/deployments/:name', authenticateMiddleware, asyncMiddleware(async (req, res) => {
|
|
112
|
-
const { name } = req.params;
|
|
113
|
-
const { token, username } = req.user;
|
|
114
|
-
|
|
115
|
-
try {
|
|
116
|
-
await del({
|
|
117
|
-
name,
|
|
118
|
-
token,
|
|
119
|
-
username
|
|
120
|
-
});
|
|
121
|
-
res.status(200).send({ success: `deployment ${name} successfully deleted` });
|
|
122
|
-
} catch(error) {
|
|
123
|
-
res.status(500).send({ error });
|
|
124
|
-
}
|
|
125
|
-
}));
|
|
126
|
-
|
|
127
|
-
app.get('/api/deployments/:name', authenticateMiddleware, asyncMiddleware(async (req, res) => {
|
|
128
|
-
const { name } = req.params;
|
|
129
|
-
const { token, username } = req.user;
|
|
130
|
-
|
|
131
|
-
try {
|
|
132
|
-
const deployment = await get({
|
|
133
|
-
username,
|
|
134
|
-
token,
|
|
135
|
-
name
|
|
136
|
-
});
|
|
137
|
-
res.status(200).send({ deployment });
|
|
138
|
-
} catch(error) {
|
|
139
|
-
res.status(500).send({ error });
|
|
140
|
-
}
|
|
141
|
-
}));
|
|
142
|
-
|
|
143
|
-
app.get('/api/logout', authenticateMiddleware, asyncMiddleware(async (req, res) => {
|
|
144
|
-
const { token, username } = req.user;
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
await logout({ username, token });
|
|
148
|
-
res.status(200).send({ success: `${username} successfully deleted` });
|
|
149
|
-
} catch(ex) {
|
|
150
|
-
res.status(500).send({ error: 'could not logout from session' });
|
|
151
|
-
}
|
|
152
|
-
}));
|
|
153
|
-
|
|
154
|
-
app.get('/api/user', authenticateMiddleware, (req, res) => {
|
|
155
|
-
const { user } = req;
|
|
156
|
-
|
|
157
|
-
delete user['token'];
|
|
158
|
-
res.status(200).send({ user });
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
app.get('*', log, proxy);
|
|
162
|
-
|
|
163
|
-
app.listen(port, () => {
|
|
164
|
-
console.log(`⛅️ deploy.sh is running on port ${port}`); // eslint-disable-line
|
|
165
|
-
});
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<style media="screen">
|
|
6
|
-
html, body {
|
|
7
|
-
height: 100%;
|
|
8
|
-
width: 100%;
|
|
9
|
-
overflow: hidden;
|
|
10
|
-
}
|
|
11
|
-
.message {
|
|
12
|
-
text-align: center;
|
|
13
|
-
top: 50%;
|
|
14
|
-
width: 100%;
|
|
15
|
-
position: absolute;
|
|
16
|
-
}
|
|
17
|
-
h3 {
|
|
18
|
-
display: inline-block;
|
|
19
|
-
border-right: 1px solid #a2a2a2;
|
|
20
|
-
padding-right: 10px;
|
|
21
|
-
}
|
|
22
|
-
</style>
|
|
23
|
-
<title>Error</title>
|
|
24
|
-
</head>
|
|
25
|
-
<body>
|
|
26
|
-
<div class="message">
|
|
27
|
-
<h3>404</h3> <span> Sorry this page could not be found 🙈 </span>
|
|
28
|
-
</div>
|
|
29
|
-
</body>
|
|
30
|
-
</html>
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<style media="screen">
|
|
6
|
-
html, body {
|
|
7
|
-
height: 100%;
|
|
8
|
-
width: 100%;
|
|
9
|
-
overflow: hidden;
|
|
10
|
-
}
|
|
11
|
-
.message {
|
|
12
|
-
text-align: center;
|
|
13
|
-
top: 50%;
|
|
14
|
-
width: 100%;
|
|
15
|
-
position: absolute;
|
|
16
|
-
}
|
|
17
|
-
h3 {
|
|
18
|
-
display: inline-block;
|
|
19
|
-
border-right: 1px solid #a2a2a2;
|
|
20
|
-
padding-right: 10px;
|
|
21
|
-
}
|
|
22
|
-
</style>
|
|
23
|
-
<title>Error</title>
|
|
24
|
-
</head>
|
|
25
|
-
<body>
|
|
26
|
-
<div class="message">
|
|
27
|
-
<h3>502</h3> <span> Sorry this page could not be loaded 🙈 </span>
|
|
28
|
-
</div>
|
|
29
|
-
</body>
|
|
30
|
-
</html>
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
const http = require('http');
|
|
2
|
-
const Url = require('url');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
|
|
6
|
-
const port = process.env.PORT;
|
|
7
|
-
|
|
8
|
-
const map = {
|
|
9
|
-
'.ico': 'image/x-icon',
|
|
10
|
-
'.html': 'text/html',
|
|
11
|
-
'.js': 'text/javascript',
|
|
12
|
-
'.json': 'application/json',
|
|
13
|
-
'.css': 'text/css',
|
|
14
|
-
'.png': 'image/png',
|
|
15
|
-
'.jpg': 'image/jpeg',
|
|
16
|
-
'.wav': 'audio/wav',
|
|
17
|
-
'.mp3': 'audio/mpeg',
|
|
18
|
-
'.svg': 'image/svg+xml',
|
|
19
|
-
'.pdf': 'application/pdf',
|
|
20
|
-
'.doc': 'application/msword'
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const cache = {};
|
|
24
|
-
|
|
25
|
-
http.createServer((req, res) => {
|
|
26
|
-
let { url } = req;
|
|
27
|
-
|
|
28
|
-
if (url === '/') url = '/index.html';
|
|
29
|
-
|
|
30
|
-
console.log(`${req.method} ${url}`); // eslint-disable-line
|
|
31
|
-
|
|
32
|
-
const parsedUrl = Url.parse(url);
|
|
33
|
-
let pathname = `.${parsedUrl.pathname}`;
|
|
34
|
-
|
|
35
|
-
if(cache[pathname]) {
|
|
36
|
-
res.setHeader('Content-Type', cache[pathname]['Content-Type']);
|
|
37
|
-
return res.end(cache[pathname]['data']);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const ext = path.parse(pathname).ext;
|
|
41
|
-
|
|
42
|
-
fs.exists(pathname, (exist) => {
|
|
43
|
-
if (!exist) {
|
|
44
|
-
res.statusCode = 404;
|
|
45
|
-
res.end(`File ${pathname} not found!`);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (fs.statSync(pathname).isDirectory()) pathname += '/index' + ext;
|
|
50
|
-
|
|
51
|
-
fs.readFile(pathname, (err, data) => {
|
|
52
|
-
if (err) {
|
|
53
|
-
res.statusCode = 500;
|
|
54
|
-
res.end(`Error getting the file: ${err}.`);
|
|
55
|
-
} else {
|
|
56
|
-
cache[pathname] = {
|
|
57
|
-
'Content-Type': map[ext] || 'text/plain',
|
|
58
|
-
data
|
|
59
|
-
};
|
|
60
|
-
// if the file is found, set Content-type and send data
|
|
61
|
-
res.setHeader('Content-Type', map[ext] || 'text/plain');
|
|
62
|
-
res.end(data);
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
}).listen(parseInt(port), () => {
|
|
68
|
-
console.log(`Server listening on port ${port}`); // eslint-disable-line
|
|
69
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
const http = require('http');
|
|
2
|
-
const port = process.env.PORT || 8000;
|
|
3
|
-
|
|
4
|
-
const server = http.createServer((req, res) => {
|
|
5
|
-
res.writeHead(200, { 'Content-type': 'text/html; charset=utf-8' });
|
|
6
|
-
res.write('Hello World 🌎');
|
|
7
|
-
res.end();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
server.listen(port, () => {
|
|
11
|
-
console.log('🚀 server has liftoff');
|
|
12
|
-
});
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "node",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"start": "node index.js",
|
|
8
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
|
-
},
|
|
10
|
-
"author": "",
|
|
11
|
-
"license": "ISC",
|
|
12
|
-
"dependencies": {
|
|
13
|
-
"express": "^4.15.3"
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<link rel="stylesheet" href="./main.css">
|
|
6
|
-
<title>Hello World</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<div style="text-align:center;width:100%;position:absolute;top:50%;transform:translateY(-50%);">
|
|
10
|
-
<h1> Welcome </h1>
|
|
11
|
-
<small> <i> This is deployed on the ⛅️ </i> </small>
|
|
12
|
-
</div>
|
|
13
|
-
</body>
|
|
14
|
-
</html>
|
|
File without changes
|
|
File without changes
|
package/test/lib/classifier.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
const test = require('tape');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
const classifier = require('../../lib/classifier');
|
|
5
|
-
|
|
6
|
-
test('@lib/classifier', async (t) => {
|
|
7
|
-
t.plan(4);
|
|
8
|
-
|
|
9
|
-
const baseDirectory = path.resolve(__dirname, '..', 'fixtures');
|
|
10
|
-
|
|
11
|
-
t.test('should be able to classify static site', async (t) => {
|
|
12
|
-
const directory = path.resolve(baseDirectory, 'static');
|
|
13
|
-
const output = await classifier(directory);
|
|
14
|
-
t.deepEqual(output, {
|
|
15
|
-
type: 'static',
|
|
16
|
-
build: `\n FROM mhart/alpine-node:base-8\n WORKDIR ${directory}\n ADD . .\n\n CMD ["node", "index.js"]\n `
|
|
17
|
-
});
|
|
18
|
-
t.end();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
t.test('should be able to classify node site', async (t) => {
|
|
22
|
-
const directory = path.resolve(baseDirectory, 'node');
|
|
23
|
-
const output = await classifier(directory);
|
|
24
|
-
t.deepEqual(output, {
|
|
25
|
-
type: 'node',
|
|
26
|
-
build: `\n FROM mhart/alpine-node:8\n WORKDIR ${directory}\n ADD . .\n\n RUN npm install\n\n CMD ["npm", "start"]\n `
|
|
27
|
-
});
|
|
28
|
-
t.end();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
t.test('should be able to classify docker site', async (t) => {
|
|
32
|
-
const directory = path.resolve(baseDirectory, 'docker');
|
|
33
|
-
const output = await classifier(directory);
|
|
34
|
-
|
|
35
|
-
t.deepEqual(output, {
|
|
36
|
-
type: 'docker',
|
|
37
|
-
build: `FROM mhart/alpine-node:8\nWORKDIR ${directory}\nADD . .\n\nCMD ["node", "index.js"]\n`
|
|
38
|
-
});
|
|
39
|
-
t.end();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
t.test('should be able to classify unknown deploy target', async (t) => {
|
|
43
|
-
const directory = path.resolve(baseDirectory, 'unknown');
|
|
44
|
-
const output = await classifier(directory);
|
|
45
|
-
|
|
46
|
-
t.deepEqual(output, {
|
|
47
|
-
type: 'unknown'
|
|
48
|
-
});
|
|
49
|
-
t.end();
|
|
50
|
-
});
|
|
51
|
-
});
|
package/test/lib/helpers/util.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
const test = require('tape');
|
|
2
|
-
const os = require('os');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
|
|
5
|
-
const { getPort, hash, contains, mk, rm } = require('../../../lib/helpers/util');
|
|
6
|
-
|
|
7
|
-
test('@lib/util', (t) => {
|
|
8
|
-
t.plan(4);
|
|
9
|
-
|
|
10
|
-
t.test('@getPort: should be able return a valid port', async (t) => {
|
|
11
|
-
let port = await getPort();
|
|
12
|
-
let port1 = await getPort();
|
|
13
|
-
t.ok(Number.isInteger(port));
|
|
14
|
-
t.ok(Number.isInteger(port1));
|
|
15
|
-
t.ok(port !== port1);
|
|
16
|
-
t.end();
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
t.test('@hash: should return a proper lowercase hash', (t) => {
|
|
20
|
-
const ret = hash(6);
|
|
21
|
-
t.ok(ret.length, 6);
|
|
22
|
-
t.ok(ret.toLowerCase(), ret);
|
|
23
|
-
t.end();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
t.test('@contains: should be able to return a proper conditional for truthy and false cases', (t) => {
|
|
27
|
-
t.ok(contains(['index.html', 'main.css'], ['index.html', '!Dockerfile', '!package.json']));
|
|
28
|
-
t.notOk(contains(['index.html', 'main.css', 'Dockerfile'], ['index.html', '!Dockerfile', '!package.json']));
|
|
29
|
-
t.notOk(contains([], ['index.html', '!Dockerfile', '!package.json']));
|
|
30
|
-
t.end();
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
t.test('@mk / @rm: should be able to make recursive directory', async (t) => {
|
|
34
|
-
let directory = `${os.tmpdir()}/hello/world/this/is/a/nested/directory`;
|
|
35
|
-
|
|
36
|
-
await mk(directory);
|
|
37
|
-
|
|
38
|
-
t.ok(fs.existsSync(directory));
|
|
39
|
-
|
|
40
|
-
await rm(directory);
|
|
41
|
-
|
|
42
|
-
t.ok(!fs.existsSync(directory));
|
|
43
|
-
|
|
44
|
-
t.end();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
});
|