@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 CHANGED
@@ -1,55 +1,53 @@
1
- import path from 'path';
2
- import fs from 'fs-extra';
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 "rollup-plugin-html";
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 method to get the path from the a filename, and force the file path
19
- * to use posix notation and remove all drive information. This will likely
20
- * be used by parent App implementations in their constructors
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
- return src;
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(template, target) {
87
- this.htmlTemplate = {template, target};
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
- async loadFeature(src) {
96
- var featurePath = path.posix.join(this.sourcePath, src);
97
- var indexPath = fixPath(path.posix.join(featurePath, 'index.js'))
98
- var indexExists = await fs.pathExists(indexPath);
99
- var builderPath = fixPath(path.posix.join(featurePath, 'build/index.js'));
100
- var builderExists = await fs.pathExists(builderPath);
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
- var module = await import(builderPath)
105
- var feature = module.default;
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', src);
143
+ console.error('error while building feature', root);
109
144
  console.log(e);
110
145
  }
111
- }
112
146
 
113
- if (indexExists) this.featureIndexes.push(indexPath);
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
- src - the path to the entry point of the loadable
128
- prefix - if given, the prefix on services created in this loadable.
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, src, prefix) {
132
- var dest = path.posix.join(this.sourcePath, src);
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
- template: this.htmlTemplate.template,
170
- target: this.htmlTemplate.target,
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
+ }
@@ -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
@@ -1,8 +1,8 @@
1
- export class Feature {
1
+ export default class Feature {
2
2
  constructor () {
3
3
  }
4
4
 
5
5
  async build(app) {
6
6
  this.app = app;
7
7
  }
8
- }
8
+ }
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import {App} from './App.js'
2
- import {Feature} from './Feature.js';
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.23",
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": "^3.14.1",
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
-
@@ -1,6 +1,7 @@
1
1
  import escapeStringRegexp from 'escape-string-regexp';
2
- import fs from 'fs-extra';
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, template, target, replaceVars } = options;
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 (!target && !template) throw new Error(INVALID_ARGS_ERROR);
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 templateFilePath = path.join(root, template);
51
- var targetFilePath = path.join(root, target);
50
+ var sourceFilePath = path.join(root, source);
51
+ var destinationFilePath = path.join(root, destination);
52
52
 
53
53
  // Read the file
54
- var buffer = await fs.readFile(templateFilePath);
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 fs.ensureFile(targetFilePath);
73
- await fs.writeFile(targetFilePath, injected);
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
-