create-yeow 0.2.67 → 0.2.68
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/package.json
CHANGED
|
Binary file
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as esbuild from 'esbuild';
|
|
2
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync, statSync, readdirSync } from 'fs';
|
|
3
|
-
import { resolve } from 'path';
|
|
2
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, statSync, readdirSync, rmdirSync, copyFileSync } from 'fs';
|
|
3
|
+
import { resolve, dirname, basename, extname } from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
|
+
import { createHash } from 'crypto';
|
|
5
6
|
import AdmZip from 'adm-zip';
|
|
6
7
|
import { execSync } from 'child_process';
|
|
7
8
|
|
|
@@ -11,26 +12,103 @@ const { name, version } = cfg;
|
|
|
11
12
|
const isTs = existsSync(resolve(root, 'src', 'index.ts'));
|
|
12
13
|
const entry = isTs ? 'src/index.ts' : 'src/index.js';
|
|
13
14
|
|
|
14
|
-
// Optional type check for TypeScript projects
|
|
15
15
|
if (isTs && cfg.typecheck !== false) {
|
|
16
16
|
try {
|
|
17
17
|
execSync('npx -p typescript tsc --noEmit', { cwd: root, stdio: 'pipe' });
|
|
18
|
-
console.log('
|
|
18
|
+
console.log(' \u2713 Type check passed');
|
|
19
19
|
} catch (e) {
|
|
20
20
|
const out = e.stdout?.toString().trim();
|
|
21
21
|
const err = e.stderr?.toString().trim();
|
|
22
22
|
if (out) console.error(out);
|
|
23
23
|
if (err) console.error(err);
|
|
24
|
-
if (!out && !err) console.error('
|
|
24
|
+
if (!out && !err) console.error(' \u2717 Type check failed');
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const outDir = resolve(root, 'dist', '.yeow');
|
|
30
|
-
mkdirSync(outDir, { recursive: true });
|
|
31
|
-
|
|
32
29
|
const apiVer = cfg.api || '1.18';
|
|
33
30
|
const isDev = process.env.YEOW_DEV === 'true';
|
|
31
|
+
const outDir = isDev ? resolve(root, 'dist', '.dev') : resolve(root, 'dist', '.yeow');
|
|
32
|
+
const assetsOutDir = resolve(outDir, '.assets');
|
|
33
|
+
const srcAssetsDir = resolve(root, 'assets');
|
|
34
|
+
|
|
35
|
+
// ── esbuild plugin: __yeow-assets virtual module ──
|
|
36
|
+
// 目录级哈希:目录整体重命名 <name>.<dirHash>/,目录内文件保持原名(内部引用不断)
|
|
37
|
+
// 根级文件独立哈希 <name>.<hash><ext>
|
|
38
|
+
const ASSET_TREE = (() => {
|
|
39
|
+
if (!existsSync(srcAssetsDir)) return { children: {}, hash: null };
|
|
40
|
+
const buildTree = (absDir) => {
|
|
41
|
+
const children = {};
|
|
42
|
+
for (const e of readdirSync(absDir, { withFileTypes: true })) {
|
|
43
|
+
const p = resolve(absDir, e.name);
|
|
44
|
+
if (e.isDirectory()) {
|
|
45
|
+
children[e.name] = buildTree(p);
|
|
46
|
+
} else {
|
|
47
|
+
children[e.name] = { isFile: true, contentHash: createHash('md5').update(readFileSync(p)).digest('hex').slice(0, 8) };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const parts = Object.keys(children).sort().map(k => {
|
|
51
|
+
const c = children[k];
|
|
52
|
+
return k + ':' + (c.isFile ? c.contentHash : c.hash);
|
|
53
|
+
});
|
|
54
|
+
return { children, isFile: false, hash: createHash('md5').update(parts.join(',')).digest('hex').slice(0, 8) };
|
|
55
|
+
};
|
|
56
|
+
return buildTree(srcAssetsDir);
|
|
57
|
+
})();
|
|
58
|
+
|
|
59
|
+
const yeowAssetPlugin = {
|
|
60
|
+
name: 'yeow-assets',
|
|
61
|
+
setup(build) {
|
|
62
|
+
build.onResolve({ filter: /^__yeow-assets$/ }, args => ({
|
|
63
|
+
path: args.path,
|
|
64
|
+
namespace: 'yeow-assets',
|
|
65
|
+
}));
|
|
66
|
+
build.onLoad({ filter: /.*/, namespace: 'yeow-assets' }, async () => {
|
|
67
|
+
const map = {};
|
|
68
|
+
mkdirSync(assetsOutDir, { recursive: true });
|
|
69
|
+
|
|
70
|
+
const deploy = (node, absSrc, origRel, hashedRel) => {
|
|
71
|
+
if (!node.isFile && hashedRel) {
|
|
72
|
+
mkdirSync(resolve(assetsOutDir, hashedRel), { recursive: true });
|
|
73
|
+
}
|
|
74
|
+
for (const [name, child] of Object.entries(node.children || {})) {
|
|
75
|
+
if (child.isFile) {
|
|
76
|
+
// 根级文件:独立哈希;目录内文件:保持原名
|
|
77
|
+
if (hashedRel === '') {
|
|
78
|
+
const ext = extname(name);
|
|
79
|
+
const base = basename(name, ext);
|
|
80
|
+
const dest = base + '.' + child.contentHash + ext;
|
|
81
|
+
copyFileSync(resolve(absSrc, name), resolve(assetsOutDir, dest));
|
|
82
|
+
map[name] = 'assets/' + dest;
|
|
83
|
+
} else {
|
|
84
|
+
copyFileSync(resolve(absSrc, name), resolve(assetsOutDir, hashedRel, name));
|
|
85
|
+
map[origRel + name] = 'assets/' + hashedRel + name;
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
const subHashed = (hashedRel === '' ? '' : hashedRel) + name + '.' + child.hash + '/';
|
|
89
|
+
deploy(child, resolve(absSrc, name), origRel + name + '/', subHashed);
|
|
90
|
+
map[origRel + name + '/'] = 'assets/' + subHashed;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
deploy(ASSET_TREE, srcAssetsDir, '', '');
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
contents: 'const _map = ' + JSON.stringify(map) + ';\n' +
|
|
99
|
+
'function _norm(p) { return p.endsWith("/") ? p.slice(0, -1) : p; }\n' +
|
|
100
|
+
'export function getPath(p) {\n' +
|
|
101
|
+
' if (_map[p]) return _map[p];\n' +
|
|
102
|
+
' const n = _norm(p);\n' +
|
|
103
|
+
' if (_map[n]) return _map[n];\n' +
|
|
104
|
+
' if (_map[n + "/"]) return _map[n + "/"];\n' +
|
|
105
|
+
' return p;\n' +
|
|
106
|
+
'}\n',
|
|
107
|
+
loader: 'js',
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
};
|
|
34
112
|
|
|
35
113
|
async function main() {
|
|
36
114
|
await esbuild.build({
|
|
@@ -45,42 +123,52 @@ async function main() {
|
|
|
45
123
|
treeShaking: true,
|
|
46
124
|
minify: false,
|
|
47
125
|
sourcemap: isDev ? 'linked' : false,
|
|
126
|
+
plugins: [yeowAssetPlugin],
|
|
48
127
|
});
|
|
49
128
|
|
|
50
129
|
const size = statSync(resolve(outDir, 'main.js')).size;
|
|
51
|
-
console.log(
|
|
130
|
+
console.log(' \u2713 Bundled (' + (size / 1024).toFixed(1) + ' KB)');
|
|
52
131
|
|
|
53
132
|
const tmplJar = resolve(root, '.yeow', 'assets', 'yeow-template-0.1.0.jar');
|
|
54
133
|
const zip = new AdmZip(tmplJar);
|
|
55
|
-
zip.updateFile('plugin.yml', Buffer.from(
|
|
134
|
+
zip.updateFile('plugin.yml', Buffer.from(
|
|
135
|
+
'name: ' + name + '\n' +
|
|
136
|
+
'version: ' + version + '\n' +
|
|
137
|
+
'main: yeow.template.Bootstrap\n' +
|
|
138
|
+
'api-version: \'' + apiVer + '\'\n' +
|
|
139
|
+
'depend:\n - Yeow-Runtime\n'));
|
|
56
140
|
|
|
57
141
|
if (isDev) {
|
|
58
142
|
const devInfo = {
|
|
59
143
|
name,
|
|
60
144
|
codeFile: resolve(outDir, 'main.js').replace(/\\/g, '/'),
|
|
61
|
-
assetsDir:
|
|
145
|
+
assetsDir: assetsOutDir.replace(/\\/g, '/'),
|
|
62
146
|
};
|
|
63
147
|
writeFileSync(resolve(outDir, 'dev.json'), JSON.stringify(devInfo, null, 2));
|
|
64
|
-
console.log(
|
|
148
|
+
console.log(' \u2713 Dev info written');
|
|
65
149
|
zip.addFile('.yeow/dev.json', readFileSync(resolve(outDir, 'dev.json')));
|
|
66
150
|
} else {
|
|
67
151
|
zip.addFile('.yeow/main.js', readFileSync(resolve(outDir, 'main.js')));
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Pack hashed assets into JAR
|
|
155
|
+
if (existsSync(assetsOutDir)) {
|
|
156
|
+
const files = readdirSync(assetsOutDir, { recursive: true });
|
|
157
|
+
for (const f of files) {
|
|
158
|
+
const fp = resolve(assetsOutDir, f);
|
|
159
|
+
if (statSync(fp).isFile()) {
|
|
160
|
+
zip.addFile('assets/' + f.replace(/\\/g, '/'), readFileSync(fp));
|
|
75
161
|
}
|
|
76
|
-
console.log(' ✓ Assets included');
|
|
77
162
|
}
|
|
163
|
+
console.log(' \u2713 Assets included (' + files.filter(f => statSync(resolve(assetsOutDir, f)).isFile()).length + ' files)');
|
|
78
164
|
}
|
|
79
165
|
|
|
80
166
|
zip.addFile('yeow.json', Buffer.from(JSON.stringify(cfg)));
|
|
81
|
-
const outJar = resolve(root, 'dist',
|
|
167
|
+
const outJar = isDev ? resolve(root, 'dist', 'plugins', name + '-' + version + '.jar')
|
|
168
|
+
: resolve(root, 'dist', name + '-' + version + '.jar');
|
|
169
|
+
mkdirSync(dirname(outJar), { recursive: true });
|
|
82
170
|
zip.writeZip(outJar);
|
|
83
|
-
console.log(
|
|
171
|
+
console.log(' \u2713 Packaged ' + outJar + '\n');
|
|
84
172
|
}
|
|
85
173
|
|
|
86
174
|
main().catch(e => { console.error(e); process.exit(1); });
|
|
@@ -231,13 +231,14 @@ function startHotReload() {
|
|
|
231
231
|
info('Source changed, rebuilding...');
|
|
232
232
|
try {
|
|
233
233
|
execSync('node .yeow/build.js', { cwd: ROOT, stdio: 'pipe', env: { ...process.env, YEOW_DEV: 'true' } });
|
|
234
|
-
const compiled = resolve(ROOT, 'dist', '.
|
|
234
|
+
const compiled = resolve(ROOT, 'dist', '.dev', 'main.js');
|
|
235
235
|
if (existsSync(compiled)) {
|
|
236
|
+
const devAssets = resolve(ROOT, 'dist', '.dev', '.assets');
|
|
236
237
|
broadcast({
|
|
237
238
|
type: 'hot-reload',
|
|
238
239
|
plugin: cfg.name,
|
|
239
240
|
codeFile: compiled.replace(/\\/g, '/'),
|
|
240
|
-
assetsDir: existsSync(
|
|
241
|
+
assetsDir: existsSync(devAssets) ? devAssets.replace(/\\/g, '/') : null,
|
|
241
242
|
});
|
|
242
243
|
_consumer = null;
|
|
243
244
|
ok('Hot reload sent via WebSocket');
|
|
@@ -289,7 +290,7 @@ async function printFormattedError(err) {
|
|
|
289
290
|
consumer = await getSourceMapConsumer();
|
|
290
291
|
}
|
|
291
292
|
if (hasMainJs && !consumer) {
|
|
292
|
-
|
|
293
|
+
const mapFile = resolve(ROOT, 'dist', '.dev', 'main.js.map');
|
|
293
294
|
out += ` ${c.D}(source-map not found: ${existsSync(mapFile) ? 'exists but failed to parse' : 'missing at ' + mapFile})${c.r}\n`;
|
|
294
295
|
}
|
|
295
296
|
|
|
@@ -374,7 +375,7 @@ async function main() {
|
|
|
374
375
|
await initServer();
|
|
375
376
|
serverProps(cfg.dev?.port || 17367);
|
|
376
377
|
buildPlugin();
|
|
377
|
-
copyToPlugins(resolve(ROOT, 'dist', `${cfg.name}-${cfg.version}.jar`), 'Plugin');
|
|
378
|
+
copyToPlugins(resolve(ROOT, 'dist', 'plugins', `${cfg.name}-${cfg.version}.jar`), 'Plugin');
|
|
378
379
|
copyToPlugins(RUNTIME, 'Runtime');
|
|
379
380
|
|
|
380
381
|
startHotReload();
|