frontfire 0.1.4 → 0.2.3

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.
@@ -0,0 +1,27 @@
1
+ name: Publish to NPM
2
+ on:
3
+ release:
4
+ types: [created]
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ matrix:
10
+ node-version: [ 16.x ]
11
+ steps:
12
+ - name: Checkout
13
+ uses: actions/checkout@v3
14
+
15
+ - name: Setup Node
16
+ uses: actions/setup-node@v3
17
+ with:
18
+ node-version: '16.x'
19
+ registry-url: 'https://registry.npmjs.org'
20
+
21
+ - name: Install dependencies 🔧
22
+ run: npm install
23
+
24
+ - name: Publish package on NPM 📦
25
+ run: npm publish
26
+ env:
27
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 InfrontJS
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2023 InfrontJS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "frontfire",
3
- "version": "0.1.4",
3
+ "version": "0.2.3",
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,13 @@
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
+ "fs-extra": "^11.1.1",
30
+ "lodash": "^4.17.21",
31
+ "php-server": "^1.0.0",
32
+ "prettier": "^2.8.4"
28
33
  },
29
34
  "bin": {
30
35
  "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,64 @@
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 fse from "fs-extra";
6
+ import path from "node:path";
7
+ import * as child from "child_process";
7
8
 
8
- const rootBuildDir = 'build';
9
+ import DEFAULT_CONFIG from "./DefaultConfig.js";
9
10
 
10
- try
11
+ export default async function frontFire( isWatch, cfg = {} )
11
12
  {
12
- if ( fs.statSync( rootBuildDir ) )
13
+ const config = _.merge( DEFAULT_CONFIG, cfg );
14
+
15
+ const indexType = _.get( config, 'debug.server.indexType', 'html' );
16
+
17
+ const rootBuildDir = _.get( config, 'buildDir', null );
18
+ if ( null === rootBuildDir )
13
19
  {
14
- console.log( "Cleaning build directory: " + rootBuildDir );
15
- fs.rmSync( rootBuildDir, { recursive: true, force: true } );
20
+ throw new Error( 'No valid buildDir.' );
16
21
  }
17
- }
18
- catch( ie )
19
- {
20
- // Fail silently
21
- console.error( ie );
22
- }
23
22
 
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() )
23
+ fse.ensureDirSync( rootBuildDir );
24
+ fse.ensureDirSync( `${rootBuildDir}${path.sep}debug` );
25
+ fse.ensureDirSync( `${rootBuildDir}${path.sep}release` );
26
+
27
+ try
29
28
  {
30
- continue;
31
- }
29
+ let dirToDelete = isWatch ? 'debug' : 'release';
30
+ dirToDelete = `${rootBuildDir}${path.sep}${dirToDelete}`;
32
31
 
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
- }
32
+ if ( fs.statSync( dirToDelete ) )
33
+ {
34
+ console.log( "Cleaning build directory: " + dirToDelete );
35
+ fs.rmSync( dirToDelete, { recursive: true, force: true } );
36
+ }
37
+ }
38
+ catch( ie )
39
+ {
40
+ // Fail silently
41
+ console.error( ie );
42
+ }
37
43
 
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
- };
44
+ let esbuildOpts = null;
73
45
 
74
46
  if ( true === isWatch )
75
47
  {
76
- opts[ "banner" ] = {
77
- js: "(() => { (new EventSource(\"/esbuild\")).addEventListener('change', () => location.reload() ); })();"
78
- };
48
+ esbuildOpts = _.get( config, 'debug.esbuild' );
49
+ }
50
+ else
51
+ {
52
+ esbuildOpts = _.get( config, 'release.esbuild' );
79
53
  }
80
54
 
81
- let ctx = await esbuild.context( opts );
55
+ let ctx = await esbuild.context( esbuildOpts );
82
56
 
83
57
  if ( true === isWatch )
