@cmmn/tools 1.9.3 → 1.9.6

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/bundle/bundle.js CHANGED
@@ -5,7 +5,7 @@ import fs from "fs";
5
5
  import path, {relative} from "path";
6
6
 
7
7
  export async function bundle(...options) {
8
- const configOptions = getConfigOptions({
8
+ const configOptions = await getConfigOptions({
9
9
  input: options.filter(x => !x.startsWith('-'))[0],
10
10
  project: options.includes('-b'),
11
11
  minify: options.includes('--prod'),
@@ -13,14 +13,16 @@ export async function bundle(...options) {
13
13
  stats: options.includes('--stats'),
14
14
  });
15
15
  const configs = configOptions.flatMap(x => new ConfigCreator(x).getConfig());
16
- const contexts = await Promise.all(configs.map(async x =>
17
- [x, await esbuild.context(x)]
18
- ));
16
+ const contexts = [];
17
+ for (let config of configs){
18
+ contexts.push([config, await esbuild.context(config)]);
19
+ }
19
20
 
20
21
  if (options.includes('--watch')) {
21
- for (let [name, context] of contexts) {
22
+ for (let [config, context] of contexts) {
22
23
  await context.watch();
23
24
  }
25
+ console.log('bundled. Continue watching...');
24
26
  }else {
25
27
  const logs = [];
26
28
  for (let [config, context] of contexts) {
@@ -54,6 +54,13 @@ export class ConfigCreator {
54
54
  return path.join(this.root, this.options.outDir);
55
55
  }
56
56
 
57
+ get importMaps(){
58
+ return JSON.stringify({
59
+ imports: Object.fromEntries(this.options.external
60
+ .map(key => key.replace('*', '/'))
61
+ .map(key => [key, `/external/${this.options.alias?.[key] ?? key}`]))
62
+ })
63
+ }
57
64
  getHtmlPlugin(){
58
65
  if (!this.options.html)
59
66
  return [];
@@ -61,21 +68,26 @@ export class ConfigCreator {
61
68
  {
62
69
  name: 'esbuild-html-plugin',
63
70
  setup: (build) => { build.onEnd(async result => {
64
- const inject = [
71
+ if (!result.metafile)
72
+ return;
73
+ const injectStyles = [];
74
+ const injectScripts = [
65
75
  `<script type="importmap">${this.importMaps}</script>`
66
76
  ];
67
77
  for (let [key, value] of Object.entries(result.metafile.outputs)){
68
78
  if (value.entryPoint !== this.options.input) continue;
69
79
  const file = path.relative(this.outDir, path.join(this.root, key));
70
- inject.push(`<script type="module" src="/${file}"/>`)
80
+ injectScripts.push(`<script type="module" src="/${file}"></script>`)
71
81
  if (value.cssBundle) {
72
82
  const file = path.relative(this.outDir, path.join(this.root, value.cssBundle));
73
- inject.push(`<style rel="stylesheet" href="/${file}"/>`)
83
+ injectStyles.push(`<link rel="stylesheet" href="/${file}"></link>`)
74
84
  }
75
85
  const html = await fs.promises.readFile(path.join(this.root, this.options.html));
76
86
  await fs.promises.writeFile(
77
87
  path.join(this.outDir, 'index.html'),
78
- html.toString().replace('</head>', `${inject.map(x => `\t${x}\n`).join('')}</head>`)
88
+ html.toString()
89
+ .replace('</head>', `${injectStyles.map(x => `\t${x}\n`).join('')}</head>`)
90
+ .replace('</body>', `${injectScripts.map(x => `\t${x}\n`).join('')}</body>`)
79
91
  );
80
92
  }
81
93
  }); }
@@ -105,14 +117,14 @@ export class ConfigCreator {
105
117
  getConfig() {
106
118
  if (this.options.external && typeof this.options.external === "string")
107
119
  this.options.external = [this.options.external]
108
- console.log(this.options.name, this.options);
120
+ // console.log(this.options.name, this.options);
109
121
  return this.modules.flatMap(format => this.platforms.map(platform => ({
110
122
  entryPoints: [
111
123
  { out: this.options.name, in: this.options.input }
112
124
  ],
113
125
  bundle: true,
114
126
  minify: this.options.minify,
115
- sourcemap: true,
127
+ sourcemap: this.options.minify ? false : 'external',
116
128
  target: ['chrome88', 'safari14', 'firefox88'],
117
129
  outdir: 'dist/bundle',
118
130
  metafile: true,
@@ -126,7 +138,10 @@ export class ConfigCreator {
126
138
  },
127
139
  platform: platform,
128
140
  tsconfig: 'tsconfig.json',
129
- external: ["*.woff2", "*.woff", ...this.options.external],
141
+ external: [
142
+ "*.woff2", "*.woff",
143
+ ...(platform !== "node" && this.options.minify ? [] : this.options.external)
144
+ ],
130
145
  define: {
131
146
  'process.env.NODE_ENV': '"production"'
132
147
  },
@@ -1,6 +1,7 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
3
  import fg from "fast-glob";
4
+ import { dependencyOrder } from "dependency-order";
4
5
 
5
6
  function getProjectConfig(rootDir, cmmn, options) {
6
7
  return {
@@ -10,21 +11,15 @@ function getProjectConfig(rootDir, cmmn, options) {
10
11
  };
11
12
  }
12
13
 
13
- function getPackageConfigs(rootDir, options, name = null) {
14
+ async function getPackageConfigs(rootDir, options, name = null, visited = []) {
14
15
  const pckPath = path.join(rootDir, 'package.json');
15
16
  if (!fs.existsSync(pckPath))
16
17
  return [];
17
18
  const results = [];
18
19
  const pkg = JSON.parse(fs.readFileSync(pckPath));
19
- if (pkg.workspaces){
20
- const dirs = pkg.workspaces.flatMap(pkg => fg.sync([pkg], {
21
- absolute: true,
22
- globstar: true,
23
- onlyDirectories: true,
24
- cwd: rootDir
25
- }));
26
- dirs.forEach(d => results.push(...getPackageConfigs(d, options, name)));
27
- }
20
+ const packageInfos = await dependencyOrder({
21
+ cwd: rootDir
22
+ });
28
23
  if (pkg.cmmn) {
29
24
  if (name) {
30
25
  results.push(getProjectConfig(rootDir, pkg.cmmn[name], {
@@ -42,32 +37,24 @@ function getPackageConfigs(rootDir, options, name = null) {
42
37
  }
43
38
  }
44
39
  }
40
+ for (let packageInfo of packageInfos) {
41
+ const root = packageInfo.packageMeta.directory;
42
+ if (visited.includes(root))
43
+ continue;
44
+ visited.push(root)
45
+ const configs = await getPackageConfigs(root, options, name, visited);
46
+ results.push(...configs);
47
+ }
45
48
  return results;
46
49
  }
47
50
 
48
- function getLernaSubPackages(lernaFile, options) {
49
- const config = JSON.parse(fs.readFileSync(lernaFile, 'utf8'));
50
- const packages = config.packages;
51
- const dirs = packages.flatMap(pkg => fg.sync([pkg], {
52
- absolute: true,
53
- globstar: true,
54
- onlyDirectories: true,
55
- cwd: path.dirname(lernaFile)
56
- }));
57
- return dirs.flatMap(dir => getPackageConfigs(dir, options));
58
- }
59
51
 
60
- export function getConfigOptions(options) {
52
+ export async function getConfigOptions(options) {
61
53
  if (!options.input || options.project) {
62
- const rootDir = process.cwd();
63
- const lernaPath = path.join(rootDir, 'lerna.json');
64
- if (fs.existsSync(lernaPath)) {
65
- return getLernaSubPackages(lernaPath, options);
66
- }
67
- return getPackageConfigs(process.cwd(), options);
54
+ return await getPackageConfigs(process.cwd(), options);
68
55
  }
69
56
  if (!options.input.includes('.') || !fs.existsSync(options.input)) {
70
- return getPackageConfigs(process.cwd(), options, options.input);
57
+ return await getPackageConfigs(process.cwd(), options, options.input);
71
58
  }
72
59
  return [options];
73
60
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmmn/tools",
3
- "version": "1.9.3",
3
+ "version": "1.9.6",
4
4
  "description": "Compilation, bundling, code generator, testing.",
5
5
  "main": "dist/rollup.config.js",
6
6
  "type": "module",
@@ -47,6 +47,7 @@
47
47
  "@types/jest": "27.x.x",
48
48
  "@types/sinon": "10.x.x",
49
49
  "@zerollup/ts-helpers": "1.7.18",
50
+ "dependency-order": "1.1.6",
50
51
  "esbuild": "0.19.5",
51
52
  "esbuild-plugin-less": "1.3.1",
52
53
  "esbuild-register": "3.5.0",
@@ -62,5 +63,5 @@
62
63
  },
63
64
  "author": "",
64
65
  "license": "ISC",
65
- "gitHead": "5b83506f4132e1876b5573f7245d8bc759fcb92d"
66
+ "gitHead": "2755b333808bf97f1d9454601c2a2c9a88e4a021"
66
67
  }
package/serve/serve.js CHANGED
@@ -5,8 +5,8 @@ import liveServer from "live-server";
5
5
  import {resolve, moduleResolve} from 'import-meta-resolve';
6
6
  import uri2path from "file-uri-to-path";
7
7
 
8
- export function serve(...options) {
9
- const configs = getConfigOptions({
8
+ export async function serve(...options) {
9
+ const configs = await getConfigOptions({
10
10
  project: options.includes('-b'),
11
11
  });
12
12
  configs.filter(x => x.port).forEach(async (x,i) => {
@@ -17,10 +17,11 @@ export function serve(...options) {
17
17
  file: 'index.html',
18
18
  port: process.env.PORT ? (+process.env.PORT + i) : x.port,
19
19
  open: false,
20
+ watch: configs.map(x => path.join(x.rootDir, x.outDir ?? 'dist/bundle')).join(','),
20
21
  mount: x.mount && Object.entries(x.mount)
21
- .map(([from, to]) => [from, path.resolve(x.rootDir, to)])
22
- .concat(configs.map(x => [`/external/${x.package}`,
23
- path.join(x.rootDir, x.outDir ?? `dist/bundle/${x.name}.js`)])),
22
+ .map(([from, to]) => [from, path.resolve(x.rootDir, to)]),
23
+ // .concat(configs.map(x => [`/external/${x.package}`,
24
+ // path.join(x.rootDir, x.outDir ?? `dist/bundle/${x.name}.js`)])),
24
25
  proxy: Object.entries(x.proxy ?? {}),
25
26
  middleware: [resolveESModule(x.rootDir, configs)].filter(x => x)
26
27
  });
@@ -36,6 +37,16 @@ function getModuleName(path) {
36
37
 
37
38
  const mappingCache = {};
38
39
 
40
+ async function resolveModule(module, root){
41
+ const conditions = ['browser', 'main', 'module', 'import', 'node', 'default'];
42
+ for (let condition of conditions) {
43
+ try {
44
+ return moduleResolve(module, root, new Set([condition]));
45
+ }catch (e){
46
+ }
47
+ }
48
+ throw new Error(`Failed resolve ${module} from ${root}`);
49
+ }
39
50
  // for resolve modules and files inside modules
40
51
  async function getFileName(moduleName, root) {
41
52
  // console.log(moduleName, root);
@@ -44,21 +55,22 @@ async function getFileName(moduleName, root) {
44
55
  let file;
45
56
  if (moduleName.match('\.[cm]?js')) {
46
57
  const module = moduleName.match(/^(@[^/]+\/)?[^/]+/)[0];
47
- const main = (await moduleResolve(module, root, new Set(['module', 'import', 'browser', 'main', 'node'])));
58
+ const main = await resolveModule(module, root);
48
59
  const file = main.href.replace(new RegExp('node_modules/' + module + '.*$'), 'node_modules/' + moduleName);
49
- console.log(file)
50
60
  return mappingCache[moduleName] = file;
51
61
  } else {
52
- const file = (await moduleResolve(moduleName, root, new Set(['module', 'import', 'browser', 'main', 'node'])));
62
+ const file = await resolveModule(moduleName, root);
53
63
  return mappingCache[moduleName] = file.href;
54
64
  }
55
65
  }
56
66
  const resolveESModule = (rootDir, configs) => async function (req, res, next) {
57
67
  const name = getModuleName(req.url);
58
- if (!name)
59
- return next();
60
- if (configs.some(x => x.package === name))
68
+ if (!name) {
69
+ console.log(`skip ${req.url}`)
61
70
  return next();
71
+ }
72
+ // if (configs.some(x => x.package === name))
73
+ // return next();
62
74
  const referer = req.headers.referer?.substring(req.headers.origin.length);
63
75
  const refererModule = referer && getModuleName(referer);
64
76
  const root = refererModule
@@ -67,7 +79,7 @@ const resolveESModule = (rootDir, configs) => async function (req, res, next) {
67
79
  try {
68
80
  const file = uri2path(await getFileName(name, root));
69
81
  var stat = fs.statSync(file);
70
-
82
+ console.info(`Resolve ${name} to ${file}`)
71
83
  res.writeHead(200, {
72
84
  'Content-Type': 'application/javascript',
73
85
  'Content-Length': stat.size