@liujitcn/kratos-uni-app-cli 0.0.31 → 0.0.33

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.
Files changed (3) hide show
  1. package/README.md +3 -0
  2. package/package.json +1 -1
  3. package/src/index.mjs +148 -26
package/README.md CHANGED
@@ -23,6 +23,9 @@ CLI 直接由 `src/index.mjs` 生成文件,不依赖外部模板目录。
23
23
  - 使用 `--with` 安装额外的已发布模块。
24
24
  - 校验模块名和包名,目标目录已存在时拒绝覆盖。
25
25
  - core、system 和本地模块的 core 依赖版本统一跟随当前 CLI 包版本。
26
+ - 固定 uni-app、Vite 和 Vue 编译链版本,避免 `latest` 依赖漂移导致脚手架无法启动。
27
+ - 生成 H5 环境配置、页面事务恢复入口和独立 workspace 的 core/system 源码别名。
28
+ - 生成空的生产环境 API 配置,生产构建前必须填写实际后端地址。
26
29
  - 生成的宿主在登录、退出和静默退出后重新加载当前身份的导航配置。
27
30
  - 为 workspace 根目录、`apps/uni-app` 和每个本地模块生成同级 `README.md`;每个包含
28
31
  `package.json` 的生成目录都有对应的结构与职责说明。
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "type": "git",
8
8
  "url": "git@github.com:liujitcn/kratos-admin.git"
9
9
  },
10
- "version": "0.0.31",
10
+ "version": "0.0.33",
11
11
  "type": "module",
12
12
  "files": [
13
13
  "bin",
package/src/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
1
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
2
2
  import { basename, resolve } from 'node:path'
3
3
 
4
4
  const cliPackage = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
@@ -29,22 +29,41 @@ export function scaffoldKratosApp(targetPath, options = {}) {
29
29
  name: projectName,
30
30
  description: `Independent pnpm workspace for ${projectName}.`,
31
31
  private: true,
32
+ packageManager: 'pnpm@10.13.1',
32
33
  scripts: {
34
+ prepare: 'pnpm run prepare:modules',
35
+ 'prepare:modules': 'node -e "process.exit(0)"',
33
36
  'dev:h5': 'pnpm --filter @liujitcn/kratos-uni-app dev:h5',
34
37
  'dev:mp-weixin': 'pnpm --filter @liujitcn/kratos-uni-app dev:mp-weixin',
35
38
  'build:h5': 'pnpm --filter @liujitcn/kratos-uni-app build:h5',
36
39
  'build:mp-weixin': 'pnpm --filter @liujitcn/kratos-uni-app build:mp-weixin',
40
+ tsc: 'pnpm --recursive --if-present run tsc',
37
41
  },
38
42
  devDependencies: {
39
- '@dcloudio/types': 'latest',
40
- '@vue/compiler-sfc': '^3.4.21',
41
- '@vue/tsconfig': 'latest',
42
- 'miniprogram-api-typings': 'latest',
43
- typescript: 'latest',
44
- 'vue-tsc': 'latest',
43
+ '@dcloudio/types': '^3.4.8',
44
+ '@rushstack/eslint-patch': '^1.1.4',
45
+ '@uni-helper/uni-app-types': '1.0.0-alpha.6',
46
+ '@uni-helper/uni-ui-types': '1.0.0-alpha.6',
47
+ '@vue/compiler-sfc': '3.4.21',
48
+ '@vue/eslint-config-prettier': '10.2.0',
49
+ '@vue/eslint-config-typescript': '14.7.0',
50
+ '@vue/tsconfig': '^0.7.0',
51
+ eslint: '9.39.1',
52
+ 'miniprogram-api-typings': '^4.0.5',
53
+ prettier: '3.6.2',
54
+ typescript: '5.4.5',
55
+ 'vue-tsc': '^1.8.8',
56
+ },
57
+ pnpm: {
58
+ onlyBuiltDependencies: ['esbuild', 'core-js', 'core-js-pure', 'vue-demi'],
45
59
  },
46
60
  }),
47
61
  )
