frontfire 0.1.3 → 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 +53 -74
- 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,87 +1,60 @@
|
|
|
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
|
-
|
|
24
|
+
let dirToDelete = isWatch ? 'debug' : 'release';
|
|
25
|
+
dirToDelete = `${rootBuildDir}${path.sep}${dirToDelete}`;
|
|
26
|
+
|
|
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 );
|
|
31
37
|
}
|
|
32
38
|
|
|
33
|
-
|
|
34
|
-
// It seems that the copy plugin requires normal slashes no matter what OS we are on
|
|
35
|
-
rootFilesToCopy.push( `src/` + rootFiles[ ri ].name );
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async function frontFire( isWatch )
|
|
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
|
{
|
|
54
|
+
fs.watchFile( `src${path.sep}index.html`, async ( curr, prev ) =>
|
|
55
|
+
{
|
|
56
|
+
const result = await ctx.rebuild();
|
|
57
|
+
});
|
|
85
58
|
await ctx.watch();
|
|
86
59
|
let { host, port } = await ctx.serve(
|
|
87
60
|
{
|
|
@@ -98,6 +71,14 @@ async function frontFire( isWatch )
|
|
|
98
71
|
path: req.url,
|
|
99
72
|
method: req.method,
|
|
100
73
|
headers: req.headers,
|
|
74
|
+
};
|
|
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;
|
|
101
82
|
}
|
|
102
83
|
|
|
103
84
|
// Check if path is a valid state route
|
|
@@ -108,15 +89,15 @@ async function frontFire( isWatch )
|
|
|
108
89
|
// If esbuild returns "not found", send a custom 404 page
|
|
109
90
|
if (proxyRes.statusCode === 404) {
|
|
110
91
|
res.writeHead(404, { 'Content-Type': 'text/html' })
|
|
111
|
-
res.end('<h1>A custom 404 page</h1>')
|
|
112
|
-
return
|
|
92
|
+
res.end('<h1>A custom 404 page</h1>');
|
|
93
|
+
return;
|
|
113
94
|
}
|
|
114
95
|
|
|
115
96
|
// Otherwise, forward the response from esbuild to the client
|
|
116
|
-
res.writeHead(proxyRes.statusCode, proxyRes.headers)
|
|
97
|
+
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
117
98
|
|
|
118
99
|
proxyRes.pipe(res, { end: true })
|
|
119
|
-
})
|
|
100
|
+
});
|
|
120
101
|
|
|
121
102
|
// Forward the body of the request to esbuild
|
|
122
103
|
req.pipe(proxyReq, { end: true })
|
|
@@ -130,6 +111,4 @@ async function frontFire( isWatch )
|
|
|
130
111
|
await ctx.rebuild();
|
|
131
112
|
ctx.dispose();
|
|
132
113
|
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
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();
|