@polylith/builder 0.0.37 → 0.0.40
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 +194 -102
- package/ConfigApp.js +23 -9
- package/ConfigFeature.js +1 -0
- package/Files.js +79 -48
- package/index.js +8 -1
- package/package.json +1 -1
- package/plugin-config.js +44 -0
- package/plugin-copy-resources.js +9 -7
- package/plugin-features.js +0 -3
- package/plugin-jsconfig.js +8 -28
- package/plugin-loader.js +3 -3
- package/plugin-main-html.js +45 -47
- package/types.js +60 -0
- package/utils.js +24 -3
package/App.js
CHANGED
|
@@ -7,33 +7,19 @@ import * as resolve from '@rollup/plugin-node-resolve';
|
|
|
7
7
|
import commonjs from '@rollup/plugin-commonjs';
|
|
8
8
|
import html from 'rollup-plugin-html';
|
|
9
9
|
import livereload from 'rollup-plugin-livereload';
|
|
10
|
+
import styles from "rollup-plugin-styles";
|
|
10
11
|
|
|
11
12
|
import loader from './plugin-loader.js';
|
|
12
13
|
import mainHTML from './plugin-main-html.js';
|
|
13
14
|
import features from './plugin-features.js';
|
|
14
|
-
import styles from "rollup-plugin-styles";
|
|
15
15
|
import resources from "./plugin-copy-resources.js";
|
|
16
16
|
import jsconfig from "./plugin-jsconfig.js";
|
|
17
|
+
import loadConfigs from "./plugin-config.js";
|
|
17
18
|
|
|
19
|
+
import {forceToPosix, fileExists} from './utils.js'
|
|
18
20
|
import ConfigFeature from './ConfigFeature.js';
|
|
19
21
|
import Files from './Files.js';
|
|
20
22
|
|
|
21
|
-
/**
|
|
22
|
-
* call this function to check if the given file exists
|
|
23
|
-
*
|
|
24
|
-
* @param {String} path the name of the file
|
|
25
|
-
* @returns {Promise<Boolean>} true if the file exists
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
async function fileExists(path) {
|
|
29
|
-
try {
|
|
30
|
-
await stat(path)
|
|
31
|
-
return true;
|
|
32
|
-
} catch (e) {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
23
|
/**
|
|
38
24
|
* The base class for applications. Applications inherit from this class
|
|
39
25
|
*/
|
|
@@ -42,16 +28,15 @@ export default class App {
|
|
|
42
28
|
* Construct the app object.
|
|
43
29
|
*
|
|
44
30
|
* @param {String} name a name for the app
|
|
45
|
-
* @param {String} root the root directory of the project.
|
|
46
|
-
*
|
|
31
|
+
* @param {String} root the full path to the root directory of the project.
|
|
32
|
+
* All other paths will be relative to this path.
|
|
47
33
|
* @param {String} index the relative path to the main source file from the
|
|
48
34
|
* root. All source paths will be assumed to be relative to this path.
|
|
49
35
|
* @param {String} dest the relative path to the destination folder from the
|
|
50
36
|
* root for rolled up files
|
|
51
37
|
*/
|
|
52
|
-
|
|
53
38
|
constructor(name, root, index, dest) {
|
|
54
|
-
root =
|
|
39
|
+
root = forceToPosix(root);
|
|
55
40
|
this.root = root;
|
|
56
41
|
|
|
57
42
|
var filename = path.posix.join(root, index);
|
|
@@ -65,34 +50,65 @@ export default class App {
|
|
|
65
50
|
this.loadables = [];
|
|
66
51
|
this.features = [];
|
|
67
52
|
this.featureIndexes = [];
|
|
68
|
-
this.configs =
|
|
53
|
+
this.configs = [];
|
|
69
54
|
this.manualChunkType = 'function';
|
|
70
55
|
this.manualChunks = [];
|
|
71
56
|
this.files = new Files(this.sourcePath, this.destPath);
|
|
57
|
+
this.cssSpecs = [];
|
|
72
58
|
this.cssFiles = [];
|
|
73
59
|
this.liveReload = true;
|
|
60
|
+
this.templateVariables = {};
|
|
61
|
+
this.ns = name.replace(/[- ]+/g, '_').toUpperCase();
|
|
62
|
+
this.codeVariables = {};
|
|
74
63
|
}
|
|
75
64
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Call this method to set the code variable name space. An object with this
|
|
67
|
+
* name will be attached to the window object with the code variables as
|
|
68
|
+
* members. The default value for the name space is the app name in upper
|
|
69
|
+
* snake case.
|
|
70
|
+
*
|
|
71
|
+
* @param {String} ns the name space name for added code variables. This
|
|
72
|
+
* must be a valid JavaScript identifier.
|
|
73
|
+
*/
|
|
74
|
+
setNamespace(ns) {
|
|
75
|
+
this.ns = ns;
|
|
79
76
|
}
|
|
80
77
|
|
|
81
78
|
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
79
|
+
* Call this method to add a code variable to the output html file. This
|
|
80
|
+
* variable will be added the namsespace for the app.
|
|
84
81
|
*
|
|
82
|
+
* @param {String} name the name of tyhe variable. This must be a valid
|
|
83
|
+
* JavaScript identifier.
|
|
84
|
+
* @param {*} value the value of the variable to set. This can be any type
|
|
85
|
+
* that can be serialized through JSON.
|
|
86
|
+
*/
|
|
87
|
+
addCodeVariable(name, value) {
|
|
88
|
+
this.codeVariables[name] = value;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Call this method to get the replacement value for ${codeVariables}. This
|
|
93
|
+
* will be the code that adds all the codeVariables to the namespace.
|
|
85
94
|
*
|
|
86
|
-
* @
|
|
87
|
-
|
|
95
|
+
* @returns {String} the replacement value for the codeVariables template
|
|
96
|
+
* variable;
|
|
88
97
|
*/
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
98
|
+
getCodeVariablesValue() {
|
|
99
|
+
var names = Object.keys(this.codeVariables);
|
|
100
|
+
if (names.length === 0) return '';
|
|
101
|
+
|
|
102
|
+
var members = names.map(function(name) {
|
|
103
|
+
return ` ${name}: ${JSON.stringify(this.codeVariables[name])},`
|
|
104
|
+
}, this);
|
|
94
105
|
|
|
95
|
-
|
|
106
|
+
var codeBlock =
|
|
107
|
+
` window.${this.ns} = {
|
|
108
|
+
${members.join('\n')}
|
|
109
|
+
}
|
|
110
|
+
`;
|
|
111
|
+
return codeBlock;
|
|
96
112
|
}
|
|
97
113
|
|
|
98
114
|
/**
|
|
@@ -109,23 +125,72 @@ export default class App {
|
|
|
109
125
|
return './' + path;
|
|
110
126
|
}
|
|
111
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Call this method with true to reload the browser when any files in the
|
|
130
|
+
* destination folder have changed.
|
|
131
|
+
*
|
|
132
|
+
* @param {Bollean} on set to true to turn on destination watching
|
|
133
|
+
*/
|
|
112
134
|
setLiveReload(on) {
|
|
113
135
|
this.liveReload = on;
|
|
114
136
|
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Call this method to set the template for the main application html. This
|
|
140
|
+
* template file must have the required replacement strings for basic
|
|
141
|
+
* functionality. Call setTemplateVariable to create application specific
|
|
142
|
+
* repalcement values.
|
|
143
|
+
*
|
|
144
|
+
* @param {String} source the relative path from the application root to the
|
|
145
|
+
* html template
|
|
146
|
+
* @param {String} destination the relative path to the destination file
|
|
147
|
+
*/
|
|
115
148
|
setHtmlTemplate(source, destination) {
|
|
116
149
|
this.htmlTemplate = {source: source, destination: destination};
|
|
117
150
|
}
|
|
118
151
|
|
|
119
|
-
|
|
120
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Call this method to set the value of a template variable. Template
|
|
154
|
+
* variables specify a location in the html template where the value will be
|
|
155
|
+
* inserted. To specify where the value should be inserted in the template
|
|
156
|
+
* file add the string "${variableName}" in the location.
|
|
157
|
+
*
|
|
158
|
+
* @param {*} name
|
|
159
|
+
* @param {*} value
|
|
160
|
+
*/
|
|
161
|
+
setTemplateVariable(name, value) {
|
|
162
|
+
this.templateVariables[name] = value;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Call this to add a configuration object to the application
|
|
167
|
+
* @param {Object} config a configuration object that will be added to the
|
|
168
|
+
* configuration store. Use get from @polylith/config to access
|
|
169
|
+
*/
|
|
170
|
+
addConfig(config) {
|
|
171
|
+
this.configs.push(config);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Call this method to add specifications for application css files These
|
|
176
|
+
* css files will be included in the html template
|
|
177
|
+
*
|
|
178
|
+
* @param {ResourceSpecList} specs the specification for the css files. These
|
|
179
|
+
* will also be added as resources to be copied.
|
|
180
|
+
*/
|
|
181
|
+
addMainCss(specs) {
|
|
182
|
+
this.cssSpecs = [...this.cssSpecs, ...specs];
|
|
121
183
|
}
|
|
122
184
|
|
|
123
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Call this method to find all the css files specified by the css specs
|
|
187
|
+
*/
|
|
188
|
+
async findMainCss() {
|
|
124
189
|
var files = new Files(this.sourcePath, this.destPath)
|
|
125
190
|
|
|
126
|
-
//
|
|
127
|
-
|
|
128
|
-
files.
|
|
191
|
+
// Find all the files frem the added css speces
|
|
192
|
+
this.cssSpecs.forEach(function(spec) {
|
|
193
|
+
files.addResourceSpec('', spec);
|
|
129
194
|
}, this)
|
|
130
195
|
|
|
131
196
|
var expanded = await files.findAllFiles();
|
|
@@ -136,35 +201,37 @@ export default class App {
|
|
|
136
201
|
}, this);
|
|
137
202
|
|
|
138
203
|
// now add them to be copied
|
|
139
|
-
this.addResources('',
|
|
204
|
+
this.addResources('', this.cssSpecs);
|
|
140
205
|
}
|
|
141
206
|
|
|
142
207
|
/**
|
|
143
208
|
* Call this method to add a list of resources that will be moved to the
|
|
144
|
-
* destination path when the application is built.
|
|
145
|
-
* feature root, or the source path
|
|
209
|
+
* destination path when the application is built.
|
|
146
210
|
*
|
|
147
|
-
* @param {
|
|
211
|
+
* @param {String} root the relative path from the source root to the path
|
|
212
|
+
* to the origin of the caller. This will either be a feature root, or
|
|
213
|
+
* empty for the main applicatio the source pathPaths specified in the
|
|
214
|
+
* resource spec are assumed to be relative to this.-
|
|
215
|
+
* @param {Array<ReourceSpec>} resourceSpecs the copy specs
|
|
148
216
|
* for all the resources being added.
|
|
149
|
-
* @param {String} root the path to the origin of the caller. Paths in
|
|
150
|
-
* the spec are assumed to be relative to this.
|
|
151
217
|
*/
|
|
152
218
|
addResources(root, resourceSpecs) {
|
|
153
219
|
resourceSpecs.forEach(function(spec) {
|
|
154
|
-
this.files.
|
|
220
|
+
this.files.addResourceSpec(root, spec);
|
|
155
221
|
}, this)
|
|
156
222
|
}
|
|
157
223
|
|
|
158
224
|
/**
|
|
159
225
|
* Call this method to add a feature to the application. This method is
|
|
160
226
|
* given a path to the root of the feature. At build time the builder will
|
|
161
|
-
* look directory for a file named build.js and if found
|
|
162
|
-
* call the default function passing it a pointner to this
|
|
227
|
+
* look in the feature directory for a file named build.js and if found
|
|
228
|
+
* import it and call the default function passing it a pointner to this
|
|
229
|
+
* object.
|
|
163
230
|
*
|
|
164
231
|
* If there is no build.js file the builder will look for a build.json file.
|
|
165
232
|
* If present that json will be loaded and used to build the feature.
|
|
166
233
|
*
|
|
167
|
-
* If that is not found it will look for an index.js file
|
|
234
|
+
* If that is not found it will look for an index.js file, and if found it
|
|
168
235
|
* will add that to the list of feature index files which will be
|
|
169
236
|
* automatically imported when the built code imports the @polylith/features
|
|
170
237
|
* module
|
|
@@ -223,54 +290,53 @@ export default class App {
|
|
|
223
290
|
}
|
|
224
291
|
|
|
225
292
|
/**
|
|
226
|
-
*
|
|
227
|
-
* default.
|
|
293
|
+
* This is called by rollup if no manual chunk specifiers are added,
|
|
228
294
|
*
|
|
229
|
-
* @param {String}
|
|
295
|
+
* @param {String} filename this is the filename of the current file being
|
|
230
296
|
* processed by rollup
|
|
231
297
|
*
|
|
232
298
|
* @returns {String} the chunk name if there is a match
|
|
233
299
|
*/
|
|
234
|
-
defaultManualChunks(
|
|
235
|
-
if (
|
|
300
|
+
defaultManualChunks(filename) {
|
|
301
|
+
if (filename.includes('node_modules')) {
|
|
236
302
|
return 'vendor';
|
|
237
303
|
}
|
|
238
304
|
}
|
|
239
305
|
|
|
240
306
|
/**
|
|
241
|
-
* This is called when manual chunk specifications have been added
|
|
242
|
-
* array.
|
|
307
|
+
* This is called by rollup when manual chunk specifications have been added
|
|
308
|
+
* as an array.
|
|
243
309
|
*
|
|
244
|
-
* @param {String}
|
|
310
|
+
* @param {String} filename this is the filename of the current file being
|
|
245
311
|
* processed by rollup
|
|
246
|
-
* @returns {String} the name
|
|
312
|
+
* @returns {String} the name oo the chunk if there is a matching chunk
|
|
247
313
|
* name specifier
|
|
248
314
|
*/
|
|
249
|
-
handleManualChunksArray(
|
|
250
|
-
var
|
|
315
|
+
handleManualChunksArray(filename) {
|
|
316
|
+
var posixFilename = forceToPosix(filename);
|
|
251
317
|
var result = this.manualChunks.find(function(spec) {
|
|
252
|
-
return
|
|
318
|
+
return posixFilename.includes(spec.includes);
|
|
253
319
|
})
|
|
254
320
|
|
|
255
321
|
if (result) return result.name;
|
|
256
322
|
}
|
|
257
323
|
|
|
258
324
|
/**
|
|
259
|
-
* This is called when the manual chunk specifiers are functions.
|
|
260
|
-
* registered function is called in the reverse order to how they were
|
|
325
|
+
* This is called by rollup when the manual chunk specifiers are functions.
|
|
326
|
+
* Each registered function is called in the reverse order to how they were
|
|
261
327
|
* added.
|
|
262
328
|
*
|
|
263
|
-
* @param {String}
|
|
329
|
+
* @param {String} filename this is the filename of the current file being
|
|
264
330
|
* processed by rollup
|
|
265
331
|
* @returns the chunk name if any of the callbacks return one
|
|
266
332
|
*/
|
|
267
|
-
handleManualChunksCallbacks(
|
|
268
|
-
var
|
|
333
|
+
handleManualChunksCallbacks(filename) {
|
|
334
|
+
var posixFilename = forceToPosix(filename);
|
|
269
335
|
if (this.manualChunks.length === 0) {
|
|
270
|
-
return this.defaultManualChunks(
|
|
336
|
+
return this.defaultManualChunks(posixFilename);
|
|
271
337
|
} else {
|
|
272
|
-
for (
|
|
273
|
-
var result =
|
|
338
|
+
for (chunk of this.manualChunks) {
|
|
339
|
+
var result = chunk(posixFilename);
|
|
274
340
|
if (result) return result;
|
|
275
341
|
}
|
|
276
342
|
}
|
|
@@ -343,40 +409,62 @@ export default class App {
|
|
|
343
409
|
|
|
344
410
|
/**
|
|
345
411
|
*
|
|
412
|
+
* @param {String} root the relative path from the source root to the
|
|
413
|
+
* feature directory. Loadable paths are assumed to be relative to this
|
|
414
|
+
* directory
|
|
346
415
|
* @param {String} name unique name of the loadable that will be passed to
|
|
347
416
|
* the load method
|
|
348
|
-
* @param {String}
|
|
349
|
-
* point of the loadable.
|
|
417
|
+
* @param {String} index the relative path from the source folder to the
|
|
418
|
+
* entry point of the loadable.
|
|
350
419
|
* @param {String} [prefix] if given, the prefix on services created in
|
|
351
420
|
* this loadable. When the loadable has been loaded, the start and
|
|
352
421
|
* ready methods will be called on all services starting with this
|
|
353
422
|
* prefix.
|
|
354
|
-
* @param {
|
|
355
|
-
* css files that will included when the
|
|
423
|
+
* @param {ResourceSpecList} [css] if give, it will be a list of resource
|
|
424
|
+
* specifications for the css files that will be included when the
|
|
425
|
+
* module is loaded
|
|
426
|
+
*/
|
|
427
|
+
async addLoadable(root, name, index, prefix, css) {
|
|
428
|
+
var indexPath = path.posix.join(this.sourcePath, index);
|
|
429
|
+
this.loadables.push({name, index: indexPath, prefix, root, css});
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Call this method to locate all the css files for a loadable. These css
|
|
434
|
+
* files will be loaded into the browser when this loadable has been loaded
|
|
435
|
+
*
|
|
436
|
+
* @param {Loadable} loadable
|
|
356
437
|
*/
|
|
357
|
-
async
|
|
358
|
-
|
|
359
|
-
var cssUris = css ? [] : undefined;
|
|
360
|
-
if (css) {
|
|
438
|
+
async findLoadableCss(loadable) {
|
|
439
|
+
if (loadable.css) {
|
|
361
440
|
var files = new Files(this.sourcePath, this.destPath)
|
|
362
|
-
css.forEach(function(spec) {
|
|
363
|
-
files.
|
|
441
|
+
loadable.css.forEach(function(spec) {
|
|
442
|
+
files.addResourceSpec(loadable.root, spec);
|
|
364
443
|
}, this)
|
|
444
|
+
|
|
365
445
|
var expanded = await files.findAllFiles();
|
|
366
446
|
var keys = Object.keys(expanded);
|
|
367
|
-
|
|
447
|
+
|
|
448
|
+
var cssUris = keys.map(function(key){
|
|
368
449
|
var file = expanded[key];
|
|
369
|
-
|
|
450
|
+
return file.uri
|
|
370
451
|
}, this)
|
|
371
|
-
}
|
|
372
452
|
|
|
373
|
-
|
|
374
|
-
|
|
453
|
+
loadable.css = cssUris;
|
|
454
|
+
}
|
|
375
455
|
}
|
|
376
456
|
|
|
377
|
-
|
|
378
|
-
|
|
457
|
+
/**
|
|
458
|
+
* Call this method to build the template variable for the main html css
|
|
459
|
+
* files
|
|
460
|
+
*
|
|
461
|
+
* @returns {Promise<String>} the value of the mainCss template variable
|
|
462
|
+
*/
|
|
463
|
+
async buildMainCss() {
|
|
379
464
|
var cssTags = '';
|
|
465
|
+
|
|
466
|
+
await this.findMainCss();
|
|
467
|
+
|
|
380
468
|
this.cssFiles.forEach(function(uri) {
|
|
381
469
|
cssTags += ` <link rel="stylesheet" href="${uri}"></link>`
|
|
382
470
|
}, this);
|
|
@@ -385,25 +473,28 @@ export default class App {
|
|
|
385
473
|
}
|
|
386
474
|
|
|
387
475
|
/**
|
|
388
|
-
* The build method calls this
|
|
389
|
-
* object
|
|
476
|
+
* The build method calls this to create the rollup configuration object
|
|
390
477
|
*
|
|
391
478
|
* @returns {Object} rollup configuration object
|
|
392
479
|
*/
|
|
393
480
|
|
|
394
|
-
buildConfiguration() {
|
|
481
|
+
async buildConfiguration() {
|
|
395
482
|
var input = [this.fullIndexPath];
|
|
396
|
-
this.loadables.forEach(function(spec) {
|
|
397
|
-
input.push(spec.path);
|
|
398
|
-
});
|
|
399
483
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
484
|
+
// using a for loop because we are making an async call
|
|
485
|
+
for (let loadable of this.loadables) {
|
|
486
|
+
// find all the css files for the loadables
|
|
487
|
+
await this.findLoadableCss(loadable);
|
|
488
|
+
input.push(loadable.index);
|
|
403
489
|
}
|
|
404
490
|
|
|
405
491
|
var manualChunks = this.getManualChunks();
|
|
406
|
-
var mainCss = this.buildMainCss();
|
|
492
|
+
var mainCss = await this.buildMainCss();
|
|
493
|
+
var codeVariables = this.getCodeVariablesValue();
|
|
494
|
+
|
|
495
|
+
this.templateVariables['mainCss'] = mainCss;
|
|
496
|
+
this.templateVariables['codeVariables'] = codeVariables;
|
|
497
|
+
|
|
407
498
|
var plugins = [
|
|
408
499
|
resolve.nodeResolve({
|
|
409
500
|
extensions: ['.js', '.jsx']
|
|
@@ -413,6 +504,7 @@ export default class App {
|
|
|
413
504
|
presets: ['@babel/preset-react'],
|
|
414
505
|
babelHelpers: 'bundled',
|
|
415
506
|
}),
|
|
507
|
+
loadConfigs(this.configs),
|
|
416
508
|
loader(this.loadables),
|
|
417
509
|
features(this.featureIndexes),
|
|
418
510
|
jsconfig(this.root),
|
|
@@ -424,7 +516,7 @@ export default class App {
|
|
|
424
516
|
root: this.root,
|
|
425
517
|
source: this.htmlTemplate.source,
|
|
426
518
|
destination: this.htmlTemplate.destination,
|
|
427
|
-
|
|
519
|
+
templateVars: this.templateVariables,
|
|
428
520
|
}),
|
|
429
521
|
resources(this.name, this.files)
|
|
430
522
|
];
|
|
@@ -449,9 +541,9 @@ export default class App {
|
|
|
449
541
|
return '[name]-[hash][extname]';
|
|
450
542
|
},
|
|
451
543
|
entryFileNames: function(chunkInfo) {
|
|
452
|
-
var entry =
|
|
544
|
+
var entry = forceToPosix(chunkInfo.facadeModuleId);
|
|
453
545
|
var found = this.loadables.find(function(loadable) {
|
|
454
|
-
return loadable.
|
|
546
|
+
return loadable.index === entry;
|
|
455
547
|
}, this);
|
|
456
548
|
var exists = Boolean(found);
|
|
457
549
|
|
|
@@ -478,7 +570,7 @@ export default class App {
|
|
|
478
570
|
|
|
479
571
|
async build() {
|
|
480
572
|
await this.buildFeatures();
|
|
481
|
-
this.config = this.buildConfiguration();
|
|
573
|
+
this.config = await this.buildConfiguration();
|
|
482
574
|
|
|
483
575
|
const bundle = await rollup.rollup(this.config.input);
|
|
484
576
|
await bundle.generate(this.config.output);
|
package/ConfigApp.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import App from './App.js';
|
|
2
2
|
import path from 'node:path/posix';
|
|
3
|
+
import {forceToPosix} from './utils.js'
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* This class is used to build an application from a configuration file.
|
|
7
|
+
*/
|
|
4
8
|
export default class ConfigApp extends App {
|
|
5
9
|
constructor (config, root) {
|
|
6
|
-
root =
|
|
10
|
+
root = forceToPosix(root);
|
|
7
11
|
var name = config.name || 'unnamed';
|
|
8
|
-
var index = config.index ||
|
|
9
|
-
var dest = config.dest ||
|
|
12
|
+
var index = config.index || 'src/index.js';
|
|
13
|
+
var dest = config.dest || 'dist';
|
|
10
14
|
|
|
11
15
|
super(name, root, index, dest);
|
|
12
16
|
this.config = config;
|
|
@@ -14,20 +18,30 @@ export default class ConfigApp extends App {
|
|
|
14
18
|
if (!index.template || !index.template.source) throw new Error('html source not defined in config file');
|
|
15
19
|
var source = index.template.source;
|
|
16
20
|
var sourceFilename = path.basename(source);
|
|
17
|
-
var destination = index.template.destination || path.join(dest, sourceFilename)
|
|
21
|
+
var destination = index.template.destination || path.join(dest, sourceFilename);
|
|
18
22
|
this.setHtmlTemplate(source, destination);
|
|
19
23
|
|
|
20
|
-
if (config.manualChunks)
|
|
24
|
+
if (config.manualChunks) {
|
|
25
|
+
config.manualChunks.forEach(function(chunk) {
|
|
26
|
+
this.addManualChunks(chunk);
|
|
27
|
+
}, this)
|
|
28
|
+
}
|
|
29
|
+
|
|
21
30
|
if (this.config.features) {
|
|
22
31
|
this.config.features.forEach(function(feature) {
|
|
23
32
|
this.addFeature(feature);
|
|
24
33
|
}.bind(this))
|
|
25
34
|
}
|
|
26
35
|
|
|
27
|
-
if (config.resources) ;
|
|
28
|
-
|
|
36
|
+
if (config.resources && Array.isArray(config.resources)) this.addResources('', config.resources);
|
|
37
|
+
if (config.css) this.addMainCss(css);
|
|
29
38
|
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
if (config.variables) {
|
|
40
|
+
var names = Object.keys(config.variables);
|
|
41
|
+
|
|
42
|
+
names.forEach(function(name) {
|
|
43
|
+
this.addCodeVariable(name, config.variables[name]);
|
|
44
|
+
}, this)
|
|
45
|
+
}
|
|
32
46
|
}
|
|
33
47
|
}
|
package/ConfigFeature.js
CHANGED
package/Files.js
CHANGED
|
@@ -3,27 +3,8 @@ import path from 'node:path/posix'
|
|
|
3
3
|
import {ensureDir} from 'fs-extra';
|
|
4
4
|
import { copyFile } from 'node:fs/promises';
|
|
5
5
|
import App from './App.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* @typedef {Object} CopySpec
|
|
9
|
-
* @property {String} dest the relative path of the copy destination from the
|
|
10
|
-
* application's destination path.
|
|
11
|
-
* @property {String} cwd the relative path from the spec root to search for
|
|
12
|
-
* files
|
|
13
|
-
* @property {String} glob the search expression for the files to copy, in glob
|
|
14
|
-
* format
|
|
15
|
-
* @property {Boolean} [keepNest] if true then the nesting of the found file
|
|
16
|
-
* relative to the cwd property will be retained when the file is copied.
|
|
17
|
-
* Defaults to false
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @typedef {Object} FileSpec
|
|
22
|
-
* @property {String} name the full path to the file being copied
|
|
23
|
-
* @property {String} searchRoot the absolute path to where the search started
|
|
24
|
-
* @property {CopySpec} spec the specifier for how to find and copy files
|
|
25
|
-
*/
|
|
26
|
-
|
|
6
|
+
import {forceToPosix} from './utils.js'
|
|
7
|
+
import './types.js'
|
|
27
8
|
/**
|
|
28
9
|
* create an instance of this class to specify and and copy files from source
|
|
29
10
|
* to destination.
|
|
@@ -40,6 +21,7 @@ export default class Files {
|
|
|
40
21
|
constructor(src, dest) {
|
|
41
22
|
this.dest = dest;
|
|
42
23
|
this.src = src;
|
|
24
|
+
/** @type {CopyInfoList} */
|
|
43
25
|
this.files = {};
|
|
44
26
|
this.specs = [];
|
|
45
27
|
}
|
|
@@ -52,20 +34,23 @@ export default class Files {
|
|
|
52
34
|
* @param {String} root the originating path of the specifier. This is a
|
|
53
35
|
* relative path from the project src path. This is probably the location
|
|
54
36
|
* of the feature, or empty for the src path itself.
|
|
55
|
-
* @param {
|
|
37
|
+
* @param {ResourceSpec} spec the specification for how to find and copy files
|
|
56
38
|
*/
|
|
57
|
-
|
|
39
|
+
addResourceSpec(root, spec) {
|
|
58
40
|
spec.root = root;
|
|
59
41
|
this.specs.push(spec);
|
|
60
42
|
}
|
|
61
43
|
|
|
62
44
|
/**
|
|
63
|
-
* call this
|
|
45
|
+
* call this method to generate the destination filename from the spec and
|
|
64
46
|
* the source filename
|
|
65
47
|
*
|
|
66
|
-
* @param {
|
|
67
|
-
*
|
|
68
|
-
* @
|
|
48
|
+
* @param {String} searchRoot the full path to the directory where the
|
|
49
|
+
* search started that found this file
|
|
50
|
+
* @param {ResourceSpec} spec the spec that found the file
|
|
51
|
+
* @param {String} srcFilename the full path to the source file
|
|
52
|
+
*
|
|
53
|
+
* @returns {String} the full path to the destination file
|
|
69
54
|
*/
|
|
70
55
|
makeDestination(searchRoot, spec, srcFilename) {
|
|
71
56
|
var fullPath = searchRoot;
|
|
@@ -87,35 +72,84 @@ export default class Files {
|
|
|
87
72
|
* different specs then the spec with the longest search root will take
|
|
88
73
|
* presidence, since it is the spec with the greatest specificity
|
|
89
74
|
*
|
|
90
|
-
* @param {
|
|
91
|
-
*
|
|
92
|
-
* @param {
|
|
75
|
+
* @param {String} searchRoot the full path to the directory where the
|
|
76
|
+
* search started that found this file
|
|
77
|
+
* @param {Array.<String>} files full paths to files that have been found
|
|
78
|
+
* @param {ResourceSpec} spec the spec that was used to find these files.
|
|
79
|
+
*
|
|
80
|
+
* @returns {CopyInfoList} the list of files found for this spec
|
|
93
81
|
*/
|
|
94
82
|
addFiles(searchRoot, files, spec) {
|
|
83
|
+
/** @type {CopyInfoList} */
|
|
84
|
+
var foundFiles = {};
|
|
85
|
+
|
|
95
86
|
// the rule here is that files that are found by multiple specs will be
|
|
96
87
|
// controlled according to the spec with the deepest nested search path.
|
|
97
|
-
// Since file paths here are absolute
|
|
88
|
+
// Since file paths here are absolute this will always be based on the
|
|
98
89
|
// string length.
|
|
99
90
|
files.forEach(function(file) {
|
|
100
|
-
file =
|
|
91
|
+
file = forceToPosix(file);
|
|
92
|
+
|
|
101
93
|
// reconcile conflicts
|
|
102
94
|
if (this.files[file]) {
|
|
103
95
|
var copyInfo = this.files[file];
|
|
104
96
|
if (copyInfo.searchRoot.length > searchRoot.length) return;
|
|
105
97
|
}
|
|
98
|
+
|
|
106
99
|
var destination = this.makeDestination(searchRoot, spec, file);
|
|
107
100
|
var uri = destination.slice(this.dest.length + 1);
|
|
108
101
|
|
|
109
|
-
|
|
102
|
+
foundFiles[file] = {
|
|
110
103
|
name: file,
|
|
104
|
+
searchRoot: searchRoot,
|
|
111
105
|
destFilename: destination,
|
|
112
106
|
uri: uri,
|
|
113
|
-
searchRoot: searchRoot,
|
|
114
107
|
spec: spec,
|
|
115
108
|
}
|
|
116
|
-
}, this)
|
|
109
|
+
}, this);
|
|
110
|
+
|
|
111
|
+
this.files = {...this.files, ...foundFiles}
|
|
112
|
+
|
|
113
|
+
return foundFiles;
|
|
117
114
|
}
|
|
118
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Call this method to get all the folders where files can copied from
|
|
118
|
+
*
|
|
119
|
+
* @returns {Array.<String>}
|
|
120
|
+
*/
|
|
121
|
+
getAllFolders() {
|
|
122
|
+
var folders = this.specs.map(function(spec){
|
|
123
|
+
return path.join(this.src, spec.root, spec.cwd);
|
|
124
|
+
}, this);
|
|
125
|
+
|
|
126
|
+
return folders;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Call this method to copy a single file into its destination location
|
|
132
|
+
*
|
|
133
|
+
* @param {String} file the full path of the file to be copied
|
|
134
|
+
*/
|
|
135
|
+
async copyOneFile(file, updated) {
|
|
136
|
+
file = forceToPosix(file);
|
|
137
|
+
|
|
138
|
+
var destination = this.files[file] && this.files[file].destFilename;
|
|
139
|
+
|
|
140
|
+
if (destination && updated) {
|
|
141
|
+
console.log(`file ${file} updated, copied to ${destination}`);
|
|
142
|
+
await copyFile(file, destination);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Call this method to find all the files specified by a spec.
|
|
148
|
+
*
|
|
149
|
+
* @param {ResourceSpec} spec the specification for the files to find
|
|
150
|
+
*
|
|
151
|
+
* @returns {Promise.<CopyInfoList>} all the files that have been found so far.
|
|
152
|
+
*/
|
|
119
153
|
async findFiles(spec) {
|
|
120
154
|
var searchRoot = path.join(this.src, spec.root, spec.cwd);
|
|
121
155
|
var options = {
|
|
@@ -136,17 +170,16 @@ export default class Files {
|
|
|
136
170
|
|
|
137
171
|
/**
|
|
138
172
|
* Call this method to locate all the files to be found from all the copy
|
|
139
|
-
* specs that have been added
|
|
173
|
+
* specs that have been added.
|
|
140
174
|
*
|
|
141
|
-
* @returns {Promise<
|
|
142
|
-
*
|
|
175
|
+
* @returns {Promise<CopyInfoList>} the list of all files that have
|
|
176
|
+
* been found. This is also stored in the object variable this.files
|
|
143
177
|
*/
|
|
144
178
|
async findAllFiles() {
|
|
145
179
|
if (this.filesFound) return this.files;
|
|
146
180
|
|
|
147
181
|
// using a for loop here because we are making async calls
|
|
148
|
-
for (let
|
|
149
|
-
let spec = this.specs[idx];
|
|
182
|
+
for (let spec of this.specs) {
|
|
150
183
|
await this.findFiles(spec);
|
|
151
184
|
}
|
|
152
185
|
|
|
@@ -156,22 +189,20 @@ export default class Files {
|
|
|
156
189
|
}
|
|
157
190
|
|
|
158
191
|
/**
|
|
159
|
-
* Call this method to copy all the files that have been specified
|
|
160
|
-
*
|
|
192
|
+
* Call this method to copy all the files that have been specified by
|
|
193
|
+
* calling addResourceSpec to their destination directories
|
|
161
194
|
*/
|
|
162
195
|
async copyFiles() {
|
|
163
196
|
await this.findAllFiles();
|
|
164
197
|
|
|
165
198
|
var filenames = Object.keys(this.files);
|
|
199
|
+
|
|
166
200
|
// using a for loop because we are making async calls
|
|
167
|
-
for (let
|
|
168
|
-
let srcFilename = filenames[idx];
|
|
201
|
+
for (let srcFilename of filenames) {
|
|
169
202
|
let destFilename = this.files[srcFilename].destFilename;
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
// unintended consequences
|
|
203
|
+
let destFilePath = path.dirname(destFilename);
|
|
204
|
+
|
|
173
205
|
try {
|
|
174
|
-
// console.log(`copying ${srcFilename} to ${destFilename}`);
|
|
175
206
|
await ensureDir(destFilePath);
|
|
176
207
|
await copyFile(srcFilename, destFilename);
|
|
177
208
|
} catch (e) {
|
package/index.js
CHANGED
|
@@ -2,5 +2,12 @@ import App from './App.js'
|
|
|
2
2
|
import Feature from './Feature.js';
|
|
3
3
|
import ConfigApp from './ConfigApp.js';
|
|
4
4
|
import ConfigFeature from './ConfigFeature.js';
|
|
5
|
+
import * as utils from './utils.js';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
var utilsExport = {
|
|
8
|
+
forceToPosix: utils.forceToPosix,
|
|
9
|
+
fileExists: utils.fileExists,
|
|
10
|
+
fileToPath: utils.fileToPath,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export {App, Feature, ConfigApp, ConfigFeature, utilsExport as utils};
|
package/package.json
CHANGED
package/plugin-config.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import config from '@polylith/config-store';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
function makeSource(configs) {
|
|
5
|
+
|
|
6
|
+
var configBody = ''
|
|
7
|
+
|
|
8
|
+
configs.forEach(function(config) {
|
|
9
|
+
configBody +=
|
|
10
|
+
`config.add(
|
|
11
|
+
${JSON.stringify(config, null, ' ')})
|
|
12
|
+
|
|
13
|
+
`
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
var source =
|
|
17
|
+
`import config from '@polylith/config-store';
|
|
18
|
+
export var config;
|
|
19
|
+
|
|
20
|
+
${configBody}
|
|
21
|
+
`
|
|
22
|
+
console.log(source);
|
|
23
|
+
return source;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default function loadConfigs(configs) {
|
|
27
|
+
return {
|
|
28
|
+
name: 'config',
|
|
29
|
+
|
|
30
|
+
resolveId (source, _, third) {
|
|
31
|
+
if (source === '@polylith/config') {
|
|
32
|
+
return source;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
async load (id) {
|
|
38
|
+
if (id === '@polylith/config') {
|
|
39
|
+
return makeSource(configs);
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
package/plugin-copy-resources.js
CHANGED
|
@@ -10,13 +10,15 @@ export default function(name, files) {
|
|
|
10
10
|
return {
|
|
11
11
|
name: "copy-resources",
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
var
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
buildStart() {
|
|
14
|
+
var folders = files.getAllFolders();
|
|
15
|
+
folders.forEach(function(name) {
|
|
16
|
+
this.addWatchFile(name);
|
|
17
|
+
}, this);
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
watchChange(file, event) {
|
|
21
|
+
files.copyOneFile(file, true);
|
|
20
22
|
},
|
|
21
23
|
|
|
22
24
|
async generateBundle(outputOptions, bundleInfo) {
|
package/plugin-features.js
CHANGED
package/plugin-jsconfig.js
CHANGED
|
@@ -1,25 +1,6 @@
|
|
|
1
1
|
import path from 'node:path/posix';
|
|
2
2
|
import {readFile, writeFile, stat} from 'node:fs/promises';
|
|
3
|
-
|
|
4
|
-
async function fileExists(path) {
|
|
5
|
-
try {
|
|
6
|
-
await stat(path)
|
|
7
|
-
return true;
|
|
8
|
-
} catch (e) {
|
|
9
|
-
return false;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function fixPath(src) {
|
|
14
|
-
src = src.replace('file:', '');
|
|
15
|
-
src = src.replace('///', '');
|
|
16
|
-
src = src.replace(/.:/, '');
|
|
17
|
-
src = src.replace(/\\/g, '/');
|
|
18
|
-
|
|
19
|
-
return src;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
3
|
+
import {forceToPosix, fileExists} from './utils.js'
|
|
23
4
|
|
|
24
5
|
/**
|
|
25
6
|
* Matches pattern with a single star against search.
|
|
@@ -58,20 +39,19 @@ function matchStar(pattern, search) {
|
|
|
58
39
|
|
|
59
40
|
async function findPathMatch(base, source, paths) {
|
|
60
41
|
var patterns = Object.keys(paths);
|
|
61
|
-
var source =
|
|
42
|
+
var source = forceToPosix(source);
|
|
62
43
|
|
|
63
44
|
if (source.indexOf(base) === 0) return
|
|
64
|
-
// source = source.slice(base.length);
|
|
65
45
|
|
|
66
|
-
for(let
|
|
67
|
-
let pattern = patterns[patternIdx];
|
|
46
|
+
for (let pattern of patterns) {
|
|
68
47
|
let searches = paths[pattern];
|
|
69
48
|
let capture = matchStar(pattern, source);
|
|
70
|
-
if (!capture) continue;
|
|
71
49
|
|
|
50
|
+
if (!capture) continue;
|
|
72
51
|
if (!Array.isArray(searches)) continue;
|
|
73
|
-
|
|
74
|
-
|
|
52
|
+
|
|
53
|
+
for (let search of searches) {
|
|
54
|
+
var tryName = path.join(base, search.replace('*', capture));
|
|
75
55
|
|
|
76
56
|
if (await fileExists(tryName)) {
|
|
77
57
|
return tryName;
|
|
@@ -111,7 +91,7 @@ export default function jsconfig(root) {
|
|
|
111
91
|
name: 'jsconfig',
|
|
112
92
|
|
|
113
93
|
async resolveId (source, importer, options) {
|
|
114
|
-
source =
|
|
94
|
+
source = forceToPosix(source);
|
|
115
95
|
|
|
116
96
|
if (previouslyMatched[source] !== undefined) return previouslyMatched[source];
|
|
117
97
|
previouslyMatched[source] === null;
|
package/plugin-loader.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from 'node:path/posix';
|
|
2
2
|
import {readFile, writeFile, stat} from 'node:fs/promises';
|
|
3
|
-
import {
|
|
3
|
+
import {forceToPosix} from './utils.js';
|
|
4
4
|
var templateSource;
|
|
5
5
|
|
|
6
6
|
function makeSource(loadables) {
|
|
@@ -38,7 +38,7 @@ ${serviceStr}
|
|
|
38
38
|
|
|
39
39
|
var switchStr =
|
|
40
40
|
` case '${loadable.name}':
|
|
41
|
-
promise = import('${loadable.
|
|
41
|
+
promise = import('${loadable.index}')${prefixStr}
|
|
42
42
|
break;
|
|
43
43
|
`
|
|
44
44
|
loadableSwitches += switchStr;
|
|
@@ -64,7 +64,7 @@ export default function loader(loadables) {
|
|
|
64
64
|
},
|
|
65
65
|
|
|
66
66
|
async load (id) {
|
|
67
|
-
var root = path.dirname(
|
|
67
|
+
var root = path.dirname(forceToPosix(import.meta.url));
|
|
68
68
|
if (!templateSource) {
|
|
69
69
|
templateSource = await readFile(path.join(root, 'loaderTemplate.txt'), 'utf-8');
|
|
70
70
|
}
|
package/plugin-main-html.js
CHANGED
|
@@ -6,12 +6,6 @@ import {readFile, writeFile} from 'node:fs/promises';
|
|
|
6
6
|
const INVALID_ARGS_ERROR =
|
|
7
7
|
"[plugin-main-html] You did not provide a template or target!";
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
* Takes an HTML file as a template and replaces variables.
|
|
11
|
-
* @param {Object} options The options object.
|
|
12
|
-
* @return {Object} The rollup code object.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
9
|
function createScriptTags(scripts) {
|
|
16
10
|
var tags = '';
|
|
17
11
|
scripts.forEach(function(script) {
|
|
@@ -22,54 +16,58 @@ function createScriptTags(scripts) {
|
|
|
22
16
|
return tags;
|
|
23
17
|
}
|
|
24
18
|
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Takes an HTML file as a template and replaces template variables with
|
|
21
|
+
* assigned values
|
|
22
|
+
*
|
|
23
|
+
* @param {Object} options The options object.
|
|
24
|
+
* @return {Object} The rollup plugin object.
|
|
25
|
+
*/
|
|
26
|
+
export default function(options = {}) {
|
|
27
|
+
|
|
28
|
+
var { root, source, destination, templateVars } = options;
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
return {
|
|
31
|
+
name: "main-html-template",
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
var names = Object.keys(bundleInfo);
|
|
36
|
-
var scripts;
|
|
33
|
+
async generateBundle(outputOptions, bundleInfo) {
|
|
34
|
+
var includes = [];
|
|
35
|
+
var names = Object.keys(bundleInfo);
|
|
36
|
+
var scripts;
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
if (!destination && !source) throw new Error(INVALID_ARGS_ERROR);
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
names.forEach(function(name) {
|
|
41
|
+
var entry = bundleInfo[name];
|
|
42
|
+
if (!entry.isDynamicEntry) {
|
|
43
|
+
includes.push(name);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
scripts = createScriptTags(includes);
|
|
48
|
+
templateVars["scripts"] = scripts;
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
var sourceFilePath = path.join(root, source);
|
|
51
|
+
var destinationFilePath = path.join(root, destination);
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
var content = await readFile(sourceFilePath, 'utf-8');
|
|
55
|
-
if (replaceVars) {
|
|
56
|
-
var varNames = Object.keys(replaceVars);
|
|
57
|
-
varNames.forEach(function(name) {
|
|
58
|
-
var replacement = replaceVars[name]
|
|
59
|
-
var escapedName = escapeStringRegexp('${' + name + '}');
|
|
60
|
-
var regex = new RegExp(escapedName, 'g');
|
|
61
|
-
content = content.replace(regex, replacement);
|
|
62
|
-
});
|
|
63
|
-
}
|
|
53
|
+
var content = await readFile(sourceFilePath, 'utf-8');
|
|
64
54
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
55
|
+
if (templateVars) {
|
|
56
|
+
var varNames = Object.keys(templateVars);
|
|
57
|
+
varNames.forEach(function(name) {
|
|
58
|
+
var replacement = templateVars[name]
|
|
59
|
+
var escapedName = escapeStringRegexp('${' + name + '}');
|
|
60
|
+
var regex = new RegExp(escapedName, 'g');
|
|
61
|
+
content = content.replace(regex, replacement);
|
|
62
|
+
});
|
|
71
63
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
|
|
65
|
+
// remove template vars that were not replaced
|
|
66
|
+
content = content.replace(/\$\{.*?\}/, '');
|
|
67
|
+
|
|
68
|
+
// write the injected template to a file
|
|
69
|
+
await ensureFile(destinationFilePath);
|
|
70
|
+
writeFile(destinationFilePath, content, 'utf-8');
|
|
71
|
+
},
|
|
72
|
+
};
|
|
75
73
|
}
|
package/types.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** @module types */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This type defines how to locate a set of files that will be copied to the
|
|
5
|
+
* dest folder.
|
|
6
|
+
*
|
|
7
|
+
* @typedef {Object} ResourceSpec
|
|
8
|
+
* @property {String} dest the relative path of the copy destination from the
|
|
9
|
+
* application's destination path.
|
|
10
|
+
* @property {String} cwd the relative path from the spec root to search for
|
|
11
|
+
* files
|
|
12
|
+
* @property {String} glob the search expression for the files to copy, in glob
|
|
13
|
+
* format
|
|
14
|
+
* @property {Boolean} [keepNest] if true then the nesting of the found file
|
|
15
|
+
* relative to the cwd property will be retained when the file is copied.
|
|
16
|
+
* Defaults to false
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* This type defines a list of ResourceSpec
|
|
21
|
+
*
|
|
22
|
+
* @typedef {Array.<ResourceSpec} ResourceSpecList
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* This defines the specification for a file that has been found from a
|
|
27
|
+
* ResourceSpec
|
|
28
|
+
*
|
|
29
|
+
* @typedef {Object} CopyInfo
|
|
30
|
+
* @property {String} name the full path to the file found
|
|
31
|
+
* @property {String} searchRoot the absolute path to where the search started.
|
|
32
|
+
* @property {String} destFilename the absolute path to where the file be copied
|
|
33
|
+
* @property {String} uri the path to the file relative to the destination
|
|
34
|
+
* directory. This can be used to reference the file from the output
|
|
35
|
+
* application.
|
|
36
|
+
* @property {ResourceSpec} spec the specifier used to locate this file
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* This type defines a list of CopyInfos
|
|
41
|
+
*
|
|
42
|
+
* @typedef {Object.<String, CopyInfo>} CopyInfoList
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* This specifies what is in a loadable object
|
|
47
|
+
*
|
|
48
|
+
* @typedef {Object} Loadable
|
|
49
|
+
* @property {String} name this is the name the loadable will be known as. This
|
|
50
|
+
* will be the string passed to the load function
|
|
51
|
+
* @property {String} root the relative path from the source directory to the
|
|
52
|
+
* root of the feature. All feature paths are assumed to be relative to
|
|
53
|
+
* this
|
|
54
|
+
* @property {String} index the absolute path to the loadables index file
|
|
55
|
+
* @property {String} prefix if given then all services that begin with this
|
|
56
|
+
* prefix will go through the start sequence when loaded
|
|
57
|
+
* @property {ResourceSpecList|Array<String>} css is either the specification for
|
|
58
|
+
* where to find the css files to load, or during build, an array of the
|
|
59
|
+
* uris for each css file.
|
|
60
|
+
*/
|
package/utils.js
CHANGED
|
@@ -1,16 +1,37 @@
|
|
|
1
1
|
import path from 'node:path/posix';
|
|
2
2
|
import {readFile, writeFile, stat} from 'node:fs/promises';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* call this function to force the file path to use posix notation and remove
|
|
6
|
+
* all drive information.
|
|
7
|
+
*
|
|
8
|
+
*
|
|
9
|
+
* @param {String} src the filename wqe
|
|
10
|
+
* @returns {String} the new path
|
|
11
|
+
*/
|
|
12
|
+
export function forceToPosix(src) {
|
|
5
13
|
src = src.replace('file:', '');
|
|
6
14
|
src = src.replace('///', '');
|
|
7
|
-
src = src.replace(
|
|
15
|
+
src = src.replace(/.*?:/, '');
|
|
8
16
|
src = src.replace(/\\/g, '/');
|
|
9
17
|
|
|
10
18
|
return src;
|
|
11
19
|
}
|
|
12
20
|
|
|
13
|
-
|
|
21
|
+
export function fileToPath(filename) {
|
|
22
|
+
filename = forceToPosix(filename);
|
|
23
|
+
return path.dirname(filename);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* call this function to check if the given file exists
|
|
29
|
+
*
|
|
30
|
+
* @param {String} path the name of the file
|
|
31
|
+
* @returns {Promise<Boolean>} true if the file exists
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
export async function fileExists(path) {
|
|
14
35
|
try {
|
|
15
36
|
await stat(path)
|
|
16
37
|
return true;
|