@h-ai/cli 0.1.0-alpha.20 → 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.
Files changed (181) hide show
  1. package/README.md +10 -7
  2. package/dist/{chunk-GSMXGUYF.js → chunk-5IGMJVV5.js} +56 -38
  3. package/dist/chunk-5IGMJVV5.js.map +1 -0
  4. package/dist/{chunk-3BBXDQ4Y.js → chunk-CFCXOKGV.js} +24 -2
  5. package/dist/chunk-CFCXOKGV.js.map +1 -0
  6. package/dist/cli-config-templates-5J5VKWWD.js +5 -0
  7. package/dist/{cli-config-templates-IGGO7P45.js.map → cli-config-templates-5J5VKWWD.js.map} +1 -1
  8. package/dist/cli-skill-templates-JMSV2SVW.js +5 -0
  9. package/dist/{cli-skill-templates-IMYZPQRG.js.map → cli-skill-templates-JMSV2SVW.js.map} +1 -1
  10. package/dist/index.js +567 -75
  11. package/dist/index.js.map +1 -1
  12. package/package.json +3 -2
  13. package/templates/README.md +40 -29
  14. package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +16 -0
  15. package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +38 -0
  16. package/templates/apps/api/apps/{{projectName}}-contract/src/app-contract.ts.hbs +27 -0
  17. package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +33 -0
  18. package/templates/apps/api/apps/{{projectName}}-contract/src/index.ts.hbs +3 -0
  19. package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +12 -0
  20. package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +18 -0
  21. package/templates/apps/api/apps/{{projectName}}-contract/tsconfig.json.hbs +12 -0
  22. package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +11 -0
  23. package/templates/apps/api/apps/{{projectName}}-contract/vitest.config.ts.hbs +9 -0
  24. package/templates/apps/api/apps/{{projectName}}-service/README.md.hbs +17 -0
  25. package/templates/apps/api/apps/{{projectName}}-service/config/_core.yml.hbs +19 -0
  26. package/templates/apps/api/apps/{{projectName}}-service/config/_serv.yml.hbs +26 -0
  27. package/templates/apps/api/apps/{{projectName}}-service/package.json.hbs +55 -0
  28. package/templates/apps/api/apps/{{projectName}}-service/src/app.ts.hbs +98 -0
  29. package/templates/apps/api/apps/{{projectName}}-service/src/index.ts.hbs +21 -0
  30. package/templates/apps/api/apps/{{projectName}}-service/src/lib/server/init.ts.hbs +184 -0
  31. package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/app-procedures.ts.hbs +49 -0
  32. package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/index.ts.hbs +18 -0
  33. package/templates/apps/api/apps/{{projectName}}-service/tests/service.test.ts.hbs +168 -0
  34. package/templates/apps/api/apps/{{projectName}}-service/tsconfig.json.hbs +16 -0
  35. package/templates/apps/api/apps/{{projectName}}-service/tsup.config.ts.hbs +11 -0
  36. package/templates/apps/api/apps/{{projectName}}-service/vitest.config.ts.hbs +9 -0
  37. package/templates/apps/api/e2e/api-service.spec.ts.hbs +18 -0
  38. package/templates/apps/api/eslint.config.js +32 -0
  39. package/templates/apps/api/package.json.hbs +29 -0
  40. package/templates/apps/api/playwright.config.ts.hbs +58 -0
  41. package/templates/apps/api/pnpm-workspace.yaml.hbs +14 -0
  42. package/templates/apps/api/tsconfig.base.json +15 -0
  43. package/templates/apps/fullstack/apps/{{projectName}}-app/.env.example.hbs +10 -0
  44. package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +24 -7
  45. package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +18 -0
  46. package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +1 -1
  47. package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +16 -0
  48. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +6 -0
  49. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +6 -0
  50. package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +51 -29
  51. package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +186 -0
  52. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.css.hbs +2 -0
  53. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +0 -1
  54. package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +18 -0
  55. package/templates/apps/fullstack/apps/{{projectName}}-app/src/main.ts.hbs +14 -0
  56. package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +1 -5
  57. package/templates/apps/fullstack/apps/{{projectName}}-app/tsconfig.json.hbs +10 -4
  58. package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +4 -3
  59. package/templates/apps/fullstack/apps/{{projectName}}-desktop/.env.example.hbs +6 -0
  60. package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +20 -6
  61. package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +1 -1
  62. package/templates/apps/fullstack/apps/{{projectName}}-desktop/index.html.hbs +15 -0
  63. package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +33 -30
  64. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +152 -0
  65. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.d.ts.hbs +1 -2
  66. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/main.ts.hbs +13 -0
  67. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/Cargo.toml.hbs +22 -0
  68. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/build.rs.hbs +6 -0
  69. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/capabilities/default.json.hbs +12 -0
  70. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128.png +0 -0
  71. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128@2x.png +0 -0
  72. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/32x32.png +0 -0
  73. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.icns +0 -0
  74. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.ico +0 -0
  75. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/lib.rs.hbs +16 -0
  76. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/main.rs.hbs +8 -0
  77. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +41 -0
  78. package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +2 -8
  79. package/templates/apps/fullstack/apps/{{projectName}}-desktop/tsconfig.json.hbs +9 -4
  80. package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +44 -21
  81. package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +15 -6
  82. package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +1 -1
  83. package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +15 -0
  84. package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +25 -27
  85. package/templates/apps/fullstack/apps/{{projectName}}-web/src/App.svelte.hbs +153 -0
  86. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.d.ts.hbs +0 -1
  87. package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +14 -0
  88. package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +1 -5
  89. package/templates/apps/fullstack/apps/{{projectName}}-web/tsconfig.json.hbs +10 -4
  90. package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +3 -2
  91. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +2 -1
  92. package/templates/apps/fullstack/eslint.config.js +0 -1
  93. package/templates/apps/fullstack/package.json.hbs +18 -17
  94. package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +3 -3
  95. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +2 -2
  96. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +2 -2
  97. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +1 -1
  98. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/{server-app.test.ts.hbs → app-server.test.ts.hbs} +1 -1
  99. package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +9 -8
  100. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/index.ts.hbs +1 -1
  101. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +5 -1
  102. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/ThemeSwitcher.svelte.hbs +1 -1
  103. package/templates/apps/fullstack/packages/{{projectName}}-shared/tsconfig.json.hbs +1 -1
  104. package/templates/apps/fullstack/playwright.config.ts.hbs +41 -4
  105. package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +15 -0
  106. package/templates/apps/mobile-app/.env.hbs +3 -0
  107. package/templates/apps/{android-app → mobile-app}/capacitor.config.ts.hbs +2 -2
  108. package/templates/apps/mobile-app/index.html.hbs +13 -0
  109. package/templates/apps/mobile-app/messages/en-US.json +36 -0
  110. package/templates/apps/mobile-app/messages/zh-CN.json +36 -0
  111. package/templates/apps/mobile-app/src/App.svelte.hbs +162 -0
  112. package/templates/apps/mobile-app/src/lib/api.ts.hbs +54 -0
  113. package/templates/apps/{android-app → mobile-app}/src/lib/capacitor.ts +5 -6
  114. package/templates/apps/mobile-app/src/main.ts.hbs +11 -0
  115. package/templates/base/.gitignore.hbs +16 -0
  116. package/templates/base/{eslint.config.js → eslint.config.js.hbs} +4 -1
  117. package/templates/base/package.json.hbs +52 -33
  118. package/templates/base/playwright.config.ts +30 -3
  119. package/templates/base/pnpm-workspace.yaml.hbs +14 -0
  120. package/templates/base/src/app.d.ts.hbs +3 -0
  121. package/templates/base/src/app.html.hbs +3 -0
  122. package/templates/base/svelte.config.js.hbs +43 -3
  123. package/templates/base/tests/scaffold.test.ts.hbs +7 -0
  124. package/templates/base/tsconfig.json.hbs +50 -0
  125. package/templates/base/vite.config.ts.hbs +10 -0
  126. package/templates/skills/AGENTS.md +57 -24
  127. package/templates/skills/CLAUDE.md +18 -7
  128. package/templates/skills/bridges/admin/AGENTS.md +66 -0
  129. package/templates/skills/bridges/admin/CLAUDE.md +19 -0
  130. package/templates/skills/bridges/admin/copilot-instructions.md +46 -0
  131. package/templates/skills/bridges/api/AGENTS.md +65 -0
  132. package/templates/skills/bridges/api/CLAUDE.md +19 -0
  133. package/templates/skills/bridges/api/copilot-instructions.md +46 -0
  134. package/templates/skills/bridges/fullstack/AGENTS.md +84 -0
  135. package/templates/skills/bridges/fullstack/CLAUDE.md +19 -0
  136. package/templates/skills/bridges/fullstack/copilot-instructions.md +54 -0
  137. package/templates/skills/bridges/h5/AGENTS.md +65 -0
  138. package/templates/skills/bridges/h5/CLAUDE.md +19 -0
  139. package/templates/skills/bridges/h5/copilot-instructions.md +44 -0
  140. package/templates/skills/bridges/mobile-app/AGENTS.md +77 -0
  141. package/templates/skills/bridges/mobile-app/CLAUDE.md +19 -0
  142. package/templates/skills/bridges/mobile-app/copilot-instructions.md +45 -0
  143. package/templates/skills/bridges/website/AGENTS.md +65 -0
  144. package/templates/skills/bridges/website/CLAUDE.md +19 -0
  145. package/templates/skills/bridges/website/copilot-instructions.md +44 -0
  146. package/templates/skills/copilot-instructions.md +27 -64
  147. package/templates/skills/hai-app-create/SKILL.md +1 -0
  148. package/templates/skills/hai-app-review/SKILL.md +1 -1
  149. package/templates/skills/hai-app-tests/SKILL.md +28 -3
  150. package/templates/skills/hai-capacitor/SKILL.md +14 -22
  151. package/templates/skills/opencode.json +1 -6
  152. package/dist/chunk-3BBXDQ4Y.js.map +0 -1
  153. package/dist/chunk-GSMXGUYF.js.map +0 -1
  154. package/dist/cli-config-templates-IGGO7P45.js +0 -5
  155. package/dist/cli-skill-templates-IMYZPQRG.js +0 -5
  156. package/templates/apps/android-app/.env.hbs +0 -3
  157. package/templates/apps/android-app/messages/en-US.json +0 -24
  158. package/templates/apps/android-app/messages/zh-CN.json +0 -24
  159. package/templates/apps/android-app/src/lib/api.ts.hbs +0 -32
  160. package/templates/apps/android-app/src/routes/+layout.svelte.hbs +0 -43
  161. package/templates/apps/android-app/src/routes/+layout.ts +0 -7
  162. package/templates/apps/android-app/src/routes/+page.svelte.hbs +0 -38
  163. package/templates/apps/api/src/routes/+layout.svelte +0 -14
  164. package/templates/apps/api/src/routes/+page.svelte +0 -11
  165. package/templates/apps/api/src/routes/api/v1/health/+server.ts +0 -14
  166. package/templates/apps/api/src/routes/api/v1/items/+server.ts +0 -37
  167. package/templates/apps/api/src/routes/api/v1/items/[id]/+server.ts +0 -30
  168. package/templates/apps/api/tests/health.test.ts.hbs +0 -26
  169. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.html.hbs +0 -14
  170. package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+layout.svelte.hbs +0 -18
  171. package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+page.svelte.hbs +0 -162
  172. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.html.hbs +0 -14
  173. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+layout.svelte.hbs +0 -18
  174. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+page.svelte.hbs +0 -162
  175. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.html.hbs +0 -14
  176. package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+layout.svelte.hbs +0 -18
  177. package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+page.svelte.hbs +0 -162
  178. package/templates/apps/fullstack/pnpm-workspace.yaml +0 -7
  179. package/templates/base/tsconfig.json +0 -20
  180. /package/templates/apps/fullstack/packages/{{projectName}}-serv/src/{server-app.ts.hbs → app-server.ts.hbs} +0 -0
  181. /package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/{theme.svelte.ts.hbs → theme-store.svelte.ts.hbs} +0 -0
