create-yeow 0.5.2 → 0.6.0
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 +1 -1
- package/templates/default/.yeow/assets/yeow-runtime-0.6.0.jar +0 -0
- package/templates/default/.yeow/assets/yeow-runtime-folia-0.6.0.jar +0 -0
- package/templates/default/.yeow/assets/yeow-template-0.6.0.jar +0 -0
- package/templates/default/.yeow/build.js +190 -177
- package/templates/default/.yeow/dev-server.js +544 -544
- package/templates/default/.yeow/yeow-assets.mjs +27 -14
- package/templates/default/package.json +1 -1
- package/templates/default/sitemap.md +10 -12
- package/templates/default/.yeow/assets/yeow-runtime-0.5.1.jar +0 -0
- package/templates/default/.yeow/assets/yeow-runtime-folia-0.5.1.jar +0 -0
- package/templates/default/.yeow/assets/yeow-template-0.5.1.jar +0 -0
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,177 +1,190 @@
|
|
|
1
|
-
import * as esbuild from 'esbuild';
|
|
2
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync, statSync, readdirSync, rmSync } from 'fs';
|
|
3
|
-
import { resolve, dirname } from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
import AdmZip from 'adm-zip';
|
|
6
|
-
import { execSync } from 'child_process';
|
|
7
|
-
import { makeAssetPlugin, assetsOutDirFor, readMergedPermissions, prepareAssets, computeNativeManifest } from './yeow-assets.mjs';
|
|
8
|
-
|
|
9
|
-
const root = resolve(fileURLToPath(import.meta.url), '..', '..');
|
|
10
|
-
const cfg = JSON.parse(readFileSync(resolve(root, 'yeow.config.json'), 'utf-8'));
|
|
11
|
-
const pkgJson = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf-8'));
|
|
12
|
-
const { name, version } = cfg;
|
|
13
|
-
const isTs = existsSync(resolve(root, 'src', 'index.ts'));
|
|
14
|
-
const entry = isTs ? 'src/index.ts' : 'src/index.js';
|
|
15
|
-
|
|
16
|
-
// ── 类型检查(TS 项目)──
|
|
17
|
-
if (isTs && cfg.typecheck !== false) {
|
|
18
|
-
try {
|
|
19
|
-
execSync('npx -p typescript tsc --noEmit', { cwd: root, stdio: 'pipe' });
|
|
20
|
-
console.log(' \u2713 Type check passed');
|
|
21
|
-
} catch (e) {
|
|
22
|
-
const out = e.stdout?.toString().trim();
|
|
23
|
-
const err = e.stderr?.toString().trim();
|
|
24
|
-
if (out) console.error(out);
|
|
25
|
-
if (err) console.error(err);
|
|
26
|
-
if (!out && !err) console.error(' \u2717 Type check failed');
|
|
27
|
-
process.exit(1);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const apiVer = cfg.api || '1.18';
|
|
32
|
-
const isDev = process.env.YEOW_DEV === 'true';
|
|
33
|
-
const outDir = isDev ? resolve(root, 'dist', '.dev') : resolve(root, 'dist', '.yeow');
|
|
34
|
-
const assetsOut = assetsOutDirFor(outDir);
|
|
35
|
-
|
|
36
|
-
async function main() {
|
|
37
|
-
// 清空资产输出,避免旧哈希目录残留
|
|
38
|
-
rmSync(assetsOut, { recursive: true, force: true });
|
|
39
|
-
|
|
40
|
-
// ── 计算最终权限(computedPermissions:合并 + 通配归一化)──
|
|
41
|
-
const mergedPerms = readMergedPermissions(root, pkgJson);
|
|
42
|
-
// 回写 computedPermissions 到主项目 yeow.config.json(开发者声明的 permissions 保持原样)
|
|
43
|
-
try {
|
|
44
|
-
const cfgPath = resolve(root, 'yeow.config.json');
|
|
45
|
-
const cfgFile = JSON.parse(readFileSync(cfgPath, 'utf-8'));
|
|
46
|
-
if (JSON.stringify(cfgFile.computedPermissions) !== JSON.stringify(mergedPerms)) {
|
|
47
|
-
cfgFile.computedPermissions = mergedPerms;
|
|
48
|
-
writeFileSync(cfgPath, JSON.stringify(cfgFile, null, 4) + '\n');
|
|
49
|
-
console.log(' \u2713 computedPermissions written back to yeow.config.json');
|
|
50
|
-
}
|
|
51
|
-
} catch (e) { /* 写回失败不阻塞构建 */ }
|
|
52
|
-
if (mergedPerms.length > 0) {
|
|
53
|
-
console.log(' \u2713 Computed permissions (' + mergedPerms.length + '): ' + mergedPerms.join(', '));
|
|
54
|
-
} else {
|
|
55
|
-
console.log(' \u2713 No permissions declared');
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// ── 资产准备(id 分配 + 部署;与插件共享,保证路径一致)──
|
|
59
|
-
const prepared = prepareAssets(root, pkgJson, outDir);
|
|
60
|
-
|
|
61
|
-
// ── Worker 打包(dev.worker 配置:先打包各 worker,再打包主插件)──
|
|
62
|
-
// 产物输出到主项目资产目录(assets/<rootId>/<dist 去 assets/ 前缀>),
|
|
63
|
-
// 主插件经 getAssetsPath(dist) 读取;dev 模式带 sourcemap(错误回显反解)。
|
|
64
|
-
const workers = (cfg.dev && cfg.dev.worker) || [];
|
|
65
|
-
for (const w of workers) {
|
|
66
|
-
if (!w?.name || !w?.entry || !w?.dist) {
|
|
67
|
-
console.warn(' ! dev.worker entry incomplete (name/entry/dist required): ' + JSON.stringify(w));
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
const distRel = String(w.dist).replace(/^assets\//, '');
|
|
71
|
-
const outfile = resolve(prepared.assetsOutDir, prepared.rootId, distRel);
|
|
72
|
-
mkdirSync(dirname(outfile), { recursive: true });
|
|
73
|
-
await esbuild.build({
|
|
74
|
-
entryPoints: [resolve(root, w.entry)],
|
|
75
|
-
outfile,
|
|
76
|
-
bundle: true,
|
|
77
|
-
format: 'iife',
|
|
78
|
-
target: 'esnext',
|
|
79
|
-
platform: 'neutral',
|
|
80
|
-
mainFields: ['module', 'main'],
|
|
81
|
-
conditions: ['import', 'browser'],
|
|
82
|
-
treeShaking: true,
|
|
83
|
-
minify: false,
|
|
84
|
-
sourcemap: isDev ? 'linked' : false,
|
|
85
|
-
plugins: [makeAssetPlugin({ root, pkgJson, outDir, prepared })],
|
|
86
|
-
});
|
|
87
|
-
console.log(' \u2713 Worker bundled: ' + w.name + ' (' + w.entry + ' \u2192 ' + w.dist + ')');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// ── 原生服务可信性声明(native manifest:打包后路径 → SHA-256)──
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
],
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
1
|
+
import * as esbuild from 'esbuild';
|
|
2
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, statSync, readdirSync, rmSync } from 'fs';
|
|
3
|
+
import { resolve, dirname } from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import AdmZip from 'adm-zip';
|
|
6
|
+
import { execSync } from 'child_process';
|
|
7
|
+
import { makeAssetPlugin, assetsOutDirFor, readMergedPermissions, prepareAssets, computeNativeManifest } from './yeow-assets.mjs';
|
|
8
|
+
|
|
9
|
+
const root = resolve(fileURLToPath(import.meta.url), '..', '..');
|
|
10
|
+
const cfg = JSON.parse(readFileSync(resolve(root, 'yeow.config.json'), 'utf-8'));
|
|
11
|
+
const pkgJson = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf-8'));
|
|
12
|
+
const { name, version } = cfg;
|
|
13
|
+
const isTs = existsSync(resolve(root, 'src', 'index.ts'));
|
|
14
|
+
const entry = isTs ? 'src/index.ts' : 'src/index.js';
|
|
15
|
+
|
|
16
|
+
// ── 类型检查(TS 项目)──
|
|
17
|
+
if (isTs && cfg.typecheck !== false) {
|
|
18
|
+
try {
|
|
19
|
+
execSync('npx -p typescript tsc --noEmit', { cwd: root, stdio: 'pipe' });
|
|
20
|
+
console.log(' \u2713 Type check passed');
|
|
21
|
+
} catch (e) {
|
|
22
|
+
const out = e.stdout?.toString().trim();
|
|
23
|
+
const err = e.stderr?.toString().trim();
|
|
24
|
+
if (out) console.error(out);
|
|
25
|
+
if (err) console.error(err);
|
|
26
|
+
if (!out && !err) console.error(' \u2717 Type check failed');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const apiVer = cfg.api || '1.18';
|
|
32
|
+
const isDev = process.env.YEOW_DEV === 'true';
|
|
33
|
+
const outDir = isDev ? resolve(root, 'dist', '.dev') : resolve(root, 'dist', '.yeow');
|
|
34
|
+
const assetsOut = assetsOutDirFor(outDir);
|
|
35
|
+
|
|
36
|
+
async function main() {
|
|
37
|
+
// 清空资产输出,避免旧哈希目录残留
|
|
38
|
+
rmSync(assetsOut, { recursive: true, force: true });
|
|
39
|
+
|
|
40
|
+
// ── 计算最终权限(computedPermissions:合并 + 通配归一化)──
|
|
41
|
+
const mergedPerms = readMergedPermissions(root, pkgJson);
|
|
42
|
+
// 回写 computedPermissions 到主项目 yeow.config.json(开发者声明的 permissions 保持原样)
|
|
43
|
+
try {
|
|
44
|
+
const cfgPath = resolve(root, 'yeow.config.json');
|
|
45
|
+
const cfgFile = JSON.parse(readFileSync(cfgPath, 'utf-8'));
|
|
46
|
+
if (JSON.stringify(cfgFile.computedPermissions) !== JSON.stringify(mergedPerms)) {
|
|
47
|
+
cfgFile.computedPermissions = mergedPerms;
|
|
48
|
+
writeFileSync(cfgPath, JSON.stringify(cfgFile, null, 4) + '\n');
|
|
49
|
+
console.log(' \u2713 computedPermissions written back to yeow.config.json');
|
|
50
|
+
}
|
|
51
|
+
} catch (e) { /* 写回失败不阻塞构建 */ }
|
|
52
|
+
if (mergedPerms.length > 0) {
|
|
53
|
+
console.log(' \u2713 Computed permissions (' + mergedPerms.length + '): ' + mergedPerms.join(', '));
|
|
54
|
+
} else {
|
|
55
|
+
console.log(' \u2713 No permissions declared');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ── 资产准备(id 分配 + 部署;与插件共享,保证路径一致)──
|
|
59
|
+
const prepared = prepareAssets(root, pkgJson, outDir);
|
|
60
|
+
|
|
61
|
+
// ── Worker 打包(dev.worker 配置:先打包各 worker,再打包主插件)──
|
|
62
|
+
// 产物输出到主项目资产目录(assets/<rootId>/<dist 去 assets/ 前缀>),
|
|
63
|
+
// 主插件经 getAssetsPath(dist) 读取;dev 模式带 sourcemap(错误回显反解)。
|
|
64
|
+
const workers = (cfg.dev && cfg.dev.worker) || [];
|
|
65
|
+
for (const w of workers) {
|
|
66
|
+
if (!w?.name || !w?.entry || !w?.dist) {
|
|
67
|
+
console.warn(' ! dev.worker entry incomplete (name/entry/dist required): ' + JSON.stringify(w));
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const distRel = String(w.dist).replace(/^assets\//, '');
|
|
71
|
+
const outfile = resolve(prepared.assetsOutDir, prepared.rootId, distRel);
|
|
72
|
+
mkdirSync(dirname(outfile), { recursive: true });
|
|
73
|
+
await esbuild.build({
|
|
74
|
+
entryPoints: [resolve(root, w.entry)],
|
|
75
|
+
outfile,
|
|
76
|
+
bundle: true,
|
|
77
|
+
format: 'iife',
|
|
78
|
+
target: 'esnext',
|
|
79
|
+
platform: 'neutral',
|
|
80
|
+
mainFields: ['module', 'main'],
|
|
81
|
+
conditions: ['import', 'browser'],
|
|
82
|
+
treeShaking: true,
|
|
83
|
+
minify: false,
|
|
84
|
+
sourcemap: isDev ? 'linked' : false,
|
|
85
|
+
plugins: [makeAssetPlugin({ root, pkgJson, outDir, prepared })],
|
|
86
|
+
});
|
|
87
|
+
console.log(' \u2713 Worker bundled: ' + w.name + ' (' + w.entry + ' \u2192 ' + w.dist + ')');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ── 原生服务可信性声明(native manifest:打包后路径 → SHA-256)──
|
|
91
|
+
// 合并来源:主项目 + 每个依赖包各自的 yeow.config.json(依赖包在自身 native 中声明)
|
|
92
|
+
const nativeManifest = computeNativeManifest(prepared);
|
|
93
|
+
if (nativeManifest.length > 0) {
|
|
94
|
+
const fileCount = nativeManifest.reduce((n, e) => n + e.files.length, 0);
|
|
95
|
+
console.log(' \u2713 Native manifest (' + nativeManifest.length + ' services, ' + fileCount + ' files, SHA-256)');
|
|
96
|
+
for (const e of nativeManifest) {
|
|
97
|
+
console.log(' - ' + e.serviceId + ' (' + e.files.length + ' file' + (e.files.length > 1 ? 's' : '') + ')');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// ── 强制声明:任一包申请了原生服务权限,合并后的 native 清单就不能为空(构建即失败,避免运行期拒绝加载)──
|
|
101
|
+
const wantsNative = mergedPerms.some(p => p === 'service:registerNative' || p === 'service:*');
|
|
102
|
+
if (wantsNative && nativeManifest.length === 0) {
|
|
103
|
+
console.error('\n \u2717 `service:registerNative` is declared (by the main project or a dependency package)');
|
|
104
|
+
console.error(' but the merged `native` manifest is empty.');
|
|
105
|
+
console.error(' Declare `native` in the declaring package\'s yeow.config.json (serviceId + binary');
|
|
106
|
+
console.error(' files) so every native binary is pinned by SHA-256, then rebuild.\n');
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ── 打包 ──
|
|
111
|
+
await esbuild.build({
|
|
112
|
+
entryPoints: [resolve(root, entry)],
|
|
113
|
+
outfile: resolve(outDir, 'main.js'),
|
|
114
|
+
bundle: true,
|
|
115
|
+
format: 'iife',
|
|
116
|
+
target: 'esnext',
|
|
117
|
+
platform: 'neutral',
|
|
118
|
+
mainFields: ['module', 'main'],
|
|
119
|
+
conditions: ['import', 'browser'],
|
|
120
|
+
treeShaking: true,
|
|
121
|
+
minify: false,
|
|
122
|
+
sourcemap: isDev ? 'linked' : false,
|
|
123
|
+
plugins: [
|
|
124
|
+
makeAssetPlugin({ root, pkgJson, outDir, prepared }),
|
|
125
|
+
],
|
|
126
|
+
});
|
|
127
|
+
console.log(' \u2713 Bundled (' + (statSync(resolve(outDir, 'main.js')).size / 1024).toFixed(1) + ' KB)');
|
|
128
|
+
|
|
129
|
+
// ── 组装 JAR ──
|
|
130
|
+
const zip = new AdmZip(resolve(root, '.yeow', 'assets', 'yeow-template-0.6.0.jar'));
|
|
131
|
+
zip.updateFile('plugin.yml', Buffer.from(
|
|
132
|
+
'name: ' + name + '\n' +
|
|
133
|
+
'version: ' + version + '\n' +
|
|
134
|
+
'main: yeow.template.Bootstrap\n' +
|
|
135
|
+
'api-version: \'' + apiVer + '\'\n' +
|
|
136
|
+
'depend:\n - Yeow\n'));
|
|
137
|
+
|
|
138
|
+
if (isDev) {
|
|
139
|
+
const devInfo = {
|
|
140
|
+
name,
|
|
141
|
+
codeFile: resolve(outDir, 'main.js').replace(/\\/g, '/'),
|
|
142
|
+
assetsDir: assetsOut.replace(/\\/g, '/'),
|
|
143
|
+
};
|
|
144
|
+
writeFileSync(resolve(outDir, 'dev.json'), JSON.stringify(devInfo, null, 2));
|
|
145
|
+
zip.addFile('.yeow/dev.json', readFileSync(resolve(outDir, 'dev.json')));
|
|
146
|
+
console.log(' \u2713 Dev info written');
|
|
147
|
+
} else {
|
|
148
|
+
zip.addFile('.yeow/main.js', readFileSync(resolve(outDir, 'main.js')));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// 资产(esbuild 插件已写入 assetsOut)
|
|
152
|
+
if (existsSync(assetsOut)) {
|
|
153
|
+
const files = readdirSync(assetsOut, { recursive: true }).filter(f => statSync(resolve(assetsOut, f)).isFile());
|
|
154
|
+
for (const f of files) {
|
|
155
|
+
zip.addFile('assets/' + f.replace(/\\/g, '/'), readFileSync(resolve(assetsOut, f)));
|
|
156
|
+
}
|
|
157
|
+
console.log(' \u2713 Assets included (' + files.length + ' files)');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
zip.addFile('yeow.json', Buffer.from(JSON.stringify({ ...cfg, computedPermissions: mergedPerms, native: nativeManifest })));
|
|
161
|
+
const outJar = resolve(root, 'dist', isDev ? 'plugins' : '', name + '-' + version + '.jar');
|
|
162
|
+
mkdirSync(dirname(outJar), { recursive: true });
|
|
163
|
+
zip.writeZip(outJar);
|
|
164
|
+
console.log(' \u2713 Packaged ' + outJar + '\n');
|
|
165
|
+
|
|
166
|
+
// ── 组装 .yeow.zip ──
|
|
167
|
+
// 平台无关插件包:生产放入 plugins/Yeow/ 被自动扫描加载(或 /yeow load/install);
|
|
168
|
+
// 开发模式同样生成(含 .yeow/dev.json 指向编译产物路径),由 dev-server 部署到 plugins/Yeow/。
|
|
169
|
+
{
|
|
170
|
+
const pkgZip = new AdmZip();
|
|
171
|
+
if (isDev) {
|
|
172
|
+
pkgZip.addFile('.yeow/dev.json', readFileSync(resolve(outDir, 'dev.json')));
|
|
173
|
+
} else {
|
|
174
|
+
pkgZip.addFile('.yeow/main.js', readFileSync(resolve(outDir, 'main.js')));
|
|
175
|
+
}
|
|
176
|
+
if (existsSync(assetsOut)) {
|
|
177
|
+
const files = readdirSync(assetsOut, { recursive: true }).filter(f => statSync(resolve(assetsOut, f)).isFile());
|
|
178
|
+
for (const f of files) {
|
|
179
|
+
pkgZip.addFile('assets/' + f.replace(/\\/g, '/'), readFileSync(resolve(assetsOut, f)));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
pkgZip.addFile('yeow.json', Buffer.from(JSON.stringify({ ...cfg, computedPermissions: mergedPerms, native: nativeManifest })));
|
|
183
|
+
const outZip = resolve(root, 'dist', isDev ? 'plugins' : '', name + '-' + version + '.yeow.zip');
|
|
184
|
+
mkdirSync(dirname(outZip), { recursive: true });
|
|
185
|
+
pkgZip.writeZip(outZip);
|
|
186
|
+
console.log(' \u2713 Packaged ' + outZip + '\n');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
main().catch(e => { console.error(e); process.exit(1); });
|