frontfire 0.3.3 → 0.5.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/README.md +3 -3
- package/package.json +3 -1
- package/src/DefaultConfig.js +29 -6
- package/src/FrontFire.js +19 -5
- package/src/index.js +155 -0
- package/src/templates/po-index.js +4 -0
- package/src/templates/state-class.js +12 -0
- package/src/templates/state-template.html.js +1 -0
- package/src/templates/wc-index.js +32 -0
- package/src/templates/wc-template.html.js +2 -0
package/README.md
CHANGED
|
@@ -6,11 +6,11 @@ It is entirely built upon the great esbuild ecosystem.
|
|
|
6
6
|
|
|
7
7
|
## Logic
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Required structure of an InfrontJS project is as follows
|
|
10
10
|
|
|
11
11
|
- src/assets/**/*
|
|
12
12
|
- src/app/main.js
|
|
13
|
-
- src/app/
|
|
13
|
+
- src/app/main.css
|
|
14
14
|
- src/index.html
|
|
15
15
|
|
|
16
|
-
Entrypoint for building is main.js and
|
|
16
|
+
Entrypoint for building is main.js and main.css
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frontfire",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -23,11 +23,13 @@
|
|
|
23
23
|
"chalk": "^5.2.0",
|
|
24
24
|
"commander": "^10.0.0",
|
|
25
25
|
"conf": "^11.0.1",
|
|
26
|
+
"ejs": "^3.1.10",
|
|
26
27
|
"esbuild": "^0.19.5",
|
|
27
28
|
"esbuild-copy-static-files": "^0.1.0",
|
|
28
29
|
"esbuild-plugin-copy": "^2.0.2",
|
|
29
30
|
"fs-extra": "^11.1.1",
|
|
30
31
|
"lodash": "^4.17.21",
|
|
32
|
+
"luxon": "^3.5.0",
|
|
31
33
|
"php-server": "^1.0.0",
|
|
32
34
|
"prettier": "^2.8.4"
|
|
33
35
|
},
|
package/src/DefaultConfig.js
CHANGED
|
@@ -6,8 +6,33 @@ import path from "node:path";
|
|
|
6
6
|
import { copy } from "esbuild-plugin-copy";
|
|
7
7
|
import copyStaticFiles from "esbuild-copy-static-files";
|
|
8
8
|
|
|
9
|
+
let currentDir = path.dirname( '.' );
|
|
10
|
+
let rootDir = null;
|
|
11
|
+
const maxCount = 10;
|
|
12
|
+
let currentCount = 0;
|
|
13
|
+
while ( null === rootDir )
|
|
14
|
+
{
|
|
15
|
+
if ( fs.existsSync( currentDir + path.sep + 'package.json' ) )
|
|
16
|
+
{
|
|
17
|
+
rootDir = currentDir;
|
|
18
|
+
}
|
|
19
|
+
else
|
|
20
|
+
{
|
|
21
|
+
currentDir += '/..';
|
|
22
|
+
currentCount++;
|
|
23
|
+
if ( currentCount > maxCount ) {
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
9
28
|
|
|
10
|
-
|
|
29
|
+
if ( rootDir === null )
|
|
30
|
+
{
|
|
31
|
+
console.error( 'Too many recursions. Root directory not found.' );
|
|
32
|
+
exit;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const rootFiles = fs.readdirSync( `${rootDir}${path.sep}src${path.sep}`, { withFileTypes : true } );
|
|
11
36
|
const rootFilesToCopy = [];
|
|
12
37
|
for ( let ri = 0; ri < rootFiles.length; ri++ )
|
|
13
38
|
{
|
|
@@ -25,21 +50,19 @@ const buildDir = `build`;
|
|
|
25
50
|
const entryPoints = [
|
|
26
51
|
/*
|
|
27
52
|
"src/app/main.js",
|
|
28
|
-
"src/app/
|
|
53
|
+
"src/app/main.css"
|
|
29
54
|
*/
|
|
30
55
|
/*
|
|
31
56
|
path.resolve( './src/app/main.js' ),
|
|
32
|
-
path.resolve( './src/app/
|
|
57
|
+
path.resolve( './src/app/main.css' )
|
|
33
58
|
*/
|
|
34
59
|
`.${path.sep}src${path.sep}app${path.sep}main.js`,
|
|
35
|
-
`.${path.sep}src${path.sep}app${path.sep}
|
|
60
|
+
`.${path.sep}src${path.sep}app${path.sep}main.css`
|
|
36
61
|
];
|
|
37
62
|
|
|
38
63
|
const outDirDebug = `${buildDir}/debug/app/`
|
|
39
64
|
const outDirRelease = `${buildDir}/release/app`;
|
|
40
65
|
|
|
41
|
-
console.log( outDirRelease );
|
|
42
|
-
|
|
43
66
|
const staticAssetsDestDebug = `${buildDir}/debug/assets`;
|
|
44
67
|
const staticAssetsDestRelease = `${buildDir}/release/assets`;
|
|
45
68
|
|
package/src/FrontFire.js
CHANGED
|
@@ -6,6 +6,8 @@ import fse from "fs-extra";
|
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import * as child from "child_process";
|
|
8
8
|
|
|
9
|
+
import { DateTime } from "luxon";
|
|
10
|
+
|
|
9
11
|
import DEFAULT_CONFIG from "./DefaultConfig.js";
|
|
10
12
|
|
|
11
13
|
export default async function frontFire( isWatch, cfg = {} )
|
|
@@ -42,10 +44,12 @@ export default async function frontFire( isWatch, cfg = {} )
|
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
let esbuildOpts = null;
|
|
47
|
+
let serverOpts = null;
|
|
45
48
|
|
|
46
49
|
if ( true === isWatch )
|
|
47
50
|
{
|
|
48
51
|
esbuildOpts = _.get( config, 'debug.esbuild' );
|
|
52
|
+
serverOpts = _.get( config, 'debug.server' );
|
|
49
53
|
}
|
|
50
54
|
else
|
|
51
55
|
{
|
|
@@ -56,6 +60,8 @@ export default async function frontFire( isWatch, cfg = {} )
|
|
|
56
60
|
|
|
57
61
|
if ( true === isWatch )
|
|
58
62
|
{
|
|
63
|
+
const outerPort = serverOpts && serverOpts.hasOwnProperty( 'port' ) ? +serverOpts.port : 3000;
|
|
64
|
+
|
|
59
65
|
fs.watchFile( `src${path.sep}index.html`, async ( curr, prev ) =>
|
|
60
66
|
{
|
|
61
67
|
const result = await ctx.rebuild();
|
|
@@ -63,11 +69,14 @@ export default async function frontFire( isWatch, cfg = {} )
|
|
|
63
69
|
await ctx.watch();
|
|
64
70
|
let { host, port } = await ctx.serve(
|
|
65
71
|
{
|
|
66
|
-
servedir : `.${path.sep}${rootBuildDir}${path.sep}debug
|
|
72
|
+
servedir : `.${path.sep}${rootBuildDir}${path.sep}debug`,
|
|
73
|
+
// @todo use param for index.html
|
|
74
|
+
fallback : `.${path.sep}${rootBuildDir}${path.sep}debug${path.sep}index.html`
|
|
75
|
+
//onRequest : function ( ) { console.log( "Hello" ); }
|
|
67
76
|
}
|
|
68
77
|
);
|
|
69
78
|
|
|
70
|
-
// Then start a proxy server
|
|
79
|
+
// Then start a proxy server
|
|
71
80
|
http.createServer((req, res) => {
|
|
72
81
|
|
|
73
82
|
const options = {
|
|
@@ -75,7 +84,7 @@ export default async function frontFire( isWatch, cfg = {} )
|
|
|
75
84
|
port: port,
|
|
76
85
|
path: req.url,
|
|
77
86
|
method: req.method,
|
|
78
|
-
headers: req.headers
|
|
87
|
+
headers: req.headers
|
|
79
88
|
};
|
|
80
89
|
|
|
81
90
|
if ( 'php' === indexType && req.url === "/" && req.method.toLowerCase() === 'get' )
|
|
@@ -107,13 +116,18 @@ export default async function frontFire( isWatch, cfg = {} )
|
|
|
107
116
|
// Forward the body of the request to esbuild
|
|
108
117
|
req.pipe(proxyReq, { end: true })
|
|
109
118
|
|
|
110
|
-
}).listen(
|
|
119
|
+
}).listen( outerPort );
|
|
111
120
|
|
|
112
|
-
console.log( `> InfrontJS:http://localhost:${
|
|
121
|
+
console.log( `> InfrontJS:http://localhost:${outerPort}` );
|
|
113
122
|
}
|
|
114
123
|
else
|
|
115
124
|
{
|
|
116
125
|
await ctx.rebuild();
|
|
117
126
|
ctx.dispose();
|
|
127
|
+
|
|
128
|
+
// CACHEBREAK
|
|
129
|
+
let indexContent = fs.readFileSync( `${rootBuildDir}${path.sep}release${path.sep}index.html`, { encoding: 'utf8', flag: 'r' } );
|
|
130
|
+
const changedContent = indexContent.replace( /IFJSCACHEBREAK/g, (DateTime.now()).valueOf() );
|
|
131
|
+
fs.writeFileSync( `${rootBuildDir}${path.sep}release${path.sep}index.html`, changedContent );
|
|
118
132
|
}
|
|
119
133
|
};
|
package/src/index.js
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
|
+
import ejs from "ejs";
|
|
5
|
+
import chalk from "chalk";
|
|
4
6
|
|
|
5
7
|
import _ from "lodash";
|
|
6
8
|
import prettier from "prettier";
|
|
7
9
|
import { program } from "commander";
|
|
10
|
+
import path from "node:path";
|
|
8
11
|
|
|
9
12
|
import frontFire from "./FrontFire.js";
|
|
10
13
|
import defaultConfig from "./DefaultConfig.js";
|
|
11
14
|
|
|
15
|
+
import wcIndex from "./templates/wc-index.js";
|
|
16
|
+
import wcTemplate from "./templates/wc-template.html.js";
|
|
17
|
+
import stateClass from "./templates/state-class.js";
|
|
18
|
+
import stateTemplate from "./templates/state-template.html.js";
|
|
19
|
+
import poIndex from "./templates/po-index.js";
|
|
20
|
+
|
|
12
21
|
async function performInit()
|
|
13
22
|
{
|
|
14
23
|
// Deep Copy
|
|
@@ -27,8 +36,131 @@ async function performInit()
|
|
|
27
36
|
}
|
|
28
37
|
)
|
|
29
38
|
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function createInfrontJsStarter( appName = null )
|
|
42
|
+
{
|
|
43
|
+
// Deep Copy
|
|
44
|
+
const initConfig = JSON.parse( JSON.stringify( defaultConfig ) );
|
|
45
|
+
|
|
46
|
+
_.unset( initConfig, 'debug.esbuild.plugins' );
|
|
47
|
+
_.unset( initConfig, 'release.esbuild.plugins' );
|
|
48
|
+
|
|
49
|
+
if ( null === appName || appName.length === 0 )
|
|
50
|
+
{
|
|
51
|
+
appName = 'InfrontJS Starter';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const srcFolder = path.resolve( '.' ) + path.separator + 'src-to-test';
|
|
55
|
+
|
|
56
|
+
if ( true === fs.existsSync( srcFolder ) )
|
|
57
|
+
{
|
|
58
|
+
console.warn( `Sourcefolder ${srcFolder} already exists!` );
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function generatesPathObject( name )
|
|
64
|
+
{
|
|
65
|
+
let fileName = null;
|
|
66
|
+
let poName = null;
|
|
67
|
+
|
|
68
|
+
fileName = name.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
|
|
69
|
+
poName = fileName.charAt( 0 ).toUpperCase() + fileName.slice( 1 );
|
|
70
|
+
|
|
71
|
+
const poFilename = path.resolve( '.' ) + path.sep + poName + '.js';
|
|
72
|
+
if ( true === fs.existsSync( poFilename ) )
|
|
73
|
+
{
|
|
74
|
+
console.error( `File "${poFilename}" already exists!` );
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
fs.writeFileSync(
|
|
79
|
+
poFilename,
|
|
80
|
+
ejs.render( poIndex, { poName: poName } )
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
console.log( chalk.green.bold( `PathObject ${poName} successfully generated.`) );
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function generatesState( name, options )
|
|
87
|
+
{
|
|
88
|
+
let fileName = null;
|
|
89
|
+
let stateName = null;
|
|
90
|
+
let stateId = null;
|
|
91
|
+
|
|
92
|
+
fileName = name.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
|
|
93
|
+
stateName = fileName.charAt( 0 ).toUpperCase() + fileName.slice( 1 );
|
|
94
|
+
stateId = stateName.replace(/[A-Z]/g, (match, offset) => (offset > 0 ? '-' : '') + match.toLowerCase());
|
|
95
|
+
|
|
96
|
+
const stateFilename = path.resolve( '.' ) + path.sep + stateName + 'State.js';
|
|
97
|
+
if ( true === fs.existsSync( stateFilename ) )
|
|
98
|
+
{
|
|
99
|
+
console.error( `File "${stateFilename}" already exists!` );
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const stateTemplatename = path.resolve( '.' ) + path.sep + stateName + 'Template.html';
|
|
104
|
+
if ( true === options.template && true === fs.existsSync( stateTemplatename ) )
|
|
105
|
+
{
|
|
106
|
+
console.error( `File "${stateTemplatename}" already exists!` );
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
fs.writeFileSync(
|
|
111
|
+
stateFilename,
|
|
112
|
+
ejs.render( stateClass, { stateName: stateName, stateId : stateId } )
|
|
113
|
+
);
|
|
114
|
+
fs.writeFileSync(
|
|
115
|
+
stateTemplatename,
|
|
116
|
+
ejs.render( stateTemplate, { stateName: stateName } )
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
console.log( chalk.green.bold( `State ${stateName} successfully generated.`) );
|
|
120
|
+
console.log( chalk.italic( 'Dont forget to add the state to your states instance, e.g.' ) );
|
|
121
|
+
console.log( chalk.italic.bgWhite( `myApp.states.add( ${stateName} );`) );
|
|
122
|
+
}
|
|
30
123
|
|
|
124
|
+
async function generatesWebComponent( name = null )
|
|
125
|
+
{
|
|
126
|
+
let fileName = null;
|
|
127
|
+
let className = null;
|
|
128
|
+
let wcName = null;
|
|
31
129
|
|
|
130
|
+
// Deep Copy
|
|
131
|
+
const initConfig = JSON.parse( JSON.stringify( defaultConfig ) );
|
|
132
|
+
|
|
133
|
+
_.unset( initConfig, 'debug.esbuild.plugins' );
|
|
134
|
+
_.unset( initConfig, 'release.esbuild.plugins' );
|
|
135
|
+
|
|
136
|
+
if ( null === name || name.length === 0 )
|
|
137
|
+
{
|
|
138
|
+
console.error( 'V')
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
fileName = name.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
|
|
142
|
+
className = fileName.charAt( 0 ).toUpperCase() + fileName.slice( 1 );
|
|
143
|
+
wcName = name.replace(/[A-Z]/g, (match, offset) => (offset > 0 ? '-' : '') + match.toLowerCase());
|
|
144
|
+
fileName = fileName.charAt(0).toLowerCase() + fileName.slice(1);
|
|
145
|
+
|
|
146
|
+
const srcFolder = path.resolve( '.' ) + path.sep + fileName;
|
|
147
|
+
if ( true === fs.existsSync( srcFolder ) )
|
|
148
|
+
{
|
|
149
|
+
console.error( `Folder "${srcFolder}" already exists!` );
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
fs.mkdirSync ( srcFolder ) ;
|
|
154
|
+
fs.writeFileSync(
|
|
155
|
+
srcFolder + path.sep + 'index.js',
|
|
156
|
+
ejs.render( wcIndex, { wcName: wcName, className: className } )
|
|
157
|
+
);
|
|
158
|
+
fs.writeFileSync(
|
|
159
|
+
srcFolder + path.sep + 'template.js',
|
|
160
|
+
ejs.render( wcTemplate, { wcName: wcName } )
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
console.log( chalk.green.bold( `Web component ${wcName} successfully created.` ) );
|
|
32
164
|
}
|
|
33
165
|
|
|
34
166
|
// Try to load custom config
|
|
@@ -61,6 +193,29 @@ program
|
|
|
61
193
|
.description( 'Creates frontfire default configuration file in current directory.' )
|
|
62
194
|
.action( function() { performInit(); } );
|
|
63
195
|
|
|
196
|
+
program
|
|
197
|
+
.command( 'create' )
|
|
198
|
+
.description( 'Creates starter InfrontJS application.' )
|
|
199
|
+
.action( function() { createInfrontJsStarter(); } );
|
|
200
|
+
|
|
201
|
+
program
|
|
202
|
+
.command( 'gwc' )
|
|
203
|
+
.argument( '<name>', 'Name of web component.' )
|
|
204
|
+
.description( 'Generates a webcomponent with specific name.' )
|
|
205
|
+
.action( function( name ) { generatesWebComponent( name ); } );
|
|
206
|
+
|
|
207
|
+
program
|
|
208
|
+
.command( 'gs' )
|
|
209
|
+
.argument( '<name>', 'Name of state.' )
|
|
210
|
+
.option( '-nt, --no-template', 'No template is generated. By default, an empty template for the State is autogenerated.' )
|
|
211
|
+
.description( 'Generates a new state.' )
|
|
212
|
+
.action( function( name, options ) { generatesState( name, options ); } );
|
|
213
|
+
|
|
214
|
+
program
|
|
215
|
+
.command( 'gpo' )
|
|
216
|
+
.argument( '<name>', 'Name of path object.' )
|
|
217
|
+
.description( 'Generates a new path object.' )
|
|
218
|
+
.action( function( name ) { generatesPathObject( name ); } );
|
|
64
219
|
|
|
65
220
|
program
|
|
66
221
|
.command( 'build' )
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export default 'import { BaseState } from "infrontjs";\n' +
|
|
2
|
+
'import template from \'./<%= stateName %>Template.html\';\n' +
|
|
3
|
+
'export class <%= stateName %> extends BaseState\n' +
|
|
4
|
+
'{\n' +
|
|
5
|
+
' static ROUTE = "/<%= stateId %>";\n' +
|
|
6
|
+
' static ID = "<%= stateId %>";\n' +
|
|
7
|
+
'\n' +
|
|
8
|
+
' async enter()\n' +
|
|
9
|
+
' {\n' +
|
|
10
|
+
' console.log( "Hello from state <%= stateName %>" );\n' +
|
|
11
|
+
' }\n' +
|
|
12
|
+
'}';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default '<h1>Hello from State <%= stateName %>!</h1>';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export default '' +
|
|
2
|
+
'// import * as IF from "infrontjs";\n' +
|
|
3
|
+
'import template from "./template.html";\n' +
|
|
4
|
+
'class <%= className %> extends HTMLElement\n' +
|
|
5
|
+
'{\n' +
|
|
6
|
+
' constructor()\n' +
|
|
7
|
+
' {\n' +
|
|
8
|
+
' super();\n' +
|
|
9
|
+
' this._isConnected = false;\n' +
|
|
10
|
+
' }\n' +
|
|
11
|
+
'\n' +
|
|
12
|
+
' connectedCallback()\n' +
|
|
13
|
+
' {\n' +
|
|
14
|
+
' if ( false === this._isConnected )\n' +
|
|
15
|
+
' {\n' +
|
|
16
|
+
' // Resolve default InfrontJS instance\n' +
|
|
17
|
+
' // this.app = IF.App.get();\n' +
|
|
18
|
+
' this.render();\n' +
|
|
19
|
+
'\n' +
|
|
20
|
+
' this._isConnected = true;\n' +
|
|
21
|
+
' }\n' +
|
|
22
|
+
' }\n' +
|
|
23
|
+
'\n' +
|
|
24
|
+
' render()\n' +
|
|
25
|
+
' {\n' +
|
|
26
|
+
' // Eg. Render template\n' +
|
|
27
|
+
' // this.innerHTML = this.app.view.getHtml( template, { user : this.app.user } );\n' +
|
|
28
|
+
' this.innerHTML = template;\n' +
|
|
29
|
+
' }\n' +
|
|
30
|
+
'}\n' +
|
|
31
|
+
'\n' +
|
|
32
|
+
'customElements.define(<%= wcName %>, <%= className %> );'
|