create-gui 8.0.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.
package/dist/index.cjs ADDED
@@ -0,0 +1,924 @@
1
+ #!/usr/bin/env node
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+
25
+ // src/index.ts
26
+ var import_chalk10 = __toESM(require("chalk"));
27
+ var import_commander = __toESM(require("commander"));
28
+ var import_detect_package_manager = require("detect-package-manager");
29
+ var import_fs_extra2 = require("fs-extra");
30
+ var import_node_child_process3 = require("node:child_process");
31
+ var import_node_fs3 = __toESM(require("node:fs"));
32
+ var import_node_path4 = __toESM(require("node:path"));
33
+ var import_node_process = require("node:process");
34
+ var import_opener = __toESM(require("opener"));
35
+ var import_prompts4 = __toESM(require("prompts"));
36
+
37
+ // package.json
38
+ var package_default = {
39
+ name: "create-gui",
40
+ version: "8.0.0",
41
+ gitHead: "a49cc7ea6b93ba384e77a4880ae48ac4a5635c14",
42
+ bin: {
43
+ "create-gui": "run.js"
44
+ },
45
+ files: [
46
+ "run.js",
47
+ "dist"
48
+ ],
49
+ sideEffects: false,
50
+ main: "dist/index.cjs",
51
+ publishConfig: {
52
+ access: "public"
53
+ },
54
+ scripts: {
55
+ start: "./run.js",
56
+ "//": "disabling for now need to migrate to new stack",
57
+ "test-disabled": "NODE_ENV=test node -r esbuild-register ../../../node_modules/.bin/playwright test integration.test.ts",
58
+ "test:debug": "bun run test --debug",
59
+ test: "bun run build:test && vitest run",
60
+ "test:web": "bun run test",
61
+ "build:test": "bun run build",
62
+ prerelease: "rimraf ./dist/",
63
+ prepublish: "bun run build",
64
+ build: "hanzogui-build --skip-types --bundle",
65
+ watch: "bun run build --watch",
66
+ clean: "hanzogui-build clean",
67
+ "clean:build": "hanzogui-build clean:build"
68
+ },
69
+ dependencies: {
70
+ "@expo/package-manager": "^1.1.2",
71
+ chalk: "^4.1.2",
72
+ commander: "2.20.0",
73
+ "detect-package-manager": "^3.0.1",
74
+ "fs-extra": "^11.2.0",
75
+ opener: "^1.5.2",
76
+ prompts: "2.1.0",
77
+ rimraf: "^5.0.1",
78
+ "validate-npm-package-name": "3.0.0"
79
+ },
80
+ devDependencies: {
81
+ "@playwright/test": "^1.49.1",
82
+ "@hanzogui/build": "workspace:*",
83
+ "@types/node": "^22.1.0",
84
+ "@types/opener": "^1.4.3",
85
+ "@types/prompts": "2.0.1",
86
+ "@types/rimraf": "3.0.0",
87
+ "@types/validate-npm-package-name": "3.0.0",
88
+ "esbuild-register": "^3.6.0",
89
+ tempy: "^3.1.0",
90
+ vitest: "4.0.4"
91
+ }
92
+ };
93
+
94
+ // src/create-gui-constants.ts
95
+ var IS_TEST = process.env.NODE_ENV === "test";
96
+
97
+ // src/helpers/asciiArts.ts
98
+ var import_chalk2 = __toESM(require("chalk"));
99
+
100
+ // src/helpers/rainbowChalk.ts
101
+ var import_chalk = __toESM(require("chalk"));
102
+ var rainbowColors = [
103
+ "#f76808",
104
+ "#f5d90a",
105
+ "#30a46c",
106
+ "#0091ff",
107
+ "#8e4ec6",
108
+ "#d6409f",
109
+ "#e5484d"
110
+ ];
111
+
112
+ // src/helpers/asciiArts.ts
113
+ var hanzoguiRainbowAsciiArt = (function() {
114
+ const char0_1 = import_chalk2.default.hex(rainbowColors[0])("\u2580\u2588\u2580");
115
+ const char0_2 = import_chalk2.default.hex(rainbowColors[0])(" \u2588 ");
116
+ const char1_1 = import_chalk2.default.hex(rainbowColors[1])("\u2584\u2580\u2588");
117
+ const char1_2 = import_chalk2.default.hex(rainbowColors[1])("\u2588\u2580\u2588");
118
+ const char2_1 = import_chalk2.default.hex(rainbowColors[2])("\u2588\u2580\u2584\u2580\u2588");
119
+ const char2_2 = import_chalk2.default.hex(rainbowColors[2])("\u2588 \u2580 \u2588");
120
+ const char3_1 = import_chalk2.default.hex(rainbowColors[3])("\u2584\u2580\u2588");
121
+ const char3_2 = import_chalk2.default.hex(rainbowColors[3])("\u2588\u2580\u2588");
122
+ const char4_1 = import_chalk2.default.hex(rainbowColors[4])("\u2588\u2580\u2580");
123
+ const char4_2 = import_chalk2.default.hex(rainbowColors[4])("\u2588\u2584\u2588");
124
+ const char5_1 = import_chalk2.default.hex(rainbowColors[5])("\u2588 \u2588");
125
+ const char5_2 = import_chalk2.default.hex(rainbowColors[5])("\u2588\u2584\u2588");
126
+ const char6_1 = import_chalk2.default.hex(rainbowColors[6])("\u2588");
127
+ const char6_2 = import_chalk2.default.hex(rainbowColors[6])("\u2588");
128
+ return `${char0_1}\u2003${char1_1}\u2003${char2_1}\u2003${char3_1}\u2003${char4_1}\u2003${char5_1}\u2003${char6_1}
129
+ ${char0_2}\u2003${char1_2}\u2003${char2_2}\u2003${char3_2}\u2003${char4_2}\u2003${char5_2}\u2003${char6_2}
130
+ `;
131
+ })();
132
+ var takeoutAsciiArt = `\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2591\u2588\u2588\u2588\u2588\u2588\u2557\u2591\u2588\u2588\u2557\u2591\u2591\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2591\u2588\u2588\u2588\u2588\u2588\u2557\u2591\u2588\u2588\u2557\u2591\u2591\u2591\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
133
+ \u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2591\u2588\u2588\u2554\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D
134
+ \u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2550\u255D\u2591\u2588\u2588\u2588\u2588\u2588\u2557\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2588\u2588\u2551\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591
135
+ \u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2588\u2588\u2557\u2591\u2588\u2588\u2554\u2550\u2550\u255D\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2588\u2588\u2551\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591
136
+ \u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2588\u2588\u2551\u2588\u2588\u2551\u2591\u255A\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2591\u2591\u2591\u2588\u2588\u2551\u2591\u2591\u2591
137
+ \u2591\u2591\u2591\u255A\u2550\u255D\u2591\u2591\u2591\u255A\u2550\u255D\u2591\u2591\u255A\u2550\u255D\u255A\u2550\u255D\u2591\u2591\u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u2591\u255A\u2550\u2550\u2550\u2550\u255D\u2591\u2591\u255A\u2550\u2550\u2550\u2550\u2550\u255D\u2591\u2591\u2591\u2591\u255A\u2550\u255D\u2591\u2591\u2591`;
138
+ var hanzoguiDuckAsciiArt = ` \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588
139
+ \u2588\u2588 \u2588\u2588
140
+ \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588
141
+ \u2588\u2588 \u2588\u2588 \u2588\u2588
142
+ \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588
143
+ \u2588\u2588 \u2588\u2588
144
+ \u2588\u2588 \u2588\u2588\u2588\u2588
145
+ \u2588\u2588 \u2588\u2588
146
+ \u2588\u2588 \u2588\u2588 `;
147
+
148
+ // src/helpers/cloneStarter.ts
149
+ var import_node_child_process = require("node:child_process");
150
+ var import_node_fs = require("node:fs");
151
+ var import_node_os = require("node:os");
152
+ var import_node_path = require("node:path");
153
+ var import_chalk3 = __toESM(require("chalk"));
154
+ var import_fs_extra = require("fs-extra");
155
+ var import_rimraf = require("rimraf");
156
+ var open = require("opener");
157
+ var exec = (cmd, options) => {
158
+ console.info(`$ `, cmd);
159
+ return (0, import_node_child_process.execSync)(cmd, {
160
+ stdio: process.env.DEBUG ? "inherit" : "ignore",
161
+ ...options
162
+ });
163
+ };
164
+ var hanzoguiDir = (0, import_node_path.join)((0, import_node_os.homedir)(), ".hanzogui-repo-cache");
165
+ var targetGitDir = "";
166
+ var cloneStarter = async (template, resolvedProjectPath, projectName) => {
167
+ targetGitDir = (0, import_node_path.join)(hanzoguiDir, "hanzogui", template.repo.url.split("/").at(-1));
168
+ console.info();
169
+ await setupGuiDotDir(template);
170
+ const starterDir = (0, import_node_path.join)(targetGitDir, ...template.repo.dir);
171
+ console.info();
172
+ console.info(
173
+ `Copying starter from ${starterDir} into ${import_chalk3.default.blueBright(projectName)}...`
174
+ );
175
+ console.info();
176
+ await (0, import_fs_extra.copy)(starterDir, resolvedProjectPath);
177
+ await (0, import_rimraf.rimraf)(`${resolvedProjectPath}/.git`);
178
+ rewriteWorkspaceVersions(resolvedProjectPath);
179
+ console.info(import_chalk3.default.green(`${projectName} created!`));
180
+ console.info();
181
+ };
182
+ async function setupGuiDotDir(template) {
183
+ console.info(`Setting up ${import_chalk3.default.blueBright(targetGitDir)}...`);
184
+ if (process.env.GITHUB_HEAD_REF) {
185
+ try {
186
+ (0, import_node_child_process.execSync)(`git switch -c ${process.env.GITHUB_HEAD_REF}`, {
187
+ cwd: targetGitDir,
188
+ stdio: "ignore"
189
+ });
190
+ } catch {
191
+ }
192
+ }
193
+ const branch = template.repo.branch;
194
+ await (0, import_fs_extra.ensureDir)(hanzoguiDir);
195
+ const isInSubDir = template.repo.dir.length > 0;
196
+ const sourceGitRepo = template.repo.url;
197
+ const sourceGitRepoSshFallback = template.repo.sshFallback;
198
+ if (!await (0, import_fs_extra.pathExists)(targetGitDir)) {
199
+ console.info(`Cloning hanzogui base directory`);
200
+ console.info();
201
+ const cmd = `git clone --branch ${branch} ${isInSubDir ? "--depth 1 --sparse --filter=blob:none " : ""}${sourceGitRepo} "${targetGitDir}"`;
202
+ try {
203
+ try {
204
+ console.info(`$ ${cmd}`);
205
+ console.info();
206
+ exec(cmd);
207
+ } catch (error) {
208
+ if (cmd.includes("https://")) {
209
+ console.info(`https failed - trying with ssh now...`);
210
+ const sshCmd = cmd.replace(sourceGitRepo, sourceGitRepoSshFallback);
211
+ console.info(`$ ${sshCmd}`);
212
+ console.info();
213
+ exec(sshCmd);
214
+ } else {
215
+ throw error;
216
+ }
217
+ }
218
+ } catch (error) {
219
+ if (error instanceof Error) {
220
+ if (template.value === "takeout-pro" || template.value === "takeout-pro-classic") {
221
+ if (error?.stderr?.includes("Repository not found")) {
222
+ console.info(
223
+ import_chalk3.default.yellow(
224
+ `You don't have access to this starter. Check \u{1F961} Gui Takeout (https://hanzogui.dev/takeout) for more info.`
225
+ )
226
+ );
227
+ open("https://hanzogui.dev/takeout");
228
+ process.exit(0);
229
+ }
230
+ }
231
+ }
232
+ throw error;
233
+ }
234
+ } else {
235
+ if (!await (0, import_fs_extra.pathExists)((0, import_node_path.join)(targetGitDir, ".git"))) {
236
+ console.error(`Corrupt Gui directory, please delete ${targetGitDir} and re-run`);
237
+ process.exit(1);
238
+ }
239
+ }
240
+ if (isInSubDir) {
241
+ const cmd = `git sparse-checkout set apps/starters`;
242
+ exec(cmd, { cwd: targetGitDir });
243
+ console.info();
244
+ }
245
+ try {
246
+ const remoteName = getDefaultRemoteName();
247
+ if (await (0, import_fs_extra.pathExists)((0, import_node_path.join)(targetGitDir, ".git"))) {
248
+ const cmd2 = `git pull --rebase --allow-unrelated-histories --depth 1 ${remoteName} ${branch}`;
249
+ try {
250
+ exec(cmd2, {
251
+ cwd: targetGitDir
252
+ });
253
+ } catch {
254
+ exec(cmd2, {
255
+ cwd: targetGitDir
256
+ });
257
+ }
258
+ console.info();
259
+ } else {
260
+ console.warn(
261
+ `Warning: ${targetGitDir} is not a git repository. Skipping pull operation.`
262
+ );
263
+ }
264
+ } catch (err) {
265
+ await (0, import_fs_extra.remove)(targetGitDir);
266
+ console.info(`Error updating: ${err.message} ${err.stack}`);
267
+ console.info(
268
+ `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=`
269
+ );
270
+ process.exit(1);
271
+ }
272
+ }
273
+ function rewriteWorkspaceVersions(projectPath2) {
274
+ const pkgPath = (0, import_node_path.join)(projectPath2, "package.json");
275
+ try {
276
+ const pkg = JSON.parse((0, import_node_fs.readFileSync)(pkgPath, "utf-8"));
277
+ if (pkg.workspaces) {
278
+ return;
279
+ }
280
+ const ctPkgPath = require.resolve("create-gui/package.json");
281
+ const ctPkg = JSON.parse((0, import_node_fs.readFileSync)(ctPkgPath, "utf-8"));
282
+ const version = `^${ctPkg.version}`;
283
+ let changed = false;
284
+ for (const field of ["dependencies", "devDependencies"]) {
285
+ const deps = pkg[field];
286
+ if (!deps) continue;
287
+ for (const [key, val] of Object.entries(deps)) {
288
+ if (val === "workspace:*") {
289
+ deps[key] = version;
290
+ changed = true;
291
+ }
292
+ }
293
+ }
294
+ if (changed) {
295
+ (0, import_node_fs.writeFileSync)(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
296
+ console.info(import_chalk3.default.dim(` Rewrote workspace:* \u2192 ${version}`));
297
+ }
298
+ } catch {
299
+ }
300
+ }
301
+ var getDefaultRemoteName = () => {
302
+ try {
303
+ if (!(0, import_fs_extra.pathExists)((0, import_node_path.join)(targetGitDir, ".git"))) {
304
+ console.warn(
305
+ 'Warning: Not in a git repository. Using default remote name "origin".'
306
+ );
307
+ return "origin";
308
+ }
309
+ const remotes = (0, import_node_child_process.execSync)("git remote", { cwd: targetGitDir }).toString().trim().split("\n");
310
+ return remotes[0] || "origin";
311
+ } catch (error) {
312
+ console.warn("Error getting default remote name:", error);
313
+ console.warn('Using default remote name "origin".');
314
+ return "origin";
315
+ }
316
+ };
317
+
318
+ // src/helpers/getProjectName.ts
319
+ var import_node_path2 = __toESM(require("node:path"));
320
+ var import_chalk4 = __toESM(require("chalk"));
321
+ var import_prompts = __toESM(require("prompts"));
322
+
323
+ // src/helpers/validateNpmPackage.ts
324
+ var import_validate_npm_package_name = __toESM(require("validate-npm-package-name"));
325
+ function validateNpmName(name) {
326
+ const nameValidation = (0, import_validate_npm_package_name.default)(name);
327
+ if (nameValidation.validForNewPackages) {
328
+ return { valid: true };
329
+ }
330
+ return {
331
+ valid: false,
332
+ problems: [...nameValidation.errors || [], ...nameValidation.warnings || []]
333
+ };
334
+ }
335
+
336
+ // src/helpers/getProjectName.ts
337
+ var getProjectName = async (projectPath2) => {
338
+ if (typeof projectPath2 === "string") {
339
+ projectPath2 = projectPath2.trim();
340
+ }
341
+ if (!projectPath2) {
342
+ const res = await (0, import_prompts.default)({
343
+ type: "text",
344
+ name: "path",
345
+ message: "Project name:",
346
+ initial: "myapp",
347
+ validate: (name) => {
348
+ const validation = validateNpmName(import_node_path2.default.basename(import_node_path2.default.resolve(name)));
349
+ if (validation.valid) {
350
+ return true;
351
+ }
352
+ return "Invalid project name: " + validation.problems[0];
353
+ }
354
+ });
355
+ if (typeof res.path === "string") {
356
+ projectPath2 = res.path.trim();
357
+ }
358
+ }
359
+ if (!projectPath2) {
360
+ console.info();
361
+ console.info("Please specify the project directory:");
362
+ console.info(
363
+ ` ${import_chalk4.default.cyan(package_default.name)} ${import_chalk4.default.green("<project-directory>")}`
364
+ );
365
+ console.info();
366
+ console.info("For example:");
367
+ console.info(` ${import_chalk4.default.cyan(package_default.name)} ${import_chalk4.default.green("my-hanzogui-app")}`);
368
+ console.info();
369
+ console.info(`Run ${import_chalk4.default.cyan(`${package_default.name} --help`)} to see all options.`);
370
+ process.exit(1);
371
+ }
372
+ return projectPath2;
373
+ };
374
+
375
+ // src/helpers/getTemplateInfo.ts
376
+ var import_prompts3 = __toESM(require("prompts"));
377
+
378
+ // src/templates.ts
379
+ var import_chalk9 = __toESM(require("chalk"));
380
+
381
+ // src/steps/expo-router.ts
382
+ var import_chalk5 = __toESM(require("chalk"));
383
+ var main = async ({ isFullClone, projectName }) => {
384
+ if (isFullClone) {
385
+ console.info(`
386
+ ${import_chalk5.default.green.bold("Done!")} created a new project under ./${projectName}
387
+
388
+ visit your project:
389
+ ${import_chalk5.default.green("cd")} ${projectName}
390
+ `);
391
+ }
392
+ };
393
+ var expo_router_default = main;
394
+
395
+ // src/steps/remix.ts
396
+ var import_chalk6 = __toESM(require("chalk"));
397
+ var packageManager = "bun";
398
+ var runCommand = (scriptName) => `${packageManager} run ${scriptName}`;
399
+ var main2 = async ({ isFullClone, projectName }) => {
400
+ if (isFullClone) {
401
+ console.info(`
402
+ ${import_chalk6.default.green.bold("Done!")} created a new project under ./${projectName}
403
+
404
+ visit your project:
405
+ ${import_chalk6.default.green("cd")} ${projectName}
406
+ `);
407
+ }
408
+ console.info(`
409
+ To start the Remix development server, run:
410
+ ${import_chalk6.default.green(runCommand("dev"))}
411
+ `);
412
+ };
413
+ var remix_default = main2;
414
+
415
+ // src/steps/starter-free.ts
416
+ var import_chalk7 = __toESM(require("chalk"));
417
+ var packageManager2 = "bun";
418
+ var runCommand2 = (scriptName) => `${packageManager2} run ${scriptName}`;
419
+ var main3 = async ({ isFullClone, projectName }) => {
420
+ console.info(`Note: you need bun for this repo.`);
421
+ if (isFullClone) {
422
+ console.info(`${import_chalk7.default.green.bold(
423
+ "Done!"
424
+ )} created a new project under ./${projectName}
425
+
426
+ visit your project:
427
+ ${import_chalk7.default.green("cd")} ${projectName}
428
+ `);
429
+ }
430
+ console.info(`
431
+ To start the Next.js development server, run:
432
+ ${import_chalk7.default.green(runCommand2("web"))}
433
+
434
+ To start Expo Go for mobile development, run:
435
+ ${import_chalk7.default.green(runCommand2("native"))}
436
+
437
+ You can also create Expo development builds by doing:
438
+
439
+ ${import_chalk7.default.green(`cd apps/expo`)}
440
+ then:
441
+ ${import_chalk7.default.green(runCommand2("ios"))}
442
+ or...
443
+ ${import_chalk7.default.green(runCommand2("android"))}
444
+
445
+ Be sure to replace yourprojectsname in app.json with the uid you'd like for your app.
446
+ `);
447
+ };
448
+ var starter_free_default = main3;
449
+
450
+ // src/steps/takeout.ts
451
+ var import_node_child_process2 = require("node:child_process");
452
+ var import_node_fs2 = require("node:fs");
453
+ var import_promises = __toESM(require("node:fs/promises"));
454
+ var import_node_path3 = __toESM(require("node:path"));
455
+ var import_chalk8 = __toESM(require("chalk"));
456
+ var import_prompts2 = __toESM(require("prompts"));
457
+ var packageManager3 = "bun";
458
+ var runCommand3 = (scriptName) => `${packageManager3} run ${scriptName}`;
459
+ var main4 = async ({ isFullClone, projectName, projectPath: projectPath2 }) => {
460
+ console.info(`
461
+ ${hanzoguiRainbowAsciiArt.split("\n").map((line) => ` ${line}`).join("\n")}
462
+ ${takeoutAsciiArt}
463
+
464
+ `);
465
+ console.info();
466
+ const { setupSupabase } = await (0, import_prompts2.default)({
467
+ name: "setupSupabase",
468
+ message: "Set up Supabase?",
469
+ type: "confirm",
470
+ initial: true
471
+ });
472
+ if (setupSupabase) {
473
+ console.info();
474
+ const { startLocalSupabase } = await (0, import_prompts2.default)({
475
+ name: "startLocalSupabase",
476
+ type: "confirm",
477
+ message: "Start local Supabase instance for you? (Requires Docker)",
478
+ initial: true
479
+ });
480
+ if (startLocalSupabase) {
481
+ const supabaseStarted = await runRetryableCommand(`bun run supa start`);
482
+ if (supabaseStarted) {
483
+ console.info();
484
+ const { setUpSupabaseEnv } = await (0, import_prompts2.default)({
485
+ name: "setUpSupabaseEnv",
486
+ type: "confirm",
487
+ message: "Do you want us to add the local env variables for you? This will create a file called .env.local.",
488
+ initial: true
489
+ });
490
+ if (setUpSupabaseEnv) {
491
+ const envs = getEnvFromSupabaseStatus(
492
+ (0, import_node_child_process2.execSync)("bun run supa status").toString()
493
+ );
494
+ const newEnvContent = Object.entries(envs).map(([key, value]) => `${key}=${value}`).join("\n");
495
+ if ((0, import_node_fs2.existsSync)(import_node_path3.default.join(projectPath2, ".env.local"))) {
496
+ if ((0, import_node_fs2.readFileSync)(import_node_path3.default.join(projectPath2, ".env.local")).toString() !== newEnvContent) {
497
+ (0, import_node_fs2.renameSync)(
498
+ import_node_path3.default.join(projectPath2, ".env.local"),
499
+ import_node_path3.default.join(projectPath2, `.env.local.old-${Number(/* @__PURE__ */ new Date())}`)
500
+ );
501
+ }
502
+ }
503
+ await import_promises.default.writeFile(import_node_path3.default.join(projectPath2, "./.env.local"), newEnvContent);
504
+ }
505
+ }
506
+ }
507
+ console.info();
508
+ const { setupRemoteSupabase } = await (0, import_prompts2.default)({
509
+ name: "setupRemoteSupabase",
510
+ type: "confirm",
511
+ message: "Link remote Supabase instance for you? (Create a project on https://app.supabase.com/projects first)",
512
+ initial: true
513
+ });
514
+ if (setupRemoteSupabase) {
515
+ await runRetryableCommand(`npx supabase login`);
516
+ console.info();
517
+ await linkSupabase();
518
+ }
519
+ }
520
+ if (isFullClone) {
521
+ console.info(`
522
+ ${import_chalk8.default.green.bold("Done!")} created a new project under ./${projectName}
523
+
524
+ visit your project:
525
+ ${import_chalk8.default.green(" cd")} ${projectName}
526
+ `);
527
+ }
528
+ console.info(`
529
+ To start the Next.js development server, run:
530
+ ${import_chalk8.default.green(runCommand3("web"))}
531
+
532
+ To start developing with Expo for native, run:
533
+ ${import_chalk8.default.green(runCommand3("native"))}
534
+
535
+ To start developing for Expo dev build, run:
536
+ ${import_chalk8.default.green(runCommand3("ios"))}
537
+ ${import_chalk8.default.green(runCommand3("android"))}
538
+
539
+ To run Supabase scripts, cd into the supabase package:
540
+ ${import_chalk8.default.green("cd supabase")}
541
+
542
+ ${import_chalk8.default.green("yarn reset")} - Resets local database
543
+ ${import_chalk8.default.green("yarn generate")} - Generates new types
544
+
545
+ Find info on the rest of the scripts in ${import_chalk8.default.cyan(`supabase/README.md`)}
546
+
547
+ If you've purchased and gained access to font and icon packages, you can run:
548
+ ${import_chalk8.default.green("yarn add:icon")}
549
+ ${import_chalk8.default.green("yarn add:font")}
550
+ `);
551
+ };
552
+ var takeout_default = main4;
553
+ async function runRetryableCommand(cmd, retriesCount = 0) {
554
+ try {
555
+ (0, import_node_child_process2.execSync)(cmd, { stdio: "inherit" });
556
+ return true;
557
+ } catch (error) {
558
+ const { tryAgain } = await (0, import_prompts2.default)({
559
+ name: "tryAgain",
560
+ message: "An error occurred. Do you want to try again?",
561
+ type: "confirm",
562
+ initial: true
563
+ });
564
+ if (tryAgain) {
565
+ await runRetryableCommand(cmd, retriesCount + 1);
566
+ } else {
567
+ console.info(
568
+ import_chalk8.default.yellow(
569
+ `\u26A0\uFE0F Skipping this step. You can try running this command later. The failed command was \`${import_chalk8.default.underline(
570
+ cmd
571
+ )}\`.`
572
+ )
573
+ );
574
+ return false;
575
+ }
576
+ }
577
+ }
578
+ async function linkSupabase() {
579
+ const { supabaseRefId } = await (0, import_prompts2.default)({
580
+ name: "supabaseRefId",
581
+ type: "text",
582
+ message: "Enter your supabase project's ID (e.g. abcdefghijklmnopqrst)",
583
+ initial: true
584
+ });
585
+ const cmd = `npx supabase link --project-ref ${supabaseRefId.trim()}`;
586
+ try {
587
+ (0, import_node_child_process2.execSync)(cmd, {
588
+ stdio: "inherit"
589
+ });
590
+ return true;
591
+ } catch (error) {
592
+ const { tryAgain } = await (0, import_prompts2.default)({
593
+ name: "tryAgain",
594
+ message: "An error occurred. Do you want to try again?",
595
+ type: "confirm",
596
+ initial: true
597
+ });
598
+ if (tryAgain) {
599
+ await linkSupabase();
600
+ } else {
601
+ console.info(
602
+ import_chalk8.default.yellow(
603
+ `\u26A0\uFE0F Skipping this step. You can try running this command later. The failed command was \`${import_chalk8.default.underline(
604
+ cmd
605
+ )}\`.`
606
+ )
607
+ );
608
+ return false;
609
+ }
610
+ }
611
+ }
612
+ function getEnvFromSupabaseStatus(status) {
613
+ return {
614
+ NEXT_PUBLIC_SUPABASE_URL: status.match(/API URL: (.*)/)?.[1],
615
+ NEXT_PUBLIC_SUPABASE_GRAPHQL_URL: status.match(/GraphQL URL: (.*)/)?.[1],
616
+ SUPABASE_DB_URL: status.match(/DB URL: (.*)/)?.[1],
617
+ NEXT_PUBLIC_SUPABASE_ANON_KEY: status.match(/anon key: (.*)/)?.[1],
618
+ SUPABASE_SERVICE_ROLE: status.match(/service_role key: (.*)/)?.[1],
619
+ SUPABASE_JWT_SECRET: status.match(/JWT secret: (.*)/)?.[1]
620
+ };
621
+ }
622
+
623
+ // src/templates.ts
624
+ var templates = [
625
+ {
626
+ title: `${import_chalk9.default.bold.underline(
627
+ `\u{1F961} ${import_chalk9.default.magenta("Takeout")} ${import_chalk9.default.green("Free")}`
628
+ )} - Full stack starter: https://hanzogui.dev/takeout`,
629
+ value: "takeout-free",
630
+ type: "free",
631
+ hidden: false,
632
+ packageManager: "bun",
633
+ repo: {
634
+ url: `https://github.com/hanzogui/takeout-free`,
635
+ sshFallback: `git@github.com:hanzogui/takeout-free.git`,
636
+ dir: [],
637
+ branch: "main"
638
+ },
639
+ extraSteps: starter_free_default
640
+ },
641
+ {
642
+ title: `${import_chalk9.default.bold.underline(
643
+ `\u{1F961} ${import_chalk9.default.magenta("Takeout")} ${import_chalk9.default.red("Pro")}`
644
+ )} - Full featured starter: https://hanzogui.dev/takeout`,
645
+ value: `takeout-pro`,
646
+ type: "premium",
647
+ packageManager: "yarn",
648
+ hidden: false,
649
+ repo: {
650
+ url: `https://github.com/hanzogui/takeout2`,
651
+ sshFallback: `git@github.com:hanzogui/takeout2.git`,
652
+ dir: [],
653
+ branch: "main"
654
+ },
655
+ extraSteps: takeout_default
656
+ },
657
+ {
658
+ title: `${import_chalk9.default.bold.underline(
659
+ `\u{1F961} ${import_chalk9.default.magenta("Takeout")} ${import_chalk9.default.yellow("Pro Classic")}`
660
+ )} - Original Pro starter: https://hanzogui.dev/takeout`,
661
+ value: `takeout-pro-classic`,
662
+ type: "premium",
663
+ packageManager: "yarn",
664
+ hidden: false,
665
+ repo: {
666
+ url: `https://github.com/hanzogui/takeout`,
667
+ sshFallback: `git@github.com:hanzogui/takeout.git`,
668
+ dir: [],
669
+ branch: "main"
670
+ },
671
+ extraSteps: takeout_default
672
+ },
673
+ {
674
+ title: `Expo Router - Expo with file-based routing`,
675
+ value: "expo-router",
676
+ type: "free",
677
+ hidden: false,
678
+ packageManager: "bun",
679
+ repo: {
680
+ url: `https://github.com/hanzoai/gui`,
681
+ sshFallback: `git@github.com:hanzogui/hanzogui.git`,
682
+ dir: ["code", "starters", "expo-router"],
683
+ branch: "main"
684
+ },
685
+ extraSteps: expo_router_default
686
+ },
687
+ {
688
+ title: `Remix - Remix with Vite`,
689
+ value: "remix",
690
+ type: "free",
691
+ hidden: false,
692
+ packageManager: "bun",
693
+ repo: {
694
+ url: `https://github.com/hanzoai/gui`,
695
+ sshFallback: `git@github.com:hanzogui/hanzogui.git`,
696
+ dir: ["code", "starters", "remix"],
697
+ branch: "main"
698
+ },
699
+ extraSteps: remix_default
700
+ },
701
+ {
702
+ title: `Next + Expo - Production ready monorepo`,
703
+ value: "starter-free",
704
+ type: "free",
705
+ hidden: false,
706
+ packageManager: "yarn",
707
+ repo: {
708
+ url: process.env.STARTER_FREE_REPO_SOURCE || `https://github.com/hanzogui/starter-free.git`,
709
+ sshFallback: `git@github.com:hanzogui/starter-free.git`,
710
+ dir: [],
711
+ branch: "main"
712
+ },
713
+ extraSteps: starter_free_default
714
+ }
715
+ ];
716
+
717
+ // src/helpers/getTemplateInfo.ts
718
+ var validTemplates = templates.map(({ value }) => value).join(", ");
719
+ var getTemplateInfo = async (template) => {
720
+ let res = getValidTemplate(template);
721
+ if (template && !res) {
722
+ console.warn(`template ${template} is not valid. valid options: ${validTemplates}`);
723
+ process.exit(1);
724
+ }
725
+ if (!res) {
726
+ template = (await (0, import_prompts3.default)({
727
+ name: "template",
728
+ type: "select",
729
+ message: `Pick a template:`,
730
+ choices: templates.filter((t) => !t.hidden)
731
+ })).template;
732
+ }
733
+ res = getValidTemplate(`${template}`);
734
+ if (!res) {
735
+ console.warn(`template ${template} is not valid. valid options: ${validTemplates}`);
736
+ process.exit(1);
737
+ }
738
+ return res;
739
+ };
740
+ var getValidTemplate = (template) => typeof template === "string" && templates.find(({ value }) => value === template);
741
+
742
+ // src/helpers/installDependencies.ts
743
+ var PackageManager = __toESM(require("@expo/package-manager"));
744
+ async function installDependencies(projectRoot, packageManager4) {
745
+ if (process.env.VITEST) {
746
+ console.warn("Skipping dependency installation because Vitest 2 is running.");
747
+ return;
748
+ }
749
+ const options = { cwd: projectRoot };
750
+ if (packageManager4 === "yarn") {
751
+ await new PackageManager.YarnPackageManager(options).installAsync();
752
+ } else if (packageManager4 === "pnpm") {
753
+ await new PackageManager.PnpmPackageManager(options).installAsync();
754
+ } else if (packageManager4 === "bun") {
755
+ await new PackageManager.BunPackageManager(options).installAsync();
756
+ } else {
757
+ await new PackageManager.NpmPackageManager(options).installAsync();
758
+ }
759
+ }
760
+
761
+ // src/index.ts
762
+ var projectPath = "";
763
+ if (IS_TEST) {
764
+ console.info(`\u{1F9D0} Running create-gui in test mode \u{1F9D0}`);
765
+ }
766
+ function exit() {
767
+ process.exit(0);
768
+ }
769
+ process.on("SIGTERM", exit);
770
+ process.on("SIGINT", exit);
771
+ var program = new import_commander.default.Command(package_default.name).version(package_default.version).arguments("<project-directory>").action((name) => {
772
+ projectPath = name;
773
+ }).option(`--info`, "Just shows the setup guide for the starter.").option(
774
+ `--template <template>, -t <template>`,
775
+ "Choose between four or more starter templates.",
776
+ ""
777
+ ).allowUnknownOption().usage(
778
+ `${import_chalk10.default.green("<project-directory>")} [options]
779
+
780
+ Example usage:
781
+
782
+ ${import_chalk10.default.blueBright(`npx ${package_default.name} next-expo`)}`
783
+ ).parse(process.argv);
784
+ if (process.argv.includes("--version")) {
785
+ console.info(package_default.version);
786
+ process.exit(0);
787
+ }
788
+ var info = !!program.info;
789
+ async function run() {
790
+ try {
791
+ if (info) {
792
+ let template2 = await getTemplateInfo(program.template);
793
+ if (template2?.extraSteps) {
794
+ await template2.extraSteps({
795
+ isFullClone: false,
796
+ projectName: import_node_path4.default.basename((0, import_node_process.cwd)()),
797
+ projectPath: (0, import_node_process.cwd)()
798
+ });
799
+ }
800
+ process.exit(0);
801
+ }
802
+ console.info();
803
+ console.info(
804
+ import_chalk10.default.bold(
805
+ ' Note: You may need to run "npm create hanzogui@latest" to get the latest version!'
806
+ )
807
+ );
808
+ console.info();
809
+ console.info();
810
+ console.info(hanzoguiRainbowAsciiArt);
811
+ console.info(import_chalk10.default.bold("Creating hanzogui app..."));
812
+ const gitVersionString = Number.parseFloat(
813
+ (0, import_node_child_process3.execSync)(`git --version`).toString().replace(`git version `, "").trim()
814
+ );
815
+ if (gitVersionString < 2.27) {
816
+ console.error(`
817
+
818
+ \u26A0\uFE0F Gui can't install: Git version must be >= 2.27
819
+
820
+ `);
821
+ process.exit(1);
822
+ }
823
+ projectPath ||= await getProjectName(projectPath);
824
+ let template = await getTemplateInfo(program.template);
825
+ if (template.type === "premium") {
826
+ const didPurchase = (await (0, import_prompts4.default)({
827
+ type: "confirm",
828
+ name: "purchased",
829
+ message: `Have you purchased Takeout on https://hanzogui.dev/takeout`
830
+ })).purchased;
831
+ if (!didPurchase) {
832
+ (0, import_opener.default)(`https://hanzogui.dev/takeout`);
833
+ console.info(
834
+ `
835
+ Opening Takeout website - once you purchase you can restart the create process. Thank you!
836
+ `
837
+ );
838
+ process.exit(0);
839
+ }
840
+ }
841
+ console.info();
842
+ const resolvedProjectPath = import_node_path4.default.resolve(process.cwd(), projectPath);
843
+ const projectName = import_node_path4.default.basename(resolvedProjectPath);
844
+ const { valid, problems } = validateNpmName(projectName);
845
+ if (!valid) {
846
+ console.error(
847
+ `Could not create a project called ${import_chalk10.default.red(
848
+ `"${projectName}"`
849
+ )} because of npm naming restrictions:`
850
+ );
851
+ problems.forEach((p) => console.error(` ${import_chalk10.default.red.bold("*")} ${p}`));
852
+ process.exit(1);
853
+ }
854
+ if (import_node_fs3.default.existsSync(resolvedProjectPath)) {
855
+ console.info();
856
+ console.info(
857
+ import_chalk10.default.red("\u{1F6A8} [hanzogui] error"),
858
+ `You tried to make a project called ${import_chalk10.default.underline(
859
+ import_chalk10.default.blueBright(projectName)
860
+ )}, but a folder with that name already exists: ${import_chalk10.default.blueBright(
861
+ resolvedProjectPath
862
+ )}
863
+
864
+ ${import_chalk10.default.bold(import_chalk10.default.red(`Please pick a different project name \u{1F978}`))}`
865
+ );
866
+ console.info();
867
+ console.info();
868
+ process.exit(1);
869
+ }
870
+ console.info();
871
+ console.info(`Creating a new hanzogui app ${import_chalk10.default.blueBright(resolvedProjectPath)}...`);
872
+ import_node_fs3.default.mkdirSync(resolvedProjectPath);
873
+ console.info(import_chalk10.default.green(`${projectName} folder created.`));
874
+ try {
875
+ await cloneStarter(template, resolvedProjectPath, projectName);
876
+ process.chdir(resolvedProjectPath);
877
+ console.info();
878
+ } catch (e) {
879
+ console.error(`[hanzogui] Failed to copy example into ${resolvedProjectPath}
880
+
881
+ `, e);
882
+ process.exit(1);
883
+ }
884
+ updatePackageJsonName(projectName, resolvedProjectPath);
885
+ console.info("Installing packages. This might take a couple of minutes.");
886
+ console.info();
887
+ const packageManager4 = ("packageManager" in template ? template.packageManager : void 0) || await (0, import_detect_package_manager.detect)();
888
+ try {
889
+ console.info("installing with " + packageManager4);
890
+ await installDependencies(resolvedProjectPath, packageManager4);
891
+ } catch (e) {
892
+ console.error("[hanzogui] error installing with " + packageManager4 + `
893
+ ${e}`);
894
+ process.exit(1);
895
+ }
896
+ await template?.extraSteps?.({
897
+ isFullClone: true,
898
+ projectName,
899
+ projectPath: resolvedProjectPath
900
+ });
901
+ console.info();
902
+ console.info(import_chalk10.default.gray(hanzoguiDuckAsciiArt));
903
+ process.exit(0);
904
+ } catch (error) {
905
+ console.error("An unexpected error occurred:", error);
906
+ process.exit(1);
907
+ }
908
+ }
909
+ function updatePackageJsonName(projectName, dir) {
910
+ const packageJsonPath = import_node_path4.default.join(dir, "package.json");
911
+ if ((0, import_fs_extra2.existsSync)(packageJsonPath)) {
912
+ const content = (0, import_fs_extra2.readFileSync)(packageJsonPath).toString();
913
+ const contentWithUpdatedName = content.replace(
914
+ /("name": ")(.*)(",)/,
915
+ `$1${projectName}$3`
916
+ );
917
+ (0, import_fs_extra2.writeFileSync)(packageJsonPath, contentWithUpdatedName);
918
+ }
919
+ }
920
+ run().catch((error) => {
921
+ console.error("An unexpected error occurred:", error);
922
+ process.exit(1);
923
+ });
924
+ //# sourceMappingURL=index.js.map