@polylith/builder 0.0.23 → 0.0.25
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/App.js +123 -59
- package/ConfigApp.js +24 -0
- package/ConfigFeature.js +23 -0
- package/Feature.js +2 -2
- package/index.js +3 -3
- package/package.json +2 -2
- package/plugin-loader.js +4 -7
- package/plugin-main-html.js +9 -15
- package/plugin-config.js +0 -29
package/App.js
CHANGED
|
@@ -1,55 +1,53 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import {readFile, writeFile, stat} from 'node:fs/promises';
|
|
3
3
|
|
|
4
4
|
import * as rollup from 'rollup';
|
|
5
5
|
import { babel } from '@rollup/plugin-babel';
|
|
6
6
|
import * as resolve from '@rollup/plugin-node-resolve';
|
|
7
7
|
import commonjs from '@rollup/plugin-commonjs';
|
|
8
|
-
import html from
|
|
8
|
+
import html from 'rollup-plugin-html';
|
|
9
9
|
|
|
10
10
|
import loader from './plugin-loader.js';
|
|
11
11
|
import mainHTML from './plugin-main-html.js';
|
|
12
12
|
import features from './plugin-features.js';
|
|
13
|
-
import config from './plugin-config.js';
|
|
14
13
|
import styles from "rollup-plugin-styles";
|
|
15
14
|
|
|
15
|
+
import ConfigFeature from './ConfigFeature.js';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* call this
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* @param {String} src the filename wqe
|
|
24
|
-
* @returns {String} the new path
|
|
18
|
+
* call this function to check if the given file exists
|
|
19
|
+
*
|
|
20
|
+
* @param {String} path the name of the file
|
|
21
|
+
* @returns {Promise<Boolean>} true if the file exists
|
|
25
22
|
*/
|
|
26
|
-
function fixPath(src) {
|
|
27
|
-
src = src.replace('file:', '');
|
|
28
|
-
src = src.replace('///', '');
|
|
29
|
-
src = src.replace(/.:/, '');
|
|
30
|
-
src = src.replace(/\\/g, '/');
|
|
31
23
|
|
|
32
|
-
|
|
24
|
+
async function fileExists(path) {
|
|
25
|
+
try {
|
|
26
|
+
await stat(path)
|
|
27
|
+
return true;
|
|
28
|
+
} catch (e) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
33
31
|
}
|
|
34
32
|
|
|
35
33
|
/**
|
|
36
34
|
* The base class for applications. Applications inherit from this class
|
|
37
35
|
*/
|
|
38
|
-
export class App {
|
|
36
|
+
export default class App {
|
|
39
37
|
/**
|
|
40
38
|
* Construct the app object.
|
|
41
|
-
*
|
|
39
|
+
*
|
|
42
40
|
* @param {String} name a name for the app
|
|
43
|
-
* @param {String} root the root directory of the project. All other
|
|
44
|
-
* paths will be relative to this path.
|
|
45
|
-
* @param {String} index the path to the main source file for the app. all
|
|
41
|
+
* @param {String} root the root directory of the project. All other
|
|
42
|
+
* paths will be relative to this path.
|
|
43
|
+
* @param {String} index the path to the main source file for the app. all
|
|
46
44
|
* source paths will be assumed to be relative to this path.
|
|
47
|
-
* @param {String} dest the path to the destination folder for the
|
|
45
|
+
* @param {String} dest the path to the destination folder for the
|
|
48
46
|
* rolled up files
|
|
49
47
|
*/
|
|
50
48
|
|
|
51
49
|
constructor(name, root, index , dest) {
|
|
52
|
-
root = fixPath(root);
|
|
50
|
+
root = App.fixPath(root);
|
|
53
51
|
this.root = root;
|
|
54
52
|
|
|
55
53
|
var filename = path.posix.join(root, index);
|
|
@@ -62,17 +60,35 @@ export class App {
|
|
|
62
60
|
|
|
63
61
|
this.loadables = [];
|
|
64
62
|
this.featureIndexes = [];
|
|
63
|
+
this.configs = {};
|
|
65
64
|
}
|
|
66
65
|
|
|
67
66
|
static fileToPath(filename) {
|
|
68
|
-
filename = fixPath(filename);
|
|
67
|
+
filename = App.fixPath(filename);
|
|
69
68
|
return path.posix.dirname(filename);
|
|
70
69
|
}
|
|
71
70
|
|
|
71
|
+
/**
|
|
72
|
+
* call this method to force the file path to use posix notation and remove
|
|
73
|
+
* all drive information.
|
|
74
|
+
*
|
|
75
|
+
*
|
|
76
|
+
* @param {String} src the filename wqe
|
|
77
|
+
* @returns {String} the new path
|
|
78
|
+
*/
|
|
79
|
+
static fixPath(src) {
|
|
80
|
+
src = src.replace('file:', '');
|
|
81
|
+
src = src.replace('///', '');
|
|
82
|
+
src = src.replace(/.:/, '');
|
|
83
|
+
src = src.replace(/\\/g, '/');
|
|
84
|
+
|
|
85
|
+
return src;
|
|
86
|
+
}
|
|
87
|
+
|
|
72
88
|
/**
|
|
73
89
|
* Call this method to generate a path relative to the src directory
|
|
74
|
-
*
|
|
75
|
-
* @param {String} path
|
|
90
|
+
*
|
|
91
|
+
* @param {String} fully qualified path
|
|
76
92
|
* @returns the path relative to the source root.
|
|
77
93
|
*/
|
|
78
94
|
rootPath(path) {
|
|
@@ -83,8 +99,12 @@ export class App {
|
|
|
83
99
|
return './' + path;
|
|
84
100
|
}
|
|
85
101
|
|
|
86
|
-
setHtmlTemplate(
|
|
87
|
-
this.htmlTemplate = {
|
|
102
|
+
setHtmlTemplate(source, destination) {
|
|
103
|
+
this.htmlTemplate = {source: source, destination: destination};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
addConfig(config, root) {
|
|
107
|
+
this.configs[root] = config;
|
|
88
108
|
}
|
|
89
109
|
|
|
90
110
|
// default implementation, applications will implement this to specify the loadable features to be used
|
|
@@ -92,25 +112,52 @@ export class App {
|
|
|
92
112
|
return [];
|
|
93
113
|
}
|
|
94
114
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
addFeatureMain(main) {
|
|
116
|
+
this.featureIndexes.push(main);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Call this method to add the feature to the app. Features are isolated
|
|
121
|
+
* pieces of code that are not a direct dependency of the main application.
|
|
122
|
+
*
|
|
123
|
+
* @param {String} root path relative to the source directory for the
|
|
124
|
+
* feature to load.
|
|
125
|
+
*/
|
|
126
|
+
async loadFeature(root) {
|
|
127
|
+
var featurePath = path.posix.join(this.sourcePath, root);
|
|
128
|
+
var indexPath = path.posix.join(featurePath, 'index.js')
|
|
129
|
+
var builderPath = path.posix.join(featurePath, 'build.js');
|
|
130
|
+
var jsonPath = path.posix.join(featurePath, 'build.json');
|
|
131
|
+
|
|
132
|
+
var indexExists = await fileExists(indexPath);
|
|
133
|
+
var builderExists = await fileExists(builderPath);
|
|
134
|
+
var jsonExists = await fileExists(jsonPath);
|
|
101
135
|
|
|
136
|
+
// If there is a builder, we will use this
|
|
102
137
|
if (builderExists) {
|
|
103
138
|
try {
|
|
104
|
-
|
|
105
|
-
|
|
139
|
+
let module = await import(builderPath)
|
|
140
|
+
let feature = module.default;
|
|
106
141
|
await feature.build(this);
|
|
107
142
|
} catch(e) {
|
|
108
|
-
console.error('error while building feature',
|
|
143
|
+
console.error('error while building feature', root);
|
|
109
144
|
console.log(e);
|
|
110
145
|
}
|
|
111
|
-
}
|
|
112
146
|
|
|
113
|
-
|
|
147
|
+
// second priority is a build configuration file.
|
|
148
|
+
} else if (jsonExists) {
|
|
149
|
+
try {
|
|
150
|
+
let content = JSON.parse(await readFile(jsonPath));
|
|
151
|
+
|
|
152
|
+
let builder = new ConfigFeature(content, featurePath);
|
|
153
|
+
await builder.build(this)
|
|
154
|
+
} catch (e) {
|
|
155
|
+
console.error(e);
|
|
156
|
+
throw e;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// if neither exist, assume the index should be added
|
|
160
|
+
} else if (indexExists) this.featureIndexes.push(indexPath);
|
|
114
161
|
}
|
|
115
162
|
|
|
116
163
|
async buildFeatures() {
|
|
@@ -118,23 +165,24 @@ export class App {
|
|
|
118
165
|
|
|
119
166
|
for (let feature of features) {
|
|
120
167
|
await(this.loadFeature(feature));
|
|
121
|
-
}
|
|
168
|
+
}
|
|
122
169
|
}
|
|
123
170
|
|
|
124
171
|
/* features will call this method if they want to add loadables
|
|
125
172
|
|
|
126
173
|
name - name of the loadable that we be passed to the load method
|
|
127
|
-
|
|
128
|
-
|
|
174
|
+
main - the relative path from the source folder to the entry point of the
|
|
175
|
+
loadable.
|
|
176
|
+
prefix - if given, the prefix on services created in this loadable.
|
|
129
177
|
The start and ready methods will be called on these services
|
|
130
178
|
*/
|
|
131
|
-
addLoadable(name,
|
|
132
|
-
var dest = path.posix.join(this.sourcePath,
|
|
179
|
+
addLoadable(name, main, prefix) {
|
|
180
|
+
var dest = path.posix.join(this.sourcePath, main);
|
|
133
181
|
|
|
134
|
-
console.log(dest)
|
|
182
|
+
console.log('addLoadable', {name, path: dest, prefix})
|
|
135
183
|
this.loadables.push({name, path: dest, prefix});
|
|
136
184
|
}
|
|
137
|
-
|
|
185
|
+
|
|
138
186
|
buildConfiguration() {
|
|
139
187
|
var input = [this.fullIndexPath];
|
|
140
188
|
this.loadables.forEach(function(path) {
|
|
@@ -152,33 +200,52 @@ export class App {
|
|
|
152
200
|
plugins: [
|
|
153
201
|
resolve.nodeResolve({
|
|
154
202
|
extensions: ['.js', '.jsx']
|
|
155
|
-
}),
|
|
156
|
-
commonjs(),
|
|
203
|
+
}),
|
|
204
|
+
commonjs(),
|
|
157
205
|
babel({
|
|
158
206
|
presets: ['@babel/preset-react'],
|
|
159
207
|
}),
|
|
160
208
|
loader(this.loadables),
|
|
161
209
|
features(this.featureIndexes),
|
|
162
|
-
config(),
|
|
163
210
|
html({
|
|
164
|
-
include: path.join(this.sourcePath, "**/*.html"),
|
|
211
|
+
include: path.join(this.sourcePath, "**/*.html"),
|
|
165
212
|
}),
|
|
166
|
-
styles(),
|
|
213
|
+
styles(),
|
|
167
214
|
mainHTML({
|
|
168
215
|
root: this.root,
|
|
169
|
-
|
|
170
|
-
|
|
216
|
+
source: this.htmlTemplate.source,
|
|
217
|
+
destination: this.htmlTemplate.destination,
|
|
171
218
|
replaceVars: {},
|
|
172
219
|
})
|
|
173
220
|
],
|
|
174
221
|
},
|
|
175
222
|
output : {
|
|
176
223
|
output : {
|
|
177
|
-
sourcemap: true,
|
|
224
|
+
sourcemap: true,
|
|
178
225
|
dir : this.destination,
|
|
179
226
|
format: 'es',
|
|
227
|
+
assetFileNames: function(chunkInfo) {
|
|
228
|
+
return '[name]-[hash][extname]';
|
|
229
|
+
},
|
|
230
|
+
entryFileNames: function(chunkInfo) {
|
|
231
|
+
var entry = App.fixPath(chunkInfo.facadeModuleId);
|
|
232
|
+
var found = this.loadables.find(function(loadable) {
|
|
233
|
+
return loadable.path === entry;
|
|
234
|
+
}, this);
|
|
235
|
+
var exists = Boolean(found);
|
|
236
|
+
|
|
237
|
+
if (exists) return (`${found.name}.js`);
|
|
238
|
+
if (entry === this.fullIndexPath) {
|
|
239
|
+
return `${this.name}.js`
|
|
240
|
+
}
|
|
241
|
+
return '[name].js';
|
|
242
|
+
}.bind(this),
|
|
243
|
+
manualChunks: function(id) {
|
|
244
|
+
if (id.includes('node_modules')) {
|
|
245
|
+
return 'vendor';
|
|
246
|
+
}
|
|
247
|
+
}
|
|
180
248
|
},
|
|
181
|
-
assetFileNames: "[name]-[hash][extname]",
|
|
182
249
|
}
|
|
183
250
|
};
|
|
184
251
|
|
|
@@ -189,12 +256,9 @@ export class App {
|
|
|
189
256
|
await this.buildFeatures();
|
|
190
257
|
var config = this.buildConfiguration();
|
|
191
258
|
|
|
192
|
-
console.log(JSON.stringify(config, null, ' '));
|
|
193
|
-
|
|
194
259
|
const bundle = await rollup.rollup(config.input);
|
|
195
260
|
await bundle.generate(config.output);
|
|
196
261
|
await bundle.write(config.output);
|
|
197
262
|
await bundle.close();
|
|
198
263
|
}
|
|
199
264
|
}
|
|
200
|
-
|
package/ConfigApp.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import App from './App';
|
|
2
|
+
import path from 'node:path/posix';
|
|
3
|
+
|
|
4
|
+
export default class ConfigApp extends App {
|
|
5
|
+
constructor (config, root) {
|
|
6
|
+
App.fixPath(root);
|
|
7
|
+
var name = config.name || 'unnamed';
|
|
8
|
+
var index = config.main || path.join(root, 'src', 'index.js');
|
|
9
|
+
var dest = config.dest || path.join(root, 'dist');
|
|
10
|
+
|
|
11
|
+
super(name, root, index, dest);
|
|
12
|
+
this.config = config;
|
|
13
|
+
|
|
14
|
+
if (!index.template || !index.template.source) throw new Error('html source not defined in config file');
|
|
15
|
+
var source = index.template.source;
|
|
16
|
+
var sourceFilename = path.basename(source);
|
|
17
|
+
var destination = index.template.destination || path.join(dest, sourceFilename)
|
|
18
|
+
this.setHtmlTemplate(source, destination)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async getFeatures() {
|
|
22
|
+
return this.config.features || [];
|
|
23
|
+
}
|
|
24
|
+
}
|
package/ConfigFeature.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import Feature from './Feature.js';
|
|
2
|
+
|
|
3
|
+
export default class ConfigFeature extends Feature {
|
|
4
|
+
constructor (config, root) {
|
|
5
|
+
super();
|
|
6
|
+
this.config = config;
|
|
7
|
+
this.root = root;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async build(app) {
|
|
11
|
+
var config = this.config;
|
|
12
|
+
|
|
13
|
+
if (config.loadables && Array.isArray(config.loadables)) {
|
|
14
|
+
config.loadables.forEach(function(loadable) {
|
|
15
|
+
if (loadable.name && loadable.main) {
|
|
16
|
+
app.addLoadable(loadable.name, loadable.main, loadable.prefix);
|
|
17
|
+
}
|
|
18
|
+
}, this);
|
|
19
|
+
}
|
|
20
|
+
if (config.main) app.addFeatureMain(config.main);
|
|
21
|
+
if (config.config) app.addConfig(config.config, this.root);
|
|
22
|
+
}
|
|
23
|
+
}
|
package/Feature.js
CHANGED
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import App from './App.js'
|
|
2
|
+
import Feature from './Feature.js';
|
|
3
3
|
|
|
4
|
-
export {App as App, Feature as Feature};
|
|
4
|
+
export {App as App, Feature as Feature};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polylith/builder",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.25",
|
|
4
4
|
"description": "The polylith builder",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"rollup": "^2.58.0",
|
|
23
23
|
"rollup-plugin-html": "^0.2.1",
|
|
24
24
|
"rollup-plugin-jsx": "^1.0.3",
|
|
25
|
-
"rollup-plugin-styles": "^
|
|
25
|
+
"rollup-plugin-styles": "^4.0.0",
|
|
26
26
|
"sass": "^1.43.4"
|
|
27
27
|
}
|
|
28
28
|
}
|
package/plugin-loader.js
CHANGED
|
@@ -15,14 +15,14 @@ function makeSource(loadables) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
var switchStr = `
|
|
18
|
-
case '${loadable.name}':
|
|
18
|
+
case '${loadable.name}':
|
|
19
19
|
promise = import('${loadable.path}')${prefixStr}
|
|
20
20
|
break;
|
|
21
|
-
`
|
|
21
|
+
`
|
|
22
22
|
loadableSwitches += switchStr;
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
-
var source =
|
|
25
|
+
var source =
|
|
26
26
|
`
|
|
27
27
|
import {registry} from '@polylith/core';
|
|
28
28
|
|
|
@@ -35,14 +35,12 @@ ${loadableSwitches}
|
|
|
35
35
|
return promise;
|
|
36
36
|
}
|
|
37
37
|
`
|
|
38
|
-
console.log(source);
|
|
39
38
|
return source;
|
|
40
39
|
}
|
|
41
40
|
|
|
42
|
-
|
|
43
41
|
export default function loader(loadables) {
|
|
44
42
|
return {
|
|
45
|
-
name: 'loader',
|
|
43
|
+
name: 'loader',
|
|
46
44
|
|
|
47
45
|
resolveId (source, _, third) {
|
|
48
46
|
if (source === '@polylith/loader') {
|
|
@@ -59,4 +57,3 @@ export default function loader(loadables) {
|
|
|
59
57
|
}
|
|
60
58
|
};
|
|
61
59
|
}
|
|
62
|
-
|
package/plugin-main-html.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import escapeStringRegexp from 'escape-string-regexp';
|
|
2
|
-
import
|
|
2
|
+
import {ensureFile} from 'fs-extra';
|
|
3
3
|
import path from 'path/posix';
|
|
4
|
+
import {readFile, writeFile} from 'node:fs/promises';
|
|
4
5
|
|
|
5
6
|
const INVALID_ARGS_ERROR =
|
|
6
7
|
"[plugin-main-html] You did not provide a template or target!";
|
|
@@ -22,20 +23,19 @@ function createScriptTags(scripts) {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export default function(options = {}) {
|
|
25
|
-
var { root,
|
|
26
|
+
var { root, source, destination, replaceVars } = options;
|
|
26
27
|
|
|
27
28
|
return {
|
|
28
29
|
name: "main-html-template",
|
|
29
30
|
|
|
30
31
|
async generateBundle(outputOptions, bundleInfo) {
|
|
31
|
-
// console.log(JSON.stringify(bundleInfo, null, ' '));
|
|
32
32
|
return new Promise(async function (resolve, reject) {
|
|
33
33
|
try {
|
|
34
34
|
var includes = [];
|
|
35
35
|
var names = Object.keys(bundleInfo);
|
|
36
36
|
var scripts;
|
|
37
37
|
|
|
38
|
-
if (!
|
|
38
|
+
if (!destination && !source) throw new Error(INVALID_ARGS_ERROR);
|
|
39
39
|
|
|
40
40
|
names.forEach(function(name) {
|
|
41
41
|
var entry = bundleInfo[name];
|
|
@@ -47,15 +47,11 @@ export default function(options = {}) {
|
|
|
47
47
|
scripts = createScriptTags(includes);
|
|
48
48
|
replaceVars["scripts"] = scripts;
|
|
49
49
|
|
|
50
|
-
var
|
|
51
|
-
var
|
|
50
|
+
var sourceFilePath = path.join(root, source);
|
|
51
|
+
var destinationFilePath = path.join(root, destination);
|
|
52
52
|
|
|
53
53
|
// Read the file
|
|
54
|
-
var
|
|
55
|
-
|
|
56
|
-
// Convert buffer to a string and replace the replaceable
|
|
57
|
-
// variables
|
|
58
|
-
var content = buffer.toString("utf8");
|
|
54
|
+
var content = await readFile(sourceFilePath, 'utf-8');
|
|
59
55
|
if (replaceVars) {
|
|
60
56
|
var varNames = Object.keys(replaceVars);
|
|
61
57
|
varNames.forEach(function(name) {
|
|
@@ -66,11 +62,9 @@ export default function(options = {}) {
|
|
|
66
62
|
});
|
|
67
63
|
}
|
|
68
64
|
|
|
69
|
-
var injected = content;
|
|
70
|
-
|
|
71
65
|
// write the injected template to a file
|
|
72
|
-
await
|
|
73
|
-
|
|
66
|
+
await ensureFile(destinationFilePath);
|
|
67
|
+
writeFile(destinationFilePath, content, 'utf-8');
|
|
74
68
|
resolve();
|
|
75
69
|
} catch (e) {
|
|
76
70
|
reject(e);
|
package/plugin-config.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import rollupPluginutils from ('rollup-pluginutils');
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export default function config() {
|
|
6
|
-
var opts = {};
|
|
7
|
-
|
|
8
|
-
opts.include = '**/*.pl-cfg'
|
|
9
|
-
|
|
10
|
-
var filter = rollupPluginutils.createFilter(opts.include, opts.exclude);
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
name: 'config',
|
|
14
|
-
|
|
15
|
-
resolveId (source, _, third) {
|
|
16
|
-
if (filter(source)) return source
|
|
17
|
-
|
|
18
|
-
return null;
|
|
19
|
-
},
|
|
20
|
-
|
|
21
|
-
async load(id) {
|
|
22
|
-
if (filter(id)) {
|
|
23
|
-
console.log(id);
|
|
24
|
-
return '';
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|