@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 +7 -5
- package/bundle/esbuild.config.js +22 -7
- package/bundle/getConfigs.js +16 -29
- package/package.json +3 -2
- package/serve/serve.js +24 -12
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 =
|
|
17
|
-
|
|
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 [
|
|
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) {
|
package/bundle/esbuild.config.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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()
|
|
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:
|
|
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: [
|
|
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
|
},
|
package/bundle/getConfigs.js
CHANGED
|
@@ -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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
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
|
+
"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": "
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|