create-gui 8.2.1 → 8.3.2

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 (125) hide show
  1. package/dist/cjs/create-gui-constants.js +5 -0
  2. package/dist/cjs/create-gui-constants.js.map +1 -0
  3. package/dist/cjs/helpers/asciiArts.js +43 -0
  4. package/dist/cjs/helpers/asciiArts.js.map +1 -0
  5. package/dist/cjs/helpers/cloneStarter.js +192 -0
  6. package/dist/cjs/helpers/cloneStarter.js.map +1 -0
  7. package/dist/cjs/helpers/getProjectName.js +46 -0
  8. package/dist/cjs/helpers/getProjectName.js.map +1 -0
  9. package/dist/cjs/helpers/getTemplateInfo.js +31 -0
  10. package/dist/cjs/helpers/getTemplateInfo.js.map +1 -0
  11. package/dist/cjs/helpers/installDependencies.js +26 -0
  12. package/dist/cjs/helpers/installDependencies.js.map +1 -0
  13. package/dist/cjs/helpers/rainbowChalk.js +20 -0
  14. package/dist/cjs/helpers/rainbowChalk.js.map +1 -0
  15. package/dist/cjs/helpers/validateNpmPackage.js +16 -0
  16. package/dist/cjs/helpers/validateNpmPackage.js.map +1 -0
  17. package/dist/cjs/here.js +6 -0
  18. package/dist/cjs/here.js.map +1 -0
  19. package/dist/cjs/index.js +165 -0
  20. package/dist/cjs/index.js.map +1 -0
  21. package/dist/cjs/manifest.js +8 -0
  22. package/dist/cjs/manifest.js.map +1 -0
  23. package/dist/cjs/package.json +1 -0
  24. package/dist/cjs/steps/expo-router.js +18 -0
  25. package/dist/cjs/steps/expo-router.js.map +1 -0
  26. package/dist/cjs/steps/remix.js +22 -0
  27. package/dist/cjs/steps/remix.js.map +1 -0
  28. package/dist/cjs/steps/starter-free.js +35 -0
  29. package/dist/cjs/steps/starter-free.js.map +1 -0
  30. package/dist/cjs/steps/takeout.js +174 -0
  31. package/dist/cjs/steps/takeout.js.map +1 -0
  32. package/dist/cjs/steps/types.js +3 -0
  33. package/dist/cjs/steps/types.js.map +1 -0
  34. package/dist/cjs/templates.js +97 -0
  35. package/dist/cjs/templates.js.map +1 -0
  36. package/dist/esm/create-gui-constants.js +2 -0
  37. package/dist/esm/create-gui-constants.js.map +1 -0
  38. package/dist/esm/helpers/asciiArts.js +39 -0
  39. package/dist/esm/helpers/asciiArts.js.map +1 -0
  40. package/dist/esm/helpers/cloneStarter.js +187 -0
  41. package/dist/esm/helpers/cloneStarter.js.map +1 -0
  42. package/dist/esm/helpers/getProjectName.js +41 -0
  43. package/dist/esm/helpers/getProjectName.js.map +1 -0
  44. package/dist/esm/helpers/getTemplateInfo.js +26 -0
  45. package/dist/esm/helpers/getTemplateInfo.js.map +1 -0
  46. package/dist/esm/helpers/installDependencies.js +22 -0
  47. package/dist/esm/helpers/installDependencies.js.map +1 -0
  48. package/dist/esm/helpers/rainbowChalk.js +15 -0
  49. package/dist/esm/helpers/rainbowChalk.js.map +1 -0
  50. package/dist/esm/helpers/validateNpmPackage.js +12 -0
  51. package/dist/esm/helpers/validateNpmPackage.js.map +1 -0
  52. package/dist/esm/here.js +3 -0
  53. package/dist/esm/here.js.map +1 -0
  54. package/dist/esm/index.js +162 -0
  55. package/dist/esm/index.js.map +1 -0
  56. package/dist/esm/manifest.js +5 -0
  57. package/dist/esm/manifest.js.map +1 -0
  58. package/dist/esm/steps/expo-router.js +15 -0
  59. package/dist/esm/steps/expo-router.js.map +1 -0
  60. package/dist/esm/steps/remix.js +19 -0
  61. package/dist/esm/steps/remix.js.map +1 -0
  62. package/dist/esm/steps/starter-free.js +32 -0
  63. package/dist/esm/steps/starter-free.js.map +1 -0
  64. package/dist/esm/steps/takeout.js +171 -0
  65. package/dist/esm/steps/takeout.js.map +1 -0
  66. package/dist/esm/steps/types.js +2 -0
  67. package/dist/esm/steps/types.js.map +1 -0
  68. package/dist/esm/templates.js +93 -0
  69. package/dist/esm/templates.js.map +1 -0
  70. package/package.json +38 -30
  71. package/src/create-gui-constants.ts +1 -0
  72. package/src/helpers/asciiArts.ts +49 -0
  73. package/src/helpers/cloneStarter.ts +220 -0
  74. package/src/helpers/getProjectName.ts +48 -0
  75. package/src/helpers/getTemplateInfo.ts +34 -0
  76. package/src/helpers/installDependencies.ts +23 -0
  77. package/src/helpers/rainbowChalk.ts +17 -0
  78. package/src/helpers/validateNpmPackage.ts +16 -0
  79. package/src/here.cjs.ts +3 -0
  80. package/src/here.ts +2 -0
  81. package/src/index.ts +223 -0
  82. package/src/manifest.ts +10 -0
  83. package/src/steps/expo-router.ts +20 -0
  84. package/src/steps/remix.ts +24 -0
  85. package/src/steps/starter-free.ts +40 -0
  86. package/src/steps/takeout.ts +210 -0
  87. package/src/steps/types.ts +5 -0
  88. package/src/templates.ts +116 -0
  89. package/types/create-gui-constants.d.ts +2 -0
  90. package/types/create-gui-constants.d.ts.map +1 -0
  91. package/types/helpers/asciiArts.d.ts +5 -0
  92. package/types/helpers/asciiArts.d.ts.map +1 -0
  93. package/types/helpers/cloneStarter.d.ts +3 -0
  94. package/types/helpers/cloneStarter.d.ts.map +1 -0
  95. package/types/helpers/getProjectName.d.ts +2 -0
  96. package/types/helpers/getProjectName.d.ts.map +1 -0
  97. package/types/helpers/getTemplateInfo.d.ts +3 -0
  98. package/types/helpers/getTemplateInfo.d.ts.map +1 -0
  99. package/types/helpers/installDependencies.d.ts +2 -0
  100. package/types/helpers/installDependencies.d.ts.map +1 -0
  101. package/types/helpers/rainbowChalk.d.ts +3 -0
  102. package/types/helpers/rainbowChalk.d.ts.map +1 -0
  103. package/types/helpers/validateNpmPackage.d.ts +5 -0
  104. package/types/helpers/validateNpmPackage.d.ts.map +1 -0
  105. package/types/here.d.ts +2 -0
  106. package/types/here.d.ts.map +1 -0
  107. package/types/index.d.ts +3 -0
  108. package/types/index.d.ts.map +1 -0
  109. package/types/manifest.d.ts +5 -0
  110. package/types/manifest.d.ts.map +1 -0
  111. package/types/steps/expo-router.d.ts +4 -0
  112. package/types/steps/expo-router.d.ts.map +1 -0
  113. package/types/steps/remix.d.ts +4 -0
  114. package/types/steps/remix.d.ts.map +1 -0
  115. package/types/steps/starter-free.d.ts +4 -0
  116. package/types/steps/starter-free.d.ts.map +1 -0
  117. package/types/steps/takeout.d.ts +4 -0
  118. package/types/steps/takeout.d.ts.map +1 -0
  119. package/types/steps/types.d.ts +6 -0
  120. package/types/steps/types.d.ts.map +1 -0
  121. package/types/templates.d.ts +16 -0
  122. package/types/templates.d.ts.map +1 -0
  123. package/dist/index.cjs +0 -929
  124. package/dist/index.native.js +0 -930
  125. package/run.js +0 -12