@@ -9,42 +9,45 @@
9
9
  "paraglide:compile": "paraglide-js compile --project ./project.inlang --outdir ./src/lib/paraglide",
10
10
  "paraglide:watch": "paraglide-js compile --project ./project.inlang --outdir ./src/lib/paraglide --watch",
11
11
  "dev": "vite dev --host 127.0.0.1 --port {{fullstack.ports.desktop}}",
12
- "build": "vite build",
12
+ "build": "pnpm paraglide:compile && vite build",
13
+ "package": "pnpm tauri:build",
14
+ "deploy": "pnpm package",
13
15
  "preview": "vite preview --host 127.0.0.1 --port {{fullstack.ports.desktop}} --strictPort",
14
- "typecheck": "pnpm paraglide:compile && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
15
- "lint": "eslint .",
16
- "test": "vitest run",
17
- "test:watch": "vitest",
18
- "clean": "rimraf .svelte-kit build .turbo src/lib/paraglide"
16
+ "typecheck": "pnpm paraglide:compile && svelte-check --tsconfig ./tsconfig.json",
17
+ "lint": "eslint src tests vite.config.ts svelte.config.js",
18
+ "lint:fix": "eslint src tests vite.config.ts svelte.config.js --fix",
19
+ "test": "pnpm paraglide:compile && vitest run",
20
+ "test:watch": "pnpm paraglide:compile && vitest",
21
+ "clean": "rimraf dist .turbo src-tauri/target src/lib/paraglide",
22
+ "tauri": "tauri",
23
+ "tauri:dev": "tauri dev",
24
+ "tauri:build": "tauri build"
19
25
  },