84
58
  {
85
- console.log( "Adding additional watcher..." );
86
59
  fs.watchFile( `src${path.sep}index.html`, async ( curr, prev ) =>
87
60
  {
88
- console.log( "Index.html changed..." );
89
61
  const result = await ctx.rebuild();
90
- console.log( result );
91
62
  });
92
63
  await ctx.watch();
93
64
  let { host, port } = await ctx.serve(
@@ -96,17 +67,6 @@ async function frontFire( isWatch )
96
67
  }
97
68
  );
98
69
 
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
70
  // Then start a proxy server on port 3000
111
71
  http.createServer((req, res) => {
112
72
 
@@ -116,8 +76,15 @@ async function frontFire( isWatch )
116
76
  path: req.url,
117
77
  method: req.method,
118
78
  headers: req.headers,
119
- }
79
+ };
120
80
 
81
+ if ( 'php' === indexType && req.url === "/" && req.method.toLowerCase() === 'get' )
82
+ {
83
+ const indexHtml = child.execSync( `php src${path.sep}index.php`);
84
+ res.writeHead( 200, { 'Content-Type': 'text/html' });
85
+ res.end( indexHtml.toString() );
86
+ return;
87
+ }
121
88
 
122
89
  // Check if path is a valid state route
123
90
  // then pass it as "index.html" to the server
@@ -127,17 +94,12 @@ async function frontFire( isWatch )
127
94
  // If esbuild returns "not found", send a custom 404 page
128
95
  if (proxyRes.statusCode === 404) {
129
96
  res.writeHead(404, { 'Content-Type': 'text/html' })
130
- res.end('<h1>A custom 404 page</h1>')
131
- return
97
+ res.end('<h1>A custom 404 page</h1>');
98
+ return;
132
99
  }
133
100
 
134
101
  // 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
- }
102
+ res.writeHead(proxyRes.statusCode, proxyRes.headers);
141
103
 
142
104
  proxyRes.pipe(res, { end: true })
143
105
  });
@@ -154,6 +116,4 @@ async function frontFire( isWatch )
154
116
  await ctx.rebuild();
155
117
  ctx.dispose();
156
118
  }
157
- }
158
-
159
- module.exports = frontFire;
119
+ };
package/src/index.js CHANGED
@@ -1,16 +1,71 @@
1
1
  #! /usr/bin/env node
2
- const { program } = require( 'commander' );
3
- const frontFire = require( "./FrontFire.js" );
4
-
5
- program
6
- .command( 'run-dev' )
7
- .description( 'Running development server.' )
8
- .action( function() {frontFire( true ); } );
9
-
10
- program
11
- .command( 'build' )
12
- .description( 'Building for production.' )
13
- .action( function() {frontFire( false ); } );
14
-
15
-
16
- program.parse();
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
+ }
33
+
34
+ // Try to load custom config
35
+ let customConfig = null;
36
+
37
+ if ( fs.statSync( 'frontfire.json', { "throwIfNoEntry": false } ) )
38
+ {
39
+ customConfig = fs.readFileSync( 'frontfire.json' );
40
+ if ( customConfig )
41
+ {
42
+ try
43
+ {
44
+ customConfig = JSON.parse( customConfig );
45
+ }
46
+ catch( e )
47
+ {
48
+ console.warn( 'Cannot read frontfire.json' );
49
+ customConfig = null;
50
+ }
51
+ }
52
+ }
53
+
54
+ program
55
+ .command( 'run-dev' )
56
+ .description( 'Running development server.' )
57
+ .action( function() { frontFire( true, customConfig ); } );
58
+
59
+ program
60
+ .command( 'init' )
61
+ .description( 'Creates frontfire default configuration file in current directory.' )
62
+ .action( function() { performInit(); } );
63
+
64
+
65
+ program
66
+ .command( 'build' )
67
+ .description( 'Building for production.' )
68
+ .action( function() { frontFire( false, customConfig ); } );
69
+
70
+
71
+ program.parse();