Skip to content

Commit d2ce901

Browse files
authored
Merge pull request #1 from Vertex-Labs/turbo360-web-host
Turbo 360 Deployment Support.
2 parents 6d3a339 + c98fedf commit d2ce901

File tree

6 files changed

+256
-5
lines changed

6 files changed

+256
-5
lines changed

@build-turbo360.js

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
const process = require('process');
2+
const fs = require('fs-extra');
3+
const child_process = require('child_process');
4+
const shell = require('shelljs');
5+
const argv = require('minimist')(process.argv.slice(1));
6+
const dotenv = require('dotenv');
7+
8+
const PR = 'BUILD\t';
9+
const TR = '\x1b[0m';
10+
const CY = '\x1b[33m';
11+
const CR = '\x1b[41m';
12+
13+
if (!shell.which('git')) {
14+
shell.echo(
15+
`\x1b[30;41m You must have git installed to run the net.create/Turbo360 devtool \x1b[0m`
16+
);
17+
shell.exit(0);
18+
}
19+
20+
const param1 = argv._[1];
21+
22+
switch (param1) {
23+
case 'package-turbo360':
24+
f_PackageWebTurbo360(argv._[2]);
25+
break;
26+
case 'deploy-turbo360':
27+
f_DeployWebTurbo360();
28+
break;
29+
30+
default:
31+
console.log(`${PR}\n- unknown command '${param1}'\n`);
32+
}
33+
34+
function f_PackageWebTurbo360(template = '_blank') {
35+
console.log(`\n`);
36+
console.log(PR, `packaging for ${CY}Turbo-360${TR}`);
37+
console.log(PR, `erasing ./public and ./dist directories`);
38+
shell.rm('-rf', './dist', './public');
39+
console.log(PR, `compiling web into ./public`);
40+
41+
// Package the net.create application in "standalone" mode
42+
let res = shell.exec(`npx brunch build -e package`, { silent: true });
43+
u_checkError(res);
44+
45+
// Prepare a local copy of the Turbo360 NodeJS/Express base template
46+
// See: https://github.com/Vertex-Labs/base-template-netcreate
47+
console.log(
48+
PR,
49+
`cloning latest ${CY}Turbo-360${TR} net.create base template into ./dist`
50+
);
51+
res = shell.exec(
52+
'git clone https://github.com/Vertex-Labs/base-template-netcreate.git dist',
53+
{ silent: true }
54+
);
55+
if (res.code !== 0) {
56+
console.error(
57+
PR,
58+
`${CR}Unable to clone Turbo 360 Base Template - do you have access?${TR}:`
59+
);
60+
process.exit(1);
61+
}
62+
63+
console.log(PR, `installing ${CY}Turbo-360${TR} Node dependencies...`);
64+
shell.cd('./dist');
65+
res = shell.exec('npm i --omit=dev', { silent: true });
66+
if (res.code !== 0) {
67+
console.error(
68+
PR,
69+
`${CR}Unable to install Turbo 360 Base Template NodeJS dependencies${TR}`
70+
);
71+
console.error(PR, `\t${res.stderr}`);
72+
process.exit(1);
73+
}
74+
shell.cd(__dirname);
75+
76+
console.log(PR, `Copying web-app...`);
77+
// Copy the created net.create web-app bundle into the template
78+
fs.copySync('./public', './dist/public');
79+
fs.moveSync('./dist/public/index.ejs', './dist/views/home.html');
80+
fs.removeSync('./dist/public/index.html');
81+
82+
// TODO: Consider copying TOML and other files
83+
// console.log(PR, `Copying resources (using template: ${template})`);
84+
// fs.copySync(`./templates/${template}/resources`, './dist/public/resources');
85+
86+
console.log(PR, `${CY}Turbo-360 packaging complete${TR}`);
87+
console.log(
88+
PR,
89+
`To deploy, type ${CY}npm run deploy-turbo360${TR} and follow the prompts`
90+
);
91+
}
92+
93+
function f_DeployWebTurbo360() {
94+
let res = 0;
95+
96+
console.log(PR, `Welcome to the Turbo-360 Deployment Tool!`);
97+
console.log(PR, `Please select the ${CY}Turbo-360${TR} project to deploy to:`);
98+
99+
// First, connect the local project:
100+
shell.cd('./dist');
101+
102+
try {
103+
child_process.execFileSync('npx turbo', ['connect'], {
104+
stdio: 'inherit',
105+
shell: true
106+
});
107+
} catch (err) {
108+
if (err.status !== 0) {
109+
f_HandleDeployError(res.code);
110+
process.exit(1);
111+
}
112+
}
113+
114+
// .env file contains the slug
115+
if (!fs.existsSync('.env')) {
116+
console.log(
117+
PR,
118+
`You must connect your local project to a Turbo-360 project by selecting an option`
119+
);
120+
process.exit(1);
121+
}
122+
123+
const { TURBO_PROJECT = null, TURBO_PROJECT_SLUG = null } = dotenv.parse(
124+
fs.readFileSync('.env') ?? ''
125+
);
126+
127+
// Second, do the two deployment steps:
128+
console.log(
129+
PR,
130+
`Deploying to ${CY}Turbo-360${TR} Project ${CY}${TURBO_PROJECT}${TR}`
131+
);
132+
133+
console.log(PR, `Beginning Turbo-360 deployment...`);
134+
console.log(PR, `Please wait, this process may take several minutes....`);
135+
try {
136+
res = shell.exec('npx turbo deploy', { silent: true });
137+
if (res.code !== 0) {
138+
f_HandleDeployError(res.code);
139+
process.exit(1);
140+
}
141+
142+
res = shell.exec('npx turbo deploy -t static', { silent: true });
143+
if (res.code !== 0) {
144+
f_HandleDeployError(res.code);
145+
process.exit(1);
146+
}
147+
148+
const url = `https://${TURBO_PROJECT_SLUG}.turbo360-staging.com`;
149+
console.log(
150+
'\nDeployment complete, you can access the site using the following URLs:'
151+
);
152+
console.log(`\tApplication: ${url}/`);
153+
} catch (err) {
154+
// Unexpected errors
155+
console.log(PR, `unexpected error during Turbo-360 deployment: ${err}`);
156+
process.exit(-1);
157+
} finally {
158+
shell.cd(__dirname);
159+
}
160+
161+
// Local function
162+
function f_HandleDeployError(exitCode) {
163+
if (exitCode) {
164+
// FUTURE: This should ideally be exported from the CLI tool, or alternatively, the CLI tool
165+
// should expose a programmatic interface rather than mediate this through the shell
166+
const TURBO360_ERRORS = {
167+
// General errors
168+
UNSPECIFIED: { exitCode: 1 },
169+
INVALID_PARAMS: { exitCode: 2 },
170+
NOT_LOGGED_IN: { exitCode: 3 },
171+
172+
// Deploy-specific errors
173+
PROJECT_NOT_CONNECTED: { exitCode: 100 },
174+
PROJECT_NOT_FOUND: { exitCode: 101 },
175+
NOT_AUTHORIZED: { exitCode: 102 }
176+
};
177+
178+
// Non-zero exit code, interpret it
179+
switch (exitCode) {
180+
case TURBO360_ERRORS.NOT_LOGGED_IN:
181+
console.log(PR, `You must log in to ${CY}Turbo-360${TR} to deploy.`);
182+
break;
183+
184+
case TURBO360_ERRORS.PROJECT_NOT_CONNECTED:
185+
console.log(
186+
PR,
187+
`Your local codebase must be connected to a ${CY}Turbo-360${TR} project to continue.`
188+
);
189+
break;
190+
191+
case TURBO360_ERRORS.PROJECT_NOT_FOUND:
192+
case TURBO360_ERRORS.NOT_AUTHORIZED:
193+
console.log(
194+
PR,
195+
`The specified ${CY}Turbo-360${TR} project does not exist or you do not have access to it.`
196+
);
197+
break;
198+
199+
default:
200+
// All other errors
201+
console.log(
202+
PR,
203+
`Unexpected error while performing the ${CY}Turbo-360${TR} deployment: ${exitCode}.`
204+
);
205+
break;
206+
}
207+
208+
console.log(
209+
PR,
210+
`\tPlease review the ${CY}Turbo-360${TR} deployment notes in ${CY}README-Turbo360.md${TR}`
211+
);
212+
}
213+
}
214+
}
215+
216+
function u_checkError(execResults) {
217+
if (!execResults.stderr) return;
218+
console.log(`${CR}*** ERROR IN NETCREATE EXEC ***${TR}`);
219+
console.log(execResults.stderr);
220+
process.exit(0);
221+
}