20
26
  "dependencies": {
21
- "@h-ai/api-client": "{{fullstack.versions.apiClient}}",
22
- "@h-ai/ui": "{{fullstack.versions.ui}}",
23
- "{{fullstack.contractPackageName}}": "workspace:*",
27
+ "@h-ai/ui": "{{haiPackageSpecifier}}",
24
28
  "{{fullstack.sharedPackageName}}": "workspace:*"
25
29
  },
26
30
  "devDependencies": {
27
- "@antfu/eslint-config": "{{fullstack.versions.antfuEslintConfig}}",
28
- "@iconify-json/tabler": "{{fullstack.versions.iconifyJsonTabler}}",
29
- "@iconify/tailwind4": "{{fullstack.versions.iconifyTailwind}}",
30
- "@inlang/paraglide-js": "{{fullstack.versions.inlangParaglide}}",
31
- "@inlang/plugin-message-format": "{{fullstack.versions.inlangMessageFormat}}",
32
- "@sveltejs/adapter-auto": "{{fullstack.versions.adapterAuto}}",
33
- "@sveltejs/kit": "{{fullstack.versions.svelteKit}}",
34
- "@sveltejs/vite-plugin-svelte": "{{fullstack.versions.sveltePlugin}}",
35
- "@tailwindcss/vite": "{{fullstack.versions.tailwindcssVite}}",
36
- "bits-ui": "{{fullstack.versions.bitsUi}}",
37
- "daisyui": "{{fullstack.versions.daisyui}}",
38
- "eslint": "{{fullstack.versions.eslint}}",
39
- "eslint-plugin-format": "{{fullstack.versions.eslintPluginFormat}}",
40
- "eslint-plugin-svelte": "{{fullstack.versions.eslintPluginSvelte}}",
41
- "svelte": "{{fullstack.versions.svelte}}",
42
- "svelte-check": "{{fullstack.versions.svelteCheck}}",
43
- "svelte-eslint-parser": "{{fullstack.versions.svelteEslintParser}}",
44
- "tailwindcss": "{{fullstack.versions.tailwindcss}}",
45
- "typescript": "{{fullstack.versions.typescript}}",
46
- "vite": "{{fullstack.versions.vite}}",
47
- "vitest": "{{fullstack.versions.vitest}}"
31
+ "@antfu/eslint-config": "{{fullstack.packageSpecifiers.antfuEslintConfig}}",
32
+ "@iconify-json/tabler": "{{fullstack.packageSpecifiers.iconifyJsonTabler}}",
33
+ "@iconify/tailwind4": "{{fullstack.packageSpecifiers.iconifyTailwind}}",
34
+ "@inlang/paraglide-js": "{{fullstack.packageSpecifiers.inlangParaglide}}",
35
+ "@inlang/plugin-message-format": "{{fullstack.packageSpecifiers.inlangMessageFormat}}",
36
+ "@sveltejs/vite-plugin-svelte": "{{fullstack.packageSpecifiers.sveltePlugin}}",
37
+ "@tailwindcss/vite": "{{fullstack.packageSpecifiers.tailwindcssVite}}",
38
+ "@tauri-apps/cli": "{{fullstack.packageSpecifiers.tauriCli}}",
39
+ "bits-ui": "{{fullstack.packageSpecifiers.bitsUi}}",
40
+ "daisyui": "{{fullstack.packageSpecifiers.daisyui}}",
41
+ "eslint": "{{fullstack.packageSpecifiers.eslint}}",
42
+ "eslint-plugin-format": "{{fullstack.packageSpecifiers.eslintPluginFormat}}",
43
+ "eslint-plugin-svelte": "{{fullstack.packageSpecifiers.eslintPluginSvelte}}",
44
+ "svelte": "{{fullstack.packageSpecifiers.svelte}}",
45
+ "svelte-check": "{{fullstack.packageSpecifiers.svelteCheck}}",
46
+ "svelte-eslint-parser": "{{fullstack.packageSpecifiers.svelteEslintParser}}",
47
+ "tailwindcss": "{{fullstack.packageSpecifiers.tailwindcss}}",
48
+ "typescript": "{{fullstack.packageSpecifiers.typescript}}",
49
+ "vite": "{{fullstack.packageSpecifiers.vite}}",
50
+ "vitest": "{{fullstack.packageSpecifiers.vitest}}"
48
51
  }
