@xunlei-open/create-miniapp 0.1.1-beta.0 → 0.1.1-beta.2
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/README.md +15 -87
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/react/README.md.ejs +44 -0
- package/templates/react-ts/README.md.ejs +45 -0
- package/templates/vanilla/README.md.ejs +43 -0
- package/templates/vanilla-ts/README.md.ejs +44 -0
- package/templates/vue/README.md.ejs +44 -0
- package/templates/vue-ts/README.md.ejs +45 -0
package/README.md
CHANGED
|
@@ -1,106 +1,34 @@
|
|
|
1
1
|
# @xunlei-open/create-miniapp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
迅雷微应用项目脚手架,支持 Vanilla、Vue、React 的 JavaScript / TypeScript 模板。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 创建项目
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- **Node.js** 20.19+ 或 22.12+(模板使用 Vite 8,[官方要求](https://vite.dev/blog/announcing-vite8#node-js-support);含 Vitest / jsdom 29)
|
|
10
|
-
|
|
11
|
-
## 能力
|
|
12
|
-
|
|
13
|
-
| Framework | Variant | 模板 ID | 包含 |
|
|
14
|
-
|-----------|---------|---------|------|
|
|
15
|
-
| Vanilla | TypeScript | `vanilla-ts` | 迅雷微应用 CLI、Vite 8、TypeScript;可选 Lint / Biome / Vitest |
|
|
16
|
-
| Vanilla | JavaScript | `vanilla` | 迅雷微应用 CLI、Vite 8;可选 Lint / Biome / Vitest |
|
|
17
|
-
| Vue | TypeScript | `vue-ts` | 迅雷微应用 CLI、Vite 8、Vue 3;可选 Lint / Biome(Experimental)/ Vitest |
|
|
18
|
-
| Vue | JavaScript | `vue` | 同上(JavaScript) |
|
|
19
|
-
| React | TypeScript | `react-ts` | Vite 8、React 19;可选 Lint / Biome / Vitest |
|
|
20
|
-
| React | JavaScript | `react` | 同上(JavaScript) |
|
|
21
|
-
|
|
22
|
-
**Lint** = ESLint + Prettier + `eslint-plugin-prettier`(规则 `prettier/prettier: error`)。编辑时红线依赖本机 ESLint 扩展读取项目配置,无需 `.vscode` 工作区文件。
|
|
23
|
-
|
|
24
|
-
**Biome** = `@biomejs/biome` 一体 lint + format,生成 `biome.json` 与 `.vscode/settings.json`。Vue 模板对 `.vue` SFC 支持为实验性,交互选项标注 `(Experimental)`。
|
|
25
|
-
|
|
26
|
-
生成的项目默认包含一个调用 `xunlei.tasks.create` 创建下载任务的页面示例,并声明最小权限 `tasks.create`;不包含 `src/events` 或 manifest `scripts`。需要介入下载任务生命周期时,可按照根目录 README 的“可选:让微应用响应下载事件”章节手动添加。
|
|
27
|
-
|
|
28
|
-
模板使用 `miniapp.config.ts`(JavaScript 模板为 `.js`)作为唯一工具配置。Vue/React 模板通过 `modules` 声明对应的 `@xunlei-open/miniapp-module-vue` 或 `@xunlei-open/miniapp-module-react`,自动加载框架的 Vite 插件;额外配置仍放在 `vite` 字段中。build 和 package 不执行类型检查,TS 模板提供可选的 `typecheck` 命令。常用命令为:
|
|
7
|
+
建议使用 Node.js 22.18+:
|
|
29
8
|
|
|
30
9
|
```bash
|
|
31
|
-
pnpm dev # xunlei-miniapp
|
|
32
|
-
pnpm build # xunlei-miniapp build
|
|
33
|
-
pnpm run package # 构建、校验并生成 ZIP
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## 使用
|
|
37
|
-
|
|
38
|
-
生成的项目不写入 `packageManager` 字段,不固定包管理器版本。可使用 npm、yarn 或 pnpm,具体版本由用户自行管理。
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
# 创建项目(推荐)
|
|
42
10
|
npm create @xunlei-open/miniapp@latest
|
|
43
|
-
|
|
44
|
-
# 等价写法
|
|
45
|
-
npx @xunlei-open/create-miniapp@latest
|
|
46
|
-
|
|
47
|
-
# 指定项目名与参数(非交互)
|
|
48
|
-
npx @xunlei-open/create-miniapp my-app -y --framework vue --variant typescript --features lint,vitest
|
|
49
|
-
|
|
50
|
-
# 使用 Biome(Vue 为实验性支持)
|
|
51
|
-
npx @xunlei-open/create-miniapp my-app -y --framework vue --variant typescript --features biome --no-install
|
|
52
|
-
|
|
53
|
-
# 本仓库开发调试
|
|
54
|
-
pnpm install
|
|
55
|
-
pnpm dev # 交互式,等同发布后的 create 命令
|
|
56
|
-
pnpm build
|
|
57
|
-
node dist/index.mjs my-demo -y --framework vue --variant typescript --features lint --no-install
|
|
58
11
|
```
|
|
59
12
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
| 参数 | 说明 |
|
|
63
|
-
|------|------|
|
|
64
|
-
| `-y, --yes` | 跳过问答,使用默认或命令行参数 |
|
|
65
|
-
| `--framework vanilla \| vue \| react` | 框架 |
|
|
66
|
-
| `--variant typescript \| javascript` | 语言变体 |
|
|
67
|
-
| `--features lint,biome,vitest` | 可选特性(逗号分隔);`lint` 与 `biome` 二选一 |
|
|
68
|
-
| `--features eslint` / `prettier` | 已合并为 `lint`,仍可作为别名传入 |
|
|
69
|
-
| (默认) | 交互时 features 默认全不选;`-y` 未传 `--features` 时不包含任何特性 |
|
|
70
|
-
| `--no-install` | 不自动安装依赖 |
|
|
13
|
+
按提示选择框架、语言和可选工具:ESLint + Prettier、Biome 或 Vitest。Lint 与 Biome 二选一;Vue 的 Biome 支持为实验性。
|
|
71
14
|
|
|
72
|
-
|
|
15
|
+
也可指定参数:
|
|
73
16
|
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
index.ts # Commander 入口
|
|
77
|
-
prompts.ts # 交互选型
|
|
78
|
-
generator.ts # EJS 渲染 + 拷贝
|
|
79
|
-
utils.ts # 包名、framework/variant/features 解析
|
|
80
|
-
types.ts # 类型定义
|
|
81
|
-
templates/
|
|
82
|
-
vanilla/
|
|
83
|
-
vanilla-ts/
|
|
84
|
-
vue/
|
|
85
|
-
vue-ts/
|
|
86
|
-
react/
|
|
87
|
-
react-ts/
|
|
17
|
+
```bash
|
|
18
|
+
npx @xunlei-open/create-miniapp@latest my-app --yes --framework vue --variant typescript --features lint,vitest --no-install
|
|
88
19
|
```
|
|
89
20
|
|
|
90
|
-
##
|
|
21
|
+
## 开发与打包
|
|
91
22
|
|
|
92
23
|
```bash
|
|
93
|
-
|
|
94
|
-
npm
|
|
24
|
+
cd my-app
|
|
25
|
+
npm install
|
|
26
|
+
npm run dev
|
|
27
|
+
npm run package
|
|
95
28
|
```
|
|
96
29
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
1. 在 `templates/` 下新增目录,并在 `resolveTemplateId` 的 `TEMPLATE_IDS` 中映射 framework + variant
|
|
100
|
-
2. 需变量替换的文件使用 `.ejs` 后缀
|
|
101
|
-
3. 勾选 `lint` 时需包含 `eslint.config.js.ejs`、`.prettierrc.ejs` 等
|
|
102
|
-
4. 勾选 `biome` 时需包含 `biome.json`、`.vscode/settings.json`,并在 `package.json.ejs` 中条件注入 `@biomejs/biome` 与 scripts
|
|
30
|
+
开发时在迅雷客户端中加载本地应用的目录,保持 dev server 运行。打包结果位于 `release/`。
|
|
103
31
|
|
|
104
|
-
|
|
32
|
+
生成项目包含创建下载任务的页面示例。应用信息和权限在 `manifest.json` 中配置,开发与构建配置使用 `miniapp.config.ts` 或 `.js`。
|
|
105
33
|
|
|
106
|
-
|
|
34
|
+
[项目入口](https://github.com/xunlei-open/miniapp-devkit#readme) · [官方文档](https://open.xunlei.com/doc/miniapp/introduction)
|
package/dist/index.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import fs from "fs-extra";
|
|
|
9
9
|
import validate from "validate-npm-package-name";
|
|
10
10
|
import { checkbox, confirm, input, select } from "@inquirer/prompts";
|
|
11
11
|
//#region package.json
|
|
12
|
-
var version = "0.1.1-beta.
|
|
12
|
+
var version = "0.1.1-beta.2";
|
|
13
13
|
//#endregion
|
|
14
14
|
//#region src/utils.ts
|
|
15
15
|
function toPackageName(input) {
|
|
@@ -206,6 +206,7 @@ async function generateProject(options) {
|
|
|
206
206
|
const context = {
|
|
207
207
|
projectName: options.projectName,
|
|
208
208
|
packageName: options.packageName,
|
|
209
|
+
packageManager: options.packageManager,
|
|
209
210
|
variant: options.variant,
|
|
210
211
|
features: options.features,
|
|
211
212
|
devkitVersion: version,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["packageJson.version","packageJson.version"],"sources":["../package.json","../src/utils.ts","../src/generator.ts","../src/prompts.ts","../src/index.ts"],"sourcesContent":["","import validate from \"validate-npm-package-name\";\nimport type { Feature, Framework, PackageManager, Variant } from \"./types.js\";\n\nexport function toPackageName(input: string): string {\n\treturn input\n\t\t.trim()\n\t\t.toLowerCase()\n\t\t.replace(/\\s+/g, \"-\")\n\t\t.replace(/[^a-z0-9-_]/g, \"-\")\n\t\t.replace(/-+/g, \"-\")\n\t\t.replace(/^-|-$/g, \"\");\n}\n\nexport function assertValidPackageName(name: string): void {\n\tconst result = validate(name);\n\tif (!result.validForNewPackages) {\n\t\tconst errors = [...(result.errors ?? []), ...(result.warnings ?? [])];\n\t\tthrow new Error(`Invalid package name \"${name}\": ${errors.join(\", \")}`);\n\t}\n}\n\nconst ALL_FEATURES: Feature[] = [\"lint\", \"biome\", \"vitest\"];\n\nconst FEATURE_ALIASES: Record<string, Feature> = {\n\tlint: \"lint\",\n\teslint: \"lint\",\n\tprettier: \"lint\",\n\tbiome: \"biome\",\n\tvitest: \"vitest\",\n};\n\nconst TEMPLATE_IDS: Record<Framework, Record<Variant, string>> = {\n\tvanilla: {\n\t\tjavascript: \"vanilla\",\n\t\ttypescript: \"vanilla-ts\",\n\t},\n\tvue: {\n\t\tjavascript: \"vue\",\n\t\ttypescript: \"vue-ts\",\n\t},\n\treact: {\n\t\tjavascript: \"react\",\n\t\ttypescript: \"react-ts\",\n\t},\n};\n\n/** Map CLI framework / variant to the templates/ directory name. */\nexport function resolveTemplateId(\n\tframework: Framework,\n\tvariant: Variant,\n): string {\n\treturn TEMPLATE_IDS[framework][variant];\n}\n\nexport function parseFramework(input: string): Framework | undefined {\n\tconst key = input.trim().toLowerCase();\n\tconst map: Record<string, Framework> = {\n\t\tvanilla: \"vanilla\",\n\t\tvue: \"vue\",\n\t\treact: \"react\",\n\t};\n\treturn map[key];\n}\n\nexport function parsePackageManager(input: string): PackageManager | undefined {\n\tconst key = input.trim().toLowerCase();\n\tconst map: Record<string, PackageManager> = {\n\t\tnpm: \"npm\",\n\t\tyarn: \"yarn\",\n\t\tpnpm: \"pnpm\",\n\t};\n\treturn map[key];\n}\n\nfunction pkgFromUserAgent(\n\tuserAgent: string | undefined,\n): { name: string; version: string } | undefined {\n\tif (!userAgent) return undefined;\n\tconst pkgSpec = userAgent.split(\" \")[0];\n\tconst [name, version] = pkgSpec?.split(\"/\") ?? [];\n\tif (!name) return undefined;\n\treturn { name, version: version ?? \"\" };\n}\n\n/** Infer npm / yarn / pnpm from npx, pnpx, yarn dlx, pnpm create, etc. */\nexport function detectInvokedPackageManager(): PackageManager {\n\tconst pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent);\n\tif (pkgInfo) {\n\t\tconst pm = parsePackageManager(pkgInfo.name);\n\t\tif (pm) return pm;\n\t}\n\n\tconst execPath = process.env.npm_execpath ?? \"\";\n\tif (execPath.includes(\"pnpm\")) return \"pnpm\";\n\tif (execPath.includes(\"yarn\")) return \"yarn\";\n\n\treturn \"npm\";\n}\n\nexport function pmInstallCommand(pm: PackageManager): string {\n\treturn pm === \"yarn\" ? \"yarn\" : `${pm} install`;\n}\n\nexport function pmDevCommand(pm: PackageManager): string {\n\treturn pm === \"npm\" ? \"npm run dev\" : `${pm} dev`;\n}\n\nexport function pmTestCommand(pm: PackageManager): string {\n\treturn pm === \"npm\" ? \"npm test\" : `${pm} test`;\n}\n\nexport function pmDevArgs(pm: PackageManager): string[] {\n\treturn pm === \"npm\" ? [\"run\", \"dev\"] : [\"dev\"];\n}\n\nexport function parseVariant(input: string): Variant | undefined {\n\tconst key = input.trim().toLowerCase();\n\tconst map: Record<string, Variant> = {\n\t\ttypescript: \"typescript\",\n\t\tts: \"typescript\",\n\t\tjavascript: \"javascript\",\n\t\tjs: \"javascript\",\n\t};\n\treturn map[key];\n}\n\nexport function parseFeatures(input: string): Feature[] {\n\tconst features: Feature[] = [];\n\tfor (const part of input.split(/[,+]/)) {\n\t\tconst key = part.trim().toLowerCase();\n\t\tif (!key) continue;\n\t\tconst feature = FEATURE_ALIASES[key];\n\t\tif (feature && !features.includes(feature)) {\n\t\t\tfeatures.push(feature);\n\t\t}\n\t}\n\treturn resolveMutuallyExclusiveLint(features);\n}\n\nexport function hasFeature(features: Feature[], feature: Feature): boolean {\n\treturn features.includes(feature);\n}\n\nexport function supportsOptionalFeatures(_framework: Framework): boolean {\n\treturn true;\n}\n\nexport function defaultFeatures(_framework: Framework): Feature[] {\n\treturn [];\n}\n\n/** lint and biome are mutually exclusive; prefer lint when both are present. */\nexport function resolveMutuallyExclusiveLint(features: Feature[]): Feature[] {\n\tif (features.includes(\"lint\") && features.includes(\"biome\")) {\n\t\treturn features.filter((f) => f !== \"biome\");\n\t}\n\treturn features;\n}\n\nexport function supportsBiomeLinter(framework: Framework): boolean {\n\treturn (\n\t\tframework === \"vanilla\" || framework === \"react\" || framework === \"vue\"\n\t);\n}\n\nexport function isBiomeExperimental(framework: Framework): boolean {\n\treturn framework === \"vue\";\n}\n\nexport function normalizeFeatures(\n\tfeatures: Feature[] | undefined,\n\tframework: Framework,\n): Feature[] {\n\tlet result: Feature[] = [];\n\n\tfor (const f of features ?? []) {\n\t\tif (ALL_FEATURES.includes(f) && !result.includes(f)) {\n\t\t\tresult.push(f);\n\t\t}\n\t}\n\n\tresult = resolveMutuallyExclusiveLint(result);\n\n\tif (result.includes(\"biome\") && !supportsBiomeLinter(framework)) {\n\t\tresult = result.filter((f) => f !== \"biome\");\n\t}\n\n\treturn result;\n}\n","import path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport ejs from \"ejs\";\nimport fs from \"fs-extra\";\nimport { green, red } from \"kolorist\";\nimport packageJson from \"../package.json\";\nimport type { CreateOptions, TemplateContext } from \"./types.js\";\nimport {\n\thasFeature,\n\tpmDevCommand,\n\tpmInstallCommand,\n\tpmTestCommand,\n\tresolveTemplateId,\n} from \"./utils.js\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nfunction getTemplatesRoot(): string {\n\t// dist/index.mjs -> ../templates ; dev tsx -> ../templates\n\treturn path.resolve(__dirname, \"../templates\");\n}\n\nfunction shouldSkip(relPath: string, options: CreateOptions): boolean {\n\tconst normalized = relPath.replace(/\\\\/g, \"/\");\n\tconst { features } = options;\n\n\tif (!hasFeature(features, \"vitest\")) {\n\t\tif (\n\t\t\tnormalized.startsWith(\"tests/\") ||\n\t\t\tnormalized.includes(\"/tests/\") ||\n\t\t\tnormalized.includes(\"vitest.config\") ||\n\t\t\tnormalized.startsWith(\"src/test/\")\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\tif (!hasFeature(features, \"lint\")) {\n\t\tif (\n\t\t\tnormalized.endsWith(\"eslint.config.js\") ||\n\t\t\tnormalized.endsWith(\"eslint.config.js.ejs\")\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\tif (relPath.endsWith(\".prettierrc.ejs\")) return true;\n\t\tif (relPath.endsWith(\".prettierignore\")) return true;\n\t}\n\tif (!hasFeature(features, \"biome\")) {\n\t\tif (normalized === \"biome.json\" || normalized.endsWith(\"/biome.json\")) {\n\t\t\treturn true;\n\t\t}\n\t\tif (\n\t\t\tnormalized === \".vscode/settings.json\" ||\n\t\t\tnormalized.endsWith(\"/.vscode/settings.json\")\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\tif (\n\t\trelPath.endsWith(\"pnpm-lock.yaml\") ||\n\t\trelPath.endsWith(\"package-lock.json\") ||\n\t\trelPath.endsWith(\"yarn.lock\")\n\t) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nasync function renderFile(\n\tsrc: string,\n\tdest: string,\n\tcontext: TemplateContext,\n): Promise<void> {\n\tconst content = await fs.readFile(src, \"utf-8\");\n\tconst rendered = ejs.render(content, context, { rmWhitespace: false });\n\tawait fs.ensureDir(path.dirname(dest));\n\tawait fs.writeFile(dest, rendered, \"utf-8\");\n}\n\nasync function copyTemplateDir(\n\ttemplateDir: string,\n\ttargetDir: string,\n\tcontext: TemplateContext,\n\toptions: CreateOptions,\n\trelBase = \"\",\n): Promise<void> {\n\tconst entries = await fs.readdir(templateDir, { withFileTypes: true });\n\n\tfor (const entry of entries) {\n\t\tconst srcPath = path.join(templateDir, entry.name);\n\t\tconst relPath = relBase ? `${relBase}/${entry.name}` : entry.name;\n\n\t\tif (shouldSkip(relPath, options)) continue;\n\n\t\tif (entry.isDirectory()) {\n\t\t\tawait copyTemplateDir(\n\t\t\t\tsrcPath,\n\t\t\t\tpath.join(targetDir, entry.name),\n\t\t\t\tcontext,\n\t\t\t\toptions,\n\t\t\t\trelPath,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst isEjs = entry.name.endsWith(\".ejs\");\n\t\tconst templateName = isEjs ? entry.name.slice(0, -4) : entry.name;\n\t\t// npm excludes .gitignore files from published tarballs, so templates\n\t\t// store the file under a portable name and restore it during generation.\n\t\tconst outName = templateName === \"_gitignore\" ? \".gitignore\" : templateName;\n\t\tconst destPath = path.join(targetDir, outName);\n\n\t\tif (isEjs) {\n\t\t\tawait renderFile(srcPath, destPath, context);\n\t\t} else {\n\t\t\tawait fs.ensureDir(path.dirname(destPath));\n\t\t\tawait fs.copy(srcPath, destPath);\n\t\t}\n\t}\n}\n\nexport async function generateProject(options: CreateOptions): Promise<string> {\n\tconst templateId = resolveTemplateId(options.framework, options.variant);\n\tconst templateDir = path.join(getTemplatesRoot(), templateId);\n\n\tif (!(await fs.pathExists(templateDir))) {\n\t\tthrow new Error(\n\t\t\t`Template \"${templateId}\" is not available (${options.framework} + ${options.variant}).`,\n\t\t);\n\t}\n\n\tconst targetDir = path.resolve(process.cwd(), options.projectName);\n\n\tif (await fs.pathExists(targetDir)) {\n\t\tconst files = await fs.readdir(targetDir);\n\t\tif (files.length > 0) {\n\t\t\tthrow new Error(`Target directory is not empty: ${targetDir}`);\n\t\t}\n\t}\n\n\tconst context: TemplateContext = {\n\t\tprojectName: options.projectName,\n\t\tpackageName: options.packageName,\n\t\tvariant: options.variant,\n\t\tfeatures: options.features,\n\t\tdevkitVersion: packageJson.version,\n\t\tisTypeScript: options.variant === \"typescript\",\n\t};\n\n\tawait fs.ensureDir(targetDir);\n\tawait copyTemplateDir(templateDir, targetDir, context, options);\n\n\treturn targetDir;\n}\n\nexport function printNextSteps(\n\ttargetDir: string,\n\toptions: CreateOptions,\n\tinstalled: boolean,\n\tautoStartDev = false,\n): void {\n\tconst rel = path.relative(process.cwd(), targetDir) || \".\";\n\tconst commands: string[] = [];\n\n\tif (rel !== \".\" && !autoStartDev) {\n\t\tcommands.push(`cd ${rel}`);\n\t}\n\tconst { packageManager } = options;\n\n\tif (!installed) {\n\t\tcommands.push(pmInstallCommand(packageManager));\n\t}\n\tif (!autoStartDev) {\n\t\tcommands.push(pmDevCommand(packageManager));\n\t}\n\tif (hasFeature(options.features, \"vitest\")) {\n\t\tcommands.push(pmTestCommand(packageManager));\n\t}\n\n\tif (commands.length > 0) {\n\t\tconsole.log(green(\"\\nDone. Now run:\\n\"));\n\t\tfor (const command of commands) {\n\t\t\tconsole.log(` ${command}`);\n\t\t}\n\t\tconsole.log(\"\");\n\t} else {\n\t\tconsole.log(green(\"\\nDone.\\n\"));\n\t}\n\n\tconsole.log(\"Optional: Initialize Git in your project directory with:\\n\");\n\tconsole.log(' git init && git add -A && git commit -m \"initial commit\"');\n\tconsole.log(\"\");\n}\n\nexport function printError(err: unknown): void {\n\tconst msg = err instanceof Error ? err.message : String(err);\n\tconsole.error(red(`\\n✖ ${msg}\\n`));\n}\n","import { checkbox, confirm, input, select } from \"@inquirer/prompts\";\nimport type { CreateOptions, Feature, Framework, Variant } from \"./types.js\";\nimport {\n\tassertValidPackageName,\n\tdefaultFeatures,\n\tdetectInvokedPackageManager,\n\tisBiomeExperimental,\n\tsupportsBiomeLinter,\n\tsupportsOptionalFeatures,\n\ttoPackageName,\n} from \"./utils.js\";\n\nexport async function runPrompts(\n\tdefaults: Partial<CreateOptions> = {},\n): Promise<CreateOptions> {\n\tconst projectName = await input({\n\t\tmessage: \"Project name:\",\n\t\tdefault: defaults.projectName ?? \"xunlei-plugin-project\",\n\t});\n\n\tconst packageName = toPackageName(defaults.packageName ?? projectName);\n\tassertValidPackageName(packageName);\n\n\tconst framework = await select({\n\t\tmessage: \"Select a framework:\",\n\t\tchoices: [\n\t\t\t{ name: \"Vanilla\", value: \"vanilla\" as const },\n\t\t\t{ name: \"Vue\", value: \"vue\" as const },\n\t\t\t{ name: \"React\", value: \"react\" as const },\n\t\t],\n\t\tdefault: defaults.framework ?? \"vanilla\",\n\t});\n\n\tconst variant = await selectVariant(defaults.variant);\n\n\tconst features = supportsOptionalFeatures(framework)\n\t\t? await promptFeatures(\n\t\t\t\tframework,\n\t\t\t\tvariant,\n\t\t\t\tdefaults.features ?? defaultFeatures(framework),\n\t\t\t)\n\t\t: [];\n\n\tconst packageManager =\n\t\tdefaults.packageManager ?? detectInvokedPackageManager();\n\n\tconst install = await confirm({\n\t\tmessage: `Install dependencies with ${packageManager} and start now?`,\n\t\tdefault: defaults.install ?? true,\n\t});\n\n\treturn {\n\t\tprojectName,\n\t\tpackageName,\n\t\tframework,\n\t\tvariant,\n\t\tfeatures,\n\t\tpackageManager,\n\t\tinstall,\n\t};\n}\n\nasync function promptFeatures(\n\tframework: Framework,\n\t_variant: Variant,\n\tdefaultSelected: Feature[],\n): Promise<Feature[]> {\n\tconst features: Feature[] = [];\n\n\tconst wantsLint = await promptAddLinter(defaultSelected);\n\tif (wantsLint) {\n\t\tfeatures.push(await promptLintTool(framework, defaultSelected));\n\t}\n\n\tconst extra = await checkbox({\n\t\tmessage: \"Select additional features:\",\n\t\tchoices: [\n\t\t\t{\n\t\t\t\tname: \"Vitest (unit testing)\",\n\t\t\t\tvalue: \"vitest\",\n\t\t\t\tchecked: defaultSelected.includes(\"vitest\"),\n\t\t\t},\n\t\t],\n\t});\n\tfeatures.push(...(extra as Feature[]));\n\n\treturn features;\n}\n\nasync function promptAddLinter(_defaultSelected: Feature[]): Promise<boolean> {\n\treturn select({\n\t\tmessage: \"Add linter / formatter?\",\n\t\tchoices: [\n\t\t\t{ name: \"No\", value: false as const },\n\t\t\t{ name: \"Yes\", value: true as const },\n\t\t],\n\t\tdefault: true,\n\t});\n}\n\nasync function promptLintTool(\n\tframework: Framework,\n\tdefaultSelected: Feature[],\n): Promise<\"lint\" | \"biome\"> {\n\tconst biomeLabel = isBiomeExperimental(framework)\n\t\t? \"Biome (lint + format) (Experimental)\"\n\t\t: \"Biome (lint + format)\";\n\n\tconst choices = supportsBiomeLinter(framework)\n\t\t? [\n\t\t\t\t{ name: \"ESLint + Prettier\", value: \"lint\" as const },\n\t\t\t\t{ name: biomeLabel, value: \"biome\" as const },\n\t\t\t]\n\t\t: [{ name: \"ESLint + Prettier\", value: \"lint\" as const }];\n\n\treturn select({\n\t\tmessage: \"Select linter / formatter:\",\n\t\tchoices,\n\t\tdefault: defaultSelected.includes(\"biome\") ? \"biome\" : \"lint\",\n\t});\n}\n\nasync function selectVariant(defaultVariant?: Variant): Promise<Variant> {\n\treturn select({\n\t\tmessage: \"Select a variant:\",\n\t\tchoices: [\n\t\t\t{ name: \"TypeScript\", value: \"typescript\" as const },\n\t\t\t{ name: \"JavaScript\", value: \"javascript\" as const },\n\t\t],\n\t\tdefault: defaultVariant ?? \"typescript\",\n\t});\n}\n","import { Command } from \"commander\";\nimport { execa } from \"execa\";\nimport { cyan } from \"kolorist\";\nimport packageJson from \"../package.json\";\nimport { generateProject, printError, printNextSteps } from \"./generator.js\";\nimport { runPrompts } from \"./prompts.js\";\nimport type { CreateOptions, Framework, Variant } from \"./types.js\";\nimport {\n\tassertValidPackageName,\n\tdetectInvokedPackageManager,\n\tnormalizeFeatures,\n\tparseFeatures,\n\tparseFramework,\n\tparsePackageManager,\n\tparseVariant,\n\tpmDevArgs,\n\tpmDevCommand,\n\ttoPackageName,\n} from \"./utils.js\";\n\nconst CLI_NAME = \"@xunlei-open/create-miniapp\";\n\nconst program = new Command();\n\nprogram\n\t.name(CLI_NAME)\n\t.description(\"Xunlei Open Platform plugin scaffold\")\n\t.version(packageJson.version)\n\t.argument(\"[project-name]\", \"project name\")\n\t.option(\"--framework <framework>\", \"vanilla | vue | react\")\n\t.option(\"--variant <variant>\", \"typescript | javascript\")\n\t.option(\n\t\t\"--features <features>\",\n\t\t\"comma-separated: lint,biome,vitest (lint and biome are mutually exclusive; eslint/prettier alias lint)\",\n\t)\n\t.option(\"--package-manager <pm>\", \"npm | yarn | pnpm\")\n\t.option(\"--no-install\", \"skip dependency installation\")\n\t.option(\"-y, --yes\", \"use defaults and skip prompts\")\n\t.action(async (projectName: string | undefined, opts) => {\n\t\ttry {\n\t\t\tconst defaults: Partial<CreateOptions> = {};\n\t\t\tif (projectName) defaults.projectName = projectName;\n\n\t\t\tconst frameworkInput = opts.framework;\n\t\t\tif (frameworkInput) {\n\t\t\t\tconst parsed = parseFramework(frameworkInput);\n\t\t\t\tif (!parsed) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unknown framework: ${frameworkInput} (supported: vanilla | vue | react)`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tdefaults.framework = parsed;\n\t\t\t}\n\n\t\t\tconst variantInput = opts.variant;\n\t\t\tif (variantInput) {\n\t\t\t\tconst parsed = parseVariant(variantInput);\n\t\t\t\tif (!parsed) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unknown variant: ${variantInput} (supported: typescript | javascript)`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tdefaults.variant = parsed;\n\t\t\t}\n\n\t\t\tconst featuresInput = opts.features;\n\t\t\tif (featuresInput) {\n\t\t\t\tconst parsed = parseFeatures(featuresInput);\n\t\t\t\tif (parsed.length === 0) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unknown features: ${featuresInput} (supported: lint, biome, vitest; eslint/prettier alias lint)`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tdefaults.features = parsed;\n\t\t\t}\n\n\t\t\tif (opts.install === false) defaults.install = false;\n\n\t\t\tconst packageManagerInput = opts.packageManager;\n\t\t\tif (packageManagerInput) {\n\t\t\t\tconst parsed = parsePackageManager(packageManagerInput);\n\t\t\t\tif (!parsed) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unknown package manager: ${packageManagerInput} (supported: npm | yarn | pnpm)`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tdefaults.packageManager = parsed;\n\t\t\t} else {\n\t\t\t\tdefaults.packageManager = detectInvokedPackageManager();\n\t\t\t}\n\n\t\t\tconsole.log(cyan(`\\n ${CLI_NAME} \\n`));\n\t\t\tconst options = opts.yes\n\t\t\t\t? resolveOptionsFromDefaults(defaults)\n\t\t\t\t: await runPrompts(defaults);\n\t\t\tconst targetDir = await generateProject(options);\n\n\t\t\tlet installed = false;\n\t\t\tif (options.install) {\n\t\t\t\tconst { packageManager: pm } = options;\n\t\t\t\tconsole.log(cyan(`\\nInstalling dependencies (${pm})...\\n`));\n\t\t\t\tawait execa(pm, [\"install\"], {\n\t\t\t\t\tcwd: targetDir,\n\t\t\t\t\tstdio: \"inherit\",\n\t\t\t\t});\n\t\t\t\tinstalled = true;\n\n\t\t\t\tprintNextSteps(targetDir, options, installed, true);\n\t\t\t\tconsole.log(cyan(`\\nStarting dev server (${pmDevCommand(pm)})...\\n`));\n\t\t\t\tawait execa(pm, pmDevArgs(pm), { cwd: targetDir, stdio: \"inherit\" });\n\t\t\t} else {\n\t\t\t\tprintNextSteps(targetDir, options, installed);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tprintError(err);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nfunction resolveOptionsFromDefaults(\n\tdefaults: Partial<CreateOptions>,\n): CreateOptions {\n\tconst projectName = defaults.projectName ?? \"xunlei-plugin-project\";\n\tconst packageName = toPackageName(defaults.packageName ?? projectName);\n\tassertValidPackageName(packageName);\n\n\tconst framework = (defaults.framework ?? \"vanilla\") as Framework;\n\tconst variant = (defaults.variant ?? \"typescript\") as Variant;\n\n\tconst features = normalizeFeatures(defaults.features, framework);\n\tconst packageManager =\n\t\tdefaults.packageManager ?? detectInvokedPackageManager();\n\tconst install = defaults.install ?? true;\n\n\treturn {\n\t\tprojectName,\n\t\tpackageName,\n\t\tframework,\n\t\tvariant,\n\t\tfeatures,\n\t\tpackageManager,\n\t\tinstall,\n\t};\n}\n\nprogram.parse();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["packageJson.version","packageJson.version"],"sources":["../package.json","../src/utils.ts","../src/generator.ts","../src/prompts.ts","../src/index.ts"],"sourcesContent":["","import validate from \"validate-npm-package-name\";\nimport type { Feature, Framework, PackageManager, Variant } from \"./types.js\";\n\nexport function toPackageName(input: string): string {\n\treturn input\n\t\t.trim()\n\t\t.toLowerCase()\n\t\t.replace(/\\s+/g, \"-\")\n\t\t.replace(/[^a-z0-9-_]/g, \"-\")\n\t\t.replace(/-+/g, \"-\")\n\t\t.replace(/^-|-$/g, \"\");\n}\n\nexport function assertValidPackageName(name: string): void {\n\tconst result = validate(name);\n\tif (!result.validForNewPackages) {\n\t\tconst errors = [...(result.errors ?? []), ...(result.warnings ?? [])];\n\t\tthrow new Error(`Invalid package name \"${name}\": ${errors.join(\", \")}`);\n\t}\n}\n\nconst ALL_FEATURES: Feature[] = [\"lint\", \"biome\", \"vitest\"];\n\nconst FEATURE_ALIASES: Record<string, Feature> = {\n\tlint: \"lint\",\n\teslint: \"lint\",\n\tprettier: \"lint\",\n\tbiome: \"biome\",\n\tvitest: \"vitest\",\n};\n\nconst TEMPLATE_IDS: Record<Framework, Record<Variant, string>> = {\n\tvanilla: {\n\t\tjavascript: \"vanilla\",\n\t\ttypescript: \"vanilla-ts\",\n\t},\n\tvue: {\n\t\tjavascript: \"vue\",\n\t\ttypescript: \"vue-ts\",\n\t},\n\treact: {\n\t\tjavascript: \"react\",\n\t\ttypescript: \"react-ts\",\n\t},\n};\n\n/** Map CLI framework / variant to the templates/ directory name. */\nexport function resolveTemplateId(\n\tframework: Framework,\n\tvariant: Variant,\n): string {\n\treturn TEMPLATE_IDS[framework][variant];\n}\n\nexport function parseFramework(input: string): Framework | undefined {\n\tconst key = input.trim().toLowerCase();\n\tconst map: Record<string, Framework> = {\n\t\tvanilla: \"vanilla\",\n\t\tvue: \"vue\",\n\t\treact: \"react\",\n\t};\n\treturn map[key];\n}\n\nexport function parsePackageManager(input: string): PackageManager | undefined {\n\tconst key = input.trim().toLowerCase();\n\tconst map: Record<string, PackageManager> = {\n\t\tnpm: \"npm\",\n\t\tyarn: \"yarn\",\n\t\tpnpm: \"pnpm\",\n\t};\n\treturn map[key];\n}\n\nfunction pkgFromUserAgent(\n\tuserAgent: string | undefined,\n): { name: string; version: string } | undefined {\n\tif (!userAgent) return undefined;\n\tconst pkgSpec = userAgent.split(\" \")[0];\n\tconst [name, version] = pkgSpec?.split(\"/\") ?? [];\n\tif (!name) return undefined;\n\treturn { name, version: version ?? \"\" };\n}\n\n/** Infer npm / yarn / pnpm from npx, pnpx, yarn dlx, pnpm create, etc. */\nexport function detectInvokedPackageManager(): PackageManager {\n\tconst pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent);\n\tif (pkgInfo) {\n\t\tconst pm = parsePackageManager(pkgInfo.name);\n\t\tif (pm) return pm;\n\t}\n\n\tconst execPath = process.env.npm_execpath ?? \"\";\n\tif (execPath.includes(\"pnpm\")) return \"pnpm\";\n\tif (execPath.includes(\"yarn\")) return \"yarn\";\n\n\treturn \"npm\";\n}\n\nexport function pmInstallCommand(pm: PackageManager): string {\n\treturn pm === \"yarn\" ? \"yarn\" : `${pm} install`;\n}\n\nexport function pmDevCommand(pm: PackageManager): string {\n\treturn pm === \"npm\" ? \"npm run dev\" : `${pm} dev`;\n}\n\nexport function pmTestCommand(pm: PackageManager): string {\n\treturn pm === \"npm\" ? \"npm test\" : `${pm} test`;\n}\n\nexport function pmDevArgs(pm: PackageManager): string[] {\n\treturn pm === \"npm\" ? [\"run\", \"dev\"] : [\"dev\"];\n}\n\nexport function parseVariant(input: string): Variant | undefined {\n\tconst key = input.trim().toLowerCase();\n\tconst map: Record<string, Variant> = {\n\t\ttypescript: \"typescript\",\n\t\tts: \"typescript\",\n\t\tjavascript: \"javascript\",\n\t\tjs: \"javascript\",\n\t};\n\treturn map[key];\n}\n\nexport function parseFeatures(input: string): Feature[] {\n\tconst features: Feature[] = [];\n\tfor (const part of input.split(/[,+]/)) {\n\t\tconst key = part.trim().toLowerCase();\n\t\tif (!key) continue;\n\t\tconst feature = FEATURE_ALIASES[key];\n\t\tif (feature && !features.includes(feature)) {\n\t\t\tfeatures.push(feature);\n\t\t}\n\t}\n\treturn resolveMutuallyExclusiveLint(features);\n}\n\nexport function hasFeature(features: Feature[], feature: Feature): boolean {\n\treturn features.includes(feature);\n}\n\nexport function supportsOptionalFeatures(_framework: Framework): boolean {\n\treturn true;\n}\n\nexport function defaultFeatures(_framework: Framework): Feature[] {\n\treturn [];\n}\n\n/** lint and biome are mutually exclusive; prefer lint when both are present. */\nexport function resolveMutuallyExclusiveLint(features: Feature[]): Feature[] {\n\tif (features.includes(\"lint\") && features.includes(\"biome\")) {\n\t\treturn features.filter((f) => f !== \"biome\");\n\t}\n\treturn features;\n}\n\nexport function supportsBiomeLinter(framework: Framework): boolean {\n\treturn (\n\t\tframework === \"vanilla\" || framework === \"react\" || framework === \"vue\"\n\t);\n}\n\nexport function isBiomeExperimental(framework: Framework): boolean {\n\treturn framework === \"vue\";\n}\n\nexport function normalizeFeatures(\n\tfeatures: Feature[] | undefined,\n\tframework: Framework,\n): Feature[] {\n\tlet result: Feature[] = [];\n\n\tfor (const f of features ?? []) {\n\t\tif (ALL_FEATURES.includes(f) && !result.includes(f)) {\n\t\t\tresult.push(f);\n\t\t}\n\t}\n\n\tresult = resolveMutuallyExclusiveLint(result);\n\n\tif (result.includes(\"biome\") && !supportsBiomeLinter(framework)) {\n\t\tresult = result.filter((f) => f !== \"biome\");\n\t}\n\n\treturn result;\n}\n","import path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport ejs from \"ejs\";\nimport fs from \"fs-extra\";\nimport { green, red } from \"kolorist\";\nimport packageJson from \"../package.json\";\nimport type { CreateOptions, TemplateContext } from \"./types.js\";\nimport {\n\thasFeature,\n\tpmDevCommand,\n\tpmInstallCommand,\n\tpmTestCommand,\n\tresolveTemplateId,\n} from \"./utils.js\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nfunction getTemplatesRoot(): string {\n\t// dist/index.mjs -> ../templates ; dev tsx -> ../templates\n\treturn path.resolve(__dirname, \"../templates\");\n}\n\nfunction shouldSkip(relPath: string, options: CreateOptions): boolean {\n\tconst normalized = relPath.replace(/\\\\/g, \"/\");\n\tconst { features } = options;\n\n\tif (!hasFeature(features, \"vitest\")) {\n\t\tif (\n\t\t\tnormalized.startsWith(\"tests/\") ||\n\t\t\tnormalized.includes(\"/tests/\") ||\n\t\t\tnormalized.includes(\"vitest.config\") ||\n\t\t\tnormalized.startsWith(\"src/test/\")\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\tif (!hasFeature(features, \"lint\")) {\n\t\tif (\n\t\t\tnormalized.endsWith(\"eslint.config.js\") ||\n\t\t\tnormalized.endsWith(\"eslint.config.js.ejs\")\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\tif (relPath.endsWith(\".prettierrc.ejs\")) return true;\n\t\tif (relPath.endsWith(\".prettierignore\")) return true;\n\t}\n\tif (!hasFeature(features, \"biome\")) {\n\t\tif (normalized === \"biome.json\" || normalized.endsWith(\"/biome.json\")) {\n\t\t\treturn true;\n\t\t}\n\t\tif (\n\t\t\tnormalized === \".vscode/settings.json\" ||\n\t\t\tnormalized.endsWith(\"/.vscode/settings.json\")\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\tif (\n\t\trelPath.endsWith(\"pnpm-lock.yaml\") ||\n\t\trelPath.endsWith(\"package-lock.json\") ||\n\t\trelPath.endsWith(\"yarn.lock\")\n\t) {\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nasync function renderFile(\n\tsrc: string,\n\tdest: string,\n\tcontext: TemplateContext,\n): Promise<void> {\n\tconst content = await fs.readFile(src, \"utf-8\");\n\tconst rendered = ejs.render(content, context, { rmWhitespace: false });\n\tawait fs.ensureDir(path.dirname(dest));\n\tawait fs.writeFile(dest, rendered, \"utf-8\");\n}\n\nasync function copyTemplateDir(\n\ttemplateDir: string,\n\ttargetDir: string,\n\tcontext: TemplateContext,\n\toptions: CreateOptions,\n\trelBase = \"\",\n): Promise<void> {\n\tconst entries = await fs.readdir(templateDir, { withFileTypes: true });\n\n\tfor (const entry of entries) {\n\t\tconst srcPath = path.join(templateDir, entry.name);\n\t\tconst relPath = relBase ? `${relBase}/${entry.name}` : entry.name;\n\n\t\tif (shouldSkip(relPath, options)) continue;\n\n\t\tif (entry.isDirectory()) {\n\t\t\tawait copyTemplateDir(\n\t\t\t\tsrcPath,\n\t\t\t\tpath.join(targetDir, entry.name),\n\t\t\t\tcontext,\n\t\t\t\toptions,\n\t\t\t\trelPath,\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst isEjs = entry.name.endsWith(\".ejs\");\n\t\tconst templateName = isEjs ? entry.name.slice(0, -4) : entry.name;\n\t\t// npm excludes .gitignore files from published tarballs, so templates\n\t\t// store the file under a portable name and restore it during generation.\n\t\tconst outName = templateName === \"_gitignore\" ? \".gitignore\" : templateName;\n\t\tconst destPath = path.join(targetDir, outName);\n\n\t\tif (isEjs) {\n\t\t\tawait renderFile(srcPath, destPath, context);\n\t\t} else {\n\t\t\tawait fs.ensureDir(path.dirname(destPath));\n\t\t\tawait fs.copy(srcPath, destPath);\n\t\t}\n\t}\n}\n\nexport async function generateProject(options: CreateOptions): Promise<string> {\n\tconst templateId = resolveTemplateId(options.framework, options.variant);\n\tconst templateDir = path.join(getTemplatesRoot(), templateId);\n\n\tif (!(await fs.pathExists(templateDir))) {\n\t\tthrow new Error(\n\t\t\t`Template \"${templateId}\" is not available (${options.framework} + ${options.variant}).`,\n\t\t);\n\t}\n\n\tconst targetDir = path.resolve(process.cwd(), options.projectName);\n\n\tif (await fs.pathExists(targetDir)) {\n\t\tconst files = await fs.readdir(targetDir);\n\t\tif (files.length > 0) {\n\t\t\tthrow new Error(`Target directory is not empty: ${targetDir}`);\n\t\t}\n\t}\n\n\tconst context: TemplateContext = {\n\t\tprojectName: options.projectName,\n\t\tpackageName: options.packageName,\n\t\tpackageManager: options.packageManager,\n\t\tvariant: options.variant,\n\t\tfeatures: options.features,\n\t\tdevkitVersion: packageJson.version,\n\t\tisTypeScript: options.variant === \"typescript\",\n\t};\n\n\tawait fs.ensureDir(targetDir);\n\tawait copyTemplateDir(templateDir, targetDir, context, options);\n\n\treturn targetDir;\n}\n\nexport function printNextSteps(\n\ttargetDir: string,\n\toptions: CreateOptions,\n\tinstalled: boolean,\n\tautoStartDev = false,\n): void {\n\tconst rel = path.relative(process.cwd(), targetDir) || \".\";\n\tconst commands: string[] = [];\n\n\tif (rel !== \".\" && !autoStartDev) {\n\t\tcommands.push(`cd ${rel}`);\n\t}\n\tconst { packageManager } = options;\n\n\tif (!installed) {\n\t\tcommands.push(pmInstallCommand(packageManager));\n\t}\n\tif (!autoStartDev) {\n\t\tcommands.push(pmDevCommand(packageManager));\n\t}\n\tif (hasFeature(options.features, \"vitest\")) {\n\t\tcommands.push(pmTestCommand(packageManager));\n\t}\n\n\tif (commands.length > 0) {\n\t\tconsole.log(green(\"\\nDone. Now run:\\n\"));\n\t\tfor (const command of commands) {\n\t\t\tconsole.log(` ${command}`);\n\t\t}\n\t\tconsole.log(\"\");\n\t} else {\n\t\tconsole.log(green(\"\\nDone.\\n\"));\n\t}\n\n\tconsole.log(\"Optional: Initialize Git in your project directory with:\\n\");\n\tconsole.log(' git init && git add -A && git commit -m \"initial commit\"');\n\tconsole.log(\"\");\n}\n\nexport function printError(err: unknown): void {\n\tconst msg = err instanceof Error ? err.message : String(err);\n\tconsole.error(red(`\\n✖ ${msg}\\n`));\n}\n","import { checkbox, confirm, input, select } from \"@inquirer/prompts\";\nimport type { CreateOptions, Feature, Framework, Variant } from \"./types.js\";\nimport {\n\tassertValidPackageName,\n\tdefaultFeatures,\n\tdetectInvokedPackageManager,\n\tisBiomeExperimental,\n\tsupportsBiomeLinter,\n\tsupportsOptionalFeatures,\n\ttoPackageName,\n} from \"./utils.js\";\n\nexport async function runPrompts(\n\tdefaults: Partial<CreateOptions> = {},\n): Promise<CreateOptions> {\n\tconst projectName = await input({\n\t\tmessage: \"Project name:\",\n\t\tdefault: defaults.projectName ?? \"xunlei-plugin-project\",\n\t});\n\n\tconst packageName = toPackageName(defaults.packageName ?? projectName);\n\tassertValidPackageName(packageName);\n\n\tconst framework = await select({\n\t\tmessage: \"Select a framework:\",\n\t\tchoices: [\n\t\t\t{ name: \"Vanilla\", value: \"vanilla\" as const },\n\t\t\t{ name: \"Vue\", value: \"vue\" as const },\n\t\t\t{ name: \"React\", value: \"react\" as const },\n\t\t],\n\t\tdefault: defaults.framework ?? \"vanilla\",\n\t});\n\n\tconst variant = await selectVariant(defaults.variant);\n\n\tconst features = supportsOptionalFeatures(framework)\n\t\t? await promptFeatures(\n\t\t\t\tframework,\n\t\t\t\tvariant,\n\t\t\t\tdefaults.features ?? defaultFeatures(framework),\n\t\t\t)\n\t\t: [];\n\n\tconst packageManager =\n\t\tdefaults.packageManager ?? detectInvokedPackageManager();\n\n\tconst install = await confirm({\n\t\tmessage: `Install dependencies with ${packageManager} and start now?`,\n\t\tdefault: defaults.install ?? true,\n\t});\n\n\treturn {\n\t\tprojectName,\n\t\tpackageName,\n\t\tframework,\n\t\tvariant,\n\t\tfeatures,\n\t\tpackageManager,\n\t\tinstall,\n\t};\n}\n\nasync function promptFeatures(\n\tframework: Framework,\n\t_variant: Variant,\n\tdefaultSelected: Feature[],\n): Promise<Feature[]> {\n\tconst features: Feature[] = [];\n\n\tconst wantsLint = await promptAddLinter(defaultSelected);\n\tif (wantsLint) {\n\t\tfeatures.push(await promptLintTool(framework, defaultSelected));\n\t}\n\n\tconst extra = await checkbox({\n\t\tmessage: \"Select additional features:\",\n\t\tchoices: [\n\t\t\t{\n\t\t\t\tname: \"Vitest (unit testing)\",\n\t\t\t\tvalue: \"vitest\",\n\t\t\t\tchecked: defaultSelected.includes(\"vitest\"),\n\t\t\t},\n\t\t],\n\t});\n\tfeatures.push(...(extra as Feature[]));\n\n\treturn features;\n}\n\nasync function promptAddLinter(_defaultSelected: Feature[]): Promise<boolean> {\n\treturn select({\n\t\tmessage: \"Add linter / formatter?\",\n\t\tchoices: [\n\t\t\t{ name: \"No\", value: false as const },\n\t\t\t{ name: \"Yes\", value: true as const },\n\t\t],\n\t\tdefault: true,\n\t});\n}\n\nasync function promptLintTool(\n\tframework: Framework,\n\tdefaultSelected: Feature[],\n): Promise<\"lint\" | \"biome\"> {\n\tconst biomeLabel = isBiomeExperimental(framework)\n\t\t? \"Biome (lint + format) (Experimental)\"\n\t\t: \"Biome (lint + format)\";\n\n\tconst choices = supportsBiomeLinter(framework)\n\t\t? [\n\t\t\t\t{ name: \"ESLint + Prettier\", value: \"lint\" as const },\n\t\t\t\t{ name: biomeLabel, value: \"biome\" as const },\n\t\t\t]\n\t\t: [{ name: \"ESLint + Prettier\", value: \"lint\" as const }];\n\n\treturn select({\n\t\tmessage: \"Select linter / formatter:\",\n\t\tchoices,\n\t\tdefault: defaultSelected.includes(\"biome\") ? \"biome\" : \"lint\",\n\t});\n}\n\nasync function selectVariant(defaultVariant?: Variant): Promise<Variant> {\n\treturn select({\n\t\tmessage: \"Select a variant:\",\n\t\tchoices: [\n\t\t\t{ name: \"TypeScript\", value: \"typescript\" as const },\n\t\t\t{ name: \"JavaScript\", value: \"javascript\" as const },\n\t\t],\n\t\tdefault: defaultVariant ?? \"typescript\",\n\t});\n}\n","import { Command } from \"commander\";\nimport { execa } from \"execa\";\nimport { cyan } from \"kolorist\";\nimport packageJson from \"../package.json\";\nimport { generateProject, printError, printNextSteps } from \"./generator.js\";\nimport { runPrompts } from \"./prompts.js\";\nimport type { CreateOptions, Framework, Variant } from \"./types.js\";\nimport {\n\tassertValidPackageName,\n\tdetectInvokedPackageManager,\n\tnormalizeFeatures,\n\tparseFeatures,\n\tparseFramework,\n\tparsePackageManager,\n\tparseVariant,\n\tpmDevArgs,\n\tpmDevCommand,\n\ttoPackageName,\n} from \"./utils.js\";\n\nconst CLI_NAME = \"@xunlei-open/create-miniapp\";\n\nconst program = new Command();\n\nprogram\n\t.name(CLI_NAME)\n\t.description(\"Xunlei Open Platform plugin scaffold\")\n\t.version(packageJson.version)\n\t.argument(\"[project-name]\", \"project name\")\n\t.option(\"--framework <framework>\", \"vanilla | vue | react\")\n\t.option(\"--variant <variant>\", \"typescript | javascript\")\n\t.option(\n\t\t\"--features <features>\",\n\t\t\"comma-separated: lint,biome,vitest (lint and biome are mutually exclusive; eslint/prettier alias lint)\",\n\t)\n\t.option(\"--package-manager <pm>\", \"npm | yarn | pnpm\")\n\t.option(\"--no-install\", \"skip dependency installation\")\n\t.option(\"-y, --yes\", \"use defaults and skip prompts\")\n\t.action(async (projectName: string | undefined, opts) => {\n\t\ttry {\n\t\t\tconst defaults: Partial<CreateOptions> = {};\n\t\t\tif (projectName) defaults.projectName = projectName;\n\n\t\t\tconst frameworkInput = opts.framework;\n\t\t\tif (frameworkInput) {\n\t\t\t\tconst parsed = parseFramework(frameworkInput);\n\t\t\t\tif (!parsed) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unknown framework: ${frameworkInput} (supported: vanilla | vue | react)`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tdefaults.framework = parsed;\n\t\t\t}\n\n\t\t\tconst variantInput = opts.variant;\n\t\t\tif (variantInput) {\n\t\t\t\tconst parsed = parseVariant(variantInput);\n\t\t\t\tif (!parsed) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unknown variant: ${variantInput} (supported: typescript | javascript)`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tdefaults.variant = parsed;\n\t\t\t}\n\n\t\t\tconst featuresInput = opts.features;\n\t\t\tif (featuresInput) {\n\t\t\t\tconst parsed = parseFeatures(featuresInput);\n\t\t\t\tif (parsed.length === 0) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unknown features: ${featuresInput} (supported: lint, biome, vitest; eslint/prettier alias lint)`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tdefaults.features = parsed;\n\t\t\t}\n\n\t\t\tif (opts.install === false) defaults.install = false;\n\n\t\t\tconst packageManagerInput = opts.packageManager;\n\t\t\tif (packageManagerInput) {\n\t\t\t\tconst parsed = parsePackageManager(packageManagerInput);\n\t\t\t\tif (!parsed) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unknown package manager: ${packageManagerInput} (supported: npm | yarn | pnpm)`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tdefaults.packageManager = parsed;\n\t\t\t} else {\n\t\t\t\tdefaults.packageManager = detectInvokedPackageManager();\n\t\t\t}\n\n\t\t\tconsole.log(cyan(`\\n ${CLI_NAME} \\n`));\n\t\t\tconst options = opts.yes\n\t\t\t\t? resolveOptionsFromDefaults(defaults)\n\t\t\t\t: await runPrompts(defaults);\n\t\t\tconst targetDir = await generateProject(options);\n\n\t\t\tlet installed = false;\n\t\t\tif (options.install) {\n\t\t\t\tconst { packageManager: pm } = options;\n\t\t\t\tconsole.log(cyan(`\\nInstalling dependencies (${pm})...\\n`));\n\t\t\t\tawait execa(pm, [\"install\"], {\n\t\t\t\t\tcwd: targetDir,\n\t\t\t\t\tstdio: \"inherit\",\n\t\t\t\t});\n\t\t\t\tinstalled = true;\n\n\t\t\t\tprintNextSteps(targetDir, options, installed, true);\n\t\t\t\tconsole.log(cyan(`\\nStarting dev server (${pmDevCommand(pm)})...\\n`));\n\t\t\t\tawait execa(pm, pmDevArgs(pm), { cwd: targetDir, stdio: \"inherit\" });\n\t\t\t} else {\n\t\t\t\tprintNextSteps(targetDir, options, installed);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tprintError(err);\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nfunction resolveOptionsFromDefaults(\n\tdefaults: Partial<CreateOptions>,\n): CreateOptions {\n\tconst projectName = defaults.projectName ?? \"xunlei-plugin-project\";\n\tconst packageName = toPackageName(defaults.packageName ?? projectName);\n\tassertValidPackageName(packageName);\n\n\tconst framework = (defaults.framework ?? \"vanilla\") as Framework;\n\tconst variant = (defaults.variant ?? \"typescript\") as Variant;\n\n\tconst features = normalizeFeatures(defaults.features, framework);\n\tconst packageManager =\n\t\tdefaults.packageManager ?? detectInvokedPackageManager();\n\tconst install = defaults.install ?? true;\n\n\treturn {\n\t\tprojectName,\n\t\tpackageName,\n\t\tframework,\n\t\tvariant,\n\t\tfeatures,\n\t\tpackageManager,\n\t\tinstall,\n\t};\n}\n\nprogram.parse();\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# <%= packageName %>
|
|
2
|
+
|
|
3
|
+
基于 React + JavaScript 的迅雷微应用,包含创建下载任务的页面示例。
|
|
4
|
+
|
|
5
|
+
## 环境要求
|
|
6
|
+
|
|
7
|
+
- Node.js 22.18+
|
|
8
|
+
|
|
9
|
+
## 项目结构
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
.
|
|
13
|
+
├── dist/ # 开发或构建生成的代码产物
|
|
14
|
+
├── release/ # 打包生成的 ZIP 安装包
|
|
15
|
+
├── src/ # 应用源码
|
|
16
|
+
│ ├── main.jsx # 页面入口
|
|
17
|
+
│ ├── App.jsx # 页面组件
|
|
18
|
+
│ └── index.css # 页面样式
|
|
19
|
+
<% if (features.includes('vitest')) { %>├── tests/ # 测试用例
|
|
20
|
+
<% } %>├── index.html # HTML 入口
|
|
21
|
+
├── manifest.json # 应用信息与权限
|
|
22
|
+
├── miniapp.config.js # 开发与构建配置
|
|
23
|
+
└── package.json # 依赖与命令
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 开发
|
|
27
|
+
|
|
28
|
+
在项目目录执行:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
<%= packageManager %> install
|
|
32
|
+
<%= packageManager %> run dev
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
在迅雷客户端中加载本地应用的目录(默认 `dist`),并保持 dev server 运行。
|
|
36
|
+
|
|
37
|
+
## 构建与打包
|
|
38
|
+
|
|
39
|
+
| 命令 | 用途 |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| `<%= packageManager %> run build` | 构建应用 |
|
|
42
|
+
| `<%= packageManager %> run package` | 自动构建并打包,无需先执行 build |
|
|
43
|
+
|
|
44
|
+
[开发文档](https://open.xunlei.com/doc/miniapp/introduction) · [示例代码](https://github.com/xunlei-open/miniapp-devkit/tree/main/examples)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# <%= packageName %>
|
|
2
|
+
|
|
3
|
+
基于 React + TypeScript 的迅雷微应用,包含创建下载任务的页面示例。
|
|
4
|
+
|
|
5
|
+
## 环境要求
|
|
6
|
+
|
|
7
|
+
- Node.js 22.18+
|
|
8
|
+
|
|
9
|
+
## 项目结构
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
.
|
|
13
|
+
├── dist/ # 开发或构建生成的代码产物
|
|
14
|
+
├── release/ # 打包生成的 ZIP 安装包
|
|
15
|
+
├── src/ # 应用源码
|
|
16
|
+
│ ├── main.tsx # 页面入口
|
|
17
|
+
│ ├── App.tsx # 页面组件
|
|
18
|
+
│ └── index.css # 页面样式
|
|
19
|
+
<% if (features.includes('vitest')) { %>├── tests/ # 测试用例
|
|
20
|
+
<% } %>├── index.html # HTML 入口
|
|
21
|
+
├── manifest.json # 应用信息与权限
|
|
22
|
+
├── miniapp.config.ts # 开发与构建配置
|
|
23
|
+
└── package.json # 依赖与命令
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 开发
|
|
27
|
+
|
|
28
|
+
在项目目录执行:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
<%= packageManager %> install
|
|
32
|
+
<%= packageManager %> run dev
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
在迅雷客户端中加载本地应用的目录(默认 `dist`),并保持 dev server 运行。
|
|
36
|
+
|
|
37
|
+
## 构建与打包
|
|
38
|
+
|
|
39
|
+
| 命令 | 用途 |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| `<%= packageManager %> run build` | 构建应用 |
|
|
42
|
+
| `<%= packageManager %> run package` | 自动构建并打包,无需先执行 build |
|
|
43
|
+
| `<%= packageManager %> run typecheck` | 检查类型 |
|
|
44
|
+
|
|
45
|
+
[开发文档](https://open.xunlei.com/doc/miniapp/introduction) · [示例代码](https://github.com/xunlei-open/miniapp-devkit/tree/main/examples)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# <%= packageName %>
|
|
2
|
+
|
|
3
|
+
基于 Vanilla + JavaScript 的迅雷微应用,包含创建下载任务的页面示例。
|
|
4
|
+
|
|
5
|
+
## 环境要求
|
|
6
|
+
|
|
7
|
+
- Node.js 22.18+
|
|
8
|
+
|
|
9
|
+
## 项目结构
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
.
|
|
13
|
+
├── dist/ # 开发或构建生成的代码产物
|
|
14
|
+
├── release/ # 打包生成的 ZIP 安装包
|
|
15
|
+
├── src/ # 应用源码
|
|
16
|
+
│ ├── main.js # 页面入口与示例逻辑
|
|
17
|
+
│ └── style.css # 页面样式
|
|
18
|
+
<% if (features.includes('vitest')) { %>├── tests/ # 测试用例
|
|
19
|
+
<% } %>├── index.html # HTML 入口
|
|
20
|
+
├── manifest.json # 应用信息与权限
|
|
21
|
+
├── miniapp.config.js # 开发与构建配置
|
|
22
|
+
└── package.json # 依赖与命令
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 开发
|
|
26
|
+
|
|
27
|
+
在项目目录执行:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
<%= packageManager %> install
|
|
31
|
+
<%= packageManager %> run dev
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
在迅雷客户端中加载本地应用的目录(默认 `dist`),并保持 dev server 运行。
|
|
35
|
+
|
|
36
|
+
## 构建与打包
|
|
37
|
+
|
|
38
|
+
| 命令 | 用途 |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| `<%= packageManager %> run build` | 构建应用 |
|
|
41
|
+
| `<%= packageManager %> run package` | 自动构建并打包,无需先执行 build |
|
|
42
|
+
|
|
43
|
+
[开发文档](https://open.xunlei.com/doc/miniapp/introduction) · [示例代码](https://github.com/xunlei-open/miniapp-devkit/tree/main/examples)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# <%= packageName %>
|
|
2
|
+
|
|
3
|
+
基于 Vanilla + TypeScript 的迅雷微应用,包含创建下载任务的页面示例。
|
|
4
|
+
|
|
5
|
+
## 环境要求
|
|
6
|
+
|
|
7
|
+
- Node.js 22.18+
|
|
8
|
+
|
|
9
|
+
## 项目结构
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
.
|
|
13
|
+
├── dist/ # 开发或构建生成的代码产物
|
|
14
|
+
├── release/ # 打包生成的 ZIP 安装包
|
|
15
|
+
├── src/ # 应用源码
|
|
16
|
+
│ ├── main.ts # 页面入口与示例逻辑
|
|
17
|
+
│ └── style.css # 页面样式
|
|
18
|
+
<% if (features.includes('vitest')) { %>├── tests/ # 测试用例
|
|
19
|
+
<% } %>├── index.html # HTML 入口
|
|
20
|
+
├── manifest.json # 应用信息与权限
|
|
21
|
+
├── miniapp.config.ts # 开发与构建配置
|
|
22
|
+
└── package.json # 依赖与命令
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## 开发
|
|
26
|
+
|
|
27
|
+
在项目目录执行:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
<%= packageManager %> install
|
|
31
|
+
<%= packageManager %> run dev
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
在迅雷客户端中加载本地应用的目录(默认 `dist`),并保持 dev server 运行。
|
|
35
|
+
|
|
36
|
+
## 构建与打包
|
|
37
|
+
|
|
38
|
+
| 命令 | 用途 |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| `<%= packageManager %> run build` | 构建应用 |
|
|
41
|
+
| `<%= packageManager %> run package` | 自动构建并打包,无需先执行 build |
|
|
42
|
+
| `<%= packageManager %> run typecheck` | 检查类型 |
|
|
43
|
+
|
|
44
|
+
[开发文档](https://open.xunlei.com/doc/miniapp/introduction) · [示例代码](https://github.com/xunlei-open/miniapp-devkit/tree/main/examples)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# <%= packageName %>
|
|
2
|
+
|
|
3
|
+
基于 Vue + JavaScript 的迅雷微应用,包含创建下载任务的页面示例。
|
|
4
|
+
|
|
5
|
+
## 环境要求
|
|
6
|
+
|
|
7
|
+
- Node.js 22.18+
|
|
8
|
+
|
|
9
|
+
## 项目结构
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
.
|
|
13
|
+
├── dist/ # 开发或构建生成的代码产物
|
|
14
|
+
├── release/ # 打包生成的 ZIP 安装包
|
|
15
|
+
├── src/ # 应用源码
|
|
16
|
+
│ ├── main.js # 页面入口
|
|
17
|
+
│ ├── App.vue # 页面组件
|
|
18
|
+
│ └── assets/ # 样式与静态资源
|
|
19
|
+
<% if (features.includes('vitest')) { %>├── tests/ # 测试用例
|
|
20
|
+
<% } %>├── index.html # HTML 入口
|
|
21
|
+
├── manifest.json # 应用信息与权限
|
|
22
|
+
├── miniapp.config.js # 开发与构建配置
|
|
23
|
+
└── package.json # 依赖与命令
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 开发
|
|
27
|
+
|
|
28
|
+
在项目目录执行:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
<%= packageManager %> install
|
|
32
|
+
<%= packageManager %> run dev
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
在迅雷客户端中加载本地应用的目录(默认 `dist`),并保持 dev server 运行。
|
|
36
|
+
|
|
37
|
+
## 构建与打包
|
|
38
|
+
|
|
39
|
+
| 命令 | 用途 |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| `<%= packageManager %> run build` | 构建应用 |
|
|
42
|
+
| `<%= packageManager %> run package` | 自动构建并打包,无需先执行 build |
|
|
43
|
+
|
|
44
|
+
[开发文档](https://open.xunlei.com/doc/miniapp/introduction) · [示例代码](https://github.com/xunlei-open/miniapp-devkit/tree/main/examples)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# <%= packageName %>
|
|
2
|
+
|
|
3
|
+
基于 Vue + TypeScript 的迅雷微应用,包含创建下载任务的页面示例。
|
|
4
|
+
|
|
5
|
+
## 环境要求
|
|
6
|
+
|
|
7
|
+
- Node.js 22.18+
|
|
8
|
+
|
|
9
|
+
## 项目结构
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
.
|
|
13
|
+
├── dist/ # 开发或构建生成的代码产物
|
|
14
|
+
├── release/ # 打包生成的 ZIP 安装包
|
|
15
|
+
├── src/ # 应用源码
|
|
16
|
+
│ ├── main.ts # 页面入口
|
|
17
|
+
│ ├── App.vue # 页面组件
|
|
18
|
+
│ └── assets/ # 样式与静态资源
|
|
19
|
+
<% if (features.includes('vitest')) { %>├── tests/ # 测试用例
|
|
20
|
+
<% } %>├── index.html # HTML 入口
|
|
21
|
+
├── manifest.json # 应用信息与权限
|
|
22
|
+
├── miniapp.config.ts # 开发与构建配置
|
|
23
|
+
└── package.json # 依赖与命令
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 开发
|
|
27
|
+
|
|
28
|
+
在项目目录执行:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
<%= packageManager %> install
|
|
32
|
+
<%= packageManager %> run dev
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
在迅雷客户端中加载本地应用的目录(默认 `dist`),并保持 dev server 运行。
|
|
36
|
+
|
|
37
|
+
## 构建与打包
|
|
38
|
+
|
|
39
|
+
| 命令 | 用途 |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| `<%= packageManager %> run build` | 构建应用 |
|
|
42
|
+
| `<%= packageManager %> run package` | 自动构建并打包,无需先执行 build |
|
|
43
|
+
| `<%= packageManager %> run typecheck` | 检查类型 |
|
|
44
|
+
|
|
45
|
+
[开发文档](https://open.xunlei.com/doc/miniapp/introduction) · [示例代码](https://github.com/xunlei-open/miniapp-devkit/tree/main/examples)
|