62
+ writeEnvironmentFiles(target)
63
+ copyFileSync(
64
+ new URL('../assets/favicon.ico', import.meta.url),
65
+ resolve(target, 'apps/uni-app/favicon.ico'),
66
+ )
48
67
  write(
49
68
  target,
50
69
  'README.md',
@@ -75,21 +94,29 @@ pnpm build:h5
75
94
  pnpm build:mp-weixin
76
95
  \`\`\`
77
96
 
97
+ H5 通过局域网 IP 访问时,先在仓库根目录运行 bash scripts/generate-dev-cert.sh 192.168.1.100 生成证书,再在 .env.development-h5.local 中设置 VITE_APP_HTTPS=true;后端使用 HTTPS 时同时设置 VITE_APP_API_URL=https://localhost:7001。
98
+
78
99
  模块装配入口是 \`apps/uni-app/src/module-manifest.ts\`。新增、删除或调整模块时同步维护该清单,并在模块自己的 README 中记录页面和接口职责。
100
+
101
+ 生产构建前请在 \`.env.production\` 中填写实际 API 和静态资源地址;该文件默认留空,不应使用本机地址。
79
102
  `,
80
103
  )
81
104
  const dependencies = {
82
105
  '@liujitcn/kratos-uni-app-core': `^${publicPackageVersion}`,
83
106
  '@liujitcn/kratos-uni-app-system': `^${publicPackageVersion}`,
84
- '@dcloudio/uni-app': 'latest',
85
- '@dcloudio/uni-components': 'latest',
86
- '@dcloudio/uni-h5': 'latest',
87
- '@dcloudio/uni-mp-weixin': 'latest',
88
- '@dcloudio/uni-ui': 'latest',
89
- '@dcloudio/vite-plugin-uni': 'latest',
107
+ '@dcloudio/uni-app': '3.0.0-5010520260709002',
108
+ '@dcloudio/uni-components': '3.0.0-5010520260709002',
109
+ '@dcloudio/uni-h5': '3.0.0-5010520260709002',
110
+ '@dcloudio/uni-mp-weixin': '3.0.0-5010520260709002',
111
+ '@dcloudio/uni-ui': '^1.4.28',
112
+ '@dcloudio/vite-plugin-uni': '3.0.0-5010520260709002',
113
+ 'asmcrypto.js': '^2.3.2',
114
+ 'go-captcha-uni': '1.0.6',
90
115
  pinia: '^2.0.27',
91
- sass: '^1.77.8',
92
- vite: '^5.2.8',
116
+ 'pinia-plugin-persistedstate': '^3.2.3',
117
+ 'qrcode-generator': '^2.0.4',
118
+ sass: '1.77.8',
119
+ vite: '5.2.8',
93
120
  vue: '^3.4.21',
94
121
  ...Object.fromEntries(modules.map((name) => [`@local/${name}`, 'workspace:*'])),
95
122
  ...Object.fromEntries(packages.map((name) => [name, 'latest'])),
@@ -104,11 +131,14 @@ pnpm build:mp-weixin
104
131
  private: true,
105
132
  type: 'module',
106
133
  scripts: {
107
- 'dev:h5': 'uni --mode development',
108
- 'dev:mp-weixin': 'uni -p mp-weixin',
109
- 'build:h5': 'uni build --mode production',
110
- 'build:mp-weixin': 'uni build -p mp-weixin --mode production',
111
- tsc: 'vue-tsc --noEmit',
134
+ 'recover:pages':
135
+ 'node -e "import(\'@liujitcn/kratos-uni-app-core/vite\').then(({ recoverStalePageTransaction }) => recoverStalePageTransaction())"',
136
+ 'dev:h5': 'pnpm run recover:pages && uni --mode development-h5',
137
+ 'dev:mp-weixin': 'pnpm run recover:pages && uni -p mp-weixin --mode development',
138
+ 'build:h5':
139
+ 'pnpm run recover:pages && UNI_OUTPUT_DIR=../../../../backend/data/uni-app uni build --mode production-h5',
140
+ 'build:mp-weixin': 'pnpm run recover:pages && uni build -p mp-weixin --mode production',
141
+ tsc: 'vue-tsc --noEmit -p tsconfig.json',
112
142
  },
113
143
  dependencies,
114
144
  }),