49
52
  }
50
53
  {{/if}}
@@ -0,0 +1,152 @@
1
+ {{! @skipIfEmpty }}
2
+ {{#if fullstack.frontends.desktop}}
3
+ <script lang="ts">
4
+ import type { AppInfo } from '{{fullstack.sharedPackageName}}'
5
+ import * as appM from './lib/paraglide/messages.js'
6
+ import { setLocale } from './lib/paraglide/runtime.js'
7
+ import { Alert, Button, Card, Skeleton } from '@h-ai/ui'
8
+ import { onMount } from 'svelte'
9
+ import { AppShell, fetchAppInfo, messages as sharedM } from '{{fullstack.sharedPackageName}}'
10
+
11
+ let info = $state<AppInfo | null>(null)
12
+ let loading = $state(true)
13
+ let errorMessage = $state('')
14
+
15
+ function syncLocale(locale: string) {
16
+ setLocale(locale as Parameters<typeof setLocale>[0])
17
+ }
18
+
19
+ async function refreshStatus() {
20
+ loading = true
21
+ errorMessage = ''
22
+ try {
23
+ info = await fetchAppInfo({ clientName: '{{projectName}}-desktop' })
24
+ }
25
+ catch {
26
+ info = null
27
+ errorMessage = sharedM.home_error()
28
+ }
29
+ finally {
30
+ loading = false
31
+ }
32
+ }
33
+
34
+ onMount(() => {
35
+ document.title = appM.page_title({ name: sharedM.app_name() })
36
+ void refreshStatus()
37
+ })
38
+ </script>
39
+
40
+ <AppShell platform="desktop" onLocaleChange={syncLocale}>
41
+ <section class="space-y-8">
42
+ <div class="grid gap-6 lg:grid-cols-[1.2fr_0.8fr]">
43
+ <section class="relative overflow-hidden rounded-[1.5rem] border border-base-300/70 bg-base-100 p-6 shadow-xl lg:p-10">
44
+ <div class="max-w-2xl space-y-6">
45
+ <span class="badge badge-primary badge-lg gap-2">
46
+ <span class="icon-[tabler--device-desktop] size-4"></span>
47
+ {appM.hero_badge()}
48
+ </span>
49
+ <div class="space-y-4">
50
+ <h1 class="text-4xl font-black tracking-tight text-base-content sm:text-5xl">
51
+ {appM.hero_title({ name: sharedM.app_name() })}
52
+ </h1>
53
+ <p class="max-w-xl text-lg leading-8 text-base-content/70">
54
+ {appM.hero_subtitle()}
55
+ </p>
56
+ </div>
57
+ <div class="flex flex-wrap gap-3">
58
+ <a class="btn btn-primary" href="#status">
59
+ <span class="icon-[tabler--activity-heartbeat] size-5"></span>
60
+ {appM.hero_primary_action()}
61
+ </a>
62
+ <a class="btn btn-ghost" href="#customize">
63
+ <span class="icon-[tabler--adjustments] size-5"></span>
64
+ {appM.hero_secondary_action()}
65
+ </a>
66
+ </div>
67
+ </div>
68
+ </section>
69
+
70
+ <aside class="rounded-[1.5rem] border border-base-300/70 bg-base-100 p-5 shadow-lg">
71
+ <div class="mockup-window border border-base-300 bg-base-200/70">
72
+ <div class="space-y-4 bg-base-100 p-5">
73
+ <div class="flex items-center justify-between">
74
+ <div>
75
+ <p class="text-sm font-semibold">{appM.preview_title()}</p>
76
+ <p class="text-xs text-base-content/55">{appM.preview_body()}</p>
77
+ </div>
78
+ <span class="badge badge-success badge-outline">{appM.platform_name()}</span>
79
+ </div>
80
+ <div class="grid gap-3 text-sm">
81
+ <div class="rounded-2xl bg-primary/10 p-4">
82
+ <span class="icon-[tabler--components] mb-2 size-6 text-primary"></span>
83
+ <p class="font-semibold">{appM.preview_metric_shared()}</p>
84
+ </div>
85
+ <div class="grid grid-cols-2 gap-3">
86
+ <div class="rounded-2xl bg-secondary/10 p-4">
87
+ <span class="icon-[tabler--language] mb-2 size-6 text-secondary"></span>
88
+ <p class="font-semibold">{appM.preview_metric_local()}</p>
89
+ </div>
90
+ <div class="rounded-2xl bg-accent/10 p-4">
91
+ <span class="icon-[tabler--palette] mb-2 size-6 text-accent"></span>
92
+ <p class="font-semibold">{appM.preview_metric_theme()}</p>
93
+ </div>
94
+ </div>
95
+ </div>
96
+ </div>
97
+ </div>
98
+ </aside>
99
+ </div>
100
+
101
+ <div class="grid gap-6 lg:grid-cols-[0.95fr_1.05fr]">
102
+ <div id="status">
103
+ <Card title={appM.status_title()} bordered shadow="md" class="bg-base-100">
104
+ <p class="mb-5 text-sm text-base-content/65">{appM.status_description()}</p>
105
+ {#if loading}
106
+ <Skeleton variant="title" class="mb-3" />
107
+ <Skeleton count={3} />
108
+ <p class="sr-only" data-testid="service-status">{sharedM.home_loading()}</p>
109
+ {:else if info}
110
+ <Alert variant="success" title={appM.status_online({ name: info.name })}>
111
+ <p data-testid="service-status">{info.name}</p>
112
+ </Alert>
113
+ <dl class="mt-5 grid gap-3 text-sm sm:grid-cols-2">
114
+ <div class="rounded-box border border-base-300/70 bg-base-200/60 p-4">
115
+ <dt class="text-xs text-base-content/55">{appM.status_version()}</dt>
116
+ <dd class="mt-1 font-semibold">{info.version}</dd>
117
+ </div>
118
+ <div class="rounded-box border border-base-300/70 bg-base-200/60 p-4">
119
+ <dt class="text-xs text-base-content/55">{appM.status_started({ time: info.startedAt })}</dt>
120
+ <dd class="mt-1 font-semibold">{appM.status_frontends_count({ count: String(info.frontends.length) })}</dd>
121
+ </div>
122
+ </dl>
123
+ {:else}
124
+ <Alert variant="error" title={sharedM.home_error()}>
125
+ <p data-testid="service-status">{errorMessage}</p>
126
+ </Alert>
127
+ {/if}
128
+
129
+ <div class="mt-5">
130
+ <Button type="button" variant="primary" loading={loading} onclick={refreshStatus}>
131
+ {sharedM.home_refresh()}
132
+ </Button>
133
+ </div>
134
+ </Card>
135
+ </div>
136
+
137
+ <section id="customize" class="grid gap-4 sm:grid-cols-2">
138
+ <div class="rounded-[1.5rem] border border-base-300/70 bg-base-100 p-5 shadow-md">
139
+ <span class="icon-[tabler--package] mb-4 size-7 text-primary"></span>
140
+ <h2 class="text-lg font-bold">{appM.custom_shared_title()}</h2>
141
+ <p class="mt-2 text-sm leading-6 text-base-content/65">{appM.custom_shared_body()}</p>
142
+ </div>
143
+ <div class="rounded-[1.5rem] border border-base-300/70 bg-base-100 p-5 shadow-md">
144
+ <span class="icon-[tabler--message-language] mb-4 size-7 text-secondary"></span>
145
+ <h2 class="text-lg font-bold">{appM.custom_local_title()}</h2>
146
+ <p class="mt-2 text-sm leading-6 text-base-content/65">{appM.custom_local_body()}</p>
147
+ </div>
148
+ </section>
149
+ </div>
150
+ </section>
151
+ </AppShell>
152
+ {{/if}}
@@ -1,9 +1,8 @@
1
1
  {{! @skipIfEmpty }}
2
2
  {{#if fullstack.frontends.desktop}}
3
- /// <reference types="@sveltejs/kit" />
4
3
  /// <reference types="vite/client" />
5
4
 
6
5
  import '@h-ai/ui/auto-import'
7
6
 
8
7
  declare module '*.css'
9
- {{/if}}
8
+ {{/if}}
@@ -0,0 +1,13 @@
1
+ {{! @skipIfEmpty }}
2
+ {{#if fullstack.frontends.desktop}}
3
+ import { mount } from 'svelte'
4
+ import App from './App.svelte'
5
+ import './app.css'
6
+
7
+ const target = document.getElementById('app')
8
+ if (!target) {
9
+ throw new Error('Root element #app not found')
10
+ }
11
+
12
+ export default mount(App, { target })
13
+ {{/if}}
@@ -0,0 +1,22 @@
1
+ {{! @skipIfEmpty }}
2
+ {{#if fullstack.frontends.desktop}}
3
+ [package]
4
+ name = "{{fullstack.nativeAppIdSegment}}_desktop"
5
+ version = "0.1.0"
6
+ description = "{{projectName}} Desktop App"
7
+ authors = ["hai"]
8
+ edition = "2021"
9
+
10
+ [lib]
11
+ name = "{{fullstack.nativeAppIdSegment}}_desktop_lib"
12
+ crate-type = ["staticlib", "cdylib", "rlib"]
13
+
14
+ [build-dependencies]
15
+ tauri-build = { version = "2", features = [] }
16
+
17
+ [dependencies]
18
+ tauri = { version = "2", features = [] }
19
+ tauri-plugin-shell = "2"
20
+ serde = { version = "1", features = ["derive"] }
21
+ serde_json = "1"
22
+ {{/if}}
@@ -0,0 +1,6 @@
1
+ {{! @skipIfEmpty }}
2
+ {{#if fullstack.frontends.desktop}}
3
+ fn main() {
4
+ tauri_build::build()
5
+ }
6
+ {{/if}}
@@ -0,0 +1,12 @@
1
+ {{! @skipIfEmpty }}
2
+ {{#if fullstack.frontends.desktop}}
3
+ {
4
+ "identifier": "default",
5
+ "description": "{{projectName}} Desktop 默认权限",
6
+ "windows": ["main"],
7
+ "permissions": [
8
+ "core:default",
9
+ "shell:allow-open"
10
+ ]
11
+ }
12
+ {{/if}}
@@ -0,0 +1,16 @@
1
+ {{! @skipIfEmpty }}
2
+ {{#if fullstack.frontends.desktop}}
3
+ #[tauri::command]
4
+ fn greet(name: &str) -> String {
5
+ format!("Hello, {}! Welcome to {{projectName}} Desktop.", name)
6
+ }
7
+
8
+ #[cfg_attr(mobile, tauri::mobile_entry_point)]
9
+ pub fn run() {
10
+ tauri::Builder::default()
11
+ .plugin(tauri_plugin_shell::init())
12
+ .invoke_handler(tauri::generate_handler![greet])
13
+ .run(tauri::generate_context!())
14
+ .expect("error while running tauri application");
15
+ }
16
+ {{/if}}
@@ -0,0 +1,8 @@
1
+ {{! @skipIfEmpty }}
2
+ {{#if fullstack.frontends.desktop}}
3
+ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
4
+
5
+ fn main() {
6
+ {{fullstack.nativeAppIdSegment}}_desktop_lib::run()
7
+ }
8
+ {{/if}}
@@ -0,0 +1,41 @@
1
+ {{! @skipIfEmpty }}
2
+ {{#if fullstack.frontends.desktop}}
3
+ {
4
+ "$schema": "https://schema.tauri.app/config/2",
5
+ "productName": "{{projectName}} Desktop",
6
+ "version": "0.1.0",
7
+ "identifier": "com.hai.{{fullstack.nativeAppIdSegment}}.desktop",
8
+ "build": {
9
+ "beforeDevCommand": "pnpm dev",
10
+ "beforeBuildCommand": "pnpm build",
11
+ "devUrl": "http://localhost:{{fullstack.ports.desktop}}",
12
+ "frontendDist": "../dist"
13
+ },
14
+ "app": {
15
+ "windows": [
16
+ {
17
+ "title": "{{projectName}} Desktop",
18
+ "width": 1280,
19
+ "height": 800,
20
+ "resizable": true,
21
+ "fullscreen": false,
22
+ "center": true
23
+ }
24
+ ],
25
+ "security": {
26
+ "csp": "default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self'; connect-src 'self' http://localhost:3000 http://127.0.0.1:3000 ws://localhost:* ws://127.0.0.1:*; font-src 'self' data:"
27
+ }
28
+ },
29
+ "bundle": {
30
+ "active": true,
31
+ "targets": "all",
32
+ "icon": [
33
+ "icons/32x32.png",
34
+ "icons/128x128.png",
35
+ "icons/128x128@2x.png",
36
+ "icons/icon.icns",
37
+ "icons/icon.ico"
38
+ ]
39
+ }
40
+ }
41
+ {{/if}}
@@ -1,20 +1,14 @@
1
1
  {{! @skipIfEmpty }}
2
2
  {{#if fullstack.frontends.desktop}}
3
3
  import { autoImportHaiUi } from '@h-ai/ui/auto-import'
4
- import adapter from '@sveltejs/adapter-auto'
5
4
  import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
6
5
 
7
- /** @type {import('@sveltejs/kit').Config} */
8
- const config = {
6
+ /** @type {import('@sveltejs/vite-plugin-svelte').SvelteConfig} */
7
+ export default {
9
8
  preprocess: [autoImportHaiUi(), vitePreprocess()],
10
9
  compilerOptions: {
11
10
  // 使用 Svelte 5 Runes,和 @h-ai/ui 组件库保持一致。
12
11
  runes: true,
13
12
  },
14
- kit: {
15
- adapter: adapter(),
16
- },
17
13
  }
18
-
19
- export default config
20
14
  {{/if}}
@@ -1,17 +1,22 @@
1
1
  {{! @skipIfEmpty }}
2
2
  {{#if fullstack.frontends.desktop}}
3
3
  {
4
- "extends": "./.svelte-kit/tsconfig.json",
5
4
  "compilerOptions": {
5
+ "target": "ES2022",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
7
+ "module": "ESNext",
6
8
  "moduleResolution": "bundler",
7
9
  "allowImportingTsExtensions": true,
8
10
  "allowJs": true,
9
11
  "checkJs": false,
10
12
  "strict": true,
13
+ "noEmit": true,
14
+ "isolatedModules": true,
11
15
  "verbatimModuleSyntax": true,
12
- "skipLibCheck": true
16
+ "skipLibCheck": true,
17
+ "types": ["svelte", "vite/client", "node", "vitest/globals"]
13
18
  },
14
- "include": ["src/**/*", "src/**/*.svelte", "tests/**/*"],
15
- "exclude": ["node_modules", ".svelte-kit", "build"]
19
+ "include": ["src/**/*.ts", "src/**/*.svelte", "tests/**/*.ts", "vite.config.ts", "svelte.config.js"],
20
+ "exclude": ["node_modules", "dist", "src-tauri/target"]
16
21
  }
17
22
  {{/if}}
@@ -1,29 +1,52 @@
1
1
  {{! @skipIfEmpty }}
2
2
  {{#if fullstack.frontends.desktop}}
3
+ import process from 'node:process'
3
4
  import { paraglideVitePlugin } from '@inlang/paraglide-js'
4
- import { sveltekit } from '@sveltejs/kit/vite'
5
+ import { svelte } from '@sveltejs/vite-plugin-svelte'
5
6
  import tailwindcss from '@tailwindcss/vite'
7
+ import { loadEnv } from 'vite'
6
8
  import { defineConfig } from 'vitest/config'
7
9
 
8
- export default defineConfig({
9
- plugins: [
10
- paraglideVitePlugin({
11
- project: './project.inlang',
12
- outdir: './src/lib/paraglide',
13
- strategy: ['cookie', 'baseLocale'],
14
- }),
15
- sveltekit(),
16
- tailwindcss(),
17
- ],
18
- optimizeDeps: {
19
- exclude: ['bits-ui'],
20
- },
21
- ssr: {
22
- noExternal: [/@h-ai\//, /{{fullstack.sharedPackageName}}/],
23
- },
24
- test: {
25
- environment: 'node',
26
- include: ['tests/**/*.test.ts'],
27
- },
10
+ const host = process.env.TAURI_DEV_HOST
11
+
12
+ export default defineConfig(({ mode }) => {
13
+ const env = loadEnv(mode, process.cwd(), '')
14
+ Object.assign(process.env, env)
15
+
16
+ return {
17
+ plugins: [
18
+ svelte(),
19
+ tailwindcss(),
20
+ paraglideVitePlugin({
21
+ project: './project.inlang',
22
+ outdir: './src/lib/paraglide',
23
+ strategy: ['cookie', 'baseLocale'],
24
+ }),
25
+ ],
26
+ clearScreen: false,
27
+ server: {
28
+ port: {{fullstack.ports.desktop}},
29
+ strictPort: true,
30
+ host: host || false,
31
+ hmr: host
32
+ ? {
33
+ protocol: 'ws',
34
+ host,
35
+ port: {{fullstack.ports.desktop}} + 1,
36
+ }
37
+ : undefined,
38
+ watch: {
39
+ ignored: ['**/src-tauri/**'],
40
+ },
41
+ },
42
+ optimizeDeps: {
43
+ exclude: ['@h-ai/ui', 'bits-ui'],
44
+ },
45
+ envPrefix: ['VITE_', 'PUBLIC_'],
46
+ test: {
47
+ environment: 'node',
48
+ include: ['tests/**/*.test.ts'],
49
+ },
50
+ }
28
51
  })
29
52
  {{/if}}
@@ -2,7 +2,7 @@
2
2
  {{#if fullstack.frontends.web}}
3
3
  # {{projectName}}-web
4
4
 
5
- Web 前端工程,使用 `@h-ai/api-client` 绑定共享 contract 调用后端 API,并通过 `@h-ai/ui` 组件搭建页面。
5
+ Web 前端工程,通过 `packages/{{fullstack.sharedPackageName}}` 调用后端 API,并通过 `@h-ai/ui` 组件搭建页面。
6
6
 
7
7
  ## i18n 与 shared 协同
8
8
 
@@ -12,10 +12,19 @@ Web 前端工程,使用 `@h-ai/api-client` 绑定共享 contract 调用后端
12
12
 
13
13
  自定义建议:Web 独有文案放在本目录 `messages/`;跨端通用文案或组件放到 shared。
14
14
 
15
- ## 开发
15
+ ## 编译、打包与部署
16
16
 
17
- - `pnpm i18n:compile`:在工作区根目录统一编译 shared + 各前端 Paraglide 输出
18
- - `pnpm --filter {{projectName}}-web dev`,默认端口 4173
19
- - `pnpm --filter {{projectName}}-web paraglide:compile`:只编译本端 messages
20
- - `pnpm --filter {{projectName}}-web test`
17
+ ```bash
18
+ # 开发预览,默认端口 {{fullstack.ports.web}}
19
+ pnpm --filter {{projectName}}-web dev
20
+
21
+ # 编译 Web 前端
22
+ pnpm --filter {{projectName}}-web build
23
+
24
+ # 打包部署产物;默认等同 build,可按目标平台替换
25
+ pnpm --filter {{projectName}}-web package
26
+
27
+ # 当前模板的 deploy 入口默认执行 package,可替换为 CDN / 容器发布脚本
28
+ pnpm --filter {{projectName}}-web deploy
29
+ ```
21
30
  {{/if}}
@@ -4,7 +4,7 @@ import antfu from '@antfu/eslint-config'
4
4
 
5
5
  export default antfu({
6
6
  formatters: true,
7
- ignores: ['**/.svelte-kit/**', '**/build/**', '**/dist/**', '**/*.d.ts', '**/project.inlang/**', '**/src/lib/paraglide/**'],
7
+ ignores: ['**/build/**', '**/dist/**', '**/*.d.ts', '**/project.inlang/**', '**/src/lib/paraglide/**'],
8
8
  svelte: true,
9
9
  }, {
10
10
  files: ['**/*.ts', '**/*.svelte'],
@@ -0,0 +1,15 @@
1
+ {{! @skipIfEmpty }}
2
+ {{#if fullstack.frontends.web}}
3
+ <!doctype html>
4
+ <html lang="{{fullstack.i18n.baseLocale}}">
5
+ <head>
6
+ <meta charset="UTF-8" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
8
+ <title>{{projectName}} Web</title>
9
+ </head>
10
+ <body>
11
+ <div id="app"></div>
12
+ <script type="module" src="/src/main.ts"></script>
13
+ </body>
14
+ </html>
15
+ {{/if}}
@@ -9,42 +9,40 @@
9
9
  "paraglide:compile": "paraglide-js compile --project ./project.inlang --outdir ./src/lib/paraglide",
10
10
  "paraglide:watch": "paraglide-js compile --project ./project.inlang --outdir ./src/lib/paraglide --watch",
11
11
  "dev": "vite dev --host 127.0.0.1 --port {{fullstack.ports.web}}",
12
- "build": "vite build",
12
+ "build": "pnpm paraglide:compile && vite build",
13
+ "package": "pnpm build",
14
+ "deploy": "pnpm package",
13
15
  "preview": "vite preview --host 127.0.0.1 --port {{fullstack.ports.web}} --strictPort",
14
- "typecheck": "pnpm paraglide:compile && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
16
+ "typecheck": "pnpm paraglide:compile && svelte-check --tsconfig ./tsconfig.json",
15
17
  "lint": "eslint .",
16
18
  "test": "vitest run",
17
19
  "test:watch": "vitest",
18
- "clean": "rimraf .svelte-kit build .turbo src/lib/paraglide"
20
+ "clean": "rimraf dist build .turbo src/lib/paraglide"
19
21
  },
20
22
  "dependencies": {
21
- "@h-ai/api-client": "{{fullstack.versions.apiClient}}",
22
- "@h-ai/ui": "{{fullstack.versions.ui}}",
23
- "{{fullstack.contractPackageName}}": "workspace:*",
23
+ "@h-ai/ui": "{{haiPackageSpecifier}}",
24
24
  "{{fullstack.sharedPackageName}}": "workspace:*"
25
25
  },
26
26
  "devDependencies": {
27
- "@antfu/eslint-config": "{{fullstack.versions.antfuEslintConfig}}",
28
- "@iconify-json/tabler": "{{fullstack.versions.iconifyJsonTabler}}",
29
- "@iconify/tailwind4": "{{fullstack.versions.iconifyTailwind}}",
30
- "@inlang/paraglide-js": "{{fullstack.versions.inlangParaglide}}",
31
- "@inlang/plugin-message-format": "{{fullstack.versions.inlangMessageFormat}}",
32
- "@sveltejs/adapter-auto": "{{fullstack.versions.adapterAuto}}",
33
- "@sveltejs/kit": "{{fullstack.versions.svelteKit}}",
34
- "@sveltejs/vite-plugin-svelte": "{{fullstack.versions.sveltePlugin}}",
35
- "@tailwindcss/vite": "{{fullstack.versions.tailwindcssVite}}",
36
- "bits-ui": "{{fullstack.versions.bitsUi}}",
37
- "daisyui": "{{fullstack.versions.daisyui}}",
38
- "eslint": "{{fullstack.versions.eslint}}",
39
- "eslint-plugin-format": "{{fullstack.versions.eslintPluginFormat}}",
40
- "eslint-plugin-svelte": "{{fullstack.versions.eslintPluginSvelte}}",
41
- "svelte": "{{fullstack.versions.svelte}}",
42
- "svelte-check": "{{fullstack.versions.svelteCheck}}",
43
- "svelte-eslint-parser": "{{fullstack.versions.svelteEslintParser}}",
44
- "tailwindcss": "{{fullstack.versions.tailwindcss}}",
45
- "typescript": "{{fullstack.versions.typescript}}",
46
- "vite": "{{fullstack.versions.vite}}",
47
- "vitest": "{{fullstack.versions.vitest}}"
27
+ "@antfu/eslint-config": "{{fullstack.packageSpecifiers.antfuEslintConfig}}",
28
+ "@iconify-json/tabler": "{{fullstack.packageSpecifiers.iconifyJsonTabler}}",
29
+ "@iconify/tailwind4": "{{fullstack.packageSpecifiers.iconifyTailwind}}",
30
+ "@inlang/paraglide-js": "{{fullstack.packageSpecifiers.inlangParaglide}}",
31
+ "@inlang/plugin-message-format": "{{fullstack.packageSpecifiers.inlangMessageFormat}}",
32
+ "@sveltejs/vite-plugin-svelte": "{{fullstack.packageSpecifiers.sveltePlugin}}",
33
+ "@tailwindcss/vite": "{{fullstack.packageSpecifiers.tailwindcssVite}}",
34
+ "bits-ui": "{{fullstack.packageSpecifiers.bitsUi}}",
35
+ "daisyui": "{{fullstack.packageSpecifiers.daisyui}}",
36
+ "eslint": "{{fullstack.packageSpecifiers.eslint}}",
37
+ "eslint-plugin-format": "{{fullstack.packageSpecifiers.eslintPluginFormat}}",
38
+ "eslint-plugin-svelte": "{{fullstack.packageSpecifiers.eslintPluginSvelte}}",
39
+ "svelte": "{{fullstack.packageSpecifiers.svelte}}",
40
+ "svelte-check": "{{fullstack.packageSpecifiers.svelteCheck}}",
41
+ "svelte-eslint-parser": "{{fullstack.packageSpecifiers.svelteEslintParser}}",
42
+ "tailwindcss": "{{fullstack.packageSpecifiers.tailwindcss}}",
43
+ "typescript": "{{fullstack.packageSpecifiers.typescript}}",
44
+ "vite": "{{fullstack.packageSpecifiers.vite}}",
45
+ "vitest": "{{fullstack.packageSpecifiers.vitest}}"
48
46
  }
49
47
  }
50
48
  {{/if}}