@xunlei-open/miniapp 0.1.1-beta.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 miniapp-devkit contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # @xunlei-open/miniapp
2
+
3
+ 迅雷微应用统一开发工具,内部复用 Vite,提供开发、构建、校验和打包命令。
4
+
5
+ ```bash
6
+ pnpm add -D @xunlei-open/miniapp
7
+ ```
8
+
9
+ ```json
10
+ {
11
+ "scripts": {
12
+ "dev": "xunlei-miniapp",
13
+ "build": "xunlei-miniapp build",
14
+ "package": "xunlei-miniapp package"
15
+ }
16
+ }
17
+ ```
18
+
19
+ 项目使用 `miniapp.config.ts` 作为唯一工具配置:
20
+
21
+ ```ts
22
+ import { defineConfig } from '@xunlei-open/miniapp'
23
+
24
+ export default defineConfig({
25
+ vite: {
26
+ build: {
27
+ target: 'es2015',
28
+ },
29
+ },
30
+ })
31
+ ```
32
+
33
+ 框架插件、alias、CSS、开发服务器等 Vite 配置均写在 `vite` 字段中。`manifest.json` 继续作为迅雷运行时读取的应用清单。
34
+
35
+ ## 命令
36
+
37
+ Vue/React 项目可安装 `@xunlei-open/miniapp-module-vue` / `@xunlei-open/miniapp-module-react`,并在配置中声明 `modules: ['@xunlei-open/miniapp-module-vue']`。模块从项目依赖中解析,按声明顺序合并 Vite 配置,最后合并项目的 `vite` 配置,无需再次注册框架插件。Vanilla 项目无需模块。
38
+
39
+ 自定义模块默认导出 `defineMiniappModule({ name, vite })`,其中 `vite` 支持配置对象或接收 Vite `ConfigEnv` 的异步函数。`defineMiniappModule` 从 `@xunlei-open/miniapp` 导入。
40
+
41
+ dev、build 和 package 均不默认执行类型检查。TS 模板提供可选的 `typecheck` 脚本,供手动执行或 CI 使用。
42
+
43
+ 支持纯页面、纯事件、页面与事件并存三种形态。纯事件微应用只需声明 manifest 的 `scripts`,不声明 `entry`,也不需要 `index.html` 或框架模块。dev 会编译并监听事件脚本、同步 manifest 和图标,不启动页面 HTTP 服务;build 和 package 同样无需页面文件。
44
+
45
+ 开发时加载终端提示的 `dist` 目录(或 `vite.build.outDir`)。CLI 将经过 Vite 和框架插件转换的 HTML 写入该目录,并复制 manifest 和图标。本地 HTML 通过绝对 URL 从开发服务器加载模块、资源和 HMR 客户端,因此需要保持 dev 服务运行。Vue/React 的模块热更新无需整页刷新;HTML 入口修改会重新生成本地入口并刷新页面。
46
+
47
+ dev 也会将 `src/events`(或配置的 `events.dir`)中的事件脚本编译到 `dist/events`,监听脚本及其导入依赖的修改,并处理入口新增、删除。事件构建不会覆盖页面的 HMR 入口;manifest 声明的脚本缺少对应源码时,启动会报错。事件编译失败会保留上一次成功编译的产物并输出错误,修复后自动重试。
48
+
49
+ 只有 manifest 的 `icon` 字段声明的应用图标会复制到开发目录,修改、删除或重新创建图标文件也会同步。事件沙箱和宿主应用图标不使用页面 HMR:如果宿主缓存脚本或图标,需在宿主中重新加载应用。修改 manifest 的入口、脚本声明或图标路径仍需重启 dev。
50
+
51
+ 默认允许本地文件的 `null` origin 访问开发资源。如果宿主使用自己的协议并发送其他 Origin,可通过 `vite.server.cors.origin` 配置该来源;宿主也需要允许访问本机开发服务器及其 WebSocket。开发入口使用绝对资源地址,不注入 `<base>`,兼容 `base-uri 'none'`。修改 manifest 后重启 dev 并重新加载应用。发布前运行 build 生成生产产物。
52
+
53
+ ```bash
54
+ xunlei-miniapp # 启动开发服务
55
+ xunlei-miniapp build # 构建并校验 dist
56
+ xunlei-miniapp package # 构建、校验并生成 ZIP
57
+ xunlei-miniapp package --no-build
58
+ xunlei-miniapp validate # 校验当前配置对应的构建目录
59
+ ```
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ import '../dist/cli.mjs'
package/dist/cli.d.mts ADDED
@@ -0,0 +1 @@
1
+ export {}
package/dist/cli.mjs ADDED
@@ -0,0 +1,96 @@
1
+ import { i as validateBuiltMiniapp, n as buildMiniapp, r as devMiniapp, t as packageMiniapp } from "./package-BQM2LBwr.mjs";
2
+ import { parseArgs } from "node:util";
3
+ //#region src/cli.ts
4
+ const HELP = `Xunlei Miniapp CLI
5
+
6
+ Usage:
7
+ xunlei-miniapp [root] [options]
8
+ xunlei-miniapp dev [root] [options]
9
+ xunlei-miniapp build [root] [options]
10
+ xunlei-miniapp package [root] [options]
11
+ xunlei-miniapp validate [root]
12
+
13
+ Options:
14
+ --mode <mode> Set the Vite mode
15
+ --host <host> Set the dev server host
16
+ --port <port> Set the dev server port
17
+ --out <file> Set the package output ZIP
18
+ --no-build Package the existing build output
19
+ -h, --help Show this help
20
+ `;
21
+ function readPort(value) {
22
+ if (value === void 0) return void 0;
23
+ const port = Number(value);
24
+ if (!Number.isInteger(port) || port <= 0 || port > 65535) throw new Error(`Invalid port: ${value}`);
25
+ return port;
26
+ }
27
+ async function main() {
28
+ const { values, positionals } = parseArgs({
29
+ allowPositionals: true,
30
+ options: {
31
+ help: {
32
+ type: "boolean",
33
+ short: "h"
34
+ },
35
+ mode: { type: "string" },
36
+ host: { type: "string" },
37
+ port: { type: "string" },
38
+ out: { type: "string" },
39
+ "no-build": { type: "boolean" }
40
+ }
41
+ });
42
+ if (values.help) {
43
+ console.log(HELP);
44
+ return;
45
+ }
46
+ const knownCommands = /* @__PURE__ */ new Set([
47
+ "dev",
48
+ "build",
49
+ "package",
50
+ "validate"
51
+ ]);
52
+ const first = positionals[0];
53
+ const command = first && knownCommands.has(first) ? first : "dev";
54
+ const root = command === "dev" && first !== "dev" ? first : positionals[1];
55
+ if (command === "dev") {
56
+ await devMiniapp({
57
+ root,
58
+ mode: values.mode,
59
+ host: values.host,
60
+ port: readPort(values.port)
61
+ });
62
+ return;
63
+ }
64
+ if (command === "build") {
65
+ const result = await buildMiniapp({
66
+ root,
67
+ mode: values.mode
68
+ });
69
+ console.log(`Miniapp built: ${result.outDir}`);
70
+ return;
71
+ }
72
+ if (command === "package") {
73
+ const result = await packageMiniapp({
74
+ root,
75
+ mode: values.mode,
76
+ outFile: values.out,
77
+ build: !values["no-build"]
78
+ });
79
+ console.log(`Miniapp packaged: ${result.outFile}`);
80
+ return;
81
+ }
82
+ const result = await validateBuiltMiniapp({
83
+ root,
84
+ mode: values.mode
85
+ });
86
+ console.log(`Miniapp package is valid: ${result.directory}`);
87
+ }
88
+ main().catch((error) => {
89
+ const message = error instanceof Error ? error.message : String(error);
90
+ console.error(`\n✖ ${message}\n`);
91
+ process.exitCode = 1;
92
+ });
93
+ //#endregion
94
+ export {};
95
+
96
+ //# sourceMappingURL=cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { parseArgs } from 'node:util'\nimport { packageMiniapp } from './package.js'\nimport { buildMiniapp, devMiniapp, validateBuiltMiniapp } from './vite.js'\n\nconst HELP = `Xunlei Miniapp CLI\n\nUsage:\n xunlei-miniapp [root] [options]\n xunlei-miniapp dev [root] [options]\n xunlei-miniapp build [root] [options]\n xunlei-miniapp package [root] [options]\n xunlei-miniapp validate [root]\n\nOptions:\n --mode <mode> Set the Vite mode\n --host <host> Set the dev server host\n --port <port> Set the dev server port\n --out <file> Set the package output ZIP\n --no-build Package the existing build output\n -h, --help Show this help\n`\n\nfunction readPort(value: string | undefined): number | undefined {\n if (value === undefined) return undefined\n const port = Number(value)\n if (!Number.isInteger(port) || port <= 0 || port > 65_535) {\n throw new Error(`Invalid port: ${value}`)\n }\n return port\n}\n\nasync function main(): Promise<void> {\n const { values, positionals } = parseArgs({\n allowPositionals: true,\n options: {\n help: { type: 'boolean', short: 'h' },\n mode: { type: 'string' },\n host: { type: 'string' },\n port: { type: 'string' },\n out: { type: 'string' },\n 'no-build': { type: 'boolean' },\n },\n })\n\n if (values.help) {\n console.log(HELP)\n return\n }\n\n const knownCommands = new Set(['dev', 'build', 'package', 'validate'])\n const first = positionals[0]\n const command = first && knownCommands.has(first) ? first : 'dev'\n const root = command === 'dev' && first !== 'dev' ? first : positionals[1]\n\n if (command === 'dev') {\n await devMiniapp({\n root,\n mode: values.mode,\n host: values.host,\n port: readPort(values.port),\n })\n return\n }\n if (command === 'build') {\n const result = await buildMiniapp({ root, mode: values.mode })\n console.log(`Miniapp built: ${result.outDir}`)\n return\n }\n if (command === 'package') {\n const result = await packageMiniapp({\n root,\n mode: values.mode,\n outFile: values.out,\n build: !values['no-build'],\n })\n console.log(`Miniapp packaged: ${result.outFile}`)\n return\n }\n\n const result = await validateBuiltMiniapp({ root, mode: values.mode })\n console.log(`Miniapp package is valid: ${result.directory}`)\n}\n\nmain().catch((error: unknown) => {\n const message = error instanceof Error ? error.message : String(error)\n console.error(`\\n✖ ${message}\\n`)\n process.exitCode = 1\n})\n"],"mappings":";;;AAIA,MAAM,OAAO;;;;;;;;;;;;;;;;;AAkBb,SAAS,SAAS,OAA+C;CAC/D,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,MAAM,OAAO,OAAO,KAAK;CACzB,IAAI,CAAC,OAAO,UAAU,IAAI,KAAK,QAAQ,KAAK,OAAO,OACjD,MAAM,IAAI,MAAM,iBAAiB,OAAO;CAE1C,OAAO;AACT;AAEA,eAAe,OAAsB;CACnC,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC,kBAAkB;EAClB,SAAS;GACP,MAAM;IAAE,MAAM;IAAW,OAAO;GAAI;GACpC,MAAM,EAAE,MAAM,SAAS;GACvB,MAAM,EAAE,MAAM,SAAS;GACvB,MAAM,EAAE,MAAM,SAAS;GACvB,KAAK,EAAE,MAAM,SAAS;GACtB,YAAY,EAAE,MAAM,UAAU;EAChC;CACF,CAAC;CAED,IAAI,OAAO,MAAM;EACf,QAAQ,IAAI,IAAI;EAChB;CACF;CAEA,MAAM,gCAAgB,IAAI,IAAI;EAAC;EAAO;EAAS;EAAW;CAAU,CAAC;CACrE,MAAM,QAAQ,YAAY;CAC1B,MAAM,UAAU,SAAS,cAAc,IAAI,KAAK,IAAI,QAAQ;CAC5D,MAAM,OAAO,YAAY,SAAS,UAAU,QAAQ,QAAQ,YAAY;CAExE,IAAI,YAAY,OAAO;EACrB,MAAM,WAAW;GACf;GACA,MAAM,OAAO;GACb,MAAM,OAAO;GACb,MAAM,SAAS,OAAO,IAAI;EAC5B,CAAC;EACD;CACF;CACA,IAAI,YAAY,SAAS;EACvB,MAAM,SAAS,MAAM,aAAa;GAAE;GAAM,MAAM,OAAO;EAAK,CAAC;EAC7D,QAAQ,IAAI,kBAAkB,OAAO,QAAQ;EAC7C;CACF;CACA,IAAI,YAAY,WAAW;EACzB,MAAM,SAAS,MAAM,eAAe;GAClC;GACA,MAAM,OAAO;GACb,SAAS,OAAO;GAChB,OAAO,CAAC,OAAO;EACjB,CAAC;EACD,QAAQ,IAAI,qBAAqB,OAAO,SAAS;EACjD;CACF;CAEA,MAAM,SAAS,MAAM,qBAAqB;EAAE;EAAM,MAAM,OAAO;CAAK,CAAC;CACrE,QAAQ,IAAI,6BAA6B,OAAO,WAAW;AAC7D;AAEA,KAAK,CAAC,CAAC,OAAO,UAAmB;CAC/B,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;CACrE,QAAQ,MAAM,OAAO,QAAQ,GAAG;CAChC,QAAQ,WAAW;AACrB,CAAC"}
@@ -0,0 +1,100 @@
1
+ import { ConfigEnv, UserConfig, ViteDevServer } from "vite";
2
+ import { MiniappManifest } from "@xunlei-open/miniapp-types";
3
+ //#region src/types.d.ts
4
+ /** 可直接返回的值或异步返回该值的承诺对象。 */
5
+ type MaybePromise<T> = T | Promise<T>;
6
+ interface MiniappEventsConfig {
7
+ /** 事件脚本目录,默认相对于项目根目录。默认值:`src/events`。 */
8
+ dir?: string;
9
+ /** 识别的事件脚本扩展名,需包含前导点。默认值:`['.ts', '.js']`。 */
10
+ extensions?: string[];
11
+ }
12
+ interface MiniappPackageConfig {
13
+ /** 未显式指定输出文件时使用的打包目录。默认值:`release`。 */
14
+ outDir?: string;
15
+ /** 压缩包文件名,不得包含目录,须以 `.zip` 结尾。默认由清单中的名称和版本经文件名清理后拼接为 `<名称>-<版本>.zip`。 */
16
+ fileName?: string;
17
+ }
18
+ /** 构建工具配置,支持配置对象或根据运行环境同步、异步生成配置的函数。 */
19
+ type MiniappViteConfig = UserConfig | ((env: ConfigEnv) => MaybePromise<UserConfig>);
20
+ interface MiniappUserConfig {
21
+ /** 框架模块列表,按声明顺序从项目依赖中解析并加载,重复模块仅加载一次。 */
22
+ modules?: string[];
23
+ /** 微应用清单路径,默认相对于项目根目录。默认值:`manifest.json`。 */
24
+ manifest?: string;
25
+ /** 事件脚本配置。 */
26
+ events?: MiniappEventsConfig;
27
+ /** 压缩包输出配置。 */
28
+ package?: MiniappPackageConfig;
29
+ /** 项目构建配置,在框架模块提供的默认配置之后合并。 */
30
+ vite?: MiniappViteConfig;
31
+ }
32
+ interface MiniappModule {
33
+ /** 模块名称。 */
34
+ name: string;
35
+ /** 模块提供的默认构建配置,项目配置会在此基础上合并。 */
36
+ vite: MiniappViteConfig;
37
+ }
38
+ /** 加载并合并默认值、框架模块和项目配置后的结果。 */
39
+ interface ResolvedMiniappConfig {
40
+ root: string;
41
+ configFile: string;
42
+ manifestFile: string;
43
+ eventsDir: string;
44
+ eventsExtensions: string[];
45
+ packageOutDir: string;
46
+ packageFileName?: string;
47
+ vite: UserConfig;
48
+ }
49
+ /** 微应用目录校验结果,包含清单和文件列表。 */
50
+ interface MiniappValidationResult {
51
+ directory: string;
52
+ manifestPath: string;
53
+ manifest: MiniappManifest;
54
+ files: string[];
55
+ }
56
+ interface BuildMiniappOptions {
57
+ /** 项目根目录,默认为当前工作目录。 */
58
+ root?: string;
59
+ /** 运行模式。 */
60
+ mode?: string;
61
+ }
62
+ interface DevMiniappOptions extends BuildMiniappOptions {
63
+ /** 开发服务器监听地址。 */
64
+ host?: string;
65
+ /** 开发服务器监听端口。 */
66
+ port?: number;
67
+ }
68
+ interface PackageMiniappOptions extends BuildMiniappOptions {
69
+ /** 打包前是否执行构建,默认为 true。 */
70
+ build?: boolean;
71
+ /** 输出压缩包路径,相对路径以项目根目录为基准;指定后优先于打包目录和文件名配置。 */
72
+ outFile?: string;
73
+ }
74
+ //#endregion
75
+ //#region src/config.d.ts
76
+ export declare function defineConfig(config: MiniappUserConfig): MiniappUserConfig;
77
+ export declare function defineMiniappModule(module: MiniappModule): MiniappModule;
78
+ export declare function loadMiniappConfig(rootDirectory: string, env: ConfigEnv): Promise<ResolvedMiniappConfig>;
79
+ //#endregion
80
+ //#region src/package.d.ts
81
+ export declare function packageMiniapp(options?: PackageMiniappOptions): Promise<{
82
+ outFile: string;
83
+ outDir: string;
84
+ }>;
85
+ //#endregion
86
+ //#region src/validate.d.ts
87
+ export declare function readMiniappManifest(manifestPath: string): Promise<MiniappManifest>;
88
+ export declare function validateSourceManifest(manifestPath: string): Promise<MiniappManifest>;
89
+ export declare function validateMiniappDirectory(directoryPath: string): Promise<MiniappValidationResult>;
90
+ //#endregion
91
+ //#region src/vite.d.ts
92
+ export declare function buildMiniapp(options?: BuildMiniappOptions): Promise<{
93
+ config: ResolvedMiniappConfig;
94
+ outDir: string;
95
+ }>;
96
+ export declare function validateBuiltMiniapp(options?: BuildMiniappOptions): Promise<MiniappValidationResult>;
97
+ export declare function devMiniapp(options?: DevMiniappOptions): Promise<ViteDevServer>;
98
+ //#endregion
99
+ export type { BuildMiniappOptions, DevMiniappOptions, MiniappEventsConfig, MiniappModule, MiniappPackageConfig, MiniappUserConfig, MiniappValidationResult, MiniappViteConfig, PackageMiniappOptions, ResolvedMiniappConfig };
100
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/config.ts","../src/package.ts","../src/validate.ts","../src/vite.ts"],"mappings":";;;;KAIY,aAAa,KAAK,IAAI,QAAQ;UAEzB;;EAEf;;EAEA;;UAGe;;EAEf;;EAEA;;;KAIU,oBACR,eACE,KAAK,cAAc,aAAa;UAErB;;EAEf;;EAEA;;EAEA,SAAS;;EAET,UAAU;;EAEV,OAAO;;UAGQ;;EAEf;;EAEA,MAAM;;;UAIS;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA,MAAM;;;UAIS;EACf;EACA;EACA,UAAU;EACV;;UAGe;;EAEf;;EAEA;;UAGe,0BAA0B;;EAEzC;;EAEA;;UAGe,8BAA8B;;EAE7C;;EAEA;;;;wBC7Dc,aAAa,QAAQ,oBAAoB;wBAIzC,oBAAoB,QAAQ,gBAAgB;wBA0DtC,kBACpB,uBACA,KAAK,YACJ,QAAQ;;;wBClBW,eACpB,UAAS,wBACR;EAAU;EAAiB;;;;wBCRR,oBAAoB,uBAAuB,QAAQ;wBAoBnD,uBAAuB,uBAAuB,QAAQ;wBAItD,yBACpB,wBACC,QAAQ;;;wBC5CW,aACpB,UAAS,sBACR;EAAU,QAAQ;EAAuB;;wBAYtB,qBACpB,UAAS,sBAAwB,QAAxB;wBAQW,WACpB,UAAS,oBACR,QAAQ"}
package/dist/index.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import { a as readMiniappManifest, c as defineConfig, i as validateBuiltMiniapp, l as defineMiniappModule, n as buildMiniapp, o as validateMiniappDirectory, r as devMiniapp, s as validateSourceManifest, t as packageMiniapp, u as loadMiniappConfig } from "./package-BQM2LBwr.mjs";
2
+ export { buildMiniapp, defineConfig, defineMiniappModule, devMiniapp, loadMiniappConfig, packageMiniapp, readMiniappManifest, validateBuiltMiniapp, validateMiniappDirectory, validateSourceManifest };
@@ -0,0 +1,557 @@
1
+ import { createRequire } from "node:module";
2
+ import { createWriteStream, existsSync } from "node:fs";
3
+ import { basename, dirname, isAbsolute, relative, resolve, sep, win32 } from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ import { build, createServer, loadConfigFromFile, mergeConfig, normalizePath } from "vite";
6
+ import { copyFile, lstat, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
7
+ import { pipeline } from "node:stream/promises";
8
+ import yazl from "yazl";
9
+ import miniappPlugin from "@xunlei-open/vite-plugin-miniapp";
10
+ import { createHash } from "node:crypto";
11
+ import { parse, serialize } from "parse5";
12
+ //#region src/config.ts
13
+ const CONFIG_FILES = [
14
+ "miniapp.config.ts",
15
+ "miniapp.config.mts",
16
+ "miniapp.config.js",
17
+ "miniapp.config.mjs",
18
+ "miniapp.config.cts",
19
+ "miniapp.config.cjs"
20
+ ];
21
+ const DEFAULT_EVENT_EXTENSIONS = [".ts", ".js"];
22
+ function defineConfig(config) {
23
+ return config;
24
+ }
25
+ function defineMiniappModule(module) {
26
+ return module;
27
+ }
28
+ async function loadModules(names, configFile, env) {
29
+ if (!Array.isArray(names) || names.some((name) => typeof name !== "string" || !name.trim())) throw new Error("miniapp.config modules must be an array of module names");
30
+ const require = createRequire(configFile);
31
+ let config = {};
32
+ for (const name of new Set(names)) try {
33
+ const { default: module } = await import(pathToFileURL(require.resolve(name)).href);
34
+ if (!module || typeof module !== "object" || typeof module.name !== "string" || !module.vite) throw new Error("must export a MiniappModule with name and vite fields");
35
+ config = mergeConfig(config, await resolveViteConfig(module.vite, env));
36
+ } catch (error) {
37
+ throw new Error(`Failed to load miniapp module "${name}" from ${configFile}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
38
+ }
39
+ return config;
40
+ }
41
+ function findConfigFile(root) {
42
+ const matches = CONFIG_FILES.map((file) => resolve(root, file)).filter(existsSync);
43
+ if (matches.length === 0) throw new Error(`No miniapp.config file found in ${root}`);
44
+ if (matches.length > 1) throw new Error(`Multiple miniapp config files found: ${matches.map((file) => file.split("/").at(-1)).join(", ")}`);
45
+ return matches[0];
46
+ }
47
+ function assertUserConfig(value, configFile) {
48
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`${configFile} must export a configuration object`);
49
+ return value;
50
+ }
51
+ async function resolveViteConfig(vite, env) {
52
+ if (!vite) return {};
53
+ const config = typeof vite === "function" ? await vite(env) : vite;
54
+ if (typeof config !== "object" || config === null || Array.isArray(config)) throw new Error("miniapp.config vite must resolve to a Vite configuration object");
55
+ return config;
56
+ }
57
+ async function loadMiniappConfig(rootDirectory, env) {
58
+ const root = resolve(rootDirectory);
59
+ const configFile = findConfigFile(root);
60
+ const loaded = await loadConfigFromFile(env, configFile, root);
61
+ if (!loaded) throw new Error(`Failed to load ${configFile}`);
62
+ const config = assertUserConfig(loaded.config, configFile);
63
+ const eventsExtensions = config.events?.extensions ?? DEFAULT_EVENT_EXTENSIONS;
64
+ if (eventsExtensions.length === 0) throw new Error("events.extensions must contain at least one file extension");
65
+ return {
66
+ root,
67
+ configFile,
68
+ manifestFile: config.manifest ?? "manifest.json",
69
+ eventsDir: config.events?.dir ?? "src/events",
70
+ eventsExtensions,
71
+ packageOutDir: config.package?.outDir ?? "release",
72
+ packageFileName: config.package?.fileName,
73
+ vite: mergeConfig(await loadModules(config.modules ?? [], configFile, env), await resolveViteConfig(config.vite, env))
74
+ };
75
+ }
76
+ //#endregion
77
+ //#region src/validate.ts
78
+ function assertNonEmptyString(value, field) {
79
+ if (typeof value !== "string" || value.trim() === "") throw new Error(`manifest.${field} must be a non-empty string`);
80
+ }
81
+ function resolvePackagePath(directory, value, field) {
82
+ if (isAbsolute(value) || win32.isAbsolute(value)) throw new Error(`manifest.${field} must be relative to the package root`);
83
+ const target = resolve(directory, value);
84
+ const relativePath = relative(directory, target);
85
+ if (relativePath === ".." || relativePath.startsWith(`..${sep}`)) throw new Error(`manifest.${field} points outside the package root`);
86
+ return target;
87
+ }
88
+ async function assertPackageFile(directory, value, field) {
89
+ assertNonEmptyString(value, field);
90
+ const target = resolvePackagePath(directory, value, field);
91
+ let stat;
92
+ try {
93
+ stat = await lstat(target);
94
+ } catch {
95
+ throw new Error(`manifest.${field} points to a missing file: ${value}`);
96
+ }
97
+ if (!stat.isFile() || stat.isSymbolicLink()) throw new Error(`manifest.${field} must point to a regular package file: ${value}`);
98
+ }
99
+ async function collectFiles(directory, current = directory) {
100
+ const entries = await readdir(current, { withFileTypes: true });
101
+ const files = [];
102
+ for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
103
+ const absolutePath = resolve(current, entry.name);
104
+ const packagePath = relative(directory, absolutePath).split(sep).join("/");
105
+ if (entry.isSymbolicLink()) throw new Error(`Package must not contain symbolic links: ${packagePath}`);
106
+ if (entry.isDirectory()) {
107
+ files.push(...await collectFiles(directory, absolutePath));
108
+ continue;
109
+ }
110
+ if (entry.isFile()) files.push(packagePath);
111
+ }
112
+ return files;
113
+ }
114
+ async function readMiniappManifest(manifestPath) {
115
+ let value;
116
+ try {
117
+ value = JSON.parse(await readFile(manifestPath, "utf8"));
118
+ } catch (error) {
119
+ const reason = error instanceof Error ? error.message : String(error);
120
+ throw new Error(`Unable to read manifest: ${reason}`);
121
+ }
122
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("manifest.json must contain a JSON object");
123
+ const manifest = value;
124
+ assertNonEmptyString(manifest.name, "name");
125
+ assertNonEmptyString(manifest.title, "title");
126
+ assertNonEmptyString(manifest.version, "version");
127
+ return manifest;
128
+ }
129
+ async function validateSourceManifest(manifestPath) {
130
+ return readMiniappManifest(manifestPath);
131
+ }
132
+ async function validateMiniappDirectory(directoryPath) {
133
+ const directory = resolve(directoryPath);
134
+ if (!(await lstat(directory).catch(() => void 0))?.isDirectory()) throw new Error(`Miniapp output directory does not exist: ${directory}`);
135
+ const manifestPath = resolve(directory, "manifest.json");
136
+ const manifest = await readMiniappManifest(manifestPath);
137
+ if (manifest.icon !== void 0) await assertPackageFile(directory, manifest.icon, "icon");
138
+ if (manifest.entry && (manifest.entry.type ?? "miniapp") === "miniapp") {
139
+ await assertPackageFile(directory, manifest.entry.url, "entry.url");
140
+ if ((await readFile(resolve(directory, manifest.entry.url), "utf8")).startsWith("<!-- miniapp-dev-entry:")) throw new Error("Output contains a development entry. Run build before validating or packaging.");
141
+ }
142
+ for (const [index, script] of (manifest.scripts ?? []).entries()) await assertPackageFile(directory, script.entry, `scripts[${index}].entry`);
143
+ const files = await collectFiles(directory);
144
+ const sourcemap = files.find((file) => file.endsWith(".map"));
145
+ if (sourcemap) throw new Error(`Package must not contain sourcemaps: ${sourcemap}`);
146
+ const dependency = files.find((file) => file.split("/").includes("node_modules"));
147
+ if (dependency) throw new Error(`Package must not contain node_modules: ${dependency}`);
148
+ return {
149
+ directory,
150
+ manifestPath,
151
+ manifest,
152
+ files
153
+ };
154
+ }
155
+ //#endregion
156
+ //#region src/dev-entry.ts
157
+ function localPath(root, file) {
158
+ const target = resolve(root, file);
159
+ const rel = relative(root, target);
160
+ if (isAbsolute(file) || win32.isAbsolute(file) || rel === ".." || rel.startsWith(`..${sep}`)) throw new Error(`Miniapp development entry must stay inside its directory: ${file}`);
161
+ return target;
162
+ }
163
+ function localDevEntry(root, outDir, manifestFile, manifest) {
164
+ const entry = manifest.entry?.url;
165
+ if (manifest.entry && (manifest.entry.type ?? "miniapp") !== "miniapp") throw new Error("Local HMR requires a miniapp HTML entry");
166
+ const source = entry ? localPath(root, entry) : void 0;
167
+ const output = entry ? localPath(outDir, entry) : void 0;
168
+ const iconSource = manifest.icon ? localPath(root, manifest.icon) : void 0;
169
+ const iconOutput = manifest.icon ? localPath(outDir, manifest.icon) : void 0;
170
+ let iconUpdates = Promise.resolve();
171
+ let stopped = false;
172
+ const rootFromOutput = relative(outDir, root);
173
+ if (!rootFromOutput || !rootFromOutput.startsWith(`..${sep}`) && rootFromOutput !== ".." && !isAbsolute(rootFromOutput)) throw new Error("Development output must not be the project root or its parent");
174
+ let server;
175
+ let entryUrl;
176
+ let pagePath;
177
+ const inlineModules = /* @__PURE__ */ new Map();
178
+ async function copyIcon() {
179
+ if (!iconSource || !iconOutput) return;
180
+ await mkdir(dirname(iconOutput), { recursive: true });
181
+ await copyFile(iconSource, iconOutput);
182
+ }
183
+ function onIconChange(event, file) {
184
+ if (stopped || !iconSource || resolve(file) !== iconSource) return;
185
+ if (![
186
+ "add",
187
+ "change",
188
+ "unlink"
189
+ ].includes(event)) return;
190
+ iconUpdates = iconUpdates.then(async () => {
191
+ if (stopped) return;
192
+ if (event === "unlink") await rm(iconOutput, { force: true });
193
+ else await copyIcon();
194
+ server.config.logger.info("[miniapp] Manifest icon updated. Reload the application in the host to refresh its icon.");
195
+ }).catch((error) => {
196
+ server.config.logger.error(`[miniapp] Icon sync failed: ${error instanceof Error ? error.message : String(error)}`);
197
+ });
198
+ }
199
+ function rewriteEntry(html) {
200
+ const document = parse(html);
201
+ const modules = /* @__PURE__ */ new Map();
202
+ function visit(node) {
203
+ if ("tagName" in node) {
204
+ for (const attr of node.attrs) if (attr.name === "src" || attr.name === "poster" || attr.name === "href" && [
205
+ "link",
206
+ "image",
207
+ "use"
208
+ ].includes(node.tagName) || attr.name === "data" && node.tagName === "object") {
209
+ if (attr.value && !attr.value.startsWith("#")) attr.value = new URL(attr.value, entryUrl).href;
210
+ }
211
+ if (node.tagName === "script" && node.attrs.some((attr) => attr.name === "type" && attr.value.toLowerCase() === "module") && !node.attrs.some((attr) => attr.name === "src")) {
212
+ const code = node.childNodes.map((child) => "value" in child ? child.value : "").join("");
213
+ const hash = createHash("sha256").update(code).digest("hex").slice(0, 16);
214
+ const url = new URL(`./@miniapp-dev/inline-${modules.size}-${hash}.js`, entryUrl);
215
+ const id = url.pathname.slice(server.config.base.length - 1);
216
+ modules.set(id, code);
217
+ node.childNodes = [];
218
+ node.attrs.push({
219
+ name: "src",
220
+ value: url.href
221
+ });
222
+ }
223
+ }
224
+ if ("childNodes" in node) node.childNodes.forEach(visit);
225
+ if ("content" in node) visit(node.content);
226
+ }
227
+ visit(document);
228
+ inlineModules.clear();
229
+ for (const [path, code] of modules) inlineModules.set(path, code);
230
+ return serialize(document);
231
+ }
232
+ async function writeEntry() {
233
+ if (!source || !output) return;
234
+ const html = await server.transformIndexHtml(pagePath, await readFile(source, "utf8"));
235
+ await mkdir(dirname(output), { recursive: true });
236
+ await writeFile(output, `<!-- miniapp-dev-entry: run build before packaging -->\n${rewriteEntry(html)}`);
237
+ }
238
+ return {
239
+ plugin: {
240
+ name: "miniapp-local-dev-entry",
241
+ apply: "serve",
242
+ async closeBundle() {
243
+ stopped = true;
244
+ server?.watcher.off("all", onIconChange);
245
+ await iconUpdates;
246
+ },
247
+ resolveId(id) {
248
+ if (inlineModules.has(id.split("?")[0])) return id;
249
+ },
250
+ load(id) {
251
+ return inlineModules.get(id.split("?")[0]);
252
+ },
253
+ async handleHotUpdate(context) {
254
+ if (resolve(context.file) !== source) return;
255
+ await writeEntry();
256
+ context.server.ws.send({
257
+ type: "full-reload",
258
+ path: "*"
259
+ });
260
+ return [];
261
+ }
262
+ },
263
+ async write(devServer) {
264
+ server = devServer;
265
+ await mkdir(outDir, { recursive: true });
266
+ if (entry) {
267
+ const url = server.resolvedUrls?.local[0] ?? server.resolvedUrls?.network[0];
268
+ if (!url) throw new Error("Cannot determine the Vite development server URL");
269
+ server.config.server.origin ??= new URL(url).origin;
270
+ entryUrl = new URL(entry.replaceAll("\\", "/"), url).href;
271
+ pagePath = new URL(entryUrl).pathname;
272
+ await writeEntry();
273
+ }
274
+ await copyFile(resolve(root, manifestFile), resolve(outDir, "manifest.json"));
275
+ await copyIcon();
276
+ if (iconSource) {
277
+ server.watcher.add(iconSource);
278
+ server.watcher.on("all", onIconChange);
279
+ }
280
+ }
281
+ };
282
+ }
283
+ //#endregion
284
+ //#region src/dev-events.ts
285
+ /** Build sandbox scripts on disk independently from the page's Vite HMR graph. */
286
+ function devEvents(config, outDir, manifest, mode) {
287
+ const eventsDir = resolve(config.root, config.eventsDir);
288
+ let server;
289
+ let dependencies = /* @__PURE__ */ new Set();
290
+ let outputs = /* @__PURE__ */ new Set();
291
+ let pending = Promise.resolve();
292
+ let stopped = false;
293
+ let failed = false;
294
+ async function rebuild() {
295
+ const hasEntries = (await readdir(eventsDir, { withFileTypes: true }).catch((error) => {
296
+ if (error.code === "ENOENT") return [];
297
+ throw error;
298
+ })).some((source) => source.isFile() && !source.name.endsWith(".d.ts") && config.eventsExtensions.some((ext) => source.name.endsWith(ext)));
299
+ const nextDependencies = /* @__PURE__ */ new Set();
300
+ const files = /* @__PURE__ */ new Map();
301
+ if (hasEntries) {
302
+ const eventConfig = await loadMiniappConfig(config.root, {
303
+ command: "build",
304
+ mode,
305
+ isSsrBuild: false,
306
+ isPreview: false
307
+ });
308
+ const options = eventConfig.vite.build;
309
+ const result = await build({
310
+ ...eventConfig.vite,
311
+ root: config.root,
312
+ configFile: false,
313
+ mode,
314
+ publicDir: false,
315
+ logLevel: "warn",
316
+ plugins: [
317
+ ...eventConfig.vite.plugins ?? [],
318
+ miniappPlugin({
319
+ eventsOnly: true,
320
+ eventsDir: config.eventsDir,
321
+ eventsExtensions: config.eventsExtensions
322
+ }),
323
+ {
324
+ name: "miniapp-dev-events-output",
325
+ generateBundle() {
326
+ for (const file of this.getModuleIds()) {
327
+ const path = file.split("?")[0];
328
+ if (isAbsolute(path)) nextDependencies.add(resolve(path));
329
+ }
330
+ }
331
+ }
332
+ ],
333
+ build: {
334
+ ...options,
335
+ outDir,
336
+ emptyOutDir: false,
337
+ copyPublicDir: false,
338
+ write: false,
339
+ watch: null,
340
+ lib: false,
341
+ ssr: false,
342
+ sourcemap: false,
343
+ minify: false,
344
+ manifest: false,
345
+ ssrManifest: false,
346
+ rolldownOptions: void 0,
347
+ rollupOptions: {
348
+ ...options?.rollupOptions,
349
+ ...options?.rolldownOptions,
350
+ input: void 0,
351
+ output: void 0
352
+ }
353
+ }
354
+ });
355
+ for (const bundle of Array.isArray(result) ? result : [result]) {
356
+ if (!("output" in bundle)) throw new Error("Unexpected event build watcher");
357
+ for (const file of bundle.output) files.set(file.fileName, file.type === "chunk" ? file.code : file.source);
358
+ }
359
+ }
360
+ dependencies = nextDependencies;
361
+ server.watcher.add([...dependencies]);
362
+ for (const name of files.keys()) {
363
+ const path = normalizePath(relative(outDir, resolve(outDir, name)));
364
+ if (!path.startsWith("events/") || path.includes("../")) throw new Error(`Event build emitted a file outside events/: ${name}`);
365
+ }
366
+ for (const [name, content] of files) {
367
+ const path = resolve(outDir, name);
368
+ await mkdir(dirname(path), { recursive: true });
369
+ await writeFile(path, content);
370
+ }
371
+ for (const name of outputs) if (!files.has(name)) await rm(resolve(outDir, name), { force: true });
372
+ outputs = new Set(files.keys());
373
+ for (const script of manifest.scripts ?? []) {
374
+ const entry = normalizePath(relative(outDir, resolve(outDir, script.entry)));
375
+ if (!outputs.has(entry)) throw new Error(`manifest script "${script.entry}" has no built event entry. Add its source to ${config.eventsDir}.`);
376
+ }
377
+ if (hasEntries) server.config.logger.info("[miniapp] Event scripts built. Reload the application in the host if it caches scripts.");
378
+ }
379
+ function onChange(event, file) {
380
+ if (stopped || ![
381
+ "add",
382
+ "change",
383
+ "unlink"
384
+ ].includes(event)) return;
385
+ const path = resolve(file);
386
+ const entry = dirname(path) === eventsDir && config.eventsExtensions.some((ext) => path.endsWith(ext));
387
+ const relativeToOutput = relative(outDir, path);
388
+ if (relativeToOutput !== ".." && !relativeToOutput.startsWith(`..${sep}`) && !isAbsolute(relativeToOutput)) return;
389
+ if (!entry && !dependencies.has(path) && !failed) return;
390
+ pending = pending.then(async () => {
391
+ if (stopped) return;
392
+ try {
393
+ await rebuild();
394
+ failed = false;
395
+ } catch (error) {
396
+ failed = true;
397
+ server.config.logger.error(`[miniapp] Event build failed: ${error instanceof Error ? error.message : String(error)}`);
398
+ }
399
+ });
400
+ }
401
+ return {
402
+ plugin: {
403
+ name: "miniapp-dev-events",
404
+ apply: "serve",
405
+ async closeBundle() {
406
+ stopped = true;
407
+ server?.watcher.off("all", onChange);
408
+ await pending;
409
+ }
410
+ },
411
+ async start(devServer) {
412
+ server = devServer;
413
+ await rebuild();
414
+ server.watcher.add(eventsDir);
415
+ server.watcher.on("all", onChange);
416
+ }
417
+ };
418
+ }
419
+ //#endregion
420
+ //#region src/vite.ts
421
+ function configEnv(command, mode) {
422
+ return {
423
+ command,
424
+ mode,
425
+ isSsrBuild: false,
426
+ isPreview: false
427
+ };
428
+ }
429
+ function createInlineConfig(config) {
430
+ return mergeConfig(config.vite, {
431
+ root: config.root,
432
+ configFile: false,
433
+ plugins: [miniappPlugin({
434
+ eventsDir: config.eventsDir,
435
+ eventsExtensions: config.eventsExtensions,
436
+ manifestFile: config.manifestFile
437
+ })]
438
+ });
439
+ }
440
+ function resolveOutputDirectory(config) {
441
+ return resolve(config.root, config.vite.build?.outDir ?? "dist");
442
+ }
443
+ async function buildMiniapp(options = {}) {
444
+ const config = await loadMiniappConfig(options.root ?? process.cwd(), configEnv("build", options.mode ?? "production"));
445
+ await build(createInlineConfig(config));
446
+ const outDir = resolveOutputDirectory(config);
447
+ await validateMiniappDirectory(outDir);
448
+ return {
449
+ config,
450
+ outDir
451
+ };
452
+ }
453
+ async function validateBuiltMiniapp(options = {}) {
454
+ return validateMiniappDirectory(resolveOutputDirectory(await loadMiniappConfig(options.root ?? process.cwd(), configEnv("build", options.mode ?? "production"))));
455
+ }
456
+ async function devMiniapp(options = {}) {
457
+ const root = options.root ?? process.cwd();
458
+ const mode = options.mode ?? "development";
459
+ const config = await loadMiniappConfig(root, configEnv("serve", mode));
460
+ const manifest = await validateSourceManifest(resolve(config.root, config.manifestFile));
461
+ const inlineConfig = createInlineConfig(config);
462
+ const outDir = resolveOutputDirectory(config);
463
+ const devEntry = localDevEntry(config.root, outDir, config.manifestFile, manifest);
464
+ const events = devEvents(config, outDir, manifest, mode);
465
+ inlineConfig.plugins = [
466
+ ...inlineConfig.plugins ?? [],
467
+ devEntry.plugin,
468
+ events.plugin
469
+ ];
470
+ inlineConfig.server = {
471
+ ...inlineConfig.server,
472
+ cors: inlineConfig.server?.cors ?? { origin: [/^https?:\/\/(?:(?:[^:]+\.)?localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/, "null"] },
473
+ ...options.host ? { host: options.host } : {},
474
+ ...options.port ? { port: options.port } : {}
475
+ };
476
+ if (!manifest.entry) {
477
+ inlineConfig.server.middlewareMode = true;
478
+ inlineConfig.server.hmr = false;
479
+ inlineConfig.server.open = false;
480
+ }
481
+ const server = await createServer(inlineConfig);
482
+ try {
483
+ if (manifest.entry) await server.listen();
484
+ await devEntry.write(server);
485
+ await events.start(server);
486
+ } catch (error) {
487
+ await server.close();
488
+ throw error;
489
+ }
490
+ if (manifest.entry) {
491
+ server.printUrls();
492
+ server.bindCLIShortcuts({ print: true });
493
+ }
494
+ console.log(`\nLoad this directory in Xunlei: ${outDir}\n`);
495
+ return server;
496
+ }
497
+ //#endregion
498
+ //#region src/package.ts
499
+ const ZIP_DATE = /* @__PURE__ */ new Date("1980-01-01T00:00:00.000Z");
500
+ function safeFilePart(value) {
501
+ return value.trim().replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "miniapp";
502
+ }
503
+ function resolveArchivePath(config, manifest, explicitPath) {
504
+ if (explicitPath) {
505
+ if (!explicitPath.toLowerCase().endsWith(".zip")) throw new Error("--out must end with .zip");
506
+ return isAbsolute(explicitPath) ? explicitPath : resolve(config.root, explicitPath);
507
+ }
508
+ const fileName = config.packageFileName ?? `${safeFilePart(manifest.name)}-${safeFilePart(manifest.version)}.zip`;
509
+ if (!fileName.toLowerCase().endsWith(".zip")) throw new Error("package.fileName must end with .zip");
510
+ if (basename(fileName) !== fileName) throw new Error("package.fileName must not contain a directory");
511
+ return resolve(config.root, config.packageOutDir, fileName);
512
+ }
513
+ async function writeZip(directory, files, outFile) {
514
+ await mkdir(dirname(outFile), { recursive: true });
515
+ const archive = new yazl.ZipFile();
516
+ const output = createWriteStream(outFile);
517
+ const completed = pipeline(archive.outputStream, output);
518
+ try {
519
+ for (const file of files) archive.addFile(resolve(directory, file), file, {
520
+ mtime: ZIP_DATE,
521
+ mode: 420,
522
+ compress: true
523
+ });
524
+ archive.end();
525
+ await completed;
526
+ } catch (error) {
527
+ await rm(outFile, { force: true });
528
+ throw error;
529
+ }
530
+ }
531
+ async function packageMiniapp(options = {}) {
532
+ let config;
533
+ let outDir;
534
+ if (options.build ?? true) ({config, outDir} = await buildMiniapp(options));
535
+ else {
536
+ config = await loadMiniappConfig(options.root ?? process.cwd(), {
537
+ command: "build",
538
+ mode: options.mode ?? "production",
539
+ isSsrBuild: false,
540
+ isPreview: false
541
+ });
542
+ outDir = resolveOutputDirectory(config);
543
+ }
544
+ const validated = await validateMiniappDirectory(outDir);
545
+ const outFile = resolveArchivePath(config, validated.manifest, options.outFile);
546
+ const archiveRelativeToOutput = relative(outDir, outFile);
547
+ if (archiveRelativeToOutput === "" || !archiveRelativeToOutput.startsWith(`..${sep}`) && archiveRelativeToOutput !== "..") throw new Error("Package output must be outside the build output directory");
548
+ await writeZip(outDir, validated.files, outFile);
549
+ return {
550
+ outFile,
551
+ outDir
552
+ };
553
+ }
554
+ //#endregion
555
+ export { readMiniappManifest as a, defineConfig as c, validateBuiltMiniapp as i, defineMiniappModule as l, buildMiniapp as n, validateMiniappDirectory as o, devMiniapp as r, validateSourceManifest as s, packageMiniapp as t, loadMiniappConfig as u };
556
+
557
+ //# sourceMappingURL=package-BQM2LBwr.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-BQM2LBwr.mjs","names":["viteBuild"],"sources":["../src/config.ts","../src/validate.ts","../src/dev-entry.ts","../src/dev-events.ts","../src/vite.ts","../src/package.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { createRequire } from 'node:module'\nimport { resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { loadConfigFromFile, mergeConfig, type ConfigEnv, type UserConfig } from 'vite'\nimport type {\n MiniappModule,\n MiniappUserConfig,\n ResolvedMiniappConfig,\n} from './types.js'\n\nconst CONFIG_FILES = [\n 'miniapp.config.ts',\n 'miniapp.config.mts',\n 'miniapp.config.js',\n 'miniapp.config.mjs',\n 'miniapp.config.cts',\n 'miniapp.config.cjs',\n] as const\n\nconst DEFAULT_EVENT_EXTENSIONS = ['.ts', '.js']\n\nexport function defineConfig(config: MiniappUserConfig): MiniappUserConfig {\n return config\n}\n\nexport function defineMiniappModule(module: MiniappModule): MiniappModule {\n return module\n}\n\nasync function loadModules(names: string[], configFile: string, env: ConfigEnv): Promise<UserConfig> {\n if (!Array.isArray(names) || names.some(name => typeof name !== 'string' || !name.trim())) {\n throw new Error('miniapp.config modules must be an array of module names')\n }\n const require = createRequire(configFile)\n let config: UserConfig = {}\n for (const name of new Set(names)) {\n try {\n const { default: module } = await import(pathToFileURL(require.resolve(name)).href)\n if (!module || typeof module !== 'object' || typeof module.name !== 'string' || !module.vite) {\n throw new Error('must export a MiniappModule with name and vite fields')\n }\n config = mergeConfig(config, await resolveViteConfig(module.vite, env))\n } catch (error) {\n throw new Error(`Failed to load miniapp module \"${name}\" from ${configFile}: ${error instanceof Error ? error.message : String(error)}`, { cause: error })\n }\n }\n return config\n}\n\nfunction findConfigFile(root: string): string {\n const matches = CONFIG_FILES.map((file) => resolve(root, file)).filter(existsSync)\n\n if (matches.length === 0) {\n throw new Error(`No miniapp.config file found in ${root}`)\n }\n if (matches.length > 1) {\n throw new Error(\n `Multiple miniapp config files found: ${matches.map((file) => file.split('/').at(-1)).join(', ')}`,\n )\n }\n\n return matches[0]!\n}\n\nfunction assertUserConfig(value: unknown, configFile: string): MiniappUserConfig {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new Error(`${configFile} must export a configuration object`)\n }\n return value as MiniappUserConfig\n}\n\nasync function resolveViteConfig(\n vite: MiniappUserConfig['vite'],\n env: ConfigEnv,\n): Promise<UserConfig> {\n if (!vite) return {}\n const config = typeof vite === 'function' ? await vite(env) : vite\n if (typeof config !== 'object' || config === null || Array.isArray(config)) {\n throw new Error('miniapp.config vite must resolve to a Vite configuration object')\n }\n return config\n}\n\nexport async function loadMiniappConfig(\n rootDirectory: string,\n env: ConfigEnv,\n): Promise<ResolvedMiniappConfig> {\n const root = resolve(rootDirectory)\n const configFile = findConfigFile(root)\n const loaded = await loadConfigFromFile(env, configFile, root)\n\n if (!loaded) {\n throw new Error(`Failed to load ${configFile}`)\n }\n\n const config = assertUserConfig(loaded.config, configFile)\n const eventsExtensions = config.events?.extensions ?? DEFAULT_EVENT_EXTENSIONS\n\n if (eventsExtensions.length === 0) {\n throw new Error('events.extensions must contain at least one file extension')\n }\n\n return {\n root,\n configFile,\n manifestFile: config.manifest ?? 'manifest.json',\n eventsDir: config.events?.dir ?? 'src/events',\n eventsExtensions,\n packageOutDir: config.package?.outDir ?? 'release',\n packageFileName: config.package?.fileName,\n vite: mergeConfig(\n await loadModules(config.modules ?? [], configFile, env),\n await resolveViteConfig(config.vite, env),\n ),\n }\n}\n","import { lstat, readFile, readdir } from 'node:fs/promises'\nimport { isAbsolute, relative, resolve, sep, win32 } from 'node:path'\nimport type { MiniappManifest } from '@xunlei-open/miniapp-types'\nimport type { MiniappValidationResult } from './types.js'\n\nfunction assertNonEmptyString(value: unknown, field: string): asserts value is string {\n if (typeof value !== 'string' || value.trim() === '') {\n throw new Error(`manifest.${field} must be a non-empty string`)\n }\n}\n\nfunction resolvePackagePath(directory: string, value: string, field: string): string {\n if (isAbsolute(value) || win32.isAbsolute(value)) {\n throw new Error(`manifest.${field} must be relative to the package root`)\n }\n\n const target = resolve(directory, value)\n const relativePath = relative(directory, target)\n if (relativePath === '..' || relativePath.startsWith(`..${sep}`)) {\n throw new Error(`manifest.${field} points outside the package root`)\n }\n return target\n}\n\nasync function assertPackageFile(\n directory: string,\n value: unknown,\n field: string,\n): Promise<void> {\n assertNonEmptyString(value, field)\n const target = resolvePackagePath(directory, value, field)\n let stat\n try {\n stat = await lstat(target)\n } catch {\n throw new Error(`manifest.${field} points to a missing file: ${value}`)\n }\n if (!stat.isFile() || stat.isSymbolicLink()) {\n throw new Error(`manifest.${field} must point to a regular package file: ${value}`)\n }\n}\n\nasync function collectFiles(directory: string, current = directory): Promise<string[]> {\n const entries = await readdir(current, { withFileTypes: true })\n const files: string[] = []\n\n for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {\n const absolutePath = resolve(current, entry.name)\n const packagePath = relative(directory, absolutePath).split(sep).join('/')\n\n if (entry.isSymbolicLink()) {\n throw new Error(`Package must not contain symbolic links: ${packagePath}`)\n }\n if (entry.isDirectory()) {\n files.push(...(await collectFiles(directory, absolutePath)))\n continue\n }\n if (entry.isFile()) files.push(packagePath)\n }\n\n return files\n}\n\nexport async function readMiniappManifest(manifestPath: string): Promise<MiniappManifest> {\n let value: unknown\n try {\n value = JSON.parse(await readFile(manifestPath, 'utf8'))\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n throw new Error(`Unable to read manifest: ${reason}`)\n }\n\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new Error('manifest.json must contain a JSON object')\n }\n\n const manifest = value as MiniappManifest\n assertNonEmptyString(manifest.name, 'name')\n assertNonEmptyString(manifest.title, 'title')\n assertNonEmptyString(manifest.version, 'version')\n return manifest\n}\n\nexport async function validateSourceManifest(manifestPath: string): Promise<MiniappManifest> {\n return readMiniappManifest(manifestPath)\n}\n\nexport async function validateMiniappDirectory(\n directoryPath: string,\n): Promise<MiniappValidationResult> {\n const directory = resolve(directoryPath)\n const directoryStat = await lstat(directory).catch(() => undefined)\n if (!directoryStat?.isDirectory()) {\n throw new Error(`Miniapp output directory does not exist: ${directory}`)\n }\n\n const manifestPath = resolve(directory, 'manifest.json')\n const manifest = await readMiniappManifest(manifestPath)\n\n if (manifest.icon !== undefined) {\n await assertPackageFile(directory, manifest.icon, 'icon')\n }\n if (manifest.entry && (manifest.entry.type ?? 'miniapp') === 'miniapp') {\n await assertPackageFile(directory, manifest.entry.url, 'entry.url')\n const html = await readFile(resolve(directory, manifest.entry.url), 'utf8')\n if (html.startsWith('<!-- miniapp-dev-entry:')) {\n throw new Error('Output contains a development entry. Run build before validating or packaging.')\n }\n }\n for (const [index, script] of (manifest.scripts ?? []).entries()) {\n await assertPackageFile(directory, script.entry, `scripts[${index}].entry`)\n }\n\n const files = await collectFiles(directory)\n const sourcemap = files.find((file) => file.endsWith('.map'))\n if (sourcemap) {\n throw new Error(`Package must not contain sourcemaps: ${sourcemap}`)\n }\n const dependency = files.find((file) => file.split('/').includes('node_modules'))\n if (dependency) {\n throw new Error(`Package must not contain node_modules: ${dependency}`)\n }\n\n return { directory, manifestPath, manifest, files }\n}\n","import { createHash } from 'node:crypto'\nimport { copyFile, mkdir, readFile, rm, writeFile } from 'node:fs/promises'\nimport { dirname, isAbsolute, relative, resolve, sep, win32 } from 'node:path'\nimport type { MiniappManifest } from '@xunlei-open/miniapp-types'\nimport type { Plugin, ViteDevServer } from 'vite'\nimport { parse, serialize, type DefaultTreeAdapterMap } from 'parse5'\n\nfunction localPath(root: string, file: string): string {\n const target = resolve(root, file)\n const rel = relative(root, target)\n if (isAbsolute(file) || win32.isAbsolute(file) || rel === '..' || rel.startsWith(`..${sep}`)) {\n throw new Error(`Miniapp development entry must stay inside its directory: ${file}`)\n }\n return target\n}\n\nexport function localDevEntry(\n root: string,\n outDir: string,\n manifestFile: string,\n manifest: MiniappManifest,\n) {\n const entry = manifest.entry?.url\n if (manifest.entry && (manifest.entry.type ?? 'miniapp') !== 'miniapp') {\n throw new Error('Local HMR requires a miniapp HTML entry')\n }\n const source = entry ? localPath(root, entry) : undefined\n const output = entry ? localPath(outDir, entry) : undefined\n const iconSource = manifest.icon ? localPath(root, manifest.icon) : undefined\n const iconOutput = manifest.icon ? localPath(outDir, manifest.icon) : undefined\n let iconUpdates = Promise.resolve()\n let stopped = false\n const rootFromOutput = relative(outDir, root)\n if (!rootFromOutput || (!rootFromOutput.startsWith(`..${sep}`) && rootFromOutput !== '..' && !isAbsolute(rootFromOutput))) {\n throw new Error('Development output must not be the project root or its parent')\n }\n let server: ViteDevServer\n let entryUrl: string | undefined\n let pagePath: string\n const inlineModules = new Map<string, string>()\n\n async function copyIcon() {\n if (!iconSource || !iconOutput) return\n await mkdir(dirname(iconOutput), { recursive: true })\n await copyFile(iconSource, iconOutput)\n }\n\n function onIconChange(event: string, file: string) {\n if (stopped || !iconSource || resolve(file) !== iconSource) return\n if (!['add', 'change', 'unlink'].includes(event)) return\n iconUpdates = iconUpdates.then(async () => {\n if (stopped) return\n if (event === 'unlink') await rm(iconOutput!, { force: true })\n else await copyIcon()\n server.config.logger.info('[miniapp] Manifest icon updated. Reload the application in the host to refresh its icon.')\n }).catch(error => {\n server.config.logger.error(`[miniapp] Icon sync failed: ${error instanceof Error ? error.message : String(error)}`)\n })\n }\n\n function rewriteEntry(html: string): string {\n const document = parse(html)\n const modules = new Map<string, string>()\n function visit(node: DefaultTreeAdapterMap['node']) {\n if ('tagName' in node) {\n for (const attr of node.attrs) {\n if (attr.name === 'src' || attr.name === 'poster' ||\n (attr.name === 'href' && ['link', 'image', 'use'].includes(node.tagName)) ||\n (attr.name === 'data' && node.tagName === 'object')) {\n if (attr.value && !attr.value.startsWith('#')) attr.value = new URL(attr.value, entryUrl).href\n }\n }\n if (node.tagName === 'script' &&\n node.attrs.some(attr => attr.name === 'type' && attr.value.toLowerCase() === 'module') &&\n !node.attrs.some(attr => attr.name === 'src')) {\n // Framework-injected preambles must resolve imports against HTTP, not file://.\n const code = node.childNodes.map(child => 'value' in child ? child.value : '').join('')\n const hash = createHash('sha256').update(code).digest('hex').slice(0, 16)\n const url = new URL(`./@miniapp-dev/inline-${modules.size}-${hash}.js`, entryUrl)\n const id = url.pathname.slice(server.config.base.length - 1)\n modules.set(id, code)\n node.childNodes = []\n node.attrs.push({ name: 'src', value: url.href })\n }\n }\n if ('childNodes' in node) node.childNodes.forEach(visit)\n if ('content' in node) visit(node.content as DefaultTreeAdapterMap['documentFragment'])\n }\n visit(document)\n inlineModules.clear()\n for (const [path, code] of modules) inlineModules.set(path, code)\n return serialize(document)\n }\n\n async function writeEntry() {\n if (!source || !output) return\n const html = await server.transformIndexHtml(pagePath, await readFile(source, 'utf8'))\n await mkdir(dirname(output), { recursive: true })\n await writeFile(output, `<!-- miniapp-dev-entry: run build before packaging -->\\n${rewriteEntry(html)}`)\n }\n\n const plugin: Plugin = {\n name: 'miniapp-local-dev-entry',\n apply: 'serve',\n async closeBundle() {\n stopped = true\n server?.watcher.off('all', onIconChange)\n await iconUpdates\n },\n resolveId(id) {\n if (inlineModules.has(id.split('?')[0]!)) return id\n },\n load(id) {\n return inlineModules.get(id.split('?')[0]!)\n },\n async handleHotUpdate(context) {\n if (resolve(context.file) !== source) return\n await writeEntry()\n // Vite's HTML reload filter otherwise compares against the file:// pathname.\n context.server.ws.send({ type: 'full-reload', path: '*' })\n return []\n },\n }\n\n return {\n plugin,\n async write(devServer: ViteDevServer) {\n server = devServer\n await mkdir(outDir, { recursive: true })\n if (entry) {\n const url = server.resolvedUrls?.local[0] ?? server.resolvedUrls?.network[0]\n if (!url) throw new Error('Cannot determine the Vite development server URL')\n server.config.server.origin ??= new URL(url).origin\n entryUrl = new URL(entry.replaceAll('\\\\', '/'), url).href\n pagePath = new URL(entryUrl).pathname\n await writeEntry()\n }\n await copyFile(resolve(root, manifestFile), resolve(outDir, 'manifest.json'))\n await copyIcon()\n if (iconSource) {\n server.watcher.add(iconSource)\n server.watcher.on('all', onIconChange)\n }\n },\n }\n}\n","import { mkdir, readdir, rm, writeFile } from 'node:fs/promises'\nimport { dirname, isAbsolute, relative, resolve, sep } from 'node:path'\nimport type { MiniappManifest } from '@xunlei-open/miniapp-types'\nimport miniappPlugin from '@xunlei-open/vite-plugin-miniapp'\nimport { build, normalizePath, type Plugin, type ViteDevServer } from 'vite'\nimport { loadMiniappConfig } from './config.js'\nimport type { ResolvedMiniappConfig } from './types.js'\n\n/** Build sandbox scripts on disk independently from the page's Vite HMR graph. */\nexport function devEvents(config: ResolvedMiniappConfig, outDir: string, manifest: MiniappManifest, mode: string) {\n const eventsDir = resolve(config.root, config.eventsDir)\n let server: ViteDevServer\n let dependencies = new Set<string>()\n let outputs = new Set<string>()\n let pending = Promise.resolve()\n let stopped = false\n let failed = false\n\n async function rebuild() {\n const sources = await readdir(eventsDir, { withFileTypes: true }).catch(error => {\n if (error.code === 'ENOENT') return []\n throw error\n })\n const hasEntries = sources.some(source => source.isFile()\n && !source.name.endsWith('.d.ts')\n && config.eventsExtensions.some(ext => source.name.endsWith(ext)))\n const nextDependencies = new Set<string>()\n const files = new Map<string, string | Uint8Array>()\n if (hasEntries) {\n // Vite plugins can hold server state. Never reuse the live page's instances.\n const eventConfig = await loadMiniappConfig(config.root, {\n command: 'build', mode, isSsrBuild: false, isPreview: false,\n })\n const options = eventConfig.vite.build\n const result = await build({\n ...eventConfig.vite,\n root: config.root,\n configFile: false,\n mode,\n publicDir: false,\n logLevel: 'warn',\n plugins: [\n ...(eventConfig.vite.plugins ?? []),\n miniappPlugin({\n eventsOnly: true,\n eventsDir: config.eventsDir,\n eventsExtensions: config.eventsExtensions,\n }),\n {\n name: 'miniapp-dev-events-output',\n generateBundle() {\n for (const file of this.getModuleIds()) {\n const path = file.split('?')[0]!\n if (isAbsolute(path)) nextDependencies.add(resolve(path))\n }\n },\n },\n ],\n build: {\n ...options,\n outDir,\n emptyOutDir: false,\n copyPublicDir: false,\n write: false,\n watch: null,\n lib: false,\n ssr: false,\n sourcemap: false,\n minify: false,\n manifest: false,\n ssrManifest: false,\n // Only sandbox entries; never rebuild/overwrite the local HMR HTML.\n rolldownOptions: undefined,\n rollupOptions: {\n ...options?.rollupOptions,\n ...options?.rolldownOptions,\n input: undefined,\n output: undefined,\n },\n },\n })\n for (const bundle of Array.isArray(result) ? result : [result]) {\n if (!('output' in bundle)) throw new Error('Unexpected event build watcher')\n for (const file of bundle.output) {\n files.set(file.fileName, file.type === 'chunk' ? file.code : file.source)\n }\n }\n }\n\n dependencies = nextDependencies\n server.watcher.add([...dependencies])\n // Publish only event outputs, and only after a successful compilation.\n for (const name of files.keys()) {\n const path = normalizePath(relative(outDir, resolve(outDir, name)))\n if (!path.startsWith('events/') || path.includes('../')) {\n throw new Error(`Event build emitted a file outside events/: ${name}`)\n }\n }\n for (const [name, content] of files) {\n const path = resolve(outDir, name)\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, content)\n }\n for (const name of outputs) {\n if (!files.has(name)) await rm(resolve(outDir, name), { force: true })\n }\n outputs = new Set(files.keys())\n for (const script of manifest.scripts ?? []) {\n const entry = normalizePath(relative(outDir, resolve(outDir, script.entry)))\n if (!outputs.has(entry)) {\n throw new Error(`manifest script \"${script.entry}\" has no built event entry. Add its source to ${config.eventsDir}.`)\n }\n }\n if (hasEntries) server.config.logger.info('[miniapp] Event scripts built. Reload the application in the host if it caches scripts.')\n }\n\n function onChange(event: string, file: string) {\n if (stopped || !['add', 'change', 'unlink'].includes(event)) return\n const path = resolve(file)\n const entry = dirname(path) === eventsDir && config.eventsExtensions.some(ext => path.endsWith(ext))\n const relativeToOutput = relative(outDir, path)\n if (relativeToOutput !== '..' && !relativeToOutput.startsWith(`..${sep}`) && !isAbsolute(relativeToOutput)) return\n if (!entry && !dependencies.has(path) && !failed) return\n pending = pending.then(async () => {\n if (stopped) return\n try {\n await rebuild()\n failed = false\n } catch (error) {\n failed = true\n server.config.logger.error(`[miniapp] Event build failed: ${error instanceof Error ? error.message : String(error)}`)\n }\n })\n }\n\n const plugin: Plugin = {\n name: 'miniapp-dev-events',\n apply: 'serve',\n async closeBundle() {\n stopped = true\n server?.watcher.off('all', onChange)\n await pending\n },\n }\n\n return {\n plugin,\n async start(devServer: ViteDevServer) {\n server = devServer\n await rebuild()\n server.watcher.add(eventsDir)\n server.watcher.on('all', onChange)\n },\n }\n}\n","import { resolve } from 'node:path'\nimport miniappPlugin from '@xunlei-open/vite-plugin-miniapp'\nimport {\n build as viteBuild,\n createServer,\n mergeConfig,\n type ConfigEnv,\n type InlineConfig,\n type ViteDevServer,\n} from 'vite'\nimport { loadMiniappConfig } from './config.js'\nimport { localDevEntry } from './dev-entry.js'\nimport { devEvents } from './dev-events.js'\nimport type {\n BuildMiniappOptions,\n DevMiniappOptions,\n ResolvedMiniappConfig,\n} from './types.js'\nimport {\n validateMiniappDirectory,\n validateSourceManifest,\n} from './validate.js'\n\nfunction configEnv(command: ConfigEnv['command'], mode: string): ConfigEnv {\n return { command, mode, isSsrBuild: false, isPreview: false }\n}\n\nfunction createInlineConfig(config: ResolvedMiniappConfig): InlineConfig {\n return mergeConfig(config.vite, {\n root: config.root,\n configFile: false,\n plugins: [\n miniappPlugin({\n eventsDir: config.eventsDir,\n eventsExtensions: config.eventsExtensions,\n manifestFile: config.manifestFile,\n }),\n ],\n })\n}\n\nexport function resolveOutputDirectory(config: ResolvedMiniappConfig): string {\n return resolve(config.root, config.vite.build?.outDir ?? 'dist')\n}\n\nexport async function buildMiniapp(\n options: BuildMiniappOptions = {},\n): Promise<{ config: ResolvedMiniappConfig; outDir: string }> {\n const root = options.root ?? process.cwd()\n const mode = options.mode ?? 'production'\n const config = await loadMiniappConfig(root, configEnv('build', mode))\n\n await viteBuild(createInlineConfig(config))\n\n const outDir = resolveOutputDirectory(config)\n await validateMiniappDirectory(outDir)\n return { config, outDir }\n}\n\nexport async function validateBuiltMiniapp(\n options: BuildMiniappOptions = {},\n) {\n const root = options.root ?? process.cwd()\n const mode = options.mode ?? 'production'\n const config = await loadMiniappConfig(root, configEnv('build', mode))\n return validateMiniappDirectory(resolveOutputDirectory(config))\n}\n\nexport async function devMiniapp(\n options: DevMiniappOptions = {},\n): Promise<ViteDevServer> {\n const root = options.root ?? process.cwd()\n const mode = options.mode ?? 'development'\n const config = await loadMiniappConfig(root, configEnv('serve', mode))\n const manifest = await validateSourceManifest(\n resolve(config.root, config.manifestFile),\n )\n\n const inlineConfig = createInlineConfig(config)\n const outDir = resolveOutputDirectory(config)\n const devEntry = localDevEntry(config.root, outDir, config.manifestFile, manifest)\n const events = devEvents(config, outDir, manifest, mode)\n inlineConfig.plugins = [...(inlineConfig.plugins ?? []), devEntry.plugin, events.plugin]\n inlineConfig.server = {\n ...inlineConfig.server,\n // Local file pages have an opaque (\"null\") origin. Explicit user CORS wins.\n cors: inlineConfig.server?.cors ?? {\n origin: [/^https?:\\/\\/(?:(?:[^:]+\\.)?localhost|127\\.0\\.0\\.1|\\[::1\\])(?::\\d+)?$/, 'null'],\n },\n ...(options.host ? { host: options.host } : {}),\n ...(options.port ? { port: options.port } : {}),\n }\n if (!manifest.entry) {\n // Keep Vite's file watcher for sandbox builds without opening an HTTP/HMR server.\n inlineConfig.server.middlewareMode = true\n inlineConfig.server.hmr = false\n inlineConfig.server.open = false\n }\n\n const server = await createServer(inlineConfig)\n try {\n if (manifest.entry) await server.listen()\n await devEntry.write(server)\n await events.start(server)\n } catch (error) {\n await server.close()\n throw error\n }\n if (manifest.entry) {\n server.printUrls()\n server.bindCLIShortcuts({ print: true })\n }\n console.log(`\\nLoad this directory in Xunlei: ${outDir}\\n`)\n return server\n}\n","import { createWriteStream } from 'node:fs'\nimport { mkdir, rm } from 'node:fs/promises'\nimport { basename, dirname, isAbsolute, relative, resolve, sep } from 'node:path'\nimport { pipeline } from 'node:stream/promises'\nimport yazl from 'yazl'\nimport { loadMiniappConfig } from './config.js'\nimport type {\n PackageMiniappOptions,\n ResolvedMiniappConfig,\n} from './types.js'\nimport { validateMiniappDirectory } from './validate.js'\nimport { buildMiniapp, resolveOutputDirectory } from './vite.js'\n\nconst ZIP_DATE = new Date('1980-01-01T00:00:00.000Z')\n\nfunction safeFilePart(value: string): string {\n return value.trim().replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '') || 'miniapp'\n}\n\nfunction resolveArchivePath(\n config: ResolvedMiniappConfig,\n manifest: { name: string; version: string },\n explicitPath?: string,\n): string {\n if (explicitPath) {\n if (!explicitPath.toLowerCase().endsWith('.zip')) {\n throw new Error('--out must end with .zip')\n }\n return isAbsolute(explicitPath) ? explicitPath : resolve(config.root, explicitPath)\n }\n\n const fileName =\n config.packageFileName ??\n `${safeFilePart(manifest.name)}-${safeFilePart(manifest.version)}.zip`\n if (!fileName.toLowerCase().endsWith('.zip')) {\n throw new Error('package.fileName must end with .zip')\n }\n if (basename(fileName) !== fileName) {\n throw new Error('package.fileName must not contain a directory')\n }\n return resolve(config.root, config.packageOutDir, fileName)\n}\n\nasync function writeZip(\n directory: string,\n files: string[],\n outFile: string,\n): Promise<void> {\n await mkdir(dirname(outFile), { recursive: true })\n\n const archive = new yazl.ZipFile()\n const output = createWriteStream(outFile)\n const completed = pipeline(archive.outputStream, output)\n try {\n for (const file of files) {\n archive.addFile(resolve(directory, file), file, {\n mtime: ZIP_DATE,\n mode: 0o644,\n compress: true,\n })\n }\n archive.end()\n await completed\n } catch (error) {\n await rm(outFile, { force: true })\n throw error\n }\n}\n\nexport async function packageMiniapp(\n options: PackageMiniappOptions = {},\n): Promise<{ outFile: string; outDir: string }> {\n let config: ResolvedMiniappConfig\n let outDir: string\n\n if (options.build ?? true) {\n ;({ config, outDir } = await buildMiniapp(options))\n } else {\n const root = options.root ?? process.cwd()\n const mode = options.mode ?? 'production'\n config = await loadMiniappConfig(root, {\n command: 'build',\n mode,\n isSsrBuild: false,\n isPreview: false,\n })\n outDir = resolveOutputDirectory(config)\n }\n\n const validated = await validateMiniappDirectory(outDir)\n const outFile = resolveArchivePath(config, validated.manifest, options.outFile)\n const archiveRelativeToOutput = relative(outDir, outFile)\n if (\n archiveRelativeToOutput === '' ||\n (!archiveRelativeToOutput.startsWith(`..${sep}`) && archiveRelativeToOutput !== '..')\n ) {\n throw new Error('Package output must be outside the build output directory')\n }\n\n await writeZip(outDir, validated.files, outFile)\n return { outFile, outDir }\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@xunlei-open/miniapp",
3
+ "version": "0.1.1-beta.0",
4
+ "description": "Unified development CLI for Xunlei Miniapps",
5
+ "type": "module",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.mts",
8
+ "bin": {
9
+ "xunlei-miniapp": "./bin/xunlei-miniapp.mjs"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.mts",
14
+ "default": "./dist/index.mjs"
15
+ }
16
+ },
17
+ "files": [
18
+ "bin",
19
+ "dist",
20
+ "README.md"
21
+ ],
22
+ "keywords": [
23
+ "xunlei",
24
+ "miniapp",
25
+ "vite",
26
+ "cli"
27
+ ],
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/xunlei-open/miniapp-devkit.git",
32
+ "directory": "packages/miniapp"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/xunlei-open/miniapp-devkit/issues"
36
+ },
37
+ "homepage": "https://github.com/xunlei-open/miniapp-devkit#readme",
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "engines": {
42
+ "node": ">=20.19.0"
43
+ },
44
+ "dependencies": {
45
+ "parse5": "^8.0.1",
46
+ "vite": "^8.2.0",
47
+ "yazl": "^3.3.1",
48
+ "@xunlei-open/miniapp-types": "^0.1.1-beta.0",
49
+ "@xunlei-open/vite-plugin-miniapp": "^0.1.1-beta.0"
50
+ },
51
+ "devDependencies": {
52
+ "@types/yazl": "^3.3.1"
53
+ },
54
+ "scripts": {
55
+ "build": "tsdown",
56
+ "dev": "tsdown --watch",
57
+ "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
58
+ "check": "tsc --noEmit",
59
+ "test": "vitest run"
60
+ }
61
+ }