@@ -0,0 +1,93 @@
1
+ import chalk from 'chalk';
2
+ import expoRouterSteps from './steps/expo-router.js';
3
+ import remixSteps from './steps/remix.js';
4
+ import starterFree from './steps/starter-free.js';
5
+ import takeoutSteps from './steps/takeout.js';
6
+ export const templates = [
7
+ {
8
+ title: `${chalk.bold.underline(`🥡 ${chalk.magenta('Takeout')} ${chalk.green('Free')}`)} - Full stack starter: https://hanzogui.dev/takeout`,
9
+ value: 'takeout-free',
10
+ type: 'free',
11
+ hidden: false,
12
+ packageManager: 'bun',
13
+ repo: {
14
+ url: `https://github.com/hanzogui/takeout-free`,
15
+ sshFallback: `git@github.com:hanzogui/takeout-free.git`,
16
+ dir: [],
17
+ branch: 'main',
18
+ },
19
+ extraSteps: starterFree,
20
+ },
21
+ {
22
+ title: `${chalk.bold.underline(`🥡 ${chalk.magenta('Takeout')} ${chalk.red('Pro')}`)} - Full featured starter: https://hanzogui.dev/takeout`,
23
+ value: `takeout-pro`,
24
+ type: 'premium',
25
+ packageManager: 'yarn',
26
+ hidden: false,
27
+ repo: {
28
+ url: `https://github.com/hanzogui/takeout2`,
29
+ sshFallback: `git@github.com:hanzogui/takeout2.git`,
30
+ dir: [],
31
+ branch: 'main',
32
+ },
33
+ extraSteps: takeoutSteps,
34
+ },
35
+ {
36
+ title: `${chalk.bold.underline(`🥡 ${chalk.magenta('Takeout')} ${chalk.yellow('Pro Classic')}`)} - Original Pro starter: https://hanzogui.dev/takeout`,
37
+ value: `takeout-pro-classic`,
38
+ type: 'premium',
39
+ packageManager: 'yarn',
40
+ hidden: false,
41
+ repo: {
42
+ url: `https://github.com/hanzogui/takeout`,
43
+ sshFallback: `git@github.com:hanzogui/takeout.git`,
44
+ dir: [],
45
+ branch: 'main',
46
+ },
47
+ extraSteps: takeoutSteps,
48
+ },
49
+ {
50
+ title: `Expo Router - Expo with file-based routing`,
51
+ value: 'expo-router',
52
+ type: 'free',
53
+ hidden: false,
54
+ packageManager: 'bun',
55
+ repo: {
56
+ url: `https://github.com/hanzoai/gui`,
57
+ sshFallback: `git@github.com:hanzoai/gui.git`,
58
+ dir: ['apps', 'starters', 'expo-router'],
59
+ branch: 'main',
60
+ },
61
+ extraSteps: expoRouterSteps,
62
+ },
63
+ {
64
+ title: `Remix - Remix with Vite`,
65
+ value: 'remix',
66
+ type: 'free',
67
+ hidden: false,
68
+ packageManager: 'bun',
69
+ repo: {
70
+ url: `https://github.com/hanzoai/gui`,
71
+ sshFallback: `git@github.com:hanzoai/gui.git`,
72
+ dir: ['apps', 'starters', 'remix'],
73
+ branch: 'main',
74
+ },
75
+ extraSteps: remixSteps,
76
+ },
77
+ {
78
+ title: `Next + Expo - Production ready monorepo`,
79
+ value: 'starter-free',
80
+ type: 'free',
81
+ hidden: false,
82
+ packageManager: 'yarn',
83
+ repo: {
84
+ url: process.env.STARTER_FREE_REPO_SOURCE ||
85
+ `https://github.com/hanzogui/starter-free.git`,
86
+ sshFallback: `git@github.com:hanzogui/starter-free.git`,
87
+ dir: [],
88
+ branch: 'main',
89
+ },
90
+ extraSteps: starterFree,
91
+ },
92
+ ];
93
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/templates.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,56 +1,64 @@
1
1
  {
2
2
  "name": "create-gui",
3
- "version": "8.2.1",
3
+ "version": "8.3.2",
4
4
  "gitHead": "a49cc7ea6b93ba384e77a4880ae48ac4a5635c14",
5
5
  "bin": {
6
- "create-gui": "run.js"
6
+ "create-gui": "./dist/esm/index.js"
7
7
  },
8
8
  "files": [
9
- "run.js",
9
+ "src",
10
+ "types",
10
11
  "dist"
11
12
  ],
13
+ "type": "module",
12
14
  "sideEffects": false,
13
- "main": "dist/index.cjs",
15
+ "main": "./dist/cjs/index.js",
16
+ "module": "./dist/esm/index.js",
17
+ "types": "./types/index.d.ts",
18
+ "exports": {
19
+ "./package.json": "./package.json",
20
+ ".": {
21
+ "types": "./types/index.d.ts",
22
+ "react-native": "./dist/esm/index.js",
23
+ "browser": "./dist/esm/index.js",
24
+ "module": "./dist/esm/index.js",
25
+ "import": "./dist/esm/index.js",
26
+ "require": "./dist/cjs/index.js",
27
+ "default": "./dist/esm/index.js"
28
+ }
29
+ },
14
30
  "publishConfig": {
15
31
  "access": "public"
16
32
  },
17
33
  "scripts": {
18
- "start": "./run.js",
19
- "//": "disabling for now need to migrate to new stack",
20
- "test-disabled": "NODE_ENV=test node -r esbuild-register ../../../node_modules/.bin/playwright test integration.test.ts",
21
- "test:debug": "bun run test --debug",
22
- "test": "bun run build:test && vitest run",
34
+ "build": "hanzogui-build --skip-native",
35
+ "test": "bun run build && vitest run",
23
36
  "test:web": "bun run test",
24
- "build:test": "bun run build",
25
- "prerelease": "rimraf ./dist/",
26
- "prepublish": "bun run build",
27
- "build": "hanzogui-build --skip-types --bundle",
28
- "watch": "bun run build --watch",
29
37
  "clean": "hanzogui-build clean",
30
38
  "clean:build": "hanzogui-build clean:build"
31
39
  },
32
40
  "dependencies": {
33
- "@expo/package-manager": "^1.1.2",
34
- "chalk": "^4.1.2",
35
- "commander": "2.20.0",
36
- "detect-package-manager": "^3.0.1",
37
- "fs-extra": "^11.2.0",
41
+ "@expo/package-manager": "^1.13.1",
42
+ "chalk": "^6.0.0",
43
+ "commander": "^15.0.0",
44
+ "detect-package-manager": "^3.0.2",
45
+ "fs-extra": "^11.4.0",
38
46
  "opener": "^1.5.2",
39
- "prompts": "2.1.0",
40
- "rimraf": "^5.0.1",
41
- "validate-npm-package-name": "3.0.0"
47
+ "prompts": "^2.4.2",
48
+ "rimraf": "^6.1.3",
49
+ "validate-npm-package-name": "^8.0.0"
42
50
  },
43
51
  "devDependencies": {
44
- "@playwright/test": "^1.49.1",
45
- "@hanzogui/build": "8.2.1",
46
- "@types/node": "^22.1.0",
52
+ "@hanzogui/build": "8.3.2",
53
+ "@playwright/test": "^1.62.1",
54
+ "@types/node": "26.4.0",
47
55
  "@types/opener": "^1.4.3",
48
- "@types/prompts": "2.0.1",
49
- "@types/rimraf": "3.0.0",
50
- "@types/validate-npm-package-name": "3.0.0",
56
+ "@types/prompts": "^2.4.9",
57
+ "@types/rimraf": "^4.0.5",
58
+ "@types/validate-npm-package-name": "^4.0.2",
51
59
  "esbuild-register": "^3.6.0",
52
- "tempy": "^3.1.0",
53
- "vitest": "4.0.4"
60
+ "tempy": "^3.2.0",
61
+ "vitest": "^4.1.11"
54
62
  },
55
63
  "repository": {
56
64
  "type": "git",
@@ -0,0 +1 @@
1
+ export const IS_TEST = process.env.NODE_ENV === 'test'
@@ -0,0 +1,49 @@
1
+ import chalk from 'chalk'
2
+
3
+ import { rainbowColors } from './rainbowChalk.ts'
4
+
5
+ export const hanzoguiAsciiArt = `▀█▀ ▄▀█ █▀▄▀█ ▄▀█ █▀▀ █ █ █
6
+ █  █▀█ █ ▀ █ █▀█ █▄█ █▄█ █`
7
+
8
+ export const hanzoguiRainbowAsciiArt = (function () {
9
+ const char0_1 = chalk.hex(rainbowColors[0])('▀█▀')
10
+ const char0_2 = chalk.hex(rainbowColors[0])(' █ ')
11
+
12
+ const char1_1 = chalk.hex(rainbowColors[1])('▄▀█')
13
+ const char1_2 = chalk.hex(rainbowColors[1])('█▀█')
14
+
15
+ const char2_1 = chalk.hex(rainbowColors[2])('█▀▄▀█')
16
+ const char2_2 = chalk.hex(rainbowColors[2])('█ ▀ █')
17
+
18
+ const char3_1 = chalk.hex(rainbowColors[3])('▄▀█')
19
+ const char3_2 = chalk.hex(rainbowColors[3])('█▀█')
20
+
21
+ const char4_1 = chalk.hex(rainbowColors[4])('█▀▀')
22
+ const char4_2 = chalk.hex(rainbowColors[4])('█▄█')
23
+
24
+ const char5_1 = chalk.hex(rainbowColors[5])('█ █')
25
+ const char5_2 = chalk.hex(rainbowColors[5])('█▄█')
26
+
27
+ const char6_1 = chalk.hex(rainbowColors[6])('█')
28
+ const char6_2 = chalk.hex(rainbowColors[6])('█')
29
+ return `${char0_1} ${char1_1} ${char2_1} ${char3_1} ${char4_1} ${char5_1} ${char6_1}
30
+ ${char0_2} ${char1_2} ${char2_2} ${char3_2} ${char4_2} ${char5_2} ${char6_2}
31
+ `
32
+ })()
33
+
34
+ export const takeoutAsciiArt = `████████╗░█████╗░██╗░░██╗███████╗░█████╗░██╗░░░██╗████████╗
35
+ ╚══██╔══╝██╔══██╗██║░██╔╝██╔════╝██╔══██╗██║░░░██║╚══██╔══╝
36
+ ░░░██║░░░███████║█████═╝░█████╗░░██║░░██║██║░░░██║░░░██║░░░
37
+ ░░░██║░░░██╔══██║██╔═██╗░██╔══╝░░██║░░██║██║░░░██║░░░██║░░░
38
+ ░░░██║░░░██║░░██║██║░╚██╗███████╗╚█████╔╝╚██████╔╝░░░██║░░░
39
+ ░░░╚═╝░░░╚═╝░░╚═╝╚═╝░░╚═╝╚══════╝░╚════╝░░╚═════╝░░░░╚═╝░░░`
40
+
41
+ export const hanzoguiDuckAsciiArt = ` ████████████
42
+ ██ ██
43
+ ██ ██ ██████
44
+ ██ ██ ██
45
+ ██ ████████
46
+ ██ ██
47
+ ██ ████
48
+ ██ ██
49
+ ██ ██ `
@@ -0,0 +1,220 @@
1
+ import { execSync } from 'node:child_process'
2
+ import { readFileSync, writeFileSync } from 'node:fs'
3
+ import { homedir } from 'node:os'
4
+ import { join } from 'node:path'
5
+ import chalk from 'chalk'
6
+ import { copy, ensureDir, pathExists, remove } from 'fs-extra/esm'
7
+ import { rimraf } from 'rimraf'
8
+ import type { templates } from '../templates.ts'
9
+ import open from 'opener'
10
+
11
+ const exec = (cmd: string, options?: Parameters<typeof execSync>[1]) => {
12
+ console.info(`$ `, cmd)
13
+ return execSync(cmd, {
14
+ stdio: process.env.DEBUG ? 'inherit' : 'ignore',
15
+ ...options,
16
+ })
17
+ }
18
+
19
+ const hanzoguiDir = join(homedir(), '.hanzogui-repo-cache')
20
+ let targetGitDir = ''
21
+
22
+ export const cloneStarter = async (
23
+ template: (typeof templates)[number],
24
+ resolvedProjectPath: string,
25
+ projectName: string
26
+ ) => {
27
+ targetGitDir = join(hanzoguiDir, 'hanzogui', template.repo.url.split('/').at(-1)!)
28
+
29
+ console.info()
30
+ await setupGuiDotDir(template)
31
+ const starterDir = join(targetGitDir, ...template.repo.dir)
32
+ console.info()
33
+ console.info(
34
+ `Copying starter from ${starterDir} into ${chalk.blueBright(projectName)}...`
35
+ )
36
+ console.info()
37
+
38
+ // if (!(await pathExists(starterDir))) {
39
+ // console.error(`Missing template for ${template.value} in ${starterDir}`)
40
+ // process.exit(1)
41
+ // }
42
+ await copy(starterDir, resolvedProjectPath)
43
+ await rimraf(`${resolvedProjectPath}/.git`)
44
+
45
+ // rewrite workspace:* versions to real published versions
46
+ rewriteWorkspaceVersions(resolvedProjectPath)
47
+
48
+ console.info(chalk.green(`${projectName} created!`))
49
+ console.info()
50
+ }
51
+
52
+ async function setupGuiDotDir(template: (typeof templates)[number]) {
53
+ console.info(`Setting up ${chalk.blueBright(targetGitDir)}...`)
54
+
55
+ if (process.env.GITHUB_HEAD_REF) {
56
+ try {
57
+ execSync(`git switch -c ${process.env.GITHUB_HEAD_REF}`, {
58
+ cwd: targetGitDir,
59
+ stdio: 'ignore',
60
+ })
61
+ } catch {
62
+ // re-tries branch already exists
63
+ }
64
+ }
65
+
66
+ const branch = template.repo.branch
67
+
68
+ await ensureDir(hanzoguiDir)
69
+
70
+ const isInSubDir = template.repo.dir.length > 0
71
+ const sourceGitRepo = template.repo.url
72
+ const sourceGitRepoSshFallback = template.repo.sshFallback
73
+
74
+ if (!(await pathExists(targetGitDir))) {
75
+ console.info(`Cloning hanzogui base directory`)
76
+ console.info()
77
+
78
+ const cmd = `git clone --branch ${branch} ${
79
+ isInSubDir ? '--depth 1 --sparse --filter=blob:none ' : ''
80
+ }${sourceGitRepo} "${targetGitDir}"`
81
+
82
+ try {
83
+ try {
84
+ console.info(`$ ${cmd}`)
85
+ console.info()
86
+ exec(cmd)
87
+ } catch (error) {
88
+ if (cmd.includes('https://')) {
89
+ console.info(`https failed - trying with ssh now...`)
90
+ const sshCmd = cmd.replace(sourceGitRepo, sourceGitRepoSshFallback)
91
+ console.info(`$ ${sshCmd}`)
92
+ console.info()
93
+ exec(sshCmd)
94
+ } else {
95
+ throw error
96
+ }
97
+ }
98
+ } catch (error) {
99
+ if (error instanceof Error) {
100
+ if (
101
+ template.value === 'takeout-pro' ||
102
+ template.value === 'takeout-pro-classic'
103
+ ) {
104
+ if ((error as any)?.stderr?.includes('Repository not found')) {
105
+ console.info(
106
+ chalk.yellow(
107
+ `You don't have access to this starter. Check 🥡 Gui Takeout (https://hanzogui.dev/takeout) for more info.`
108
+ )
109
+ )
110
+ open('https://hanzogui.dev/takeout')
111
+ process.exit(0)
112
+ }
113
+ }
114
+ }
115
+ throw error
116
+ }
117
+ } else {
118
+ if (!(await pathExists(join(targetGitDir, '.git')))) {
119
+ console.error(`Corrupt Gui directory, please delete ${targetGitDir} and re-run`)
120
+ process.exit(1)
121
+ }
122
+ }
123
+
124
+ if (isInSubDir) {
125
+ const cmd = `git sparse-checkout set apps/starters`
126
+ exec(cmd, { cwd: targetGitDir })
127
+ console.info()
128
+ }
129
+
130
+ try {
131
+ const remoteName = getDefaultRemoteName()
132
+ if (await pathExists(join(targetGitDir, '.git'))) {
133
+ const cmd2 = `git pull --rebase --allow-unrelated-histories --depth 1 ${remoteName} ${branch}`
134
+
135
+ // this can fail with "could not parse commit" but if you re-run it generally works
136
+ try {
137
+ exec(cmd2, {
138
+ cwd: targetGitDir,
139
+ })
140
+ } catch {
141
+ // so lets just retry on first failure at least
142
+ exec(cmd2, {
143
+ cwd: targetGitDir,
144
+ })
145
+ }
146
+ console.info()
147
+ } else {
148
+ console.warn(
149
+ `Warning: ${targetGitDir} is not a git repository. Skipping pull operation.`
150
+ )
151
+ }
152
+ } catch (err: any) {
153
+ await remove(targetGitDir)
154
+ console.info(`Error updating: ${err.message} ${err.stack}`)
155
+ console.info(
156
+ `We removed the old template cache, so re-running may fix. If not, please file an issue: https://github.com/hanzoai/gui/issues/new?assignees=&labels=&template=bug_report.md&title=`
157
+ )
158
+ process.exit(1)
159
+ }
160
+ }
161
+
162
+ function rewriteWorkspaceVersions(projectPath: string) {
163
+ const pkgPath = join(projectPath, 'package.json')
164
+ try {
165
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))
166
+
167
+ // if the copied project is itself a workspace root (e.g. takeout-pro copies
168
+ // the whole monorepo, packages/* included), leave `workspace:*` alone —
169
+ // bun/yarn/pnpm resolve it natively against the local packages. rewriting
170
+ // would point at versions that don't exist on npm.
171
+ if (pkg.workspaces) {
172
+ return
173
+ }
174
+
175
+ // read create-gui's own version as the target
176
+ const ctPkgPath = require.resolve('create-gui/package.json')
177
+ const ctPkg = JSON.parse(readFileSync(ctPkgPath, 'utf-8'))
178
+ const version = `^${ctPkg.version}`
179
+
180
+ let changed = false
181
+ for (const field of ['dependencies', 'devDependencies'] as const) {
182
+ const deps = pkg[field]
183
+ if (!deps) continue
184
+ for (const [key, val] of Object.entries(deps)) {
185
+ if (val === 'workspace:*') {
186
+ deps[key] = version
187
+ changed = true
188
+ }
189
+ }
190
+ }
191
+
192
+ if (changed) {
193
+ writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
194
+ console.info(chalk.dim(` Rewrote workspace:* → ${version}`))
195
+ }
196
+ } catch {
197
+ // non-fatal, user can fix manually
198
+ }
199
+ }
200
+
201
+ // Get the default remote name
202
+ const getDefaultRemoteName = () => {
203
+ try {
204
+ if (!pathExists(join(targetGitDir, '.git'))) {
205
+ console.warn(
206
+ 'Warning: Not in a git repository. Using default remote name "origin".'
207
+ )
208
+ return 'origin'
209
+ }
210
+ const remotes = execSync('git remote', { cwd: targetGitDir })
211
+ .toString()
212
+ .trim()
213
+ .split('\n')
214
+ return remotes[0] || 'origin'
215
+ } catch (error) {
216
+ console.warn('Error getting default remote name:', error)
217
+ console.warn('Using default remote name "origin".')
218
+ return 'origin'
219
+ }
220
+ }
@@ -0,0 +1,48 @@
1
+ import path from 'node:path'
2
+
3
+ import chalk from 'chalk'
4
+ import prompts from 'prompts'
5
+
6
+ import { validateNpmName } from './validateNpmPackage.ts'
7
+ import { packageJson } from '../manifest.ts'
8
+
9
+ export const getProjectName = async (projectPath?: string) => {
10
+ if (typeof projectPath === 'string') {
11
+ projectPath = projectPath.trim()
12
+ }
13
+
14
+ if (!projectPath) {
15
+ const res = await prompts({
16
+ type: 'text',
17
+ name: 'path',
18
+ message: 'Project name:',
19
+ initial: 'myapp',
20
+ validate: (name) => {
21
+ const validation = validateNpmName(path.basename(path.resolve(name)))
22
+ if (validation.valid) {
23
+ return true
24
+ }
25
+ return 'Invalid project name: ' + validation.problems![0]
26
+ },
27
+ })
28
+
29
+ if (typeof res.path === 'string') {
30
+ projectPath = res.path.trim()
31
+ }
32
+ }
33
+
34
+ if (!projectPath) {
35
+ console.info()
36
+ console.info('Please specify the project directory:')
37
+ console.info(
38
+ ` ${chalk.cyan(packageJson.name)} ${chalk.green('<project-directory>')}`
39
+ )
40
+ console.info()
41
+ console.info('For example:')
42
+ console.info(` ${chalk.cyan(packageJson.name)} ${chalk.green('my-hanzogui-app')}`)
43
+ console.info()
44
+ console.info(`Run ${chalk.cyan(`${packageJson.name} --help`)} to see all options.`)
45
+ process.exit(1)
46
+ }
47
+ return projectPath
48
+ }
@@ -0,0 +1,34 @@
1
+ import prompts from 'prompts'
2
+
3
+ import { templates } from '../templates.ts'
4
+
5
+ const validTemplates = templates.map(({ value }) => value).join(', ')
6
+
7
+ export const getTemplateInfo = async (
8
+ template?: string
9
+ ): Promise<(typeof templates)[number]> => {
10
+ let res = getValidTemplate(template)
11
+ if (template && !res) {
12
+ console.warn(`template ${template} is not valid. valid options: ${validTemplates}`)
13
+ process.exit(1)
14
+ }
15
+ if (!res) {
16
+ template = (
17
+ await prompts({
18
+ name: 'template',
19
+ type: 'select',
20
+ message: `Pick a template:`,
21
+ choices: templates.filter((t) => !t.hidden),
22
+ })
23
+ ).template
24
+ }
25
+ res = getValidTemplate(`${template}`)
26
+ if (!res) {
27
+ console.warn(`template ${template} is not valid. valid options: ${validTemplates}`)
28
+ process.exit(1)
29
+ }
30
+ return res
31
+ }
32
+
33
+ const getValidTemplate = (template?: string) =>
34
+ typeof template === 'string' && templates.find(({ value }) => value === template)
@@ -0,0 +1,23 @@
1
+ import * as PackageManager from '@expo/package-manager'
2
+
3
+ export async function installDependencies(
4
+ projectRoot: string,
5
+ packageManager: 'yarn' | 'npm' | 'pnpm' | 'bun'
6
+ ) {
7
+ // Check if Vitest 2 is running
8
+ if (process.env.VITEST) {
9
+ console.warn('Skipping dependency installation because Vitest 2 is running.')
10
+ return
11
+ }
12
+
13
+ const options = { cwd: projectRoot }
14
+ if (packageManager === 'yarn') {
15
+ await new PackageManager.YarnPackageManager(options).installAsync()
16
+ } else if (packageManager === 'pnpm') {
17
+ await new PackageManager.PnpmPackageManager(options).installAsync()
18
+ } else if (packageManager === 'bun') {
19
+ await new PackageManager.BunPackageManager(options).installAsync()
20
+ } else {
21
+ await new PackageManager.NpmPackageManager(options).installAsync()
22
+ }
23
+ }
@@ -0,0 +1,17 @@
1
+ import chalk from 'chalk'
2
+
3
+ export const rainbowColors = [
4
+ '#f76808',
5
+ '#f5d90a',
6
+ '#30a46c',
7
+ '#0091ff',
8
+ '#8e4ec6',
9
+ '#d6409f',
10
+ '#e5484d',
11
+ ]
12
+
13
+ export const makeRainbowChalk = (text: string) =>
14
+ text
15
+ .split('')
16
+ .map((char, idx) => chalk.hex(rainbowColors[idx % rainbowColors.length])(char))
17
+ .join('')
@@ -0,0 +1,16 @@
1
+ import validateProjectName from 'validate-npm-package-name'
2
+
3
+ export function validateNpmName(name: string): {
4
+ valid: boolean
5
+ problems?: string[]
6
+ } {
7
+ const nameValidation = validateProjectName(name)
8
+ if (nameValidation.validForNewPackages) {
9
+ return { valid: true }
10
+ }
11
+
12
+ return {
13
+ valid: false,
14
+ problems: [...(nameValidation.errors || []), ...(nameValidation.warnings || [])],
15
+ }
16
+ }
@@ -0,0 +1,3 @@
1
+ import { pathToFileURL } from 'node:url'
2
+
3
+ export const url = pathToFileURL(__filename).href
package/src/here.ts ADDED
@@ -0,0 +1,2 @@
1
+ // This module's own URL. A require made from it resolves from this package.
2
+ export const url = import.meta.url