@h-ai/cli 0.1.0-alpha.19 → 0.1.0-alpha.21
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 +10 -7
- package/dist/{chunk-GSMXGUYF.js → chunk-5IGMJVV5.js} +56 -38
- package/dist/chunk-5IGMJVV5.js.map +1 -0
- package/dist/{chunk-BPO34NRL.js → chunk-CFCXOKGV.js} +27 -5
- package/dist/chunk-CFCXOKGV.js.map +1 -0
- package/dist/cli-config-templates-5J5VKWWD.js +5 -0
- package/dist/{cli-config-templates-JCS7T3NU.js.map → cli-config-templates-5J5VKWWD.js.map} +1 -1
- package/dist/cli-skill-templates-JMSV2SVW.js +5 -0
- package/dist/{cli-skill-templates-IMYZPQRG.js.map → cli-skill-templates-JMSV2SVW.js.map} +1 -1
- package/dist/index.js +627 -107
- package/dist/index.js.map +1 -1
- package/dist/{src-N4NPS7AG.js → src-QNEJJ3BV.js} +261 -103
- package/dist/src-QNEJJ3BV.js.map +1 -0
- package/package.json +3 -2
- package/templates/README.md +40 -29
- package/templates/apps/admin/messages/en-US.json +5 -0
- package/templates/apps/admin/messages/zh-CN.json +5 -0
- package/templates/apps/admin/src/routes/+layout.svelte.hbs +5 -5
- package/templates/apps/admin/src/routes/+page.svelte.hbs +32 -12
- package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +37 -20
- package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +33 -24
- package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +16 -13
- package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +16 -0
- package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +38 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/app-contract.ts.hbs +27 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +33 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/index.ts.hbs +3 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +12 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +18 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tsconfig.json.hbs +12 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +11 -0
- package/templates/apps/api/apps/{{projectName}}-contract/vitest.config.ts.hbs +9 -0
- package/templates/apps/api/apps/{{projectName}}-service/README.md.hbs +17 -0
- package/templates/apps/api/apps/{{projectName}}-service/config/_core.yml.hbs +19 -0
- package/templates/apps/api/apps/{{projectName}}-service/config/_serv.yml.hbs +26 -0
- package/templates/apps/api/apps/{{projectName}}-service/package.json.hbs +55 -0
- package/templates/apps/api/apps/{{projectName}}-service/src/app.ts.hbs +98 -0
- package/templates/apps/api/apps/{{projectName}}-service/src/index.ts.hbs +21 -0
- package/templates/apps/api/apps/{{projectName}}-service/src/lib/server/init.ts.hbs +184 -0
- package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/app-procedures.ts.hbs +49 -0
- package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/index.ts.hbs +18 -0
- package/templates/apps/api/apps/{{projectName}}-service/tests/service.test.ts.hbs +168 -0
- package/templates/apps/api/apps/{{projectName}}-service/tsconfig.json.hbs +16 -0
- package/templates/apps/api/apps/{{projectName}}-service/tsup.config.ts.hbs +11 -0
- package/templates/apps/api/apps/{{projectName}}-service/vitest.config.ts.hbs +9 -0
- package/templates/apps/api/e2e/api-service.spec.ts.hbs +18 -0
- package/templates/apps/api/eslint.config.js +32 -0
- package/templates/apps/api/package.json.hbs +29 -0
- package/templates/apps/api/playwright.config.ts.hbs +58 -0
- package/templates/apps/api/pnpm-workspace.yaml.hbs +14 -0
- package/templates/apps/api/tsconfig.base.json +15 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/.env.example.hbs +10 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +24 -7
- package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +16 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +51 -29
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +186 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.css.hbs +2 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +0 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/main.ts.hbs +14 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +1 -5
- package/templates/apps/fullstack/apps/{{projectName}}-app/tsconfig.json.hbs +10 -4
- package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +4 -3
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/.env.example.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +20 -6
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/index.html.hbs +15 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +33 -30
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +152 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.d.ts.hbs +1 -2
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/main.ts.hbs +13 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/Cargo.toml.hbs +22 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/build.rs.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/capabilities/default.json.hbs +12 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128@2x.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/32x32.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.icns +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.ico +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/lib.rs.hbs +16 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/main.rs.hbs +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +41 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +2 -8
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/tsconfig.json.hbs +9 -4
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +44 -21
- package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +15 -6
- package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +15 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +25 -27
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/App.svelte.hbs +153 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.d.ts.hbs +0 -1
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +14 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +1 -5
- package/templates/apps/fullstack/apps/{{projectName}}-web/tsconfig.json.hbs +10 -4
- package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +3 -2
- package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +2 -1
- package/templates/apps/fullstack/eslint.config.js +0 -1
- package/templates/apps/fullstack/package.json.hbs +18 -17
- package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +3 -3
- package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +5 -2
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +14 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +13 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +2 -2
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/{server-app.ts.hbs → app-server.ts.hbs} +23 -3
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +4 -1
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/{server-app.test.ts.hbs → app-server.test.ts.hbs} +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +9 -8
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/index.ts.hbs +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +5 -1
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/ThemeSwitcher.svelte.hbs +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tsconfig.json.hbs +1 -1
- package/templates/apps/fullstack/playwright.config.ts.hbs +41 -4
- package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +15 -0
- package/templates/apps/h5/messages/en-US.json +3 -0
- package/templates/apps/h5/messages/zh-CN.json +3 -0
- package/templates/apps/h5/src/routes/+layout.svelte.hbs +30 -29
- package/templates/apps/h5/src/routes/+page.svelte.hbs +17 -6
- package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +17 -6
- package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +17 -6
- package/templates/apps/mobile-app/.env.hbs +3 -0
- package/templates/apps/{android-app → mobile-app}/capacitor.config.ts.hbs +2 -2
- package/templates/apps/mobile-app/index.html.hbs +13 -0
- package/templates/apps/mobile-app/messages/en-US.json +36 -0
- package/templates/apps/mobile-app/messages/zh-CN.json +36 -0
- package/templates/apps/mobile-app/src/App.svelte.hbs +162 -0
- package/templates/apps/mobile-app/src/lib/api.ts.hbs +54 -0
- package/templates/apps/{android-app → mobile-app}/src/lib/capacitor.ts +6 -7
- package/templates/apps/mobile-app/src/main.ts.hbs +11 -0
- package/templates/apps/website/src/routes/+layout.svelte.hbs +35 -26
- package/templates/apps/website/src/routes/+page.svelte.hbs +28 -10
- package/templates/apps/website/src/routes/about/+page.svelte.hbs +11 -6
- package/templates/apps/website/src/routes/contact/+page.svelte.hbs +37 -34
- package/templates/apps/website/src/routes/services/+page.svelte.hbs +27 -40
- package/templates/base/.gitignore.hbs +16 -0
- package/templates/base/{eslint.config.js → eslint.config.js.hbs} +4 -1
- package/templates/base/package.json.hbs +55 -31
- package/templates/base/playwright.config.ts +30 -3
- package/templates/base/pnpm-workspace.yaml.hbs +14 -0
- package/templates/base/src/app.d.ts.hbs +3 -0
- package/templates/base/src/app.html.hbs +7 -0
- package/templates/base/src/hooks.server.ts.hbs +17 -7
- package/templates/base/src/lib/server/init.ts.hbs +20 -12
- package/templates/base/static/favicon.png +0 -0
- package/templates/base/svelte.config.js.hbs +43 -3
- package/templates/base/tests/scaffold.test.ts.hbs +16 -1
- package/templates/base/tsconfig.json.hbs +50 -0
- package/templates/base/vite.config.ts.hbs +13 -3
- package/templates/features/iam/routes-admin/(auth)/+layout.svelte.hbs +5 -5
- package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +34 -32
- package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +46 -48
- package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +35 -31
- package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +41 -38
- package/templates/skills/AGENTS.md +60 -17
- package/templates/skills/CLAUDE.md +18 -6
- package/templates/skills/bridges/admin/AGENTS.md +66 -0
- package/templates/skills/bridges/admin/CLAUDE.md +19 -0
- package/templates/skills/bridges/admin/copilot-instructions.md +46 -0
- package/templates/skills/bridges/api/AGENTS.md +65 -0
- package/templates/skills/bridges/api/CLAUDE.md +19 -0
- package/templates/skills/bridges/api/copilot-instructions.md +46 -0
- package/templates/skills/bridges/fullstack/AGENTS.md +84 -0
- package/templates/skills/bridges/fullstack/CLAUDE.md +19 -0
- package/templates/skills/bridges/fullstack/copilot-instructions.md +54 -0
- package/templates/skills/bridges/h5/AGENTS.md +65 -0
- package/templates/skills/bridges/h5/CLAUDE.md +19 -0
- package/templates/skills/bridges/h5/copilot-instructions.md +44 -0
- package/templates/skills/bridges/mobile-app/AGENTS.md +77 -0
- package/templates/skills/bridges/mobile-app/CLAUDE.md +19 -0
- package/templates/skills/bridges/mobile-app/copilot-instructions.md +45 -0
- package/templates/skills/bridges/website/AGENTS.md +65 -0
- package/templates/skills/bridges/website/CLAUDE.md +19 -0
- package/templates/skills/bridges/website/copilot-instructions.md +44 -0
- package/templates/skills/copilot-instructions.md +29 -50
- package/templates/skills/hai-ai/SKILL.md +115 -648
- package/templates/skills/hai-ai/reference.md +197 -0
- package/templates/skills/hai-api-client/SKILL.md +3 -1
- package/templates/skills/hai-app-create/SKILL.md +2 -1
- package/templates/skills/hai-app-review/SKILL.md +2 -2
- package/templates/skills/hai-app-tests/SKILL.md +28 -3
- package/templates/skills/hai-capacitor/SKILL.md +14 -22
- package/templates/skills/hai-deploy/SKILL.md +12 -9
- package/templates/skills/hai-kit/SKILL.md +5 -3
- package/templates/skills/hai-serv/SKILL.md +2 -0
- package/templates/skills/hai-ui/SKILL.md +25 -11
- package/templates/skills/opencode.json +1 -6
- package/dist/chunk-BPO34NRL.js.map +0 -1
- package/dist/chunk-GSMXGUYF.js.map +0 -1
- package/dist/cli-config-templates-JCS7T3NU.js +0 -5
- package/dist/cli-skill-templates-IMYZPQRG.js +0 -5
- package/dist/src-N4NPS7AG.js.map +0 -1
- package/templates/apps/android-app/.env.hbs +0 -3
- package/templates/apps/android-app/messages/en-US.json +0 -24
- package/templates/apps/android-app/messages/zh-CN.json +0 -24
- package/templates/apps/android-app/src/lib/api.ts.hbs +0 -31
- package/templates/apps/android-app/src/routes/+layout.svelte.hbs +0 -42
- package/templates/apps/android-app/src/routes/+layout.ts +0 -7
- package/templates/apps/android-app/src/routes/+page.svelte.hbs +0 -27
- package/templates/apps/api/src/routes/+layout.svelte +0 -14
- package/templates/apps/api/src/routes/+page.svelte +0 -11
- package/templates/apps/api/src/routes/api/v1/health/+server.ts +0 -14
- package/templates/apps/api/src/routes/api/v1/items/+server.ts +0 -37
- package/templates/apps/api/src/routes/api/v1/items/[id]/+server.ts +0 -30
- package/templates/apps/api/tests/health.test.ts.hbs +0 -26
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.html.hbs +0 -14
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+layout.svelte.hbs +0 -18
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+page.svelte.hbs +0 -162
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.html.hbs +0 -14
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+layout.svelte.hbs +0 -18
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+page.svelte.hbs +0 -162
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.html.hbs +0 -14
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+layout.svelte.hbs +0 -18
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+page.svelte.hbs +0 -162
- package/templates/apps/fullstack/pnpm-workspace.yaml +0 -7
- package/templates/base/tsconfig.json +0 -20
- /package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/{theme.svelte.ts.hbs → theme-store.svelte.ts.hbs} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { generateConfigFile } from './chunk-
|
|
3
|
-
import './chunk-
|
|
2
|
+
import { generateConfigFile } from './chunk-CFCXOKGV.js';
|
|
3
|
+
import './chunk-5IGMJVV5.js';
|
|
4
4
|
import './chunk-2H7UOFLK.js';
|
|
5
|
-
import { readFileSync, existsSync } from 'fs';
|
|
6
|
-
import path2, { resolve } from 'path';
|
|
7
5
|
import process3 from 'process';
|
|
8
|
-
import { fileURLToPath } from 'url';
|
|
9
6
|
import { core } from '@h-ai/core';
|
|
10
7
|
import { cac } from 'cac';
|
|
11
8
|
import chalk from 'chalk';
|
|
12
|
-
import {
|
|
9
|
+
import path2, { resolve } from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
13
11
|
import fse from 'fs-extra';
|
|
12
|
+
import Handlebars from 'handlebars';
|
|
14
13
|
import ora from 'ora';
|
|
15
14
|
import prompts from 'prompts';
|
|
16
|
-
import
|
|
15
|
+
import { Buffer } from 'buffer';
|
|
17
16
|
import { execSync, execFileSync } from 'child_process';
|
|
17
|
+
import { existsSync, readFileSync } from 'fs';
|
|
18
18
|
import { parse } from 'yaml';
|
|
19
19
|
|
|
20
20
|
var CAMEL_CASE_SEPARATOR_REGEX = /[-_\s]+(.)?/g;
|
|
@@ -53,6 +53,22 @@ async function fileExists(filePath) {
|
|
|
53
53
|
return false;
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
+
function getCliVersion() {
|
|
57
|
+
let dir = path2.dirname(fileURLToPath(import.meta.url));
|
|
58
|
+
for (let i = 0; i < 6; i++) {
|
|
59
|
+
try {
|
|
60
|
+
const pkg = fse.readJsonSync(path2.join(dir, "package.json"));
|
|
61
|
+
if (pkg.name === "@h-ai/cli")
|
|
62
|
+
return pkg.version ?? "0.0.0";
|
|
63
|
+
} catch {
|
|
64
|
+
}
|
|
65
|
+
const parent = path2.dirname(dir);
|
|
66
|
+
if (parent === dir)
|
|
67
|
+
break;
|
|
68
|
+
dir = parent;
|
|
69
|
+
}
|
|
70
|
+
return "0.0.0";
|
|
71
|
+
}
|
|
56
72
|
async function detectPackageManager(cwd) {
|
|
57
73
|
if (await fileExists(path2.join(cwd, "pnpm-lock.yaml"))) {
|
|
58
74
|
return "pnpm";
|
|
@@ -83,20 +99,30 @@ registerHelpers();
|
|
|
83
99
|
Handlebars.registerHelper("if_eq", function(a, b, options) {
|
|
84
100
|
return a === b ? options.fn(this) : options.inverse(this);
|
|
85
101
|
});
|
|
86
|
-
var HAI_VERSION = `^${fse.readJsonSync(fileURLToPath(new URL("../../package.json", import.meta.url))).version}`;
|
|
87
102
|
var TEMPLATE_SKIP_IF_EMPTY_MARKER = "@skipIfEmpty";
|
|
88
103
|
var NORMALIZED_RENDER_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".js", ".svelte", ".json", ".css"]);
|
|
104
|
+
var CAPACITOR_SKIPPED_SERVER_FILES = /* @__PURE__ */ new Set([
|
|
105
|
+
"src/hooks.server.ts",
|
|
106
|
+
"src/lib/server/init.ts"
|
|
107
|
+
]);
|
|
89
108
|
var VERSIONS = {
|
|
90
109
|
antfuEslintConfig: "^9.0.0",
|
|
91
|
-
|
|
92
|
-
apiClient: HAI_VERSION,
|
|
93
|
-
core: HAI_VERSION,
|
|
94
|
-
serv: HAI_VERSION,
|
|
95
|
-
ui: HAI_VERSION,
|
|
110
|
+
capacitorSecureStorage: "^8.0.0",
|
|
96
111
|
// UI / Icon
|
|
97
112
|
bitsUi: "^2.18.1",
|
|
98
113
|
iconifyJsonTabler: "^1.2.35",
|
|
99
114
|
iconifyTailwind: "^1.2.3",
|
|
115
|
+
// Capacitor
|
|
116
|
+
capacitorAndroid: "^8.3.4",
|
|
117
|
+
capacitorApp: "^8.0.1",
|
|
118
|
+
capacitorCamera: "^8.0.1",
|
|
119
|
+
capacitorCli: "^8.3.4",
|
|
120
|
+
capacitorCore: "^8.3.4",
|
|
121
|
+
capacitorDevice: "^8.0.1",
|
|
122
|
+
capacitorIos: "^8.3.4",
|
|
123
|
+
capacitorPreferences: "^8.0.1",
|
|
124
|
+
capacitorPushNotifications: "^8.0.1",
|
|
125
|
+
capacitorStatusBar: "^8.0.1",
|
|
100
126
|
// Tailwind / DaisyUI
|
|
101
127
|
daisyui: "^5.5.20",
|
|
102
128
|
tailwindcss: "^4.3.0",
|
|
@@ -104,13 +130,10 @@ var VERSIONS = {
|
|
|
104
130
|
// i18n
|
|
105
131
|
inlangParaglide: "^2.18.1",
|
|
106
132
|
inlangMessageFormat: "^4.4.0",
|
|
107
|
-
// Svelte /
|
|
133
|
+
// Svelte / Vite
|
|
108
134
|
svelte: "^5.55.9",
|
|
109
|
-
svelteKit: "^2.61.1",
|
|
110
135
|
svelteCheck: "^4.4.8",
|
|
111
136
|
sveltePlugin: "^7.1.2",
|
|
112
|
-
adapterAuto: "^7.0.1",
|
|
113
|
-
adapterStatic: "^3.0.10",
|
|
114
137
|
// Build / Test
|
|
115
138
|
vite: "^8.0.14",
|
|
116
139
|
vitest: "^4.1.7",
|
|
@@ -127,12 +150,14 @@ var VERSIONS = {
|
|
|
127
150
|
// E2E
|
|
128
151
|
playwright: "^1.60.0",
|
|
129
152
|
// Validation
|
|
130
|
-
zod: "^4.4.3"
|
|
153
|
+
zod: "^4.4.3",
|
|
154
|
+
// Tauri
|
|
155
|
+
tauriCli: "^2.10.1"
|
|
131
156
|
};
|
|
132
157
|
var FRONTEND_PORTS_DEFAULT = {
|
|
133
158
|
web: 4173,
|
|
134
|
-
app:
|
|
135
|
-
desktop:
|
|
159
|
+
app: 5175,
|
|
160
|
+
desktop: 5176
|
|
136
161
|
};
|
|
137
162
|
var FRONTEND_LABELS = {
|
|
138
163
|
web: "Web",
|
|
@@ -144,6 +169,277 @@ var IMPLEMENTED_FRONTENDS = ["web", "app", "desktop"];
|
|
|
144
169
|
var DEFAULT_FULLSTACK_FRONTENDS = ["web", "app", "desktop"];
|
|
145
170
|
var DEFAULT_THEMES = ["light", "dark"];
|
|
146
171
|
var DEFAULT_THEME_NAME = "light";
|
|
172
|
+
var HAI_PACKAGE_VERSION = `^${getCliVersion()}`;
|
|
173
|
+
var HAI_PACKAGE_SPECIFIER_CATALOG = "catalog:";
|
|
174
|
+
var HAI_CATALOG_PACKAGE_NAMES = [
|
|
175
|
+
"@h-ai/ai",
|
|
176
|
+
"@h-ai/api-client",
|
|
177
|
+
"@h-ai/api-contract",
|
|
178
|
+
"@h-ai/audit",
|
|
179
|
+
"@h-ai/cache",
|
|
180
|
+
"@h-ai/capacitor",
|
|
181
|
+
"@h-ai/core",
|
|
182
|
+
"@h-ai/crypto",
|
|
183
|
+
"@h-ai/datapipe",
|
|
184
|
+
"@h-ai/deploy",
|
|
185
|
+
"@h-ai/iam",
|
|
186
|
+
"@h-ai/kit",
|
|
187
|
+
"@h-ai/payment",
|
|
188
|
+
"@h-ai/reach",
|
|
189
|
+
"@h-ai/reldb",
|
|
190
|
+
"@h-ai/scheduler",
|
|
191
|
+
"@h-ai/serv",
|
|
192
|
+
"@h-ai/storage",
|
|
193
|
+
"@h-ai/ui",
|
|
194
|
+
"@h-ai/vecdb"
|
|
195
|
+
];
|
|
196
|
+
var HAI_CATALOG_PACKAGES = Object.fromEntries(
|
|
197
|
+
HAI_CATALOG_PACKAGE_NAMES.map((packageName) => [packageName, HAI_PACKAGE_VERSION])
|
|
198
|
+
);
|
|
199
|
+
var FULLSTACK_EXTERNAL_CATALOG_PACKAGES = {
|
|
200
|
+
"@antfu/eslint-config": VERSIONS.antfuEslintConfig,
|
|
201
|
+
"@aparajita/capacitor-secure-storage": VERSIONS.capacitorSecureStorage,
|
|
202
|
+
"@capacitor/android": VERSIONS.capacitorAndroid,
|
|
203
|
+
"@capacitor/app": VERSIONS.capacitorApp,
|
|
204
|
+
"@capacitor/camera": VERSIONS.capacitorCamera,
|
|
205
|
+
"@capacitor/cli": VERSIONS.capacitorCli,
|
|
206
|
+
"@capacitor/core": VERSIONS.capacitorCore,
|
|
207
|
+
"@capacitor/device": VERSIONS.capacitorDevice,
|
|
208
|
+
"@capacitor/ios": VERSIONS.capacitorIos,
|
|
209
|
+
"@capacitor/preferences": VERSIONS.capacitorPreferences,
|
|
210
|
+
"@capacitor/push-notifications": VERSIONS.capacitorPushNotifications,
|
|
211
|
+
"@capacitor/status-bar": VERSIONS.capacitorStatusBar,
|
|
212
|
+
"@iconify-json/tabler": VERSIONS.iconifyJsonTabler,
|
|
213
|
+
"@iconify/tailwind4": VERSIONS.iconifyTailwind,
|
|
214
|
+
"@inlang/paraglide-js": VERSIONS.inlangParaglide,
|
|
215
|
+
"@inlang/plugin-message-format": VERSIONS.inlangMessageFormat,
|
|
216
|
+
"@playwright/test": VERSIONS.playwright,
|
|
217
|
+
"@sveltejs/vite-plugin-svelte": VERSIONS.sveltePlugin,
|
|
218
|
+
"@tailwindcss/vite": VERSIONS.tailwindcssVite,
|
|
219
|
+
"@tauri-apps/cli": VERSIONS.tauriCli,
|
|
220
|
+
"@types/node": VERSIONS.nodeTypes,
|
|
221
|
+
"bits-ui": VERSIONS.bitsUi,
|
|
222
|
+
"daisyui": VERSIONS.daisyui,
|
|
223
|
+
"eslint": VERSIONS.eslint,
|
|
224
|
+
"eslint-plugin-format": VERSIONS.eslintPluginFormat,
|
|
225
|
+
"eslint-plugin-svelte": VERSIONS.eslintPluginSvelte,
|
|
226
|
+
"rimraf": VERSIONS.rimraf,
|
|
227
|
+
"svelte": VERSIONS.svelte,
|
|
228
|
+
"svelte-check": VERSIONS.svelteCheck,
|
|
229
|
+
"svelte-eslint-parser": VERSIONS.svelteEslintParser,
|
|
230
|
+
"tailwindcss": VERSIONS.tailwindcss,
|
|
231
|
+
"tsup": VERSIONS.tsup,
|
|
232
|
+
"typescript": VERSIONS.typescript,
|
|
233
|
+
"vite": VERSIONS.vite,
|
|
234
|
+
"vitest": VERSIONS.vitest,
|
|
235
|
+
"zod": VERSIONS.zod
|
|
236
|
+
};
|
|
237
|
+
var FULLSTACK_CATALOG_PACKAGES = {
|
|
238
|
+
...HAI_CATALOG_PACKAGES,
|
|
239
|
+
...FULLSTACK_EXTERNAL_CATALOG_PACKAGES
|
|
240
|
+
};
|
|
241
|
+
var FULLSTACK_ROOT_CATALOG_PACKAGE_NAMES = [
|
|
242
|
+
"@antfu/eslint-config",
|
|
243
|
+
"@playwright/test",
|
|
244
|
+
"@sveltejs/vite-plugin-svelte",
|
|
245
|
+
"@types/node",
|
|
246
|
+
"eslint",
|
|
247
|
+
"eslint-plugin-format",
|
|
248
|
+
"eslint-plugin-svelte",
|
|
249
|
+
"rimraf",
|
|
250
|
+
"svelte",
|
|
251
|
+
"svelte-check",
|
|
252
|
+
"svelte-eslint-parser",
|
|
253
|
+
"tsup",
|
|
254
|
+
"typescript",
|
|
255
|
+
"vite",
|
|
256
|
+
"vitest"
|
|
257
|
+
];
|
|
258
|
+
var FULLSTACK_CONTRACT_CATALOG_PACKAGE_NAMES = [
|
|
259
|
+
"@h-ai/api-contract",
|
|
260
|
+
"@h-ai/core",
|
|
261
|
+
"zod"
|
|
262
|
+
];
|
|
263
|
+
var FULLSTACK_SERV_CATALOG_PACKAGE_NAMES = [
|
|
264
|
+
"@h-ai/core",
|
|
265
|
+
"@h-ai/serv"
|
|
266
|
+
];
|
|
267
|
+
var FULLSTACK_SHARED_CATALOG_PACKAGE_NAMES = [
|
|
268
|
+
"@h-ai/api-client",
|
|
269
|
+
"@h-ai/ui",
|
|
270
|
+
"@inlang/paraglide-js",
|
|
271
|
+
"@inlang/plugin-message-format",
|
|
272
|
+
"svelte",
|
|
273
|
+
"svelte-check",
|
|
274
|
+
"typescript",
|
|
275
|
+
"vite",
|
|
276
|
+
"vitest"
|
|
277
|
+
];
|
|
278
|
+
var FULLSTACK_WEB_CATALOG_PACKAGE_NAMES = [
|
|
279
|
+
"@antfu/eslint-config",
|
|
280
|
+
"@h-ai/ui",
|
|
281
|
+
"@iconify-json/tabler",
|
|
282
|
+
"@iconify/tailwind4",
|
|
283
|
+
"@inlang/paraglide-js",
|
|
284
|
+
"@inlang/plugin-message-format",
|
|
285
|
+
"@sveltejs/vite-plugin-svelte",
|
|
286
|
+
"@tailwindcss/vite",
|
|
287
|
+
"bits-ui",
|
|
288
|
+
"daisyui",
|
|
289
|
+
"eslint",
|
|
290
|
+
"eslint-plugin-format",
|
|
291
|
+
"eslint-plugin-svelte",
|
|
292
|
+
"svelte",
|
|
293
|
+
"svelte-check",
|
|
294
|
+
"svelte-eslint-parser",
|
|
295
|
+
"tailwindcss",
|
|
296
|
+
"typescript",
|
|
297
|
+
"vite",
|
|
298
|
+
"vitest"
|
|
299
|
+
];
|
|
300
|
+
var FULLSTACK_APP_CATALOG_PACKAGE_NAMES = [
|
|
301
|
+
...FULLSTACK_WEB_CATALOG_PACKAGE_NAMES,
|
|
302
|
+
"@aparajita/capacitor-secure-storage",
|
|
303
|
+
"@capacitor/android",
|
|
304
|
+
"@capacitor/app",
|
|
305
|
+
"@capacitor/camera",
|
|
306
|
+
"@capacitor/cli",
|
|
307
|
+
"@capacitor/core",
|
|
308
|
+
"@capacitor/device",
|
|
309
|
+
"@capacitor/ios",
|
|
310
|
+
"@capacitor/preferences",
|
|
311
|
+
"@capacitor/push-notifications",
|
|
312
|
+
"@capacitor/status-bar",
|
|
313
|
+
"@h-ai/capacitor"
|
|
314
|
+
];
|
|
315
|
+
var FULLSTACK_DESKTOP_CATALOG_PACKAGE_NAMES = [
|
|
316
|
+
...FULLSTACK_WEB_CATALOG_PACKAGE_NAMES,
|
|
317
|
+
"@tauri-apps/cli"
|
|
318
|
+
];
|
|
319
|
+
var API_WORKSPACE_EXTERNAL_CATALOG_PACKAGE_NAMES = [
|
|
320
|
+
"@antfu/eslint-config",
|
|
321
|
+
"@playwright/test",
|
|
322
|
+
"@types/node",
|
|
323
|
+
"eslint",
|
|
324
|
+
"eslint-plugin-format",
|
|
325
|
+
"rimraf",
|
|
326
|
+
"tsup",
|
|
327
|
+
"typescript",
|
|
328
|
+
"vitest",
|
|
329
|
+
"zod"
|
|
330
|
+
];
|
|
331
|
+
function pickCatalogPackages(packageNames, availableCatalogPackages) {
|
|
332
|
+
return Object.fromEntries(
|
|
333
|
+
[...new Set(packageNames)].sort((left, right) => left.localeCompare(right)).map((packageName) => {
|
|
334
|
+
const version = availableCatalogPackages[packageName];
|
|
335
|
+
if (!version) {
|
|
336
|
+
throw new Error(`Missing catalog version for package "${packageName}"`);
|
|
337
|
+
}
|
|
338
|
+
return [packageName, version];
|
|
339
|
+
})
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
function buildFullstackPackageSpecifiers(useCatalogProtocol) {
|
|
343
|
+
return Object.fromEntries(
|
|
344
|
+
Object.entries(VERSIONS).map(([key, version]) => [key, useCatalogProtocol ? HAI_PACKAGE_SPECIFIER_CATALOG : version])
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
function buildApiWorkspaceCatalogPackages(featureMap) {
|
|
348
|
+
const packageNames = [
|
|
349
|
+
...API_WORKSPACE_EXTERNAL_CATALOG_PACKAGE_NAMES,
|
|
350
|
+
"@h-ai/api-client",
|
|
351
|
+
"@h-ai/api-contract",
|
|
352
|
+
"@h-ai/core",
|
|
353
|
+
"@h-ai/serv"
|
|
354
|
+
];
|
|
355
|
+
if (featureMap.db)
|
|
356
|
+
packageNames.push("@h-ai/reldb");
|
|
357
|
+
if (featureMap.cache)
|
|
358
|
+
packageNames.push("@h-ai/cache");
|
|
359
|
+
if (featureMap.iam)
|
|
360
|
+
packageNames.push("@h-ai/iam");
|
|
361
|
+
if (featureMap.crypto)
|
|
362
|
+
packageNames.push("@h-ai/crypto");
|
|
363
|
+
if (featureMap.storage)
|
|
364
|
+
packageNames.push("@h-ai/storage");
|
|
365
|
+
if (featureMap.ai)
|
|
366
|
+
packageNames.push("@h-ai/ai");
|
|
367
|
+
if (featureMap.audit)
|
|
368
|
+
packageNames.push("@h-ai/audit");
|
|
369
|
+
if (featureMap.reach)
|
|
370
|
+
packageNames.push("@h-ai/reach");
|
|
371
|
+
if (featureMap.payment)
|
|
372
|
+
packageNames.push("@h-ai/payment");
|
|
373
|
+
if (featureMap.vecdb)
|
|
374
|
+
packageNames.push("@h-ai/vecdb");
|
|
375
|
+
if (featureMap.datapipe)
|
|
376
|
+
packageNames.push("@h-ai/datapipe");
|
|
377
|
+
if (featureMap.scheduler)
|
|
378
|
+
packageNames.push("@h-ai/scheduler");
|
|
379
|
+
if (featureMap.deploy)
|
|
380
|
+
packageNames.push("@h-ai/deploy");
|
|
381
|
+
return pickCatalogPackages(packageNames, FULLSTACK_CATALOG_PACKAGES);
|
|
382
|
+
}
|
|
383
|
+
function buildAppHaiCatalogPackages(options) {
|
|
384
|
+
const packageNames = [];
|
|
385
|
+
if (options.isSvelteOnlyApp) {
|
|
386
|
+
packageNames.push("@h-ai/api-client", "@h-ai/capacitor", "@h-ai/ui");
|
|
387
|
+
return pickCatalogPackages(packageNames, HAI_CATALOG_PACKAGES);
|
|
388
|
+
}
|
|
389
|
+
packageNames.push("@h-ai/core", "@h-ai/kit");
|
|
390
|
+
if (options.hasUi)
|
|
391
|
+
packageNames.push("@h-ai/ui");
|
|
392
|
+
if (options.featureMap.db)
|
|
393
|
+
packageNames.push("@h-ai/reldb");
|
|
394
|
+
if (options.featureMap.cache)
|
|
395
|
+
packageNames.push("@h-ai/cache");
|
|
396
|
+
if (options.featureMap.iam)
|
|
397
|
+
packageNames.push("@h-ai/iam");
|
|
398
|
+
if (options.featureMap.crypto)
|
|
399
|
+
packageNames.push("@h-ai/crypto");
|
|
400
|
+
if (options.featureMap.storage)
|
|
401
|
+
packageNames.push("@h-ai/storage");
|
|
402
|
+
if (options.featureMap.ai)
|
|
403
|
+
packageNames.push("@h-ai/ai");
|
|
404
|
+
if (options.featureMap.audit)
|
|
405
|
+
packageNames.push("@h-ai/audit");
|
|
406
|
+
if (options.featureMap.reach)
|
|
407
|
+
packageNames.push("@h-ai/reach");
|
|
408
|
+
if (options.featureMap.payment)
|
|
409
|
+
packageNames.push("@h-ai/payment");
|
|
410
|
+
if (options.featureMap.vecdb)
|
|
411
|
+
packageNames.push("@h-ai/vecdb");
|
|
412
|
+
if (options.featureMap.datapipe)
|
|
413
|
+
packageNames.push("@h-ai/datapipe");
|
|
414
|
+
if (options.featureMap.scheduler)
|
|
415
|
+
packageNames.push("@h-ai/scheduler");
|
|
416
|
+
if (options.featureMap.deploy)
|
|
417
|
+
packageNames.push("@h-ai/deploy");
|
|
418
|
+
if (options.featureMap["api-client"])
|
|
419
|
+
packageNames.push("@h-ai/api-client");
|
|
420
|
+
if (options.featureMap.capacitor)
|
|
421
|
+
packageNames.push("@h-ai/capacitor");
|
|
422
|
+
if (options.isCapacitorApp && !options.featureMap["api-client"])
|
|
423
|
+
packageNames.push("@h-ai/api-client");
|
|
424
|
+
if (options.isCapacitorApp && !options.featureMap.capacitor)
|
|
425
|
+
packageNames.push("@h-ai/capacitor");
|
|
426
|
+
return pickCatalogPackages(packageNames, HAI_CATALOG_PACKAGES);
|
|
427
|
+
}
|
|
428
|
+
function buildFullstackCatalogPackages(frontends) {
|
|
429
|
+
const packageNames = [
|
|
430
|
+
...FULLSTACK_ROOT_CATALOG_PACKAGE_NAMES,
|
|
431
|
+
...FULLSTACK_CONTRACT_CATALOG_PACKAGE_NAMES,
|
|
432
|
+
...FULLSTACK_SERV_CATALOG_PACKAGE_NAMES,
|
|
433
|
+
...FULLSTACK_SHARED_CATALOG_PACKAGE_NAMES
|
|
434
|
+
];
|
|
435
|
+
if (frontends.includes("web"))
|
|
436
|
+
packageNames.push(...FULLSTACK_WEB_CATALOG_PACKAGE_NAMES);
|
|
437
|
+
if (frontends.includes("app"))
|
|
438
|
+
packageNames.push(...FULLSTACK_APP_CATALOG_PACKAGE_NAMES);
|
|
439
|
+
if (frontends.includes("desktop"))
|
|
440
|
+
packageNames.push(...FULLSTACK_DESKTOP_CATALOG_PACKAGE_NAMES);
|
|
441
|
+
return pickCatalogPackages(packageNames, FULLSTACK_CATALOG_PACKAGES);
|
|
442
|
+
}
|
|
147
443
|
var FEATURE_ROUTE_DIRS = {
|
|
148
444
|
iam: ["routes-shared"],
|
|
149
445
|
storage: ["routes"],
|
|
@@ -160,6 +456,7 @@ var FEATURE_APP_ROUTE_DIRS = {
|
|
|
160
456
|
};
|
|
161
457
|
var FEATURE_ID_REGEX = /^[a-z0-9-]+$/;
|
|
162
458
|
var HBS_SUFFIX_REGEX = /\.hbs$/;
|
|
459
|
+
var FULLSTACK_FRONTEND_TEMPLATE_PATH_REGEX = /^apps\/\{\{projectName\}\}-(web|app|desktop|miniapp)\//;
|
|
163
460
|
var NON_IDENTIFIER_CHAR_REGEX = /[^a-z0-9]+/i;
|
|
164
461
|
var IDENTIFIER_START_REGEX = /^[a-z_$]/i;
|
|
165
462
|
function getTemplatesRoot() {
|
|
@@ -210,6 +507,28 @@ async function findHbsFiles(dir) {
|
|
|
210
507
|
await walk(dir);
|
|
211
508
|
return results;
|
|
212
509
|
}
|
|
510
|
+
async function findRenderedStaticPathFiles(dir) {
|
|
511
|
+
if (!await fse.pathExists(dir)) {
|
|
512
|
+
return [];
|
|
513
|
+
}
|
|
514
|
+
const results = [];
|
|
515
|
+
async function walk(current) {
|
|
516
|
+
const entries = await fse.readdir(current, { withFileTypes: true });
|
|
517
|
+
for (const entry of entries) {
|
|
518
|
+
const fullPath = path2.join(current, entry.name);
|
|
519
|
+
if (entry.isDirectory()) {
|
|
520
|
+
await walk(fullPath);
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
const relPath = path2.relative(dir, fullPath);
|
|
524
|
+
if (!entry.name.endsWith(".hbs") && (relPath.includes("{{") || relPath.includes("}}"))) {
|
|
525
|
+
results.push(relPath);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
await walk(dir);
|
|
530
|
+
return results;
|
|
531
|
+
}
|
|
213
532
|
function buildTemplateContext(options) {
|
|
214
533
|
const featureMap = {};
|
|
215
534
|
for (const f of options.features) {
|
|
@@ -225,24 +544,62 @@ function buildTemplateContext(options) {
|
|
|
225
544
|
}
|
|
226
545
|
const isApi = options.appType === "api";
|
|
227
546
|
const isFullstack = options.appType === "fullstack";
|
|
228
|
-
const isCapacitorApp = options.appType === "
|
|
547
|
+
const isCapacitorApp = options.appType === "mobile-app";
|
|
548
|
+
const isSvelteOnlyApp = isCapacitorApp;
|
|
549
|
+
const useCatalogProtocol = options.packageManager === "pnpm";
|
|
550
|
+
const hasUi = !isApi && !isFullstack;
|
|
551
|
+
const selectedFrontends = options.frontends ?? DEFAULT_FULLSTACK_FRONTENDS;
|
|
552
|
+
let haiCatalogPackages;
|
|
553
|
+
if (isFullstack) {
|
|
554
|
+
haiCatalogPackages = buildFullstackCatalogPackages(selectedFrontends);
|
|
555
|
+
} else if (isApi) {
|
|
556
|
+
haiCatalogPackages = buildApiWorkspaceCatalogPackages(featureMap);
|
|
557
|
+
} else {
|
|
558
|
+
haiCatalogPackages = buildAppHaiCatalogPackages({
|
|
559
|
+
featureMap,
|
|
560
|
+
hasUi,
|
|
561
|
+
isCapacitorApp,
|
|
562
|
+
isSvelteOnlyApp
|
|
563
|
+
});
|
|
564
|
+
}
|
|
229
565
|
return {
|
|
230
566
|
projectName: options.name,
|
|
567
|
+
useCatalogProtocol,
|
|
568
|
+
haiPackageSpecifier: useCatalogProtocol ? HAI_PACKAGE_SPECIFIER_CATALOG : HAI_PACKAGE_VERSION,
|
|
569
|
+
haiPackageVersion: HAI_PACKAGE_VERSION,
|
|
570
|
+
haiCatalogPackages,
|
|
231
571
|
appType: options.appType,
|
|
232
572
|
features: featureMap,
|
|
233
|
-
hasUi
|
|
573
|
+
hasUi,
|
|
234
574
|
hasI18n: !isApi && !isFullstack,
|
|
235
575
|
isCapacitorApp,
|
|
576
|
+
isApiWorkspace: isApi,
|
|
577
|
+
isSvelteOnlyApp,
|
|
236
578
|
defaultLocale: options.moduleConfigs?.core?.defaultLocale ?? "zh-CN",
|
|
237
579
|
packageManager: options.packageManager,
|
|
580
|
+
api: isApi ? buildApiWorkspaceTemplateContext(options.name, useCatalogProtocol) : void 0,
|
|
238
581
|
fullstack: isFullstack ? buildFullstackTemplateContext(
|
|
239
582
|
options.name,
|
|
240
|
-
|
|
241
|
-
options.moduleConfigs
|
|
583
|
+
selectedFrontends,
|
|
584
|
+
options.moduleConfigs,
|
|
585
|
+
useCatalogProtocol
|
|
242
586
|
) : void 0
|
|
243
587
|
};
|
|
244
588
|
}
|
|
245
|
-
function
|
|
589
|
+
function buildApiWorkspaceTemplateContext(projectName, useCatalogProtocol = false) {
|
|
590
|
+
const identifier = toIdentifier(projectName);
|
|
591
|
+
const pascalName = toPascalIdentifier(identifier);
|
|
592
|
+
return {
|
|
593
|
+
versions: VERSIONS,
|
|
594
|
+
packageSpecifiers: buildFullstackPackageSpecifiers(useCatalogProtocol),
|
|
595
|
+
contractPackageName: `${projectName}-contract`,
|
|
596
|
+
contractExportName: `${identifier}Contract`,
|
|
597
|
+
servicePackageName: `${projectName}-service`,
|
|
598
|
+
serviceAppFactoryName: `create${pascalName}App`,
|
|
599
|
+
serviceProceduresFactoryName: `create${pascalName}Procedures`
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
function buildFullstackTemplateContext(projectName, frontendsInput, moduleConfigs, useCatalogProtocol = false) {
|
|
246
603
|
const selectedFrontends = [...new Set(frontendsInput.length > 0 ? frontendsInput : DEFAULT_FULLSTACK_FRONTENDS)];
|
|
247
604
|
const portsConfig = moduleConfigs?.fullstack?.ports ?? {};
|
|
248
605
|
const portFor = (target) => portsConfig[target] ?? FRONTEND_PORTS_DEFAULT[target];
|
|
@@ -254,9 +611,11 @@ function buildFullstackTemplateContext(projectName, frontendsInput, moduleConfig
|
|
|
254
611
|
}));
|
|
255
612
|
return {
|
|
256
613
|
versions: VERSIONS,
|
|
614
|
+
packageSpecifiers: buildFullstackPackageSpecifiers(useCatalogProtocol),
|
|
257
615
|
contractPackageName: `${projectName}-contract`,
|
|
258
616
|
contractExportName: `${toIdentifier(projectName)}Contract`,
|
|
259
617
|
servPackageName: `${projectName}-serv`,
|
|
618
|
+
nativeAppIdSegment: toIdentifier(projectName).toLowerCase(),
|
|
260
619
|
sharedPackageName: `${projectName}-shared`,
|
|
261
620
|
selectedFrontends,
|
|
262
621
|
selectedFrontendsJson: `[${selectedFrontends.map((f) => `'${f}'`).join(", ")}]`,
|
|
@@ -311,9 +670,14 @@ function toIdentifier(value) {
|
|
|
311
670
|
return "app";
|
|
312
671
|
return IDENTIFIER_START_REGEX.test(camel) ? camel : `app${camel}`;
|
|
313
672
|
}
|
|
673
|
+
function toPascalIdentifier(value) {
|
|
674
|
+
if (!value)
|
|
675
|
+
return "App";
|
|
676
|
+
return `${value.charAt(0).toUpperCase()}${value.slice(1)}`;
|
|
677
|
+
}
|
|
314
678
|
async function generateFromTemplates(projectPath, context) {
|
|
315
679
|
const root = getTemplatesRoot();
|
|
316
|
-
const includeBaseTemplate = context.appType !== "fullstack";
|
|
680
|
+
const includeBaseTemplate = context.appType !== "fullstack" && !context.isApiWorkspace;
|
|
317
681
|
if (includeBaseTemplate) {
|
|
318
682
|
await copyStaticDir(path2.join(root, "base"), projectPath);
|
|
319
683
|
}
|
|
@@ -322,29 +686,37 @@ async function generateFromTemplates(projectPath, context) {
|
|
|
322
686
|
const appExcludes = context.hasI18n ? [] : ["messages"];
|
|
323
687
|
await copyStaticDir(appDir, projectPath, appExcludes);
|
|
324
688
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
if (!FEATURE_ID_REGEX.test(featureId)) {
|
|
330
|
-
continue;
|
|
331
|
-
}
|
|
332
|
-
const featureDir = path2.join(root, "features", featureId);
|
|
333
|
-
if (!await fse.pathExists(featureDir)) {
|
|
334
|
-
continue;
|
|
335
|
-
}
|
|
336
|
-
const sharedDirs = FEATURE_ROUTE_DIRS[featureId] || [];
|
|
337
|
-
for (const dirName of sharedDirs) {
|
|
338
|
-
const routesSrc = path2.join(featureDir, dirName);
|
|
339
|
-
if (await fse.pathExists(routesSrc)) {
|
|
340
|
-
await copyStaticDir(routesSrc, path2.join(projectPath, "src", "routes"));
|
|
689
|
+
if (!context.isApiWorkspace) {
|
|
690
|
+
for (const featureId of Object.keys(context.features)) {
|
|
691
|
+
if (context.isSvelteOnlyApp) {
|
|
692
|
+
continue;
|
|
341
693
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
694
|
+
if (!context.features[featureId]) {
|
|
695
|
+
continue;
|
|
696
|
+
}
|
|
697
|
+
if (!FEATURE_ID_REGEX.test(featureId)) {
|
|
698
|
+
continue;
|
|
699
|
+
}
|
|
700
|
+
const featureDir = path2.join(root, "features", featureId);
|
|
701
|
+
if (!await fse.pathExists(featureDir)) {
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
const sharedDirs = FEATURE_ROUTE_DIRS[featureId] || [];
|
|
705
|
+
for (const dirName of sharedDirs) {
|
|
706
|
+
if (context.isCapacitorApp && dirName === "routes-shared") {
|
|
707
|
+
continue;
|
|
708
|
+
}
|
|
709
|
+
const routesSrc = path2.join(featureDir, dirName);
|
|
710
|
+
if (await fse.pathExists(routesSrc)) {
|
|
711
|
+
await copyStaticDir(routesSrc, path2.join(projectPath, "src", "routes"));
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
const appSpecificTypes = FEATURE_APP_ROUTE_DIRS[featureId] || [];
|
|
715
|
+
if (appSpecificTypes.includes(context.appType)) {
|
|
716
|
+
const appRouteSrc = path2.join(featureDir, `routes-${context.appType}`);
|
|
717
|
+
if (await fse.pathExists(appRouteSrc)) {
|
|
718
|
+
await copyStaticDir(appRouteSrc, path2.join(projectPath, "src", "routes"));
|
|
719
|
+
}
|
|
348
720
|
}
|
|
349
721
|
}
|
|
350
722
|
}
|
|
@@ -360,15 +732,22 @@ async function generateFromTemplates(projectPath, context) {
|
|
|
360
732
|
}
|
|
361
733
|
}
|
|
362
734
|
async function renderDynamicFiles(templatesRoot, projectPath, context) {
|
|
363
|
-
const rootDirs = context.appType === "fullstack" ? [path2.join(templatesRoot, "apps", context.appType)] : [
|
|
735
|
+
const rootDirs = context.appType === "fullstack" || context.isApiWorkspace ? [path2.join(templatesRoot, "apps", context.appType)] : [
|
|
364
736
|
path2.join(templatesRoot, "base"),
|
|
365
737
|
path2.join(templatesRoot, "apps", context.appType)
|
|
366
738
|
];
|
|
367
739
|
for (const dir of rootDirs) {
|
|
368
740
|
await renderHbsInDir(dir, projectPath, context);
|
|
741
|
+
await copyRenderedStaticPathFiles(dir, projectPath, context);
|
|
742
|
+
}
|
|
743
|
+
if (context.isApiWorkspace) {
|
|
744
|
+
return;
|
|
369
745
|
}
|
|
370
746
|
const routesDest = path2.join(projectPath, "src", "routes");
|
|
371
747
|
for (const featureId of Object.keys(context.features)) {
|
|
748
|
+
if (context.isSvelteOnlyApp) {
|
|
749
|
+
continue;
|
|
750
|
+
}
|
|
372
751
|
if (!context.features[featureId]) {
|
|
373
752
|
continue;
|
|
374
753
|
}
|
|
@@ -378,6 +757,9 @@ async function renderDynamicFiles(templatesRoot, projectPath, context) {
|
|
|
378
757
|
}
|
|
379
758
|
const sharedDirs = FEATURE_ROUTE_DIRS[featureId] || [];
|
|
380
759
|
for (const dirName of sharedDirs) {
|
|
760
|
+
if (context.isCapacitorApp && dirName === "routes-shared") {
|
|
761
|
+
continue;
|
|
762
|
+
}
|
|
381
763
|
await renderHbsInDir(path2.join(featureDir, dirName), routesDest, context);
|
|
382
764
|
}
|
|
383
765
|
const appSpecificTypes = FEATURE_APP_ROUTE_DIRS[featureId] || [];
|
|
@@ -405,12 +787,43 @@ async function renderHbsInDir(dir, destRoot, context) {
|
|
|
405
787
|
if (!isSafeRelativePath(outRelPath)) {
|
|
406
788
|
continue;
|
|
407
789
|
}
|
|
790
|
+
if (context.isCapacitorApp && CAPACITOR_SKIPPED_SERVER_FILES.has(outRelPath.split(path2.sep).join("/"))) {
|
|
791
|
+
continue;
|
|
792
|
+
}
|
|
408
793
|
const destPath = path2.join(destRoot, outRelPath);
|
|
409
794
|
const normalizedRendered = normalizeRenderedContent(rendered, outRelPath);
|
|
410
795
|
await fse.ensureDir(path2.dirname(destPath));
|
|
411
796
|
await fse.writeFile(destPath, normalizedRendered, "utf-8");
|
|
412
797
|
}
|
|
413
798
|
}
|
|
799
|
+
async function copyRenderedStaticPathFiles(dir, destRoot, context) {
|
|
800
|
+
const staticFiles = await findRenderedStaticPathFiles(dir);
|
|
801
|
+
for (const relPath of staticFiles) {
|
|
802
|
+
if (!shouldCopyRenderedStaticPathFile(relPath, context)) {
|
|
803
|
+
continue;
|
|
804
|
+
}
|
|
805
|
+
const outRelPath = renderOutputPath(relPath, context);
|
|
806
|
+
if (!isSafeRelativePath(outRelPath)) {
|
|
807
|
+
continue;
|
|
808
|
+
}
|
|
809
|
+
const srcPath = path2.join(dir, relPath);
|
|
810
|
+
const destPath = path2.join(destRoot, outRelPath);
|
|
811
|
+
await fse.ensureDir(path2.dirname(destPath));
|
|
812
|
+
await fse.copyFile(srcPath, destPath);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
function shouldCopyRenderedStaticPathFile(relPath, context) {
|
|
816
|
+
if (context.appType !== "fullstack" || !context.fullstack) {
|
|
817
|
+
return true;
|
|
818
|
+
}
|
|
819
|
+
const normalizedPath = relPath.split(path2.sep).join("/");
|
|
820
|
+
const frontendMatch = FULLSTACK_FRONTEND_TEMPLATE_PATH_REGEX.exec(normalizedPath);
|
|
821
|
+
if (!frontendMatch) {
|
|
822
|
+
return true;
|
|
823
|
+
}
|
|
824
|
+
const target = frontendMatch[1];
|
|
825
|
+
return Boolean(context.fullstack.frontends[target]);
|
|
826
|
+
}
|
|
414
827
|
function normalizeRenderedContent(content, outRelPath) {
|
|
415
828
|
const normalizedLineEndings = content.replace(/\r\n/g, "\n");
|
|
416
829
|
const ext = path2.extname(outRelPath);
|
|
@@ -454,13 +867,13 @@ var APP_TYPES = {
|
|
|
454
867
|
},
|
|
455
868
|
"api": {
|
|
456
869
|
name: "API \u670D\u52A1",
|
|
457
|
-
description: "
|
|
870
|
+
description: "typed API workspace\uFF0C\u542B contract + service \u53CC\u5DE5\u7A0B\u3001\u65E0 UI",
|
|
458
871
|
defaultFeatures: ["db", "cache"]
|
|
459
872
|
},
|
|
460
|
-
"
|
|
461
|
-
name: "
|
|
462
|
-
description: "
|
|
463
|
-
defaultFeatures: ["
|
|
873
|
+
"mobile-app": {
|
|
874
|
+
name: "\u79FB\u52A8\u5E94\u7528",
|
|
875
|
+
description: "\u79FB\u52A8\u7AEF\u5E94\u7528\uFF08Capacitor + Svelte 5 + Vite\uFF09\uFF0C\u53EF\u6253\u5305\u4E3A Android/iOS",
|
|
876
|
+
defaultFeatures: ["api-client", "capacitor"]
|
|
464
877
|
},
|
|
465
878
|
"fullstack": {
|
|
466
879
|
name: "\u524D\u540E\u7AEF\u5206\u79BB\u5DE5\u7A0B",
|
|
@@ -470,9 +883,9 @@ var APP_TYPES = {
|
|
|
470
883
|
};
|
|
471
884
|
var FRONTEND_TARGETS = {
|
|
472
885
|
web: { name: "Web", description: "\u6D4F\u89C8\u5668 Web \u5E94\u7528", implemented: true },
|
|
473
|
-
app: { name: "App", description: "\u79FB\u52A8\u7AEF
|
|
886
|
+
app: { name: "App", description: "\u79FB\u52A8\u7AEF Capacitor App / H5 \u524D\u7AEF", implemented: true },
|
|
474
887
|
miniapp: { name: "\u5C0F\u7A0B\u5E8F", description: "\u9884\u7559\u76EE\u6807\uFF0C\u5F53\u524D\u53EA\u751F\u6210\u8BF4\u660E\u5360\u4F4D", implemented: false },
|
|
475
|
-
desktop: { name: "\u684C\u9762\u7AEF", description: "\u684C\u9762\u7AEF\u524D\u7AEF\u5DE5\u7A0B
|
|
888
|
+
desktop: { name: "\u684C\u9762\u7AEF", description: "Tauri \u684C\u9762\u7AEF\u524D\u7AEF\u5DE5\u7A0B", implemented: true }
|
|
476
889
|
};
|
|
477
890
|
var DEFAULT_FULLSTACK_FRONTENDS2 = ["web", "app", "desktop"];
|
|
478
891
|
var FEATURES = {
|
|
@@ -663,29 +1076,36 @@ async function createProject(options) {
|
|
|
663
1076
|
});
|
|
664
1077
|
await generateFromTemplates(projectPath, context);
|
|
665
1078
|
if (resolvedOptions.appType !== "fullstack") {
|
|
666
|
-
const { generateConfigFile: generateConfigFile2 } = await import('./cli-config-templates-
|
|
1079
|
+
const { generateConfigFile: generateConfigFile2, generateEnvExample } = await import('./cli-config-templates-5J5VKWWD.js');
|
|
667
1080
|
const configs = resolvedOptions.moduleConfigs;
|
|
1081
|
+
const isApiWorkspace = resolvedOptions.appType === "api";
|
|
1082
|
+
const configDir = isApiWorkspace ? path2.join(projectPath, "apps", `${resolvedOptions.name}-service`, "config") : path2.join(projectPath, "config");
|
|
1083
|
+
const envExamplePath = isApiWorkspace ? path2.join(projectPath, "apps", `${resolvedOptions.name}-service`, ".env.example") : path2.join(projectPath, ".env.example");
|
|
668
1084
|
for (const featureId of resolvedOptions.features) {
|
|
669
1085
|
const configKey = getFeatureConfigKey(featureId);
|
|
670
1086
|
if (configKey) {
|
|
671
1087
|
const content = generateConfigFile2(configKey, configs);
|
|
672
|
-
await writeFile(path2.join(
|
|
1088
|
+
await writeFile(path2.join(configDir, `_${configKey}.yml`), content);
|
|
673
1089
|
}
|
|
674
1090
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
1091
|
+
if (!isApiWorkspace) {
|
|
1092
|
+
await writeFile(
|
|
1093
|
+
path2.join(configDir, "_core.yml"),
|
|
1094
|
+
generateConfigFile2("core", configs)
|
|
1095
|
+
);
|
|
1096
|
+
}
|
|
1097
|
+
const envExample = isApiWorkspace ? `${generateEnvExample(resolvedOptions.features, configs)}
|
|
1098
|
+
# =============================================================================
|
|
1099
|
+
# Service Runtime
|
|
1100
|
+
# =============================================================================
|
|
1101
|
+
PORT=3000
|
|
1102
|
+
` : generateEnvExample(resolvedOptions.features, configs);
|
|
1103
|
+
await writeFile(envExamplePath, envExample);
|
|
684
1104
|
}
|
|
685
|
-
const { generateSkillFiles } = await import('./cli-skill-templates-
|
|
1105
|
+
const { generateSkillFiles } = await import('./cli-skill-templates-JMSV2SVW.js');
|
|
686
1106
|
await generateSkillFiles(projectPath, resolvedOptions.features, resolvedOptions.appType);
|
|
687
1107
|
const appTypeLabel = APP_TYPES[resolvedOptions.appType].name;
|
|
688
|
-
const readmeContent = resolvedOptions.appType === "fullstack" ? generateFullstackReadme(resolvedOptions.name, resolvedOptions.packageManager, resolvedOptions.frontends) : generateReadme(resolvedOptions.name, appTypeLabel, resolvedOptions.packageManager);
|
|
1108
|
+
const readmeContent = resolvedOptions.appType === "fullstack" ? generateFullstackReadme(resolvedOptions.name, resolvedOptions.packageManager, resolvedOptions.frontends) : resolvedOptions.appType === "api" ? generateApiWorkspaceReadme(resolvedOptions.name, resolvedOptions.packageManager) : generateReadme(resolvedOptions.name, appTypeLabel, resolvedOptions.packageManager);
|
|
689
1109
|
await writeFile(
|
|
690
1110
|
path2.join(projectPath, "README.md"),
|
|
691
1111
|
readmeContent
|
|
@@ -706,8 +1126,7 @@ async function createProject(options) {
|
|
|
706
1126
|
}
|
|
707
1127
|
if (resolvedOptions.install) {
|
|
708
1128
|
spinner.start(`\u5B89\u88C5\u4F9D\u8D56 (${resolvedOptions.packageManager})...`);
|
|
709
|
-
|
|
710
|
-
execSync(installCmd, { cwd: projectPath, stdio: "ignore" });
|
|
1129
|
+
installDependencies(projectPath, resolvedOptions.packageManager);
|
|
711
1130
|
spinner.succeed();
|
|
712
1131
|
}
|
|
713
1132
|
printCompletionMessage(resolvedOptions);
|
|
@@ -827,7 +1246,7 @@ async function resolveOptions(options) {
|
|
|
827
1246
|
addExamples = examples;
|
|
828
1247
|
}
|
|
829
1248
|
const detected = await detectPackageManager(options.cwd ?? ".");
|
|
830
|
-
let packageManager = selectedAppType === "fullstack" ? "pnpm" : options.packageManager;
|
|
1249
|
+
let packageManager = selectedAppType === "fullstack" || selectedAppType === "api" ? "pnpm" : options.packageManager;
|
|
831
1250
|
if (!packageManager && useDefaults) {
|
|
832
1251
|
packageManager = detected;
|
|
833
1252
|
}
|
|
@@ -1141,31 +1560,119 @@ function getInstallCommand(pm) {
|
|
|
1141
1560
|
return "npm install";
|
|
1142
1561
|
}
|
|
1143
1562
|
}
|
|
1563
|
+
function getRunCommand(pm, script) {
|
|
1564
|
+
return pm === "npm" ? `npm run ${script}` : `${pm} ${script}`;
|
|
1565
|
+
}
|
|
1566
|
+
function installDependencies(projectPath, pm) {
|
|
1567
|
+
const installCmd = getInstallCommand(pm);
|
|
1568
|
+
try {
|
|
1569
|
+
execSync(installCmd, {
|
|
1570
|
+
cwd: projectPath,
|
|
1571
|
+
stdio: "pipe",
|
|
1572
|
+
encoding: "utf-8",
|
|
1573
|
+
maxBuffer: 10 * 1024 * 1024
|
|
1574
|
+
});
|
|
1575
|
+
} catch (error) {
|
|
1576
|
+
const details = formatCommandFailure(installCmd, error);
|
|
1577
|
+
throw new Error(`\u5B89\u88C5\u4F9D\u8D56\u5931\u8D25\uFF08${pm}\uFF09\u3002
|
|
1578
|
+
${details}`);
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
function formatCommandFailure(command, error) {
|
|
1582
|
+
if (!error || typeof error !== "object") {
|
|
1583
|
+
return `\u547D\u4EE4: ${command}`;
|
|
1584
|
+
}
|
|
1585
|
+
const failure = error;
|
|
1586
|
+
const stdout = normalizeChildOutput(failure.stdout);
|
|
1587
|
+
const stderr = normalizeChildOutput(failure.stderr);
|
|
1588
|
+
const status = typeof failure.status === "number" ? `\u9000\u51FA\u7801: ${failure.status}` : "";
|
|
1589
|
+
const signal = typeof failure.signal === "string" ? `\u4FE1\u53F7: ${failure.signal}` : "";
|
|
1590
|
+
const output = [
|
|
1591
|
+
`\u547D\u4EE4: ${command}`,
|
|
1592
|
+
status,
|
|
1593
|
+
signal,
|
|
1594
|
+
stderr ? `stderr:
|
|
1595
|
+
${stderr}` : "",
|
|
1596
|
+
stdout ? `stdout:
|
|
1597
|
+
${stdout}` : ""
|
|
1598
|
+
].filter(Boolean);
|
|
1599
|
+
return output.join("\n\n");
|
|
1600
|
+
}
|
|
1601
|
+
function normalizeChildOutput(output) {
|
|
1602
|
+
if (typeof output === "string") {
|
|
1603
|
+
return output.trim();
|
|
1604
|
+
}
|
|
1605
|
+
if (Buffer.isBuffer(output)) {
|
|
1606
|
+
return output.toString("utf-8").trim();
|
|
1607
|
+
}
|
|
1608
|
+
return "";
|
|
1609
|
+
}
|
|
1144
1610
|
function generateReadme(name, appTypeLabel, pm) {
|
|
1611
|
+
const install = getInstallCommand(pm);
|
|
1145
1612
|
return `# ${name}
|
|
1146
1613
|
|
|
1147
1614
|
\u57FA\u4E8E hai Agent Framework \u6784\u5EFA\u7684${appTypeLabel}\u5E94\u7528\u3002
|
|
1148
1615
|
|
|
1149
1616
|
## \u5F00\u53D1
|
|
1150
1617
|
|
|
1618
|
+
\`\`\`bash
|
|
1619
|
+
${install}
|
|
1620
|
+
${getRunCommand(pm, "dev")}
|
|
1621
|
+
\`\`\`
|
|
1622
|
+
|
|
1623
|
+
## \u6784\u5EFA
|
|
1624
|
+
|
|
1625
|
+
\`\`\`bash
|
|
1626
|
+
${getRunCommand(pm, "build")}
|
|
1627
|
+
${getRunCommand(pm, "i18n:compile")}
|
|
1628
|
+
${getRunCommand(pm, "preview")}
|
|
1629
|
+
\`\`\`
|
|
1630
|
+
|
|
1631
|
+
## \u6587\u6863
|
|
1632
|
+
|
|
1633
|
+
- [hai Agent Framework](https://github.com/hai-series/hai-framework)
|
|
1634
|
+
- [Svelte 5](https://svelte.dev/)
|
|
1635
|
+
`;
|
|
1636
|
+
}
|
|
1637
|
+
function generateApiWorkspaceReadme(name, pm) {
|
|
1638
|
+
return `# ${name}
|
|
1639
|
+
|
|
1640
|
+
\u57FA\u4E8E hai Agent Framework \u6784\u5EFA\u7684 typed API workspace\u3002
|
|
1641
|
+
|
|
1642
|
+
## \u5DE5\u7A0B\u7ED3\u6784
|
|
1643
|
+
|
|
1644
|
+
- \`apps/${name}-contract\`\uFF1A\u5171\u4EAB API contract\u3001Zod schema \u4E0E\u7C7B\u578B
|
|
1645
|
+
- \`apps/${name}-service\`\uFF1A\u540E\u7AEF API service\uFF0C\u57FA\u4E8E \`@h-ai/serv\` \u66B4\u9732 HTTP \u5E94\u7528
|
|
1646
|
+
|
|
1647
|
+
## \u5F00\u53D1
|
|
1648
|
+
|
|
1151
1649
|
\`\`\`bash
|
|
1152
1650
|
${pm} install
|
|
1153
1651
|
${pm} dev
|
|
1154
1652
|
\`\`\`
|
|
1155
1653
|
|
|
1156
|
-
## \
|
|
1654
|
+
## \u8D28\u91CF\u95E8\u7981
|
|
1157
1655
|
|
|
1158
1656
|
\`\`\`bash
|
|
1657
|
+
${pm} typecheck
|
|
1658
|
+
${pm} lint
|
|
1159
1659
|
${pm} build
|
|
1160
|
-
${pm}
|
|
1161
|
-
${pm}
|
|
1660
|
+
${pm} test
|
|
1661
|
+
${pm} test:e2e
|
|
1162
1662
|
\`\`\`
|
|
1163
1663
|
|
|
1664
|
+
## \u6269\u5C55\u5EFA\u8BAE
|
|
1665
|
+
|
|
1666
|
+
- \u5728 \`${name}-contract\` \u4E2D\u7EF4\u62A4\u5E94\u7528\u7EA7 contract\uFF0C\u524D\u540E\u7AEF\u5171\u7528\u540C\u4E00\u4EFD\u7C7B\u578B\u4E0E\u8DEF\u5F84\u5B9A\u4E49\u3002
|
|
1667
|
+
- \u5728 \`${name}-service\` \u4E2D\u6269\u5C55 procedures\u3001\u6A21\u5757\u521D\u59CB\u5316\u4E0E\u914D\u7F6E\u3002
|
|
1668
|
+
- \u9700\u8981 IAM / storage / ai \u65F6\uFF0C\u4F18\u5148\u590D\u7528 \`@h-ai/api-contract\` \u4E0E \`@h-ai/serv/features/*\`\u3002
|
|
1669
|
+
|
|
1164
1670
|
## \u6587\u6863
|
|
1165
1671
|
|
|
1166
1672
|
- [hai Agent Framework](https://github.com/hai-series/hai-framework)
|
|
1167
|
-
- [
|
|
1168
|
-
- [
|
|
1673
|
+
- [@h-ai/serv](./.agents/skills/hai-serv/SKILL.md)
|
|
1674
|
+
- [@h-ai/api-contract](./.agents/skills/hai-api-contract/SKILL.md)
|
|
1675
|
+
- [@h-ai/api-client](./.agents/skills/hai-api-client/SKILL.md)
|
|
1169
1676
|
`;
|
|
1170
1677
|
}
|
|
1171
1678
|
function generateFullstackReadme(name, pm, frontends) {
|
|
@@ -1186,13 +1693,28 @@ function generateFullstackReadme(name, pm, frontends) {
|
|
|
1186
1693
|
|
|
1187
1694
|
\u5DF2\u542F\u7528\u524D\u7AEF\uFF1A${enabledFrontends || "Web / App / Desktop"}
|
|
1188
1695
|
|
|
1189
|
-
## \u5F00\u53D1
|
|
1696
|
+
## \u5F00\u53D1\u3001\u7F16\u8BD1\u4E0E\u6253\u5305
|
|
1190
1697
|
|
|
1191
1698
|
\`\`\`bash
|
|
1192
1699
|
${pm} install
|
|
1193
1700
|
${pm} dev
|
|
1701
|
+
|
|
1702
|
+
# \u4E00\u952E\u7F16\u8BD1\uFF1A\u7C7B\u578B\u68C0\u67E5 + \u5168\u5DE5\u4F5C\u533A\u6784\u5EFA
|
|
1703
|
+
${pm} compile
|
|
1704
|
+
|
|
1705
|
+
# \u4E00\u952E\u6253\u5305\uFF1AWeb build\u3001App Capacitor sync\u3001Desktop Tauri build\uFF08\u6309\u542F\u7528\u524D\u7AEF\u6267\u884C\uFF09
|
|
1706
|
+
${pm} package
|
|
1707
|
+
|
|
1708
|
+
# \u90E8\u7F72\u5165\u53E3\uFF1A\u9ED8\u8BA4\u6267\u884C package\uFF0C\u53EF\u66FF\u6362\u4E3A\u56E2\u961F\u81EA\u5DF1\u7684 CI/CD \u53D1\u5E03\u811A\u672C
|
|
1709
|
+
${pm} deploy
|
|
1194
1710
|
\`\`\`
|
|
1195
1711
|
|
|
1712
|
+
\u524D\u7AEF\u5355\u72EC\u4EA4\u4ED8\u547D\u4EE4\uFF1A
|
|
1713
|
+
|
|
1714
|
+
- Web\uFF1A\`${pm} --filter ${name}-web build\` / \`${pm} --filter ${name}-web package\`
|
|
1715
|
+
- App\uFF1A\`${pm} --filter ${name}-app package\`\uFF0CAndroid/iOS \u53EF\u7528 \`cap:build:android:debug\` / \`cap:build:android:release\` / \`cap:build:ios\`
|
|
1716
|
+
- Desktop\uFF1A\`${pm} --filter ${name}-desktop tauri:dev\` / \`${pm} --filter ${name}-desktop package\`
|
|
1717
|
+
|
|
1196
1718
|
## i18n \u4E0E shared \u534F\u540C
|
|
1197
1719
|
|
|
1198
1720
|
- shared\uFF1A\`packages/${name}-shared/project.inlang\` + \`messages/\`\uFF0C\u53EA\u653E\u8DE8\u7AEF\u5171\u4EAB\u7EC4\u4EF6\u6587\u6848\u3002
|
|
@@ -1219,7 +1741,6 @@ ${pm} test:e2e
|
|
|
1219
1741
|
## \u6587\u6863
|
|
1220
1742
|
|
|
1221
1743
|
- [hai Agent Framework](https://github.com/hai-series/hai-framework)
|
|
1222
|
-
- [SvelteKit](https://kit.svelte.dev/)
|
|
1223
1744
|
- [@h-ai/serv](./.agents/skills/hai-serv/SKILL.md)
|
|
1224
1745
|
- [@h-ai/ui](./.agents/skills/hai-ui/SKILL.md)
|
|
1225
1746
|
`;
|
|
@@ -1241,14 +1762,15 @@ function printCompletionMessage(options) {
|
|
|
1241
1762
|
core.logger.info("\u4E0B\u4E00\u6B65\uFF1A");
|
|
1242
1763
|
core.logger.info(chalk.cyan(` cd ${options.name}`));
|
|
1243
1764
|
if (!options.install) {
|
|
1244
|
-
core.logger.info(chalk.cyan(` ${options.packageManager}
|
|
1765
|
+
core.logger.info(chalk.cyan(` ${getInstallCommand(options.packageManager)}`));
|
|
1245
1766
|
}
|
|
1246
|
-
if (options.appType === "fullstack") {
|
|
1247
|
-
core.logger.info(chalk.cyan(` ${options.packageManager}
|
|
1248
|
-
core.logger.info(chalk.cyan(` ${options.packageManager}
|
|
1249
|
-
core.logger.info(chalk.cyan(` ${options.packageManager
|
|
1767
|
+
if (options.appType === "fullstack" || options.appType === "api") {
|
|
1768
|
+
core.logger.info(chalk.cyan(` ${getRunCommand(options.packageManager, "dev")}`));
|
|
1769
|
+
core.logger.info(chalk.cyan(` ${getRunCommand(options.packageManager, "typecheck")}`));
|
|
1770
|
+
core.logger.info(chalk.cyan(` ${getRunCommand(options.packageManager, "test")}`));
|
|
1771
|
+
core.logger.info(chalk.cyan(` ${getRunCommand(options.packageManager, "test:e2e")}`));
|
|
1250
1772
|
} else {
|
|
1251
|
-
core.logger.info(chalk.cyan(` ${options.packageManager
|
|
1773
|
+
core.logger.info(chalk.cyan(` ${getRunCommand(options.packageManager, "dev")}`));
|
|
1252
1774
|
}
|
|
1253
1775
|
core.logger.info("", {});
|
|
1254
1776
|
}
|
|
@@ -1332,7 +1854,7 @@ async function addModule(options) {
|
|
|
1332
1854
|
core.logger.info(`\u53EF\u7528\u6A21\u5757: ${Object.keys(MODULE_MAP).join(", ")}`);
|
|
1333
1855
|
return;
|
|
1334
1856
|
}
|
|
1335
|
-
const { generateProjectAiSupport, resolveSkillNamesForPackages } = await import('./cli-skill-templates-
|
|
1857
|
+
const { generateProjectAiSupport, resolveSkillNamesForPackages } = await import('./cli-skill-templates-JMSV2SVW.js');
|
|
1336
1858
|
if (moduleDef.packages.every((p) => project.haiPackages.includes(p))) {
|
|
1337
1859
|
const generatedFiles2 = await generateProjectAiSupport(
|
|
1338
1860
|
cwd,
|
|
@@ -1368,9 +1890,8 @@ async function addModule(options) {
|
|
|
1368
1890
|
const pkg = await fse.readJson(pkgPath);
|
|
1369
1891
|
if (!pkg.dependencies)
|
|
1370
1892
|
pkg.dependencies = {};
|
|
1371
|
-
const
|
|
1372
|
-
const
|
|
1373
|
-
const depVersion = `^${cliPkg.version}`;
|
|
1893
|
+
const existingHaiSpecifier = Object.entries(pkg.dependencies).find(([pkgName]) => pkgName.startsWith("@h-ai/"))?.[1];
|
|
1894
|
+
const depVersion = existingHaiSpecifier === "catalog:" ? "catalog:" : `^${getCliVersion()}`;
|
|
1374
1895
|
for (const pkgName of allPackages) {
|
|
1375
1896
|
if (!pkg.dependencies[pkgName]) {
|
|
1376
1897
|
pkg.dependencies[pkgName] = depVersion;
|
|
@@ -1443,18 +1964,19 @@ async function deployCommand(options) {
|
|
|
1443
1964
|
const spinner = ora();
|
|
1444
1965
|
const cwd = options.cwd ?? process3.cwd();
|
|
1445
1966
|
const appDir = resolve(cwd, options.appDir ?? ".");
|
|
1967
|
+
let closeDeploy = null;
|
|
1446
1968
|
try {
|
|
1447
1969
|
let deployModule;
|
|
1448
1970
|
try {
|
|
1449
|
-
deployModule = await import('./src-
|
|
1971
|
+
deployModule = await import('./src-QNEJJ3BV.js');
|
|
1450
1972
|
} catch {
|
|
1451
1973
|
core.logger.error(chalk.red("Deploy module not found. Install @h-ai/deploy first:"));
|
|
1452
1974
|
core.logger.info(chalk.cyan(" pnpm add @h-ai/deploy"));
|
|
1453
1975
|
return;
|
|
1454
1976
|
}
|
|
1455
|
-
const { deploy
|
|
1977
|
+
const { deploy } = deployModule;
|
|
1456
1978
|
spinner.start("Loading credentials...");
|
|
1457
|
-
const credResult =
|
|
1979
|
+
const credResult = deploy.credentials.load();
|
|
1458
1980
|
if (!credResult.success) {
|
|
1459
1981
|
spinner.fail(chalk.red(`Failed to load credentials: ${credResult.error.message}`));
|
|
1460
1982
|
return;
|
|
@@ -1472,7 +1994,7 @@ async function deployCommand(options) {
|
|
|
1472
1994
|
const deployConfig = parse(rawConfig);
|
|
1473
1995
|
spinner.succeed("Deploy config loaded");
|
|
1474
1996
|
spinner.start("Scanning application...");
|
|
1475
|
-
const scanResult = await
|
|
1997
|
+
const scanResult = await deploy.scan(appDir);
|
|
1476
1998
|
if (!scanResult.success) {
|
|
1477
1999
|
spinner.fail(chalk.red(`Scan failed: ${scanResult.error.message}`));
|
|
1478
2000
|
return;
|
|
@@ -1485,6 +2007,7 @@ async function deployCommand(options) {
|
|
|
1485
2007
|
spinner.fail(chalk.red(`Init failed: ${initResult.error.message}`));
|
|
1486
2008
|
return;
|
|
1487
2009
|
}
|
|
2010
|
+
closeDeploy = () => deploy.close();
|
|
1488
2011
|
spinner.succeed("Deploy module initialized");
|
|
1489
2012
|
spinner.start("Deploying application...");
|
|
1490
2013
|
const deployResult = await deploy.deployApp(appDir, {
|
|
@@ -1494,7 +2017,6 @@ async function deployCommand(options) {
|
|
|
1494
2017
|
});
|
|
1495
2018
|
if (!deployResult.success) {
|
|
1496
2019
|
spinner.fail(chalk.red(`Deploy failed: ${deployResult.error.message}`));
|
|
1497
|
-
await deploy.close();
|
|
1498
2020
|
return;
|
|
1499
2021
|
}
|
|
1500
2022
|
spinner.succeed(chalk.green("Deployment successful!"));
|
|
@@ -1505,11 +2027,18 @@ async function deployCommand(options) {
|
|
|
1505
2027
|
core.logger.info(chalk.gray(` Env: ${deployResult.data.envVarsSet.join(", ")}`));
|
|
1506
2028
|
}
|
|
1507
2029
|
core.logger.info("");
|
|
1508
|
-
await deploy.close();
|
|
1509
2030
|
} catch (error) {
|
|
1510
2031
|
spinner.fail(chalk.red("Deploy command failed"));
|
|
1511
2032
|
core.logger.error(error instanceof Error ? error.message : String(error));
|
|
1512
2033
|
throw error;
|
|
2034
|
+
} finally {
|
|
2035
|
+
if (closeDeploy) {
|
|
2036
|
+
try {
|
|
2037
|
+
await closeDeploy();
|
|
2038
|
+
} catch (error) {
|
|
2039
|
+
core.logger.error("Failed to close deploy module", { error });
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
1513
2042
|
}
|
|
1514
2043
|
}
|
|
1515
2044
|
function interpolateEnvFallback(content) {
|
|
@@ -1808,6 +2337,7 @@ export const down: MigrationFn = async (db) => {
|
|
|
1808
2337
|
}
|
|
1809
2338
|
var MODULE_CONFIG_MAP = {
|
|
1810
2339
|
"@h-ai/core": { configKey: "core", label: "Core" },
|
|
2340
|
+
"@h-ai/serv": { configKey: "serv", label: "Service" },
|
|
1811
2341
|
"@h-ai/reldb": { configKey: "db", label: "Database" },
|
|
1812
2342
|
"@h-ai/cache": { configKey: "cache", label: "Cache" },
|
|
1813
2343
|
"@h-ai/iam": { configKey: "iam", label: "IAM" },
|
|
@@ -1923,21 +2453,11 @@ async function initProject(options) {
|
|
|
1923
2453
|
}
|
|
1924
2454
|
|
|
1925
2455
|
// src/cli-main.ts
|
|
1926
|
-
|
|
1927
|
-
try {
|
|
1928
|
-
const here = path2.dirname(fileURLToPath(import.meta.url));
|
|
1929
|
-
const pkgPath = path2.resolve(here, "../package.json");
|
|
1930
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
1931
|
-
return pkg.version ?? "0.0.0";
|
|
1932
|
-
} catch {
|
|
1933
|
-
return "0.0.0";
|
|
1934
|
-
}
|
|
1935
|
-
}
|
|
1936
|
-
var VERSION = readCliVersion();
|
|
2456
|
+
var VERSION = getCliVersion();
|
|
1937
2457
|
var cli = cac("hai");
|
|
1938
2458
|
cli.option("-v, --verbose", "\u663E\u793A\u8BE6\u7EC6\u8F93\u51FA");
|
|
1939
2459
|
cli.option("-C, --cwd <path>", "\u5DE5\u4F5C\u76EE\u5F55");
|
|
1940
|
-
cli.command("create [name]", "\u521B\u5EFA\u65B0\u7684 hai \u9879\u76EE").option("--type <type>", "\u5E94\u7528\u7C7B\u578B (admin, website, h5, api,
|
|
2460
|
+
cli.command("create [name]", "\u521B\u5EFA\u65B0\u7684 hai \u9879\u76EE").option("--type <type>", "\u5E94\u7528\u7C7B\u578B (admin, website, h5, api, mobile-app, fullstack)").option("--frontends <targets>", "\u524D\u540E\u7AEF\u5206\u79BB\u5DE5\u7A0B\u524D\u7AEF\u76EE\u6807 (\u9017\u53F7\u5206\u9694: web,app,miniapp,desktop)").option("-t, --template <template>", "\u9879\u76EE\u6A21\u677F (minimal, default, full, custom)").option("-f, --features <features>", "\u529F\u80FD\u5217\u8868 (\u9017\u53F7\u5206\u9694: iam,db,cache,ai,storage,crypto)").option("--examples", "\u6DFB\u52A0\u793A\u4F8B\u4EE3\u7801").option("--no-examples", "\u4E0D\u6DFB\u52A0\u793A\u4F8B\u4EE3\u7801").option("--no-install", "\u4E0D\u5B89\u88C5\u4F9D\u8D56").option("-p, --package-manager <pm>", "\u5305\u7BA1\u7406\u5668 (pnpm, npm, yarn)").option("--no-git", "\u4E0D\u521D\u59CB\u5316 Git").option("--git-remote <url>", "Git \u8FDC\u7A0B\u4ED3\u5E93\u5730\u5740").option("-y, --yes", "\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E\uFF0C\u8DF3\u8FC7\u4EA4\u4E92").action(async (name, options) => {
|
|
1941
2461
|
try {
|
|
1942
2462
|
const features = typeof options.features === "string" ? options.features.split(",").map((f) => f.trim()) : void 0;
|
|
1943
2463
|
const frontends = typeof options.frontends === "string" ? options.frontends.split(",").map((f) => f.trim()).filter(Boolean) : void 0;
|