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 CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "frontfire",
3
- "version": "0.1.3",
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.4",
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
- const esbuild = require( "esbuild" );
2
- const { copy } = require( "esbuild-plugin-copy" );
3
- const copyStaticFiles = require( "esbuild-copy-static-files" );
4
- const http = require( "node:http" );
5
- const fs = require( 'node:fs' );
6
- const path = require( 'node:path' );
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
- const rootBuildDir = 'build';
8
+ import DEFAULT_CONFIG from "./DefaultConfig.js";
9
9
 
10
- try
10
+ export default async function frontFire( isWatch, cfg = {} )
11
11
  {
12
- if ( fs.statSync( rootBuildDir ) )
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
- console.log( "Cleaning build directory: " + rootBuildDir );
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
- const rootFiles = fs.readdirSync( `src${path.sep}`, { withFileTypes : true } );
25
- const rootFilesToCopy = [];
26
- for ( let ri = 0; ri < rootFiles.length; ri++ )
27
- {
28
- if ( rootFiles[ ri ].isDirectory() )
22
+ try
29
23
  {
30
- continue;
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
- // Note
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
- opts[ "banner" ] = {
77
- js: "(() => { (new EventSource(\"/esbuild\")).addEventListener('change', () => location.reload()); })();"
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( opts );
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
- const { program } = require( 'commander' );
3
- const frontFire = require( "./FrontFire.js" );
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();