create-weapp-vite 2.8.8 → 2.8.10
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 +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/src-JDRZr-IM.js +588 -0
- package/package.json +4 -4
- package/dist/src-CURGHP0i.js +0 -640
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-weapp-vite",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.8.
|
|
4
|
+
"version": "2.8.10",
|
|
5
5
|
"description": "create-weapp-vite",
|
|
6
6
|
"author": "ice breaker <1324318532@qq.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -47,11 +47,11 @@
|
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@inquirer/prompts": "^8.7.0",
|
|
50
|
-
"pathe": "^2.0.3",
|
|
51
|
-
"pkg-types": "^2.3.1",
|
|
52
50
|
"@weapp-core/init": "6.0.16",
|
|
53
51
|
"@weapp-core/logger": "3.1.1",
|
|
54
|
-
"@weapp-core/shared": "3.2.0"
|
|
52
|
+
"@weapp-core/shared": "3.2.0",
|
|
53
|
+
"pathe": "^2.0.3",
|
|
54
|
+
"pkg-types": "^2.3.1"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"catalog:sync": "node --import tsx scripts/generate-template-catalog.ts",
|
package/dist/src-CURGHP0i.js
DELETED
|
@@ -1,640 +0,0 @@
|
|
|
1
|
-
import { fileURLToPath } from "node:url";
|
|
2
|
-
import logger from "@weapp-core/logger";
|
|
3
|
-
import { fs } from "@weapp-core/shared/fs";
|
|
4
|
-
import path from "pathe";
|
|
5
|
-
import https from "node:https";
|
|
6
|
-
import { spawn } from "node:child_process";
|
|
7
|
-
import process from "node:process";
|
|
8
|
-
//#region ../../packages-runtime/react/package.json
|
|
9
|
-
var version$4 = "0.2.2";
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region ../../packages-runtime/wevu/package.json
|
|
12
|
-
var version$3 = "7.0.0";
|
|
13
|
-
//#endregion
|
|
14
|
-
//#region ../dashboard/package.json
|
|
15
|
-
var version$2 = "7.0.0";
|
|
16
|
-
//#endregion
|
|
17
|
-
//#region ../eslint/package.json
|
|
18
|
-
var version$1 = "0.2.2";
|
|
19
|
-
//#endregion
|
|
20
|
-
//#region ../weapp-vite/package.json
|
|
21
|
-
var version = "7.0.0";
|
|
22
|
-
//#endregion
|
|
23
|
-
//#region src/enums.ts
|
|
24
|
-
let TemplateName = /* @__PURE__ */ function(TemplateName) {
|
|
25
|
-
TemplateName["default"] = "default";
|
|
26
|
-
TemplateName["multiPlatform"] = "multi-platform";
|
|
27
|
-
TemplateName["multiPlatformSfc"] = "multi-platform-sfc";
|
|
28
|
-
TemplateName["plugin"] = "plugin";
|
|
29
|
-
TemplateName["wevu"] = "wevu";
|
|
30
|
-
TemplateName["tailwindcss"] = "tailwindcss";
|
|
31
|
-
TemplateName["vant"] = "vant";
|
|
32
|
-
TemplateName["tdesign"] = "tdesign";
|
|
33
|
-
TemplateName["wevuTdesign"] = "wevu-tdesign";
|
|
34
|
-
TemplateName["react"] = "react";
|
|
35
|
-
TemplateName["lib"] = "lib";
|
|
36
|
-
return TemplateName;
|
|
37
|
-
}({});
|
|
38
|
-
//#endregion
|
|
39
|
-
//#region src/agents.ts
|
|
40
|
-
function supportsWevu(templateName) {
|
|
41
|
-
return [
|
|
42
|
-
"wevu",
|
|
43
|
-
"wevu-tdesign",
|
|
44
|
-
"multi-platform-sfc"
|
|
45
|
-
].includes(templateName);
|
|
46
|
-
}
|
|
47
|
-
function supportsReact(templateName) {
|
|
48
|
-
return templateName === "react";
|
|
49
|
-
}
|
|
50
|
-
function supportsNativePages(templateName) {
|
|
51
|
-
return !supportsWevu(templateName) && !supportsReact(templateName);
|
|
52
|
-
}
|
|
53
|
-
function supportsPlugin(templateName) {
|
|
54
|
-
return templateName === "plugin";
|
|
55
|
-
}
|
|
56
|
-
function supportsMultiPlatform(templateName) {
|
|
57
|
-
return ["multi-platform", "multi-platform-sfc"].includes(templateName);
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* @description 生成新项目的 AGENTS 指引
|
|
61
|
-
*/
|
|
62
|
-
function createAgentsGuidelines(templateName) {
|
|
63
|
-
const lines = [
|
|
64
|
-
"# AGENTS Guidelines",
|
|
65
|
-
"",
|
|
66
|
-
"## Local Docs First",
|
|
67
|
-
"",
|
|
68
|
-
"- After dependencies are installed, prefer reading local package docs under `node_modules/weapp-vite/dist/docs/` first.",
|
|
69
|
-
"- Start with `node_modules/weapp-vite/dist/docs/index.md`, then read `README.md` and `mcp.md` as needed.",
|
|
70
|
-
"- Prefer local package docs over stale model memory or old web pages when command behavior is unclear.",
|
|
71
|
-
"",
|
|
72
|
-
"## CLI Entry",
|
|
73
|
-
"",
|
|
74
|
-
"- This project supports both `weapp-vite` and `wv` CLI commands.",
|
|
75
|
-
"- Treat `weapp-vite dev` and `wv dev` as equivalent forms.",
|
|
76
|
-
"- Prefer project scripts such as `pnpm dev`, `pnpm build`, `pnpm open`, and `pnpm g` before ad-hoc shell commands.",
|
|
77
|
-
"- Use `weapp-vite prepare` or `wv prepare` when managed support files under `.weapp-vite/` need to be refreshed.",
|
|
78
|
-
"- Prefer `weapp-vite screenshot` or `wv screenshot` for mini-program screenshot acceptance.",
|
|
79
|
-
"- Prefer `weapp-vite compare` or `wv compare` for mini-program screenshot diff, baseline comparison, and visual regression checks.",
|
|
80
|
-
"- Prefer `weapp-vite ide logs --open` or `wv ide logs --open` for DevTools terminal log bridging.",
|
|
81
|
-
"- Do not default to generic browser screenshot tools when the target is the mini-program runtime in WeChat DevTools.",
|
|
82
|
-
"",
|
|
83
|
-
"## AI Intent Routing",
|
|
84
|
-
"",
|
|
85
|
-
"- When the request mentions screenshot, 截图, 页面快照, runtime screenshot, or capture the current mini-program page, default to `weapp-vite screenshot` / `wv screenshot`.",
|
|
86
|
-
"- When the request mentions screenshot compare, 截图对比, diff, baseline, visual regression, 像素对比, or acceptance comparison, default to `weapp-vite compare` / `wv compare`.",
|
|
87
|
-
"- Treat these commands as the primary screenshot contract for AI workflows in this project.",
|
|
88
|
-
"- Only fall back to generic browser screenshot tools when the target is explicitly the web runtime instead of WeChat DevTools.",
|
|
89
|
-
"",
|
|
90
|
-
"## Weapp-vite Workflow",
|
|
91
|
-
"",
|
|
92
|
-
"- Keep `vite.config.ts` as the source of truth for `weapp` config, output behavior, and IDE/MCP automation.",
|
|
93
|
-
"- Confirm `weapp.srcRoot`, routes, subpackages, and auto-import strategy before broad refactors.",
|
|
94
|
-
"- Prefer minimal scoped verification: targeted `pnpm build`, targeted tests, then broader checks only when required.",
|
|
95
|
-
"- If editing package source in a monorepo dependency, rebuild the touched package before validating downstream apps to avoid stale `dist`.",
|
|
96
|
-
"- Keep CLI ownership explicit: native `weapp-vite` commands first, IDE passthrough second.",
|
|
97
|
-
"- For Rust/native acceleration, treat JS ↔ Rust boundary crossings as a primary performance cost. Prefer batch analysis that sends source once, parses once, and returns structured results; only put fine-grained native APIs on hot paths when profiling proves a net win.",
|
|
98
|
-
"- Keep native AST fast paths optional and explicitly enabled. They must fall back to Babel/Oxc/Vue compiler behavior on load, parse, or runtime failure, and new native coverage needs correctness tests plus real profiling.",
|
|
99
|
-
"",
|
|
100
|
-
"## WeChat DevTools",
|
|
101
|
-
"",
|
|
102
|
-
"- Before using screenshot, preview, upload, automator, or `--open`, ensure WeChat DevTools is logged in and the service port is enabled.",
|
|
103
|
-
"- `wv open`, `wv dev -o`, and `wv build -o` use the official DevTools CLI first, then connect automator; if the IDE is open but automator is unavailable, run `wv ide doctor --json` before retrying.",
|
|
104
|
-
"- Use `--ide-open-strategy automator` only for explicit compatibility debugging; do not treat it as the default startup path.",
|
|
105
|
-
"- Prefer writing screenshots to workspace paths such as `.tmp/acceptance.png`.",
|
|
106
|
-
"",
|
|
107
|
-
"## AI Skills",
|
|
108
|
-
"",
|
|
109
|
-
"- Recommend installing shared skills with `npx skills add sonofmagic/skills`.",
|
|
110
|
-
"- In Codex/Claude environments, prefer these skills first when available:",
|
|
111
|
-
" - `$weapp-vite-best-practices` for config, build, subpackage, route, DevTools CLI orchestration, and screenshot/compare command work.",
|
|
112
|
-
" - `$weapp-vite-vue-sfc-best-practices` for `.vue` SFC macros, JSON blocks, and template compatibility.",
|
|
113
|
-
" - `$release-and-changeset-best-practices` for issue delivery, pnpm change intents, repoctl release decisions, and PR workflow.",
|
|
114
|
-
" - `$docs-and-website-sync` when documentation or AI guidance must be refreshed together with code changes.",
|
|
115
|
-
" - Use `$weapp-vite-best-practices` for stateful HMR, pluginRoot/dist-plugin, Web runtime compatibility, and native AST profiling; use `$wevu-best-practices` for `wevu/router` navigation semantics.",
|
|
116
|
-
" - Use `$weapp-devtools-e2e-best-practices` for serialized DevTools runtime suites, shared automator sessions, and known host compatibility skips."
|
|
117
|
-
];
|
|
118
|
-
if (supportsWevu(templateName)) lines.push(" - `$wevu-best-practices` for `wevu` runtime lifecycle, state, store, and event contracts.", "", "## Wevu Authoring", "", "- Import runtime APIs from `wevu` in business code.", "- Register lifecycle hooks synchronously in `setup()` and avoid hook registration after `await`.", "- Prefer `ref`, `reactive`, `computed`, and explicit event contracts over large opaque state writes.", "- Use `storeToRefs` when destructuring store state/getters.", "- Treat mini-program runtime constraints as primary; do not assume Vue web-only behavior.");
|
|
119
|
-
if (supportsReact(templateName)) lines.push(" - `$weapp-vite-react-best-practices` for React 19 JSX/TSX ownership, render modes, root lifecycle, React Compiler, and native/Wevu component bridges.", "", "## React Mini-program Authoring", "", "- Keep `weapp.react` as the project-level owner for all `.jsx` and `.tsx` modules; do not mix Wevu JSX in the same build.", "- Use React 19.2.x, `react-reconciler` 0.33.x, and `@weapp-vite/react` without `react-dom`.", "- Start with `renderMode: 'auto'`; use `dynamic` only for reconciler-tree diagnostics and `static` for strict static-shape validation.", "- Create and unmount `createReactMiniProgramRoot` in the native page/component lifecycle, and forward host events through the root.", "- Register native or Wevu custom components in `usingComponents` before declaring a top-level `createNativeComponent()` bridge in the current TSX file.", "- Treat the current React runtime as WeChat-only; Web, Alipay, and Douyin builds are not runtime compatibility evidence.");
|
|
120
|
-
if (supportsNativePages(templateName)) lines.push(" - `$native-to-weapp-vite-wevu-migration` when migrating native mini-program projects to `weapp-vite + native`, or further toward Vue SFC / wevu.", "", "## Native Mini-program Authoring", "", "- Keep native page/component structure consistent with the template unless there is a clear migration goal.", "- Prefer `weapp-vite generate` or `wv generate` for new app/page/component scaffolds.", "- If migrating this project, first decide whether the target is `weapp-vite + native` or a further Vue SFC / `wevu` migration, then keep each migration wave explicit.");
|
|
121
|
-
if (supportsMultiPlatform(templateName)) lines.push("", "## Multi-platform Workflow", "", "- This project builds one target at a time. Always pass an explicit platform or use `pnpm dev:<platform>` / `pnpm build:<platform>`.", "- Keep platform IDE configuration under `config/<platform>` and import `dist/<platform>` into the matching mini-program IDE.", "- Use `pnpm dev:web` for browser compatibility work, but keep mini-program DevTools or device acceptance as the release authority.", "- Treat WeChat, Web, official IDE compilation, and unsupported automator targets as separate verification layers; do not report a build-only check as runtime E2E.");
|
|
122
|
-
if (supportsPlugin(templateName)) lines.push("", "## Plugin Authoring", "", "- Keep `src/` as the host app source and `plugin/` as the plugin source root declared by `weapp.pluginRoot`.", "- Validate both `dist/` and `dist-plugin/` outputs after structural changes to host pages, plugin pages, or plugin public components.", "- If you change plugin AppID or switch away from local `dev` linkage, update both `project.config.json.appid` and `src/app.json` -> `plugins.*.provider` together.", "- Treat shared modules under `shared/` as regular source code that can be imported by both host and plugin entries.");
|
|
123
|
-
return `${lines.join("\n")}\n`;
|
|
124
|
-
}
|
|
125
|
-
//#endregion
|
|
126
|
-
//#region src/generated/catalog.ts
|
|
127
|
-
const TEMPLATE_CATALOG = {
|
|
128
|
-
"@babel/core": "^8.0.1",
|
|
129
|
-
"@babel/generator": "^8.0.0",
|
|
130
|
-
"@babel/parser": "^8.0.4",
|
|
131
|
-
"@babel/traverse": "^8.0.4",
|
|
132
|
-
"@babel/types": "^8.0.4",
|
|
133
|
-
"@douyin-microapp/typings": "^1.3.1",
|
|
134
|
-
"@egoist/tailwindcss-icons": "^1.9.2",
|
|
135
|
-
"@icebreakers/eslint-config": "^7.1.0",
|
|
136
|
-
"@icebreakers/stylelint-config": "^5.0.6",
|
|
137
|
-
"@iconify-json/mdi": "^1.2.3",
|
|
138
|
-
"@iconify/tailwind4": "^1.2.3",
|
|
139
|
-
"@mini-types/alipay": "^3.0.14",
|
|
140
|
-
"@tailwindcss/vite": "^4.3.3",
|
|
141
|
-
"@types/node": "^26.4.0",
|
|
142
|
-
"@types/react": "19.2.18",
|
|
143
|
-
"@types/react-reconciler": "0.33.0",
|
|
144
|
-
"@types/semver": "^7.8.0",
|
|
145
|
-
"@vant/weapp": "^1.11.7",
|
|
146
|
-
"@vitejs/plugin-vue": "^6.0.8",
|
|
147
|
-
"@vue/babel-plugin-jsx": "3.0.0",
|
|
148
|
-
"@vue/compiler-core": "^3.5.42",
|
|
149
|
-
"@vue/compiler-dom": "^3.5.42",
|
|
150
|
-
"@vue/language-core": "^3.3.11",
|
|
151
|
-
"@wot-ui/ui": "2.3.2",
|
|
152
|
-
"antd-mini": "^3.4.3",
|
|
153
|
-
"bundle-require": "^5.1.0",
|
|
154
|
-
"class-variance-authority": "^0.7.1",
|
|
155
|
-
"comment-json": "^5.0.0",
|
|
156
|
-
"estree-walker": "^3.0.3",
|
|
157
|
-
"gm-crypto": "^0.1.12",
|
|
158
|
-
"graphql-request": "^7.4.0",
|
|
159
|
-
"happy-dom": "^20.12.0",
|
|
160
|
-
"lru-cache": "^11.5.2",
|
|
161
|
-
"magic-string": "^1.2.3",
|
|
162
|
-
"miniprogram-api-typings": "^5.2.3",
|
|
163
|
-
"oxc-parser": "^0.147.0",
|
|
164
|
-
"oxc-walker": "^1.1.1",
|
|
165
|
-
"pkg-types": "^2.3.1",
|
|
166
|
-
"postcss-selector-parser": "^7.1.5",
|
|
167
|
-
"react-reconciler": "0.33.0",
|
|
168
|
-
"sass-embedded": "^1.103.1",
|
|
169
|
-
"socket.io-client": "^4.8.3",
|
|
170
|
-
"tailwind-merge": "^3.6.0",
|
|
171
|
-
"tailwind-variants": "^3.3.1",
|
|
172
|
-
"tdesign-miniprogram": "^1.16.0",
|
|
173
|
-
"ts-morph": "^28.0.0",
|
|
174
|
-
"uview-plus": "3.8.113",
|
|
175
|
-
"vite-plugin-inspect": "^12.0.2",
|
|
176
|
-
"vue-tsc": "^3.3.11",
|
|
177
|
-
"weapp-tailwindcss": "^5.4.2",
|
|
178
|
-
autoprefixer: "^10.5.4",
|
|
179
|
-
axios: "^1.20.0",
|
|
180
|
-
clsx: "^2.1.1",
|
|
181
|
-
dayjs: "^1.11.23",
|
|
182
|
-
echarts: "^6.1.0",
|
|
183
|
-
esbuild: "^0.28.2",
|
|
184
|
-
eslint: "^10.9.1",
|
|
185
|
-
fdir: "^6.5.0",
|
|
186
|
-
htmlparser2: "^12.0.0",
|
|
187
|
-
lodash: "^4.18.1",
|
|
188
|
-
merge: "^2.1.1",
|
|
189
|
-
obug: "^2.1.4",
|
|
190
|
-
pathe: "^2.0.3",
|
|
191
|
-
picocolors: "^1.1.1",
|
|
192
|
-
postcss: "^8.5.26",
|
|
193
|
-
react: "19.2.8",
|
|
194
|
-
rolldown: "1.2.6",
|
|
195
|
-
sass: "^1.103.1",
|
|
196
|
-
sharp: "^0.35.4",
|
|
197
|
-
stylelint: "^17.14.1",
|
|
198
|
-
tailwindcss: "^4.3.3",
|
|
199
|
-
tslib: "^2.8.1",
|
|
200
|
-
tsx: "^4.23.13",
|
|
201
|
-
typescript: "^6.0.3",
|
|
202
|
-
vite: "8.2.2",
|
|
203
|
-
vue: "^3.5.42",
|
|
204
|
-
zod: "^4.5.4"
|
|
205
|
-
};
|
|
206
|
-
const TEMPLATE_NAMED_CATALOG = {
|
|
207
|
-
"tdesign-miniprogram-fixed": { "tdesign-miniprogram": "1.16.0" },
|
|
208
|
-
"weapp-tailwindcss-fixed": { "weapp-tailwindcss": "5.4.2" },
|
|
209
|
-
latest: {
|
|
210
|
-
"miniprogram-api-typings": "^5.2.3",
|
|
211
|
-
typescript: "^6.0.3"
|
|
212
|
-
},
|
|
213
|
-
tailwind3: { tailwindcss: "^3.4.19" },
|
|
214
|
-
tailwind4: { tailwindcss: "^4.3.3" }
|
|
215
|
-
};
|
|
216
|
-
//#endregion
|
|
217
|
-
//#region src/npm.ts
|
|
218
|
-
/**
|
|
219
|
-
* @description 从 npm registry 获取包的最新版本号
|
|
220
|
-
*/
|
|
221
|
-
function getLatestVersionFromNpm(packageName) {
|
|
222
|
-
return new Promise((resolve, reject) => {
|
|
223
|
-
const url = `https://registry.npmjs.org/${packageName}/latest`;
|
|
224
|
-
https.get(url, (res) => {
|
|
225
|
-
if (!res || res.statusCode && res.statusCode >= 400) {
|
|
226
|
-
res?.resume();
|
|
227
|
-
reject(/* @__PURE__ */ new Error(`Request to ${url} failed with status ${res?.statusCode ?? "unknown"}`));
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
let data = "";
|
|
231
|
-
res.setEncoding("utf8");
|
|
232
|
-
res.on("data", (chunk) => data += chunk);
|
|
233
|
-
res.on("end", () => {
|
|
234
|
-
try {
|
|
235
|
-
const json = JSON.parse(data);
|
|
236
|
-
if (!json.version || typeof json.version !== "string") {
|
|
237
|
-
reject(/* @__PURE__ */ new Error(`Unexpected response when fetching ${packageName}: missing version`));
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
resolve(json.version);
|
|
241
|
-
} catch (err) {
|
|
242
|
-
reject(err);
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
res.on("error", reject);
|
|
246
|
-
}).on("error", reject);
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
async function latestVersion(packageName, prefix = "^", fetch = getLatestVersionFromNpm) {
|
|
250
|
-
try {
|
|
251
|
-
const resolved = await fetch(packageName);
|
|
252
|
-
if (!resolved) return null;
|
|
253
|
-
return `${prefix}${resolved}`;
|
|
254
|
-
} catch {
|
|
255
|
-
return null;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
//#endregion
|
|
259
|
-
//#region src/skills.ts
|
|
260
|
-
const RECOMMENDED_SKILLS_SOURCE = "sonofmagic/skills";
|
|
261
|
-
const RECOMMENDED_SKILLS_INSTALL_COMMAND = `npx skills add ${RECOMMENDED_SKILLS_SOURCE}`;
|
|
262
|
-
function resolveNpxCommand() {
|
|
263
|
-
return process.platform === "win32" ? "npx.cmd" : "npx";
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* @description 安装推荐的 AI skills。
|
|
267
|
-
*/
|
|
268
|
-
async function installRecommendedSkills(cwd) {
|
|
269
|
-
const command = resolveNpxCommand();
|
|
270
|
-
await new Promise((resolve, reject) => {
|
|
271
|
-
const child = spawn(command, [
|
|
272
|
-
"skills",
|
|
273
|
-
"add",
|
|
274
|
-
RECOMMENDED_SKILLS_SOURCE
|
|
275
|
-
], {
|
|
276
|
-
cwd,
|
|
277
|
-
stdio: "inherit"
|
|
278
|
-
});
|
|
279
|
-
child.on("error", reject);
|
|
280
|
-
child.on("exit", (code) => {
|
|
281
|
-
if (code === 0) {
|
|
282
|
-
resolve();
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
reject(/* @__PURE__ */ new Error(`skills install exited with code ${code ?? "unknown"}`));
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
//#endregion
|
|
290
|
-
//#region src/gitignore.ts
|
|
291
|
-
const DEFAULT_GITIGNORE = `# dependencies
|
|
292
|
-
node_modules
|
|
293
|
-
.pnp
|
|
294
|
-
.pnp.js
|
|
295
|
-
|
|
296
|
-
# testing
|
|
297
|
-
coverage
|
|
298
|
-
|
|
299
|
-
# next.js
|
|
300
|
-
.next/
|
|
301
|
-
out/
|
|
302
|
-
build
|
|
303
|
-
|
|
304
|
-
# misc
|
|
305
|
-
.DS_Store
|
|
306
|
-
*.pem
|
|
307
|
-
|
|
308
|
-
# debug
|
|
309
|
-
npm-debug.log*
|
|
310
|
-
yarn-debug.log*
|
|
311
|
-
yarn-error.log*
|
|
312
|
-
.pnpm-debug.log*
|
|
313
|
-
|
|
314
|
-
# local env files
|
|
315
|
-
.env.local
|
|
316
|
-
.env.development.local
|
|
317
|
-
.env.test.local
|
|
318
|
-
.env.production.local
|
|
319
|
-
|
|
320
|
-
# turbo
|
|
321
|
-
.turbo
|
|
322
|
-
|
|
323
|
-
dist
|
|
324
|
-
dist-plugin
|
|
325
|
-
dist-web
|
|
326
|
-
dist/web
|
|
327
|
-
vite.config.ts.timestamp-*.mjs
|
|
328
|
-
.weapp-vite/`;
|
|
329
|
-
const CRLF_RE$1 = /\r\n/g;
|
|
330
|
-
function normalizeLineEndings(value) {
|
|
331
|
-
return value.replace(CRLF_RE$1, "\n");
|
|
332
|
-
}
|
|
333
|
-
function trimTrailingBlankLines(lines) {
|
|
334
|
-
let end = lines.length;
|
|
335
|
-
while (end > 0 && lines[end - 1] === "") end -= 1;
|
|
336
|
-
return lines.slice(0, end);
|
|
337
|
-
}
|
|
338
|
-
function ensureTrailingNewline(value) {
|
|
339
|
-
return value.endsWith("\n") ? value : `${value}\n`;
|
|
340
|
-
}
|
|
341
|
-
/**
|
|
342
|
-
* @description 合并已有 gitignore 内容(保持去重)
|
|
343
|
-
*/
|
|
344
|
-
function mergeGitignore(existing) {
|
|
345
|
-
const normalizedExisting = normalizeLineEndings(existing ?? "");
|
|
346
|
-
const merged = [...normalizedExisting.length ? normalizedExisting.split("\n") : []];
|
|
347
|
-
while (merged.length > 0 && merged[merged.length - 1] === "") merged.pop();
|
|
348
|
-
const seen = new Set(merged);
|
|
349
|
-
let appendedNonBlank = false;
|
|
350
|
-
for (const line of DEFAULT_GITIGNORE.split("\n")) {
|
|
351
|
-
if (line.length === 0) {
|
|
352
|
-
if (merged.length === 0 || merged[merged.length - 1] === "") continue;
|
|
353
|
-
merged.push("");
|
|
354
|
-
continue;
|
|
355
|
-
}
|
|
356
|
-
if (seen.has(line)) continue;
|
|
357
|
-
if (!appendedNonBlank && merged.length > 0 && merged[merged.length - 1] !== "") merged.push("");
|
|
358
|
-
merged.push(line);
|
|
359
|
-
seen.add(line);
|
|
360
|
-
appendedNonBlank = true;
|
|
361
|
-
}
|
|
362
|
-
return ensureTrailingNewline(trimTrailingBlankLines(merged).join("\n"));
|
|
363
|
-
}
|
|
364
|
-
//#endregion
|
|
365
|
-
//#region src/utils/fs.ts
|
|
366
|
-
/**
|
|
367
|
-
* @description 文件读取错误
|
|
368
|
-
*/
|
|
369
|
-
var FsReadError = class extends Error {
|
|
370
|
-
filepath;
|
|
371
|
-
cause;
|
|
372
|
-
constructor(filepath, cause) {
|
|
373
|
-
super(`Failed to read ${filepath}`);
|
|
374
|
-
this.filepath = filepath;
|
|
375
|
-
this.cause = cause;
|
|
376
|
-
this.name = "FsReadError";
|
|
377
|
-
}
|
|
378
|
-
};
|
|
379
|
-
/**
|
|
380
|
-
* @description 文件写入错误
|
|
381
|
-
*/
|
|
382
|
-
var FsWriteError = class extends Error {
|
|
383
|
-
filepath;
|
|
384
|
-
cause;
|
|
385
|
-
constructor(filepath, cause) {
|
|
386
|
-
super(`Failed to write ${filepath}`);
|
|
387
|
-
this.filepath = filepath;
|
|
388
|
-
this.cause = cause;
|
|
389
|
-
this.name = "FsWriteError";
|
|
390
|
-
}
|
|
391
|
-
};
|
|
392
|
-
async function readFileIfExists(filepath) {
|
|
393
|
-
try {
|
|
394
|
-
return await fs.readFile(filepath, "utf8");
|
|
395
|
-
} catch (error) {
|
|
396
|
-
if (error?.code === "ENOENT") return null;
|
|
397
|
-
throw new FsReadError(filepath, error);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
async function writeJsonFile(filepath, data, spaces = 2) {
|
|
401
|
-
try {
|
|
402
|
-
await fs.outputJSON(filepath, data, { spaces });
|
|
403
|
-
} catch (error) {
|
|
404
|
-
throw new FsWriteError(filepath, error);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
async function writeFile(filepath, contents) {
|
|
408
|
-
try {
|
|
409
|
-
await fs.outputFile(filepath, contents, "utf8");
|
|
410
|
-
} catch (error) {
|
|
411
|
-
throw new FsWriteError(filepath, error);
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
//#endregion
|
|
415
|
-
//#region src/updateGitignore.ts
|
|
416
|
-
async function updateGitIgnore(options) {
|
|
417
|
-
const { root, write = true } = options;
|
|
418
|
-
const gitignorePath = path.resolve(root, ".gitignore");
|
|
419
|
-
const existing = await readFileIfExists(gitignorePath);
|
|
420
|
-
const merged = mergeGitignore(existing);
|
|
421
|
-
if (write && merged !== (existing ?? "")) {
|
|
422
|
-
await writeFile(gitignorePath, merged);
|
|
423
|
-
logger.log(`✨ 更新 ${path.relative(root, gitignorePath)} 成功!`);
|
|
424
|
-
}
|
|
425
|
-
return merged;
|
|
426
|
-
}
|
|
427
|
-
//#endregion
|
|
428
|
-
//#region src/createProject.ts
|
|
429
|
-
const DIGIT_RE = /\d/;
|
|
430
|
-
const CRLF_RE = /\r\n/g;
|
|
431
|
-
const WINDOWS_VERBATIM_PATH_RE = /^\\\\\?\\/;
|
|
432
|
-
const TOURIST_APP_ID = "touristappid";
|
|
433
|
-
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
|
434
|
-
const TEMPLATE_DIR_MAP = {
|
|
435
|
-
["default"]: "weapp-vite-template",
|
|
436
|
-
["multi-platform"]: "weapp-vite-multi-platform-template",
|
|
437
|
-
["multi-platform-sfc"]: "weapp-vite-multi-platform-sfc-template",
|
|
438
|
-
["plugin"]: "weapp-vite-plugin-template",
|
|
439
|
-
["lib"]: "weapp-vite-lib-template",
|
|
440
|
-
["wevu"]: "weapp-vite-wevu-template",
|
|
441
|
-
["react"]: "weapp-vite-react-template",
|
|
442
|
-
["wevu-tdesign"]: "weapp-vite-wevu-tailwindcss-tdesign-template",
|
|
443
|
-
["tailwindcss"]: "weapp-vite-tailwindcss-template",
|
|
444
|
-
["tdesign"]: "weapp-vite-tailwindcss-tdesign-template",
|
|
445
|
-
["vant"]: "weapp-vite-tailwindcss-vant-template"
|
|
446
|
-
};
|
|
447
|
-
const templateCatalogMap = { ...TEMPLATE_CATALOG };
|
|
448
|
-
const templateNamedCatalogMap = Object.fromEntries(Object.entries(TEMPLATE_NAMED_CATALOG).map(([name, deps]) => [name, { ...deps }]));
|
|
449
|
-
function resolveWorkspaceTemplateDir(templateName) {
|
|
450
|
-
const templateDirName = TEMPLATE_DIR_MAP[templateName];
|
|
451
|
-
return templateDirName ? path.resolve(moduleDir, "../../../templates", templateDirName) : path.resolve(moduleDir, "../../../templates", templateName);
|
|
452
|
-
}
|
|
453
|
-
function normalizeTemplatePath(value) {
|
|
454
|
-
return value.replace(WINDOWS_VERBATIM_PATH_RE, "").split("\\").join("/");
|
|
455
|
-
}
|
|
456
|
-
function normalizeTemplateRelativePath(relativePath) {
|
|
457
|
-
if (!relativePath || relativePath === ".") return "";
|
|
458
|
-
return normalizeTemplatePath(relativePath);
|
|
459
|
-
}
|
|
460
|
-
function isGeneratedOutputSegment(segment) {
|
|
461
|
-
return segment === "dist" || segment.startsWith("dist-");
|
|
462
|
-
}
|
|
463
|
-
function hasTemplatePathSegment(relativePath, predicate) {
|
|
464
|
-
return relativePath.split("/").some(predicate);
|
|
465
|
-
}
|
|
466
|
-
async function resolveTemplateDirs(templateName) {
|
|
467
|
-
const packagedTemplateDir = path.resolve(moduleDir, "../templates", templateName);
|
|
468
|
-
const workspaceTemplateDir = resolveWorkspaceTemplateDir(templateName);
|
|
469
|
-
return {
|
|
470
|
-
packagedTemplateDir,
|
|
471
|
-
workspaceTemplateDir,
|
|
472
|
-
preferredTemplateDir: await fs.pathExists(packagedTemplateDir) ? packagedTemplateDir : workspaceTemplateDir
|
|
473
|
-
};
|
|
474
|
-
}
|
|
475
|
-
function shouldSkipTemplateFile(filePath, templateRoot) {
|
|
476
|
-
const relativePath = normalizeTemplateRelativePath(path.relative(normalizeTemplatePath(templateRoot), normalizeTemplatePath(filePath)));
|
|
477
|
-
if (!relativePath) return false;
|
|
478
|
-
return hasTemplatePathSegment(relativePath, (segment) => segment === "node_modules") || hasTemplatePathSegment(relativePath, (segment) => segment === ".weapp-vite") || hasTemplatePathSegment(relativePath, isGeneratedOutputSegment) || hasTemplatePathSegment(relativePath, (segment) => segment === ".turbo") || relativePath === "vite.config.ts.timestamp" || relativePath.endsWith("/vite.config.ts.timestamp") || relativePath === "CHANGELOG.md" || relativePath.endsWith("/CHANGELOG.md") || relativePath === ".DS_Store" || relativePath.endsWith("/.DS_Store");
|
|
479
|
-
}
|
|
480
|
-
function normalizeLines(value) {
|
|
481
|
-
return value.replace(CRLF_RE, "\n").split("\n");
|
|
482
|
-
}
|
|
483
|
-
function mergeGitignoreSource(existing, template) {
|
|
484
|
-
const merged = normalizeLines(existing);
|
|
485
|
-
const seen = new Set(merged);
|
|
486
|
-
for (const line of normalizeLines(template)) {
|
|
487
|
-
if (seen.has(line)) continue;
|
|
488
|
-
merged.push(line);
|
|
489
|
-
seen.add(line);
|
|
490
|
-
}
|
|
491
|
-
while (merged.length > 0 && merged[merged.length - 1] === "") merged.pop();
|
|
492
|
-
return `${merged.join("\n")}\n`;
|
|
493
|
-
}
|
|
494
|
-
async function copyTemplateDir(sourceDir, fallbackDir, targetDir) {
|
|
495
|
-
const copyOptions = { filter(src) {
|
|
496
|
-
return !shouldSkipTemplateFile(src, sourceDir);
|
|
497
|
-
} };
|
|
498
|
-
try {
|
|
499
|
-
await fs.copy(sourceDir, targetDir, copyOptions);
|
|
500
|
-
} catch (error) {
|
|
501
|
-
const errorCode = error?.code;
|
|
502
|
-
if (sourceDir === fallbackDir || errorCode !== "ENOENT") throw error;
|
|
503
|
-
await fs.copy(fallbackDir, targetDir, copyOptions);
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
async function ensureDotGitignore(root) {
|
|
507
|
-
const gitignorePath = path.resolve(root, "gitignore");
|
|
508
|
-
const dotGitignorePath = path.resolve(root, ".gitignore");
|
|
509
|
-
if (!await fs.pathExists(gitignorePath)) return;
|
|
510
|
-
if (await fs.pathExists(dotGitignorePath)) {
|
|
511
|
-
await fs.remove(gitignorePath);
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
await fs.move(gitignorePath, dotGitignorePath);
|
|
515
|
-
}
|
|
516
|
-
async function rewriteProjectConfigAppId(targetDir) {
|
|
517
|
-
const projectConfigPaths = [path.resolve(targetDir, "project.config.json"), path.resolve(targetDir, "config/weapp/project.config.json")];
|
|
518
|
-
for (const projectConfigPath of projectConfigPaths) {
|
|
519
|
-
if (!await fs.pathExists(projectConfigPath)) continue;
|
|
520
|
-
const projectConfig = await fs.readJSON(projectConfigPath);
|
|
521
|
-
if (!projectConfig || typeof projectConfig !== "object" || projectConfig.compileType === "plugin" || projectConfig.appid === TOURIST_APP_ID) continue;
|
|
522
|
-
projectConfig.appid = TOURIST_APP_ID;
|
|
523
|
-
await writeJsonFile(projectConfigPath, projectConfig);
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
function createEmptyPackageJson() {
|
|
527
|
-
return {
|
|
528
|
-
name: "weapp-vite-app",
|
|
529
|
-
homepage: "https://vite.weapp.dev/",
|
|
530
|
-
type: "module",
|
|
531
|
-
scripts: {},
|
|
532
|
-
devDependencies: {}
|
|
533
|
-
};
|
|
534
|
-
}
|
|
535
|
-
async function upsertTailwindcssVersion(pkgJson) {
|
|
536
|
-
if (!pkgJson.devDependencies?.["weapp-tailwindcss"]) return;
|
|
537
|
-
const resolved = await latestVersion("weapp-tailwindcss");
|
|
538
|
-
if (resolved) pkgJson.devDependencies["weapp-tailwindcss"] = resolved;
|
|
539
|
-
}
|
|
540
|
-
function upsertExistingDependencyVersion(pkgJson, packageName, resolvedVersion) {
|
|
541
|
-
if (pkgJson.dependencies?.[packageName]) pkgJson.dependencies[packageName] = resolvedVersion;
|
|
542
|
-
if (pkgJson.devDependencies?.[packageName]) pkgJson.devDependencies[packageName] = resolvedVersion;
|
|
543
|
-
if (pkgJson.peerDependencies?.[packageName]) pkgJson.peerDependencies[packageName] = resolvedVersion;
|
|
544
|
-
}
|
|
545
|
-
function toCaretVersion(version) {
|
|
546
|
-
return version.startsWith("^") ? version : `^${version}`;
|
|
547
|
-
}
|
|
548
|
-
function resolveCatalogSpec(packageName, spec) {
|
|
549
|
-
if (!spec.startsWith("catalog:")) return spec;
|
|
550
|
-
const catalogName = spec.slice(8);
|
|
551
|
-
if (!catalogName) return templateCatalogMap[packageName] ?? spec;
|
|
552
|
-
const fromNamedCatalog = templateNamedCatalogMap[catalogName]?.[packageName];
|
|
553
|
-
if (fromNamedCatalog) {
|
|
554
|
-
if (fromNamedCatalog === "latest") return templateCatalogMap[packageName] ?? fromNamedCatalog;
|
|
555
|
-
return fromNamedCatalog;
|
|
556
|
-
}
|
|
557
|
-
return templateCatalogMap[packageName] ?? spec;
|
|
558
|
-
}
|
|
559
|
-
function normalizeTemplateDependencySpecs(pkgJson) {
|
|
560
|
-
for (const field of [
|
|
561
|
-
"dependencies",
|
|
562
|
-
"devDependencies",
|
|
563
|
-
"peerDependencies",
|
|
564
|
-
"optionalDependencies"
|
|
565
|
-
]) {
|
|
566
|
-
const deps = pkgJson[field];
|
|
567
|
-
if (!deps) continue;
|
|
568
|
-
for (const [name, rawSpec] of Object.entries(deps)) {
|
|
569
|
-
if (typeof rawSpec !== "string" || !rawSpec) continue;
|
|
570
|
-
const spec = rawSpec;
|
|
571
|
-
if (spec.startsWith("catalog:")) deps[name] = resolveCatalogSpec(name, spec);
|
|
572
|
-
else if (spec.startsWith("workspace:")) {
|
|
573
|
-
const workspaceSpec = spec.slice(10);
|
|
574
|
-
if (workspaceSpec && DIGIT_RE.test(workspaceSpec)) {
|
|
575
|
-
deps[name] = workspaceSpec;
|
|
576
|
-
continue;
|
|
577
|
-
}
|
|
578
|
-
const fromCatalog = templateCatalogMap[name];
|
|
579
|
-
if (fromCatalog) deps[name] = fromCatalog;
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
function ensureManagedTypeScriptDevDependencies(pkgJson) {
|
|
585
|
-
pkgJson.devDependencies ??= {};
|
|
586
|
-
if (pkgJson.dependencies?.["@types/node"] || pkgJson.devDependencies["@types/node"] || pkgJson.peerDependencies?.["@types/node"] || pkgJson.optionalDependencies?.["@types/node"]) return;
|
|
587
|
-
pkgJson.devDependencies["@types/node"] = templateCatalogMap["@types/node"];
|
|
588
|
-
}
|
|
589
|
-
/**
|
|
590
|
-
* @description 根据模板创建项目
|
|
591
|
-
*/
|
|
592
|
-
async function createProject(targetDir = "", templateName = "default", options = {}) {
|
|
593
|
-
const { preferredTemplateDir, workspaceTemplateDir } = await resolveTemplateDirs(templateName);
|
|
594
|
-
const dotGitignorePath = path.resolve(targetDir, ".gitignore");
|
|
595
|
-
const existingGitignore = await fs.pathExists(dotGitignorePath) ? await fs.readFile(dotGitignorePath, "utf8") : null;
|
|
596
|
-
if (!await fs.pathExists(preferredTemplateDir) && !await fs.pathExists(workspaceTemplateDir)) {
|
|
597
|
-
logger.warn(`没有找到 ${templateName} 模板!`);
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
await copyTemplateDir(preferredTemplateDir, workspaceTemplateDir, targetDir);
|
|
601
|
-
await rewriteProjectConfigAppId(targetDir);
|
|
602
|
-
const templatePackagePath = path.resolve(preferredTemplateDir, "package.json");
|
|
603
|
-
const packageJsonPath = path.resolve(targetDir, "package.json");
|
|
604
|
-
await ensureDotGitignore(targetDir);
|
|
605
|
-
if (existingGitignore !== null && await fs.pathExists(dotGitignorePath)) {
|
|
606
|
-
const currentGitignore = await fs.readFile(dotGitignorePath, "utf8");
|
|
607
|
-
await fs.writeFile(dotGitignorePath, mergeGitignoreSource(existingGitignore, currentGitignore));
|
|
608
|
-
}
|
|
609
|
-
const pkgJson = await fs.pathExists(templatePackagePath) ? await fs.readJSON(templatePackagePath) : createEmptyPackageJson();
|
|
610
|
-
normalizeTemplateDependencySpecs(pkgJson);
|
|
611
|
-
ensureManagedTypeScriptDevDependencies(pkgJson);
|
|
612
|
-
if (!pkgJson.devDependencies) pkgJson.devDependencies = {};
|
|
613
|
-
upsertExistingDependencyVersion(pkgJson, "weapp-vite", toCaretVersion(version));
|
|
614
|
-
upsertExistingDependencyVersion(pkgJson, "@weapp-vite/eslint", toCaretVersion(version$1));
|
|
615
|
-
upsertExistingDependencyVersion(pkgJson, "@weapp-vite/react", toCaretVersion(version$4));
|
|
616
|
-
upsertExistingDependencyVersion(pkgJson, "wevu", toCaretVersion(version$3));
|
|
617
|
-
upsertExistingDependencyVersion(pkgJson, "@weapp-vite/dashboard", toCaretVersion(version$2));
|
|
618
|
-
await upsertTailwindcssVersion(pkgJson);
|
|
619
|
-
await writeJsonFile(packageJsonPath, pkgJson);
|
|
620
|
-
await fs.writeFile(path.resolve(targetDir, "AGENTS.md"), createAgentsGuidelines(templateName));
|
|
621
|
-
await updateGitIgnore({
|
|
622
|
-
root: targetDir,
|
|
623
|
-
write: true
|
|
624
|
-
});
|
|
625
|
-
if (options.installSkills) {
|
|
626
|
-
logger.info(`🤖 即将安装 AI skills:${RECOMMENDED_SKILLS_INSTALL_COMMAND}`);
|
|
627
|
-
logger.info("如果你更想手动执行,也可以在项目创建后自行运行上面的命令。");
|
|
628
|
-
try {
|
|
629
|
-
await installRecommendedSkills(targetDir);
|
|
630
|
-
logger.log("✨ 已安装推荐的 AI skills!");
|
|
631
|
-
} catch (error) {
|
|
632
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
633
|
-
logger.warn(`安装 AI skills 失败:${message}`);
|
|
634
|
-
logger.warn(`你可以稍后手动执行:${RECOMMENDED_SKILLS_INSTALL_COMMAND}`);
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
logger.log("✨ 创建模板成功!");
|
|
638
|
-
}
|
|
639
|
-
//#endregion
|
|
640
|
-
export { RECOMMENDED_SKILLS_INSTALL_COMMAND as n, TemplateName as r, createProject as t };
|