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 CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "frontfire",
3
- "version": "0.1.4",
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,93 +1,59 @@
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;
31
- }
24
+ let dirToDelete = isWatch ? 'debug' : 'release';
25
+ dirToDelete = `${rootBuildDir}${path.sep}${dirToDelete}`;
32
26
 
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
- }
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
- 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
  {
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
- 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();