@polylith/builder 0.0.32 → 0.0.34

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
@@ -12,6 +12,7 @@ import mainHTML from './plugin-main-html.js';
12
12
  import features from './plugin-features.js';
13
13
  import styles from "rollup-plugin-styles";
14
14
  import resources from "./plugin-copy-resources.js";
15
+ import jsconfig from "./plugin-jsconfig.js";
15
16
 
16
17
  import ConfigFeature from './ConfigFeature.js';
17
18
  import Files from './Files.js';
@@ -66,7 +67,8 @@ export default class App {
66
67
  this.configs = {};
67
68
  this.manualChunkType = 'function';
68
69
  this.manualChunks = [];
69
- this.files = new Files(this.sourcePath, this.destPath)
70
+ this.files = new Files(this.sourcePath, this.destPath);
71
+ this.cssFiles = [];
70
72
  }
71
73
 
72
74
  static fileToPath(filename) {
@@ -113,6 +115,25 @@ export default class App {
113
115
  this.configs[root] = config;
114
116
  }
115
117
 
118
+ async addMainCss(specs) {
119
+ var files = new Files(this.sourcePath, this.destPath)
120
+
121
+ // get the file paths
122
+ specs.forEach(function(spec) {
123
+ files.addCopySpec('', spec);
124
+ }, this)
125
+
126
+ var expanded = await files.findAllFiles();
127
+ var keys = Object.keys(expanded);
128
+ keys.forEach(function(key){
129
+ var file = expanded[key];
130
+ this.cssFiles.push(file.uri)
131
+ }, this);
132
+
133
+ // now add them to be copied
134
+ this.addResources('', specs);
135
+ }
136
+
116
137
  /**
117
138
  * Call this method to add a list of resources that will be moved to the
118
139
  * destination path when the application is built. This will either be a
@@ -123,7 +144,7 @@ export default class App {
123
144
  * @param {String} root the path to the origin of the caller. Paths in
124
145
  * the spec are assumed to be relative to this.
125
146
  */
126
- addResources(resourceSpecs, root) {
147
+ addResources(root, resourceSpecs) {
127
148
  resourceSpecs.forEach(function(spec) {
128
149
  this.files.addCopySpec(root, spec);
129
150
  }, this)
@@ -159,7 +180,7 @@ export default class App {
159
180
  * the application source folder.
160
181
  */
161
182
  addFeatureIndex(index) {
162
- this.featureIndexes.push(index);
183
+ this.featureIndexes.push(path.join(this.sourcePath, index));
163
184
  }
164
185
 
165
186
  /**
@@ -325,10 +346,37 @@ export default class App {
325
346
  * this loadable. When the loadable has been loaded, the start and
326
347
  * ready methods will be called on all services starting with this
327
348
  * prefix.
349
+ * @param {Array<CopySpec>} [css] if supplied it will be a copy spec of the
350
+ * css files that will included when the module is loaded
328
351
  */
329
- addLoadable(name, main, prefix) {
352
+ async addLoadable(root, name, main, prefix, css) {
353
+ // expand css specs
354
+ var cssUris = css ? [] : undefined;
355
+ if (css) {
356
+ var files = new Files(this.sourcePath, this.destPath)
357
+ css.forEach(function(spec) {
358
+ files.addCopySpec(root, spec);
359
+ }, this)
360
+ var expanded = await files.findAllFiles();
361
+ var keys = Object.keys(expanded);
362
+ keys.forEach(function(key){
363
+ var file = expanded[key];
364
+ cssUris.push(file.uri)
365
+ }, this)
366
+ }
367
+
330
368
  var dest = path.posix.join(this.sourcePath, main);
331
- this.loadables.push({name, path: dest, prefix});
369
+ this.loadables.push({name, path: dest, prefix, css: cssUris});
370
+ }
371
+
372
+
373
+ buildMainCss() {
374
+ var cssTags = '';
375
+ this.cssFiles.forEach(function(uri) {
376
+ cssTags += ` <link rel="stylesheet" href="${uri}"></link>`
377
+ }, this);
378
+
379
+ return cssTags;
332
380
  }
333
381
 
334
382
  /**
@@ -340,8 +388,8 @@ export default class App {
340
388
 
341
389
  buildConfiguration() {
342
390
  var input = [this.fullIndexPath];
343
- this.loadables.forEach(function(path) {
344
- input.push(path.path);
391
+ this.loadables.forEach(function(spec) {
392
+ input.push(spec.path);
345
393
  });
346
394
 
347
395
  this.variables = {
@@ -350,6 +398,7 @@ export default class App {
350
398
  }
351
399
 
352
400
  var manualChunks = this.getManualChunks();
401
+ var mainCss = this.buildMainCss();
353
402
 
354
403
  var config = {
355
404
  input : {
@@ -365,6 +414,7 @@ export default class App {
365
414
  }),
366
415
  loader(this.loadables),
367
416
  features(this.featureIndexes),
417
+ jsconfig(this.root),
368
418
  html({
369
419
  include: path.join(this.sourcePath, "**/*.html"),
370
420
  }),
@@ -373,7 +423,7 @@ export default class App {
373
423
  root: this.root,
374
424
  source: this.htmlTemplate.source,
375
425
  destination: this.htmlTemplate.destination,
376
- replaceVars: {},
426
+ replaceVars: {mainCss: mainCss},
377
427
  }),
378
428
  resources(this.name, this.files)
379
429
  ],
@@ -427,7 +477,7 @@ export default class App {
427
477
  watch() {
428
478
  var watchConfig = {
429
479
  ...this.config.input,
430
- ...this.config.output,
480
+ output: [this.config.output.output],
431
481
  ...this.config.watch,
432
482
  }
433
483
 
package/ConfigApp.js CHANGED
@@ -3,7 +3,7 @@ import path from 'node:path/posix';
3
3
 
4
4
  export default class ConfigApp extends App {
5
5
  constructor (config, root) {
6
- App.fixPath(root);
6
+ root = App.fixPath(root);
7
7
  var name = config.name || 'unnamed';
8
8
  var index = config.index || path.join(root, 'src', 'index.js');
9
9
  var dest = config.dest || path.join(root, 'dist');
package/ConfigFeature.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import Feature from './Feature.js';
2
+ import path from 'node:path/posix';
2
3
 
3
4
  export default class ConfigFeature extends Feature {
4
5
  /**
@@ -14,21 +15,22 @@ export default class ConfigFeature extends Feature {
14
15
 
15
16
  /**
16
17
  * The application calls the method to build the feature.
17
- * @param {App} app the application for th
18
+ *
19
+ * @param {App} app the application for the feature
18
20
  */
19
21
  async build(app) {
20
22
  var config = this.config;
21
23
 
22
24
  if (config.loadables && Array.isArray(config.loadables)) {
23
- config.loadables.forEach(function(loadable) {
25
+ for (let loadable of config.loadables){
24
26
  if (loadable.name && loadable.index) {
25
- app.addLoadable(loadable.name, loadable.index, loadable.prefix);
27
+ await app.addLoadable(this.root, loadable.name, path.join(this.root, loadable.index), loadable.prefix, loadable.css);
26
28
  }
27
- }, this);
29
+ }
28
30
  }
29
31
 
30
- if (config.index) app.addFeatureIndex(config.index);
32
+ if (config.index) app.addFeatureIndex(path.join(this.root, config.index));
31
33
  if (config.config) app.addConfig(config.config, this.root);
32
- if (config.resources && Array.isArray(config.resources)) app.addResources(config.resources, this.root);
34
+ if (config.resources && Array.isArray(config.resources)) app.addResources(this.root, config.resources);
33
35
  }
34
36
  }
package/Files.js CHANGED
@@ -59,6 +59,28 @@ export default class Files {
59
59
  this.specs.push(spec);
60
60
  }
61
61
 
62
+ /**
63
+ * call this methid to generate the destination filename from the spec and
64
+ * the source filename
65
+ *
66
+ * @param {CopySpec} spec the spec that generate the filename
67
+ * @param {String} srcFilename the source filename
68
+ * @returns
69
+ */
70
+ makeDestination(searchRoot, spec, srcFilename) {
71
+ var fullPath = searchRoot;
72
+ var relativePath = srcFilename.slice(fullPath.length + 1);
73
+ var destFilename = '';
74
+
75
+ if (spec.keepNest) {
76
+ destFilename = path.join(this.dest, spec.dest, relativePath);
77
+ } else {
78
+ destFilename = path.join(this.dest, spec.dest, path.basename(srcFilename));
79
+ }
80
+
81
+ return destFilename;
82
+ }
83
+
62
84
  /**
63
85
  * Call this method once per spec to add a list of files to the complete
64
86
  * list of all the files to be copied. If multiple files are found through
@@ -81,15 +103,37 @@ export default class Files {
81
103
  var copyInfo = this.files[file];
82
104
  if (copyInfo.searchRoot.length > searchRoot.length) return;
83
105
  }
106
+ var destination = this.makeDestination(searchRoot, spec, file);
107
+ var uri = destination.slice(this.dest.length + 1);
84
108
 
85
109
  this.files[file] = {
86
110
  name: file,
111
+ destFilename: destination,
112
+ uri: uri,
87
113
  searchRoot: searchRoot,
88
114
  spec: spec,
89
115
  }
90
116
  }, this)
91
117
  }
92
118
 
119
+ async findFiles(spec) {
120
+ var searchRoot = path.join(this.src, spec.root, spec.cwd);
121
+ var options = {
122
+ cwd: searchRoot,
123
+ ignore: ['**/node_modules'],
124
+ absolute: true,
125
+ onlyFiles: true,
126
+ unique: true,
127
+ dot: true,
128
+ }
129
+ var fullGlob = path.join(searchRoot, spec.glob);
130
+ var files = await fg(fullGlob, options);
131
+
132
+ this.addFiles(searchRoot, files, spec);
133
+
134
+ return this.files;
135
+ }
136
+
93
137
  /**
94
138
  * Call this method to locate all the files to be found from all the copy
95
139
  * specs that have been added
@@ -101,22 +145,10 @@ export default class Files {
101
145
  // using a for loop here because we are making async calls
102
146
  for (let idx = 0; idx < this.specs.length; idx++) {
103
147
  let spec = this.specs[idx];
104
- let searchRoot = path.join(this.src, spec.root, spec.cwd);
105
- let options = {
106
- cwd: searchRoot,
107
- ignore: ['**/node_modules'],
108
- absolute: true,
109
- onlyFiles: true,
110
- unique: true,
111
- dot: true,
112
- }
113
- let fullGlob = path.join(searchRoot, spec.glob);
114
- let files = await fg(fullGlob, options);
115
-
116
- this.addFiles(searchRoot, files, spec);
148
+ await this.findFiles(spec);
117
149
  }
118
150
 
119
- return this.files
151
+ return this.files;
120
152
  }
