frontfire 0.1.4 → 0.2.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/package.json +7 -3
- package/src/DefaultConfig.js +112 -0
- package/src/FrontFire.js +48 -93
- package/src/index.js +57 -4
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frontfire",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "src/index.js",
|
|
6
|
+
"type": "module",
|
|
6
7
|
"scripts": {
|
|
7
8
|
"start": "node src/index.js",
|
|
8
9
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -22,9 +23,12 @@
|
|
|
22
23
|
"chalk": "^5.2.0",
|
|
23
24
|
"commander": "^10.0.0",
|
|
24
25
|
"conf": "^11.0.1",
|
|
25
|
-
"esbuild": "^0.17.
|
|
26
|
+
"esbuild": "^0.17.8",
|
|
26
27
|
"esbuild-copy-static-files": "^0.1.0",
|
|
27
|
-
"esbuild-plugin-copy": "^2.0.2"
|
|
28
|
+
"esbuild-plugin-copy": "^2.0.2",
|
|
29
|
+
"lodash": "^4.17.21",
|
|
30
|
+
"php-server": "^1.0.0",
|
|
31
|
+
"prettier": "^2.8.4"
|
|
28
32
|
},
|
|
29
33
|
"bin": {
|
|
30
34
|
"frontfire": "src/index.js"
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Core
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
// Plugins
|
|
6
|
+
import { copy } from "esbuild-plugin-copy";
|
|
7
|
+
import copyStaticFiles from "esbuild-copy-static-files";
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const rootFiles = fs.readdirSync( `src${path.sep}`, { withFileTypes : true } );
|
|
11
|
+
const rootFilesToCopy = [];
|
|
12
|
+
for ( let ri = 0; ri < rootFiles.length; ri++ )
|
|
13
|
+
{
|
|
14
|
+
if ( rootFiles[ ri ].isDirectory() )
|
|
15
|
+
{
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Note
|
|
20
|
+
// It seems that the copy plugin requires normal slashes no matter what OS we are on
|
|
21
|
+
rootFilesToCopy.push( `src/` + rootFiles[ ri ].name );
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const buildDir = 'build';
|
|
25
|
+
const entryPoints = [
|
|
26
|
+
`src${path.sep}app${path.sep}main.js`,
|
|
27
|
+
`src${path.sep}app${path.sep}app.css`
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const outDirDebug = `${buildDir}${path.sep}debug${path.sep}app${path.sep}`
|
|
31
|
+
const outDirRelease = `${buildDir}${path.sep}release${path.sep}app${path.sep}`;
|
|
32
|
+
|
|
33
|
+
const staticAssetsDestDebug = `${buildDir}${path.sep}debug${path.sep}assets`;
|
|
34
|
+
const staticAssetsDestRelease = `${buildDir}${path.sep}release${path.sep}assets`;
|
|
35
|
+
|
|
36
|
+
export default {
|
|
37
|
+
"buildDir" : buildDir,
|
|
38
|
+
"debug" : {
|
|
39
|
+
"server" : {
|
|
40
|
+
"indexType" : "html",
|
|
41
|
+
"port" : 3000
|
|
42
|
+
},
|
|
43
|
+
"esbuild" : {
|
|
44
|
+
bundle: true,
|
|
45
|
+
sourcemap: true,
|
|
46
|
+
minify: false,
|
|
47
|
+
logLevel: "info",
|
|
48
|
+
entryPoints : entryPoints,
|
|
49
|
+
outdir : outDirDebug,
|
|
50
|
+
loader: {
|
|
51
|
+
".html" : "text",
|
|
52
|
+
".png" : "file"
|
|
53
|
+
},
|
|
54
|
+
banner : {
|
|
55
|
+
js: "(() => { (new EventSource(\"/esbuild\")).addEventListener('change', () => location.reload() ); })();"
|
|
56
|
+
},
|
|
57
|
+
plugins: [
|
|
58
|
+
copy({
|
|
59
|
+
resolveFrom : 'cwd',
|
|
60
|
+
assets: [
|
|
61
|
+
{
|
|
62
|
+
from: rootFilesToCopy,
|
|
63
|
+
to: [`${buildDir}${path.sep}debug` ]
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}),
|
|
67
|
+
copyStaticFiles({
|
|
68
|
+
src: 'src/assets',
|
|
69
|
+
dest: staticAssetsDestDebug,
|
|
70
|
+
dereference: true,
|
|
71
|
+
errorOnExist: false,
|
|
72
|
+
preserveTimestamps: true,
|
|
73
|
+
recursive: true
|
|
74
|
+
})
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
"release" : {
|
|
79
|
+
"esbuild" : {
|
|
80
|
+
bundle: true,
|
|
81
|
+
sourcemap: true,
|
|
82
|
+
minify: true,
|
|
83
|
+
logLevel: "error",
|
|
84
|
+
entryPoints : entryPoints,
|
|
85
|
+
outdir : outDirRelease,
|
|
86
|
+
loader: {
|
|
87
|
+
".html" : "text",
|
|
88
|
+
".png" : "file"
|
|
89
|
+
},
|
|
90
|
+
plugins: [
|
|
91
|
+
copy({
|
|
92
|
+
resolveFrom : 'cwd',
|
|
93
|
+
assets: [
|
|
94
|
+
{
|
|
95
|
+
from: rootFilesToCopy,
|
|
96
|
+
to: [`${buildDir}${path.sep}release` ]
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
}),
|
|
100
|
+
copyStaticFiles({
|
|
101
|
+
src: 'src/assets',
|
|
102
|
+
dest: staticAssetsDestRelease,
|
|
103
|
+
dereference: true,
|
|
104
|
+
errorOnExist: false,
|
|
105
|
+
preserveTimestamps: true,
|
|
106
|
+
recursive: true
|
|
107
|
+
})
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
};
|
package/src/FrontFire.js
CHANGED
|
@@ -1,93 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import _ from "lodash";
|
|
2
|
+
import esbuild from "esbuild";
|
|
3
|
+
import http from "node:http";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import * as child from "child_process";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
import DEFAULT_CONFIG from "./DefaultConfig.js";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
export default async function frontFire( isWatch, cfg = {} )
|
|
11
11
|
{
|
|
12
|
-
|
|
12
|
+
const config = _.merge( DEFAULT_CONFIG, cfg );
|
|
13
|
+
|
|
14
|
+
const indexType = _.get( config, 'debug.server.indexType', 'html' );
|
|
15
|
+
|
|
16
|
+
const rootBuildDir = _.get( config, 'buildDir', null );
|
|
17
|
+
if ( null === rootBuildDir )
|
|
13
18
|
{
|
|
14
|
-
|
|
15
|
-
fs.rmSync( rootBuildDir, { recursive: true, force: true } );
|
|
19
|
+
throw new Error( 'No valid buildDir.' );
|
|
16
20
|
}
|
|
17
|
-
}
|
|
18
|
-
catch( ie )
|
|
19
|
-
{
|
|
20
|
-
// Fail silently
|
|
21
|
-
console.error( ie );
|
|
22
|
-
}
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
const rootFilesToCopy = [];
|
|
26
|
-
for ( let ri = 0; ri < rootFiles.length; ri++ )
|
|
27
|
-
{
|
|
28
|
-
if ( rootFiles[ ri ].isDirectory() )
|
|
22
|
+
try
|
|
29
23
|
{
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
let dirToDelete = isWatch ? 'debug' : 'release';
|
|
25
|
+
dirToDelete = `${rootBuildDir}${path.sep}${dirToDelete}`;
|
|
32
26
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
27
|
+
if ( fs.statSync( dirToDelete ) )
|
|
28
|
+
{
|
|
29
|
+
console.log( "Cleaning build directory: " + dirToDelete );
|
|
30
|
+
fs.rmSync( dirToDelete, { recursive: true, force: true } );
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch( ie )
|
|
34
|
+
{
|
|
35
|
+
// Fail silently
|
|
36
|
+
console.error( ie );
|
|
37
|
+
}
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
let opts = {
|
|
41
|
-
// esbuild options
|
|
42
|
-
bundle: true,
|
|
43
|
-
sourcemap: true,
|
|
44
|
-
minify: isWatch ? false : true,
|
|
45
|
-
logLevel: isWatch ? "info" : "error",
|
|
46
|
-
entryPoints : [ `src${path.sep}app${path.sep}main.js`, `src${path.sep}app${path.sep}app.css` ],
|
|
47
|
-
outdir : isWatch ? `${rootBuildDir}${path.sep}debug${path.sep}app${path.sep}` : `${rootBuildDir}${path.sep}release${path.sep}app${path.sep}`,
|
|
48
|
-
loader: {
|
|
49
|
-
".html" : "text",
|
|
50
|
-
".png" : "file"
|
|
51
|
-
},
|
|
52
|
-
plugins: [
|
|
53
|
-
copy({
|
|
54
|
-
resolveFrom : 'cwd',
|
|
55
|
-
assets: [
|
|
56
|
-
{
|
|
57
|
-
from: rootFilesToCopy,
|
|
58
|
-
to: [ isWatch ? `${rootBuildDir}${path.sep}debug` : `${rootBuildDir}${path.sep}release` ]
|
|
59
|
-
}
|
|
60
|
-
]
|
|
61
|
-
}),
|
|
62
|
-
copyStaticFiles({
|
|
63
|
-
src: 'src/assets',
|
|
64
|
-
dest: isWatch ? `${rootBuildDir}${path.sep}debug${path.sep}assets` : `${rootBuildDir}${path.sep}release${path.sep}assets`,
|
|
65
|
-
dereference: true,
|
|
66
|
-
errorOnExist: false,
|
|
67
|
-
preserveTimestamps: true,
|
|
68
|
-
recursive: true
|
|
69
|
-
})
|
|
70
|
-
]
|
|
71
|
-
|
|
72
|
-
};
|
|
39
|
+
let esbuildOpts = null;
|
|
73
40
|
|
|
74
41
|
if ( true === isWatch )
|
|
75
42
|
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
43
|
+
esbuildOpts = _.get( config, 'debug.esbuild' );
|
|
44
|
+
}
|
|
45
|
+
else
|
|
46
|
+
{
|
|
47
|
+
esbuildOpts = _.get( config, 'release.esbuild' );
|
|
79
48
|
}
|
|
80
49
|
|
|
81
|
-
let ctx = await esbuild.context(
|
|
50
|
+
let ctx = await esbuild.context( esbuildOpts );
|
|
82
51
|
|
|
83
52
|
if ( true === isWatch )
|
|
84
53
|
{
|
|
85
|
-
console.log( "Adding additional watcher..." );
|
|
86
54
|
fs.watchFile( `src${path.sep}index.html`, async ( curr, prev ) =>
|
|
87
55
|
{
|
|
88
|
-
console.log( "Index.html changed..." );
|
|
89
56
|
const result = await ctx.rebuild();
|
|
90
|
-
console.log( result );
|
|
91
57
|
});
|
|
92
58
|
await ctx.watch();
|
|
93
59
|
let { host, port } = await ctx.serve(
|
|
@@ -96,17 +62,6 @@ async function frontFire( isWatch )
|
|
|
96
62
|
}
|
|
97
63
|
);
|
|
98
64
|
|
|
99
|
-
|
|
100
|
-
let sseResponse = null;
|
|
101
|
-
/*
|
|
102
|
-
// DOES NOT WORK
|
|
103
|
-
setInterval( () =>
|
|
104
|
-
{
|
|
105
|
-
console.log( "Sending sse..." );
|
|
106
|
-
sseResponse.write( 'data: esbuild' );
|
|
107
|
-
}, 5000 );
|
|
108
|
-
*/
|
|
109
|
-
|
|
110
65
|
// Then start a proxy server on port 3000
|
|
111
66
|
http.createServer((req, res) => {
|
|
112
67
|
|
|
@@ -116,8 +71,15 @@ async function frontFire( isWatch )
|
|
|
116
71
|
path: req.url,
|
|
117
72
|
method: req.method,
|
|
118
73
|
headers: req.headers,
|
|
119
|
-
}
|
|
74
|
+
};
|
|
120
75
|
|
|
76
|
+
if ( 'php' === indexType && req.url === "/" && req.method.toLowerCase() === 'get' )
|
|
77
|
+
{
|
|
78
|
+
const indexHtml = child.execSync( `php src${path.sep}index.php`);
|
|
79
|
+
res.writeHead( 200, { 'Content-Type': 'text/html' });
|
|
80
|
+
res.end( indexHtml.toString() );
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
121
83
|
|
|
122
84
|
// Check if path is a valid state route
|
|
123
85
|
// then pass it as "index.html" to the server
|
|
@@ -127,17 +89,12 @@ async function frontFire( isWatch )
|
|
|
127
89
|
// If esbuild returns "not found", send a custom 404 page
|
|
128
90
|
if (proxyRes.statusCode === 404) {
|
|
129
91
|
res.writeHead(404, { 'Content-Type': 'text/html' })
|
|
130
|
-
res.end('<h1>A custom 404 page</h1>')
|
|
131
|
-
return
|
|
92
|
+
res.end('<h1>A custom 404 page</h1>');
|
|
93
|
+
return;
|
|
132
94
|
}
|
|
133
95
|
|
|
134
96
|
// Otherwise, forward the response from esbuild to the client
|
|
135
|
-
res.writeHead(proxyRes.statusCode, proxyRes.headers)
|
|
136
|
-
|
|
137
|
-
if ( req.url === '/esbuild' )
|
|
138
|
-
{
|
|
139
|
-
sseResponse = res;
|
|
140
|
-
}
|
|
97
|
+
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
141
98
|
|
|
142
99
|
proxyRes.pipe(res, { end: true })
|
|
143
100
|
});
|
|
@@ -154,6 +111,4 @@ async function frontFire( isWatch )
|
|
|
154
111
|
await ctx.rebuild();
|
|
155
112
|
ctx.dispose();
|
|
156
113
|
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
module.exports = frontFire;
|
|
114
|
+
};
|
package/src/index.js
CHANGED
|
@@ -1,16 +1,69 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
|
|
5
|
+
import _ from "lodash";
|
|
6
|
+
import prettier from "prettier";
|
|
7
|
+
import { program } from "commander";
|
|
8
|
+
|
|
9
|
+
import frontFire from "./FrontFire.js";
|
|
10
|
+
import defaultConfig from "./DefaultConfig.js";
|
|
11
|
+
|
|
12
|
+
async function performInit()
|
|
13
|
+
{
|
|
14
|
+
// Deep Copy
|
|
15
|
+
const initConfig = JSON.parse( JSON.stringify( defaultConfig ) );
|
|
16
|
+
|
|
17
|
+
_.unset( initConfig, 'debug.esbuild.plugins' );
|
|
18
|
+
_.unset( initConfig, 'release.esbuild.plugins' );
|
|
19
|
+
|
|
20
|
+
fs.writeFileSync(
|
|
21
|
+
'frontfire.json',
|
|
22
|
+
prettier.format(
|
|
23
|
+
JSON.stringify( initConfig ),
|
|
24
|
+
{
|
|
25
|
+
semi: false,
|
|
26
|
+
parser: "json"
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Try to load custom config
|
|
33
|
+
let customConfig = null;
|
|
34
|
+
|
|
35
|
+
if ( fs.statSync( 'frontfire.json' ) )
|
|
36
|
+
{
|
|
37
|
+
customConfig = fs.readFileSync( 'frontfire.json' );
|
|
38
|
+
if ( customConfig )
|
|
39
|
+
{
|
|
40
|
+
try
|
|
41
|
+
{
|
|
42
|
+
customConfig = JSON.parse( customConfig );
|
|
43
|
+
}
|
|
44
|
+
catch( e )
|
|
45
|
+
{
|
|
46
|
+
console.warn( 'Cannot read frontfire.json' );
|
|
47
|
+
customConfig = null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
4
51
|
|
|
5
52
|
program
|
|
6
53
|
.command( 'run-dev' )
|
|
7
54
|
.description( 'Running development server.' )
|
|
8
|
-
.action( function() {frontFire( true ); } );
|
|
55
|
+
.action( function() { frontFire( true, customConfig ); } );
|
|
56
|
+
|
|
57
|
+
program
|
|
58
|
+
.command( 'init' )
|
|
59
|
+
.description( 'Creates frontfire default configuration file in current directory.' )
|
|
60
|
+
.action( function() { performInit(); } );
|
|
61
|
+
|
|
9
62
|
|
|
10
63
|
program
|
|
11
64
|
.command( 'build' )
|
|
12
65
|
.description( 'Building for production.' )
|
|
13
|
-
.action( function() {frontFire( false ); } );
|
|
66
|
+
.action( function() { frontFire( false, customConfig ); } );
|
|
14
67
|
|
|
15
68
|
|
|
16
69
|
program.parse();
|