app/assets/index.ejs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@
4141
},
4242
socket: {
4343
uaddr: '<%=uaddr%>',
44-
uport: '<%=uport%>'
44+
uport: '<%=uport%>',
45+
wss: <%=wss%>,
46+
preamble: '<%-preamble%>',
47+
heartbeat: <%=heartbeat%>
4548
}
4649
};
4750
//

app/unisys/client-network.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,22 @@ NETWORK.Connect = function (datalink, opt) {
8585

8686
// create websocket
8787
// uses values that were embedded in index.ejs on load
88-
let wsURI = `ws://${NETSOCK.uaddr}:${NETSOCK.uport}`;
88+
const wsHost = `${NETSOCK.uaddr}${NETSOCK.uport ? `:${NETSOCK.uport}` : ''}`;
89+
let wsURI = `${NETSOCK.wss ? 'wss' : 'ws'}://${wsHost}`;
90+
8991
NETSOCK.ws = new WebSocket(wsURI);
9092
if (DBG.connect) console.log(PR, 'OPEN SOCKET TO', wsURI);
9193

9294
// create listeners
9395
NETWORK.AddListener('open', function (event) {
9496
if (DBG.connect) console.log(PR, '..OPEN', event.target.url);
9597
m_status = M2_CONNECTED;
98+
99+
// If a preamble has been defined, send it upon opening the connection
100+
if (NETSOCK.preamble) {
101+
NETSOCK.ws.send(NETSOCK.preamble);
102+
}
103+
96104
// message handling continues in 'message' handler
97105
// the first message is assumed to be registration data
98106
});
@@ -153,7 +161,7 @@ function m_HandleRegistrationMessage(msgEvent) {
153161
// (4) network is initialized
154162
if (typeof m_options.success === 'function') m_options.success();
155163
// (5) initialize heartbeat timer
156-
m_ResetHearbeatTimer();
164+
if (NETSOCK.ws.heartbeat) m_ResetHearbeatTimer();
157165
}
158166
/// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
159167
/** When a heartbeat ping is received, respond with a pong to let the server

brunch-server.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,10 @@ module.exports = (config, callback) => {
111111
ukey,
112112
// socket address
113113
uaddr,
114-
uport
114+
uport,
115+
wss: false,
116+
preamble: null,
117+
heartbeat: true
115118
};
116119
res.render(indexFile, templateProps);
117120
// adding next() causes 'headers already sent' error

package-lock.json

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
"package:debug": "brunch watch -e package_debug -s",
1616
"clean": "rm -rf ./public ./node_modules && npm exec --workspaces -- npm run clean",
1717
"debug": "LOGGY_STACKS=true BRUNCH_DEVTOOLS=true ./brunch-debug watch --server",
18-
"log": "tail -f -n100 \"$(ls -at ./runtime/logs/* | head -n 1)\""
18+
"log": "tail -f -n100 \"$(ls -at ./runtime/logs/* | head -n 1)\"",
19+
"package-turbo360": "node @build-turbo360.js package-turbo360",
20+
"deploy-turbo360": "node @build-turbo360.js deploy-turbo360"
1921
},
2022
"repository": {
2123
"type": "git",
@@ -45,6 +47,7 @@
4547
"chokidar": "^3.5.3",
4648
"clean-css-brunch": "^2.10.0",
4749
"copycat-brunch": "^1.1.1",
50+
"dotenv": "^16.4.5",
4851
"ejs": "^3.1.9",
4952
"eslint": "^8.17.0",
5053
"eslint-config-prettier": "^8.5.0",

0 commit comments

Comments
 (0)