121
153
 
122
154
  /**
@@ -126,30 +158,18 @@ export default class Files {
126
158
  async copyFiles() {
127
159
  await this.findAllFiles();
128
160
 
129
-
130
161
  var filenames = Object.keys(this.files);
131
162
  // using a for loop because we are making async calls
132
163
  for (let idx = 0 ; idx < filenames.length; idx++) {
133
164
  let srcFilename = filenames[idx];
134
- let spec = this.files[srcFilename].spec;
135
- let searchRoot = this.files[srcFilename].searchRoot;
136
- let fullPath = searchRoot;
137
- let relativePath = srcFilename.slice(fullPath.length + 1);
138
- let destFilename = '';
139
-
140
- if (spec.keepNest) {
141
- destFilename = path.join(this.dest, spec.dest, relativePath);
142
- } else {
143
- destFilename = path.join(this.dest, spec.dest, path.basename(srcFilename));
144
- }
145
-
165
+ let destFilename = this.files[srcFilename].destFilename;
146
166
  var destFilePath = path.dirname(destFilename);
147
167
  // we will override existing destination files. This could have
148
168
  // unintended consequences
149
169
  try {
150
- console.log(`copying ${srcFilename} to ${destFilename}`);
151
- await ensureDir(destFilePath);
152
- await copyFile(srcFilename, destFilename);
170
+ // console.log(`copying ${srcFilename} to ${destFilename}`);
171
+ await ensureDir(destFilePath);
172
+ await copyFile(srcFilename, destFilename);
153
173
  } catch (e) {
154
174
  console.error(`Error copying file ${srcFilename} to ${destFilename}`);
155
175
  throw e;
@@ -0,0 +1,15 @@
1
+ import {App, registry} from '@polylith/core';
2
+
3
+ var loaded = {}
4
+
5
+ export async function load(name) {
6
+ if (loaded[name]) return loaded[name]
7
+ var promise;
8
+
9
+ switch (name) {
10
+ {{SWITCHES}}
11
+ }
12
+
13
+ loaded[name] = promise;
14
+ return promise;
15
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polylith/builder",
3
- "version": "0.0.32",
3
+ "version": "0.0.34",
4
4
  "description": "The polylith builder",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -2,11 +2,13 @@ function makeSource(features) {
2
2
 
3
3
  var importStatements = '';
4
4
  features.forEach(function(feature) {
5
- importStatements += `import '${feature}'\n`;
5
+ importStatements += `import ${JSON.stringify(feature)}\n`;
6
6
  })
7
7
 
8
8
  var source = `${importStatements}`
9
9
 
10
+ console.log('@polylith/features');
11
+ console.log(source);
10
12
  return source;
11
13
  }
12
14
 
@@ -0,0 +1,147 @@
1
+ import path from 'node:path/posix';
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
+
23
+
24
+ /**
25
+ * Matches pattern with a single star against search.
26
+ * Star must match at least one character to be considered a match.
27
+ *
28
+ * @param patttern for example "foo*"
29
+ * @param search for example "fooawesomebar"
30
+ * @returns the part of search that * matches, or undefined if no match.
31
+ */
32
+ function matchStar(pattern, search) {
33
+ if (search.length < pattern.length) {
34
+ return;
35
+ }
36
+ if (pattern === "*") {
37
+ return search;
38
+ }
39
+ const star = pattern.indexOf("*");
40
+
41
+ if (star === -1) {
42
+ return;
43
+ }
44
+
45
+ const part1 = pattern.substring(0, star);
46
+ const part2 = pattern.substring(star + 1);
47
+
48
+ if (search.substr(0, star) !== part1) {
49
+ return;
50
+ }
51
+
52
+ if (search.substr(search.length - part2.length) !== part2) {
53
+ return;
54
+ }
55
+
56
+ return search.substr(star, search.length - part2.length);
57
+ }
58
+
59
+ async function findPathMatch(base, source, paths) {
60
+ var patterns = Object.keys(paths);
61
+ var source = fixPath(source);
62
+
63
+ if (source.indexOf(base) === 0) return
64
+ // source = source.slice(base.length);
65
+
66
+ console.log('>>>', source)
67
+ for(let patternIdx = 0; patternIdx < patterns.length; patternIdx++) {
68
+ let pattern = patterns[patternIdx];
69
+ let searches = paths[pattern];
70
+ let capture = matchStar(pattern, source);
71
+ if (!capture) continue;
72
+
73
+ if (!Array.isArray(searches)) continue;
74
+ for (let searchIdx = 0; searchIdx < searches.length; searchIdx++) {
75
+ var tryName = path.join(base, searches[searchIdx].replace('*', capture));
76
+ console.log('\t..', searches[searchIdx], tryName);
77
+
78
+ if (await fileExists(tryName)) {
79
+ return tryName;
80
+ }
81
+ }
82
+ }
83
+ }
84
+
85
+
86
+ export default function features(root) {
87
+ var jsConfig;
88
+ var basePath;
89
+ var paths;
90
+ var previouslyMatched = {};
91
+
92
+ console.log('====root', root);
93
+ async function readJsConfig() {
94
+ var jsConfigPath = path.join(root, 'jsconfig.json');
95
+ var exists = await fileExists(jsConfigPath);
96
+ if (!exists) {
97
+ jsConfig === false;
98
+ return;
99
+ }
100
+
101
+ try {
102
+ let content = JSON.parse(await readFile(jsConfigPath));
103
+ basePath = content.compilerOptions.baseUrl;
104
+ paths = content.compilerOptions.paths;
105
+ jsConfig = content;
106
+ } catch (e) {
107
+ console.err(e)
108
+ jsConfig = false;
109
+ }
110
+ }
111
+
112
+
113
+ return {
114
+ name: 'features',
115
+
116
+ async resolveId (source, importer, options) {
117
+ source = fixPath(source);
118
+
119
+ // console.log('---', source);
120
+ if (previouslyMatched[source] !== undefined) return previouslyMatched[source];
121
+ previouslyMatched[source] === null;
122
+
123
+ if (jsConfig === undefined) await readJsConfig();
124
+ if (!jsConfig) return null;
125
+
126
+ if (basePath) {
127
+ var tryName = path.join(root, basePath, source);
128
+ if (await fileExists(tryName)) {
129
+ previouslyMatched[source] = tryName;
130
+ return tryName;
131
+ }
132
+ }
133
+ if (paths) {
134
+ if (source.indexOf(root) === 0) return null;
135
+
136
+ var matchedPath = await findPathMatch(path.join(root, basePath), source, paths);
137
+
138
+ if (matchedPath) {
139
+ previouslyMatched[source] = matchedPath;
140
+ return matchedPath;
141
+ }
142
+ }
143
+
144
+ return null;
145
+ }
146
+ }
147
+ }
package/plugin-loader.js CHANGED
@@ -1,43 +1,59 @@
1
- function makeSource(loadables) {
1
+ import path from 'node:path/posix';
2
+ import {readFile, writeFile, stat} from 'node:fs/promises';
3
+ import {fixPath} from './utils.js';
4
+ var templateSource;
2
5
 
6
+ function makeSource(loadables) {
3
7
  var loadableSwitches = '';
4
8
 
9
+ function makeCss(loadable) {
10
+ if (!loadable.css) return '';
11
+ var jsonCss = JSON.stringify(loadable.css);
12
+ return (
13
+ ` App.loadCss(${jsonCss});`
14
+ )
15
+
16
+ }
17
+
18
+ function makeServices(loadable) {
19
+ if (!loadable.prefix) return '';
20
+ return (
21
+ ` await registry.start('${loadable.prefix}');`
22
+ )
23
+ }
24
+
5
25
  loadables.forEach(function(loadable) {
6
26
  var prefixStr = ';';
27
+ var cssStr = makeCss(loadable);
28
+ var serviceStr = makeServices(loadable);
7
29
 
8
- if (loadable.prefix) {
30
+ if (loadable.prefix || loadable.css) {
9
31
  prefixStr = `
10
32
  .then(async function(result) {
11
- await registry.start('${loadable.prefix}');
12
- return result;
33
+ ${cssStr}
34
+ ${serviceStr}
13
35
  });
14
36
  `
15
37
  }
16
38
 
17
- var switchStr = `
18
- case '${loadable.name}':
39
+ var switchStr =
40
+ ` case '${loadable.name}':
19
41
  promise = import('${loadable.path}')${prefixStr}
20
42
  break;
21
43
  `
22
44
  loadableSwitches += switchStr;
23
45
  })
24
46
 
25
- var source =
26
- `
27
- import {registry} from '@polylith/core';
47
+ var source = templateSource;
48
+ var source = source.replace('{{SWITCHES}}', loadableSwitches);
49
+ var source = source.replace(/\t/g, ' ');
28
50
 
29
- export async function load(name) {
30
- var promise;
51
+ console.log(source);
31
52
 
32
- switch (name) {
33
- ${loadableSwitches}
34
- }
35
- return promise;
36
- }
37
- `
38
53
  return source;
39
54
  }
40
55
 
56
+
41
57
  export default function loader(loadables) {
42
58
  return {
43
59
  name: 'loader',
@@ -49,7 +65,13 @@ export default function loader(loadables) {
49
65
  return null;
50
66
  },
51
67
 
52
- load (id) {
68
+ async load (id) {
69
+ var root = path.dirname(fixPath(import.meta.url));
70
+ if (!templateSource) {
71
+ templateSource = await readFile(path.join(root, 'loaderTemplate.txt'), 'utf-8');
72
+ console.log(templateSource);
73
+ }
74
+
53
75
  if (id === '@polylith/loader') {
54
76
  return makeSource(loadables);
55
77
  }
package/utils.js ADDED
@@ -0,0 +1,20 @@
1
+ import path from 'node:path/posix';
2
+ import {readFile, writeFile, stat} from 'node:fs/promises';
3
+
4
+ export function fixPath(src) {
5
+ src = src.replace('file:', '');
6
+ src = src.replace('///', '');
7
+ src = src.replace(/.:/, '');
8
+ src = src.replace(/\\/g, '/');
9
+
10
+ return src;
11
+ }
12
+
13
+ async function fileExists(path) {
14
+ try {
15
+ await stat(path)
16
+ return true;
17
+ } catch (e) {
18
+ return false;
19
+ }
20
+ }