@fatdoge/wtree 0.1.0

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 (65) hide show
  1. package/README.en.md +113 -0
  2. package/README.md +136 -0
  3. package/api/app.ts +19 -0
  4. package/api/cli/wtree.ts +809 -0
  5. package/api/core/config.ts +26 -0
  6. package/api/core/exec.ts +55 -0
  7. package/api/core/git.ts +35 -0
  8. package/api/core/id.ts +8 -0
  9. package/api/core/open.ts +58 -0
  10. package/api/core/worktree.test.ts +33 -0
  11. package/api/core/worktree.ts +72 -0
  12. package/api/createApiApp.ts +33 -0
  13. package/api/index.ts +9 -0
  14. package/api/routes/worktrees.ts +255 -0
  15. package/api/server.ts +34 -0
  16. package/api/ui/startUiDev.ts +82 -0
  17. package/dist/assets/index-D9inyPb3.js +179 -0
  18. package/dist/assets/index-W34LSHWF.css +1 -0
  19. package/dist/favicon.svg +4 -0
  20. package/dist/index.html +354 -0
  21. package/dist-node/api/app.js +17 -0
  22. package/dist-node/api/cli/wtree.js +722 -0
  23. package/dist-node/api/cli/wtui.js +722 -0
  24. package/dist-node/api/core/config.js +21 -0
  25. package/dist-node/api/core/exec.js +24 -0
  26. package/dist-node/api/core/git.js +24 -0
  27. package/dist-node/api/core/id.js +6 -0
  28. package/dist-node/api/core/open.js +51 -0
  29. package/dist-node/api/core/worktree.js +58 -0
  30. package/dist-node/api/core/worktree.test.js +30 -0
  31. package/dist-node/api/createApiApp.js +26 -0
  32. package/dist-node/api/routes/worktrees.js +213 -0
  33. package/dist-node/api/server.js +29 -0
  34. package/dist-node/api/ui/startUiDev.js +65 -0
  35. package/dist-node/shared/wtui-types.js +1 -0
  36. package/index.html +24 -0
  37. package/package.json +89 -0
  38. package/postcss.config.js +10 -0
  39. package/shared/wtui-types.ts +36 -0
  40. package/src/App.tsx +28 -0
  41. package/src/assets/react.svg +1 -0
  42. package/src/components/Button.tsx +34 -0
  43. package/src/components/Empty.tsx +8 -0
  44. package/src/components/Input.tsx +16 -0
  45. package/src/components/Modal.tsx +33 -0
  46. package/src/components/ToastHost.tsx +42 -0
  47. package/src/hooks/useTheme.ts +29 -0
  48. package/src/i18n/index.ts +22 -0
  49. package/src/i18n/locales/en.json +145 -0
  50. package/src/i18n/locales/zh.json +145 -0
  51. package/src/index.css +24 -0
  52. package/src/lib/utils.ts +6 -0
  53. package/src/main.tsx +11 -0
  54. package/src/pages/CreateWorktree.tsx +181 -0
  55. package/src/pages/HelpPage.tsx +67 -0
  56. package/src/pages/Home.tsx +3 -0
  57. package/src/pages/SettingsPage.tsx +218 -0
  58. package/src/pages/Worktrees.tsx +354 -0
  59. package/src/stores/themeStore.ts +44 -0
  60. package/src/stores/toastStore.ts +29 -0
  61. package/src/stores/worktreeStore.ts +93 -0
  62. package/src/utils/api.ts +36 -0
  63. package/src/vite-env.d.ts +1 -0
  64. package/tailwind.config.js +13 -0
  65. package/vite.config.ts +46 -0
@@ -0,0 +1,82 @@
1
+ import os from 'node:os'
2
+ import path from 'node:path'
3
+ import fs from 'node:fs'
4
+ import { fileURLToPath } from 'node:url'
5
+ import { createServer } from 'vite'
6
+ import type { ViteDevServer } from 'vite'
7
+ import { createApiApp } from '../createApiApp.js'
8
+ import { openPath } from '../core/open.js'
9
+
10
+ function findUiRoot(fromDir: string) {
11
+ let cur = fromDir
12
+ for (let i = 0; i < 10; i += 1) {
13
+ const indexHtml = path.join(cur, 'index.html')
14
+ const viteConfig = path.join(cur, 'vite.config.ts')
15
+ if (exists(indexHtml) && exists(viteConfig)) return cur
16
+ const parent = path.dirname(cur)
17
+ if (parent === cur) break
18
+ cur = parent
19
+ }
20
+ return fromDir
21
+ }
22
+
23
+ function exists(p: string) {
24
+ return fs.existsSync(p)
25
+ }
26
+
27
+ export type UiDevHandle = {
28
+ uiUrl: string
29
+ close: () => Promise<void>
30
+ }
31
+
32
+ export async function startUiDevServer(options: {
33
+ repoRoot: string
34
+ uiPort?: number
35
+ open?: boolean
36
+ }) : Promise<UiDevHandle> {
37
+ const repoRoot = options.repoRoot
38
+ const open = options.open !== false
39
+ const uiPort = Number.isFinite(options.uiPort) ? (options.uiPort as number) : 5173
40
+
41
+ const apiApp = createApiApp(() => repoRoot)
42
+ const apiServer = apiApp.listen(0, '127.0.0.1')
43
+ await new Promise<void>((resolve) => apiServer.once('listening', () => resolve()))
44
+ const apiAddress = apiServer.address()
45
+ const apiPort = typeof apiAddress === 'object' && apiAddress ? apiAddress.port : 0
46
+ process.env.WTUI_API_URL = `http://127.0.0.1:${apiPort}`
47
+ process.env.VITE_WTUI_API_URL = process.env.WTUI_API_URL
48
+
49
+ const here = path.dirname(fileURLToPath(import.meta.url))
50
+ const uiRoot = findUiRoot(path.resolve(here, '..', '..'))
51
+ const prevCwd = process.cwd()
52
+ process.chdir(uiRoot)
53
+
54
+ const vite: ViteDevServer = await createServer({
55
+ root: uiRoot,
56
+ configFile: path.join(uiRoot, 'vite.config.ts'),
57
+ cacheDir: path.join(os.tmpdir(), 'wtui-vite-cache'),
58
+ server: {
59
+ host: '127.0.0.1',
60
+ port: uiPort,
61
+ strictPort: false,
62
+ },
63
+ clearScreen: false,
64
+ appType: 'spa',
65
+ })
66
+
67
+ await vite.listen()
68
+ const url = vite.resolvedUrls?.local?.[0] || `http://127.0.0.1:${uiPort}/`
69
+
70
+ if (open) {
71
+ openPath(url)
72
+ }
73
+
74
+ return {
75
+ uiUrl: url,
76
+ close: async () => {
77
+ await vite.close()
78
+ await new Promise<void>((resolve) => apiServer.close(() => resolve()))
79
+ process.chdir(prevCwd)
80
+ },
81
+ }
82
+ }