@@ -154,7 +184,7 @@ pnpm build:mp-weixin
154
184
  )
155
185
  const imports = [
156
186
  "import { coreModule } from '@liujitcn/kratos-uni-app-core/module'",
157
- "import systemModule from '@liujitcn/kratos-uni-app-system'",
187
+ "import { systemModule } from '@liujitcn/kratos-uni-app-system/module'",
158
188
  ...modules.map((name, index) => `import localModule${index} from '@local/${name}'`),
159
189
  ...packages.map((name, index) => `import packageModule${index} from '${name}'`),
160
190
  ]
@@ -247,18 +277,87 @@ export function createApp() {
247
277
  target,
248
278
  'apps/uni-app/index.html',
249
279
  `<!doctype html>
250
- <html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>${projectName}</title></head>
280
+ <html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><link rel="icon" href="./favicon.ico"><title>${projectName}</title></head>
251
281
  <body><div id="app"><!--app-html--></div><script type="module" src="/src/main.ts"></script></body></html>
252
282
  `,
253
283
  )
254
284
  write(
255
285
  target,
256
286
  'apps/uni-app/vite.config.ts',
257
- `import { createKratosUniPlugin, defineConfig, kratosApp } from '@liujitcn/kratos-uni-app-core/vite'
287
+ `import { dirname, resolve } from 'node:path'
288
+ import { existsSync, readFileSync } from 'node:fs'
289
+ import { fileURLToPath } from 'node:url'
290
+ import {
291
+ createKratosUniPlugin,
292
+ defineConfig,
293
+ kratosApp,
294
+ loadEnv,
295
+ type ConfigEnv,
296
+ type UserConfig,
297
+ } from '@liujitcn/kratos-uni-app-core/vite'
258
298
  import { moduleManifest } from './src/module-manifest'
259
- export default defineConfig({
260
- resolve: { preserveSymlinks: true },
261
- plugins: [kratosApp({ modules: moduleManifest }), createKratosUniPlugin()],
299
+ const workspaceRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../..')
300
+ const coreRoot = resolve(workspaceRoot, 'node_modules/@liujitcn/kratos-uni-app-core')
301
+ const systemRoot = resolve(workspaceRoot, 'node_modules/@liujitcn/kratos-uni-app-system')
302
+
303
+ function resolveHttpsOptions(env, root) {
304
+ if (env.VITE_APP_HTTPS !== 'true') return undefined
305
+ const keyPath = resolve(root, env.VITE_APP_HTTPS_KEY || '../../certs/dev-key.pem')
306
+ const certPath = resolve(root, env.VITE_APP_HTTPS_CERT || '../../certs/dev-cert.pem')
307
+ if (!existsSync(keyPath) || !existsSync(certPath)) {
308
+ throw new Error('VITE_APP_HTTPS 已开启,但未找到证书文件,请先在仓库根目录运行 scripts/generate-dev-cert.sh;期望路径:' + keyPath + ' 和 ' + certPath)
309
+ }
310
+ return { key: readFileSync(keyPath), cert: readFileSync(certPath) }
311
+ }
312
+
313
+ function resolveEnv(mode) {
314
+ const modeEnv = loadEnv(mode, workspaceRoot, '')
315
+ if (mode === 'development-h5') return { ...loadEnv('development', workspaceRoot, ''), ...modeEnv }
316
+ if (mode === 'production-h5') return { ...loadEnv('production', workspaceRoot, ''), ...modeEnv }
317
+ return modeEnv
318
+ }
319
+
320
+ export default defineConfig(({ mode }) => {
321
+ const env = resolveEnv(mode)
322
+ const devEnv = mode === 'development-h5' ? loadEnv('development', workspaceRoot, '') : env
323
+ const base = env.VITE_APP_BASE_PATH || (mode === 'production-h5' ? '/app/' : '/')
324
+ const httpsOptions = resolveHttpsOptions(env, workspaceRoot)
325
+ const apiProxyOptions = devEnv.VITE_APP_API_URL?.startsWith('https://') ? { secure: false } : {}
326
+ return {
327
+ base,
328
+ envDir: workspaceRoot,
329
+ resolve: {
330
+ preserveSymlinks: true,
331
+ alias: [
332
+ { find: '@', replacement: resolve(coreRoot, 'src') },
333
+ { find: '@system', replacement: resolve(systemRoot, 'src') },
334
+ ],
335
+ },
336
+ define: {
337
+ process: JSON.stringify({ env: {} }),
338
+ global: 'globalThis',
339
+ 'import.meta.env.VITE_APP_PORT': JSON.stringify(env.VITE_APP_PORT || ''),
340
+ 'import.meta.env.VITE_APP_BASE_PATH': JSON.stringify(base),
341
+ 'import.meta.env.VITE_APP_BASE_API': JSON.stringify(env.VITE_APP_BASE_API || ''),
342
+ 'import.meta.env.VITE_APP_API_URL': JSON.stringify(env.VITE_APP_API_URL || ''),
343
+ 'import.meta.env.VITE_APP_STATIC_API': JSON.stringify(env.VITE_APP_STATIC_API || ''),
344
+ 'import.meta.env.VITE_APP_STATIC_URL': JSON.stringify(env.VITE_APP_STATIC_URL || ''),
345
+ },
346
+ server: {
347
+ host: '0.0.0.0',
348
+ port: Number(env.VITE_APP_PORT || 5004),
349
+ https: httpsOptions,
350
+ proxy: {
351
+ [env.VITE_APP_BASE_API || '/api']: { changeOrigin: true, target: devEnv.VITE_APP_API_URL, ...apiProxyOptions },
352
+ '/events': { changeOrigin: true, target: devEnv.VITE_APP_API_URL, ...apiProxyOptions },
353
+ },
354
+ },
355
+ build: {
356
+ ...(process.env.UNI_OUTPUT_DIR ? { outDir: process.env.UNI_OUTPUT_DIR, emptyOutDir: true } : {}),
357
+ sourcemap: process.env.NODE_ENV === 'development',
358
+ },
359
+ plugins: [kratosApp({ modules: moduleManifest }), createKratosUniPlugin()],
360
+ }
262
361
  })
263
362
  `,
264
363
  )
@@ -342,6 +441,29 @@ export default module
342
441
  return target
343
442
  }
344
443
 
444
+ function writeEnvironmentFiles(target) {
445
+ write(
446
+ target,
447
+ '.env.development',
448
+ 'VITE_APP_BASE_API=/api\nVITE_APP_API_URL=http://localhost:7001\nVITE_APP_STATIC_API=\nVITE_APP_STATIC_URL=http://localhost:7001\n',
449
+ )
450
+ write(
451
+ target,
452
+ '.env.development-h5',
453
+ 'VITE_APP_PORT=5004\nVITE_APP_HTTPS=false\n# VITE_APP_HTTPS_KEY=../../certs/dev-key.pem\n# VITE_APP_HTTPS_CERT=../../certs/dev-cert.pem\n# 后端使用 HTTPS 时,在 .env.development-h5.local 覆盖 VITE_APP_API_URL=https://localhost:7001\nVITE_APP_BASE_PATH=/\nVITE_APP_BASE_API=/api\nVITE_APP_API_URL=http://localhost:7001\nVITE_APP_STATIC_API=\nVITE_APP_STATIC_URL=http://localhost:7001\n',
454
+ )
455
+ write(
456
+ target,
457
+ '.env.production',
458
+ 'VITE_APP_BASE_API=/api\nVITE_APP_API_URL=\nVITE_APP_STATIC_API=\nVITE_APP_STATIC_URL=\n',
459
+ )
460
+ write(
461
+ target,
462
+ '.env.production-h5',
463
+ 'VITE_APP_BASE_PATH=/app/\nVITE_APP_BASE_API=/api\nVITE_APP_API_URL=\nVITE_APP_STATIC_API=\nVITE_APP_STATIC_URL=\n',
464
+ )
465
+ }
466
+
345
467
  function validateModuleName(name) {
346
468
  if (!/^[a-z][a-z0-9-]*$/.test(name)) throw new Error(`模块名无效:${name}`)
347
469
  }