@mayrlabs/setup-project 0.1.3 → 0.1.5

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.mjs CHANGED
@@ -16,6 +16,19 @@ var __commonJS = (cb, mod) => function __require() {
16
16
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
17
17
  };
18
18
 
19
+ // node_modules/tsup/assets/esm_shims.js
20
+ import path from "path";
21
+ import { fileURLToPath } from "url";
22
+ var getFilename, getDirname, __dirname;
23
+ var init_esm_shims = __esm({
24
+ "node_modules/tsup/assets/esm_shims.js"() {
25
+ "use strict";
26
+ getFilename = () => fileURLToPath(import.meta.url);
27
+ getDirname = () => path.dirname(getFilename());
28
+ __dirname = /* @__PURE__ */ getDirname();
29
+ }
30
+ });
31
+
19
32
  // src/utils/pm.ts
20
33
  import { execa } from "execa";
21
34
  async function getPackageManager() {
@@ -48,37 +61,156 @@ async function installPackages(packages, dev = false) {
48
61
  var init_pm = __esm({
49
62
  "src/utils/pm.ts"() {
50
63
  "use strict";
64
+ init_esm_shims();
51
65
  }
52
66
  });
53
67
 
54
- // src/services/husky.ts
55
- import { select, text } from "@clack/prompts";
56
- import { execa as execa2 } from "execa";
57
- import fs from "fs-extra";
58
- async function promptHusky(config) {
59
- const hookType = await select({
60
- message: "What pre-commit hook would you like to use?",
61
- options: [
68
+ // src/constants/options.ts
69
+ var TOOL_OPTIONS, HUSKY_HOOK_OPTIONS, FORMATTER_OPTIONS, LINTER_OPTIONS, LINT_STAGED_EXTENSIONS, ENV_VARIANT_OPTIONS, ENV_VALIDATOR_OPTIONS, ENV_PRESET_OPTIONS, ENV_SPLIT_OPTIONS, TEST_RUNNER_OPTIONS, EDITOR_CONFIG_OPTIONS, LICENSE_TYPE_OPTIONS;
70
+ var init_options = __esm({
71
+ "src/constants/options.ts"() {
72
+ "use strict";
73
+ init_esm_shims();
74
+ TOOL_OPTIONS = [
75
+ { value: "husky", label: "Husky" },
76
+ { value: "formatter", label: "Formatter (Prettier/Oxfmt)" },
77
+ { value: "linter", label: "Linter (Eslint/Oxlint)" },
78
+ { value: "lint-staged", label: "Lint-staged" },
79
+ { value: "env", label: "Env Validation (@t3-oss/env)" },
80
+ { value: "test", label: "Test Runner (Vitest/Jest)" },
81
+ { value: "editorConfig", label: "EditorConfig" },
82
+ { value: "license", label: "License" }
83
+ ];
84
+ HUSKY_HOOK_OPTIONS = [
62
85
  { value: "lint-staged", label: "lint-staged" },
63
86
  { value: "custom", label: "Custom script" },
64
87
  { value: "none", label: "None" }
65
- ]
66
- });
67
- config.huskyHookType = hookType;
88
+ ];
89
+ FORMATTER_OPTIONS = [
90
+ { value: "prettier", label: "Prettier" },
91
+ { value: "oxfmt", label: "Oxfmt" }
92
+ ];
93
+ LINTER_OPTIONS = [
94
+ { value: "eslint", label: "ESLint" },
95
+ { value: "oxlint", label: "Oxlint" }
96
+ ];
97
+ LINT_STAGED_EXTENSIONS = [
98
+ { value: "js", label: "js" },
99
+ { value: "ts", label: "ts" },
100
+ { value: "jsx", label: "jsx" },
101
+ { value: "tsx", label: "tsx" },
102
+ { value: "html", label: "html" },
103
+ { value: "vue", label: "vue" },
104
+ { value: "svelte", label: "svelte" },
105
+ { value: "css", label: "css" },
106
+ { value: "scss", label: "scss" },
107
+ { value: "json", label: "json" },
108
+ { value: "yaml", label: "yaml" },
109
+ { value: "md", label: "md" }
110
+ ];
111
+ ENV_VARIANT_OPTIONS = [
112
+ { value: "@t3-oss/env-nextjs", label: "Next.js" },
113
+ { value: "@t3-oss/env-nuxt", label: "Nuxt" },
114
+ { value: "@t3-oss/env-core", label: "Core" }
115
+ ];
116
+ ENV_VALIDATOR_OPTIONS = [
117
+ { value: "zod", label: "Zod" },
118
+ { value: "valibot", label: "Valibot" },
119
+ { value: "arktype", label: "Arktype" }
120
+ ];
121
+ ENV_PRESET_OPTIONS = [
122
+ { value: "netlify", label: "Netlify" },
123
+ { value: "vercel", label: "Vercel" },
124
+ { value: "neonVercel", label: "Neon (Vercel)" },
125
+ { value: "supabaseVercel", label: "Supabase (Vercel)" },
126
+ { value: "uploadThing", label: "UploadThing" },
127
+ { value: "render", label: "Render" },
128
+ { value: "railway", label: "Railway" },
129
+ { value: "fly.io", label: "Fly.io" },
130
+ { value: "upstashRedis", label: "Upstash Redis" },
131
+ { value: "coolify", label: "Coolify" },
132
+ { value: "vite", label: "Vite" },
133
+ { value: "wxt", label: "WXT" }
134
+ ];
135
+ ENV_SPLIT_OPTIONS = [
136
+ { value: "split", label: "Split (env/server.ts, env/client.ts)" },
137
+ { value: "joined", label: "Joined (env.ts)" }
138
+ ];
139
+ TEST_RUNNER_OPTIONS = [
140
+ { value: "vitest", label: "Vitest" },
141
+ { value: "jest", label: "Jest" }
142
+ ];
143
+ EDITOR_CONFIG_OPTIONS = [
144
+ { value: "default", label: "Default (Spaces 2)" },
145
+ { value: "spaces4", label: "Spaces 4" },
146
+ { value: "tabs", label: "Tabs" }
147
+ ];
148
+ LICENSE_TYPE_OPTIONS = [
149
+ { value: "MIT", label: "MIT" },
150
+ { value: "ISC", label: "ISC" },
151
+ { value: "Apache-2.0", label: "Apache 2.0" },
152
+ { value: "UNLICENSED", label: "UNLICENSED" }
153
+ ];
154
+ }
155
+ });
156
+
157
+ // src/utils/handle-cancel.ts
158
+ import { cancel, isCancel, confirm } from "@clack/prompts";
159
+ async function withCancelHandling(promptFn, cancelMessage = "Operation cancelled.") {
160
+ while (true) {
161
+ const response = await promptFn();
162
+ if (isCancel(response)) {
163
+ const shouldCancel = await confirm({
164
+ message: "Do you really want to cancel options selection?"
165
+ });
166
+ if (isCancel(shouldCancel) || shouldCancel) {
167
+ cancel(cancelMessage);
168
+ process.exit(0);
169
+ }
170
+ continue;
171
+ } else {
172
+ return response;
173
+ }
174
+ }
175
+ }
176
+ var init_handle_cancel = __esm({
177
+ "src/utils/handle-cancel.ts"() {
178
+ "use strict";
179
+ init_esm_shims();
180
+ }
181
+ });
182
+
183
+ // src/services/husky.ts
184
+ import { select, log, text } from "@clack/prompts";
185
+ import { execa as execa2 } from "execa";
186
+ import fs from "fs-extra";
187
+ import pc from "picocolors";
188
+ async function promptHusky(config2) {
189
+ log.message(pc.bgMagenta(pc.black(" Husky Configuration ")));
190
+ const hookType = await withCancelHandling(
191
+ async () => select({
192
+ message: "What pre-commit hook would you like to use?",
193
+ options: HUSKY_HOOK_OPTIONS
194
+ })
195
+ );
196
+ const huskyConfig = config2.get("husky");
197
+ huskyConfig.options = { hookType };
68
198
  if (hookType === "lint-staged") {
69
- config.lintStaged = true;
199
+ config2.enableTool("lintStaged");
70
200
  } else if (hookType === "custom") {
71
- const script = await text({
72
- message: "Enter your custom pre-commit script:",
73
- placeholder: "npm test",
74
- validate(value) {
75
- if (value.length === 0) return "Value is required!";
76
- }
77
- });
78
- config.huskyCustomScript = script;
201
+ const script = await withCancelHandling(
202
+ async () => text({
203
+ message: "Enter your custom pre-commit script:",
204
+ placeholder: huskyConfig.options.customScript,
205
+ validate(value) {
206
+ if (value.length === 0) return "Value is required!";
207
+ }
208
+ })
209
+ );
210
+ huskyConfig.options.customScript = script;
79
211
  }
80
212
  }
81
- async function installHusky(config) {
213
+ async function installHusky(config2) {
82
214
  await installPackages(["husky"], true);
83
215
  try {
84
216
  await execa2("npx", ["husky", "init"]);
@@ -86,12 +218,15 @@ async function installHusky(config) {
86
218
  await execa2("npm", ["pkg", "set", "scripts.prepare=husky"]);
87
219
  await execa2("npm", ["run", "prepare"]);
88
220
  }
89
- if (config.huskyHookType === "lint-staged") {
221
+ const husky = config2.get("husky");
222
+ const hookType = husky.options.hookType;
223
+ const customScript = husky.options.customScript;
224
+ if (hookType === "lint-staged") {
90
225
  await fs.outputFile(".husky/pre-commit", "npx lint-staged\n", {
91
226
  mode: 493
92
227
  });
93
- } else if (config.huskyHookType === "custom" && config.huskyCustomScript) {
94
- await fs.outputFile(".husky/pre-commit", `${config.huskyCustomScript}
228
+ } else if (hookType === "custom" && customScript) {
229
+ await fs.outputFile(".husky/pre-commit", `${customScript}
95
230
  `, {
96
231
  mode: 493
97
232
  });
@@ -100,27 +235,32 @@ async function installHusky(config) {
100
235
  var init_husky = __esm({
101
236
  "src/services/husky.ts"() {
102
237
  "use strict";
238
+ init_esm_shims();
103
239
  init_pm();
240
+ init_options();
241
+ init_handle_cancel();
104
242
  }
105
243
  });
106
244
 
107
245
  // src/services/formatter.ts
108
- import { select as select2 } from "@clack/prompts";
246
+ import { select as select2, log as log2 } from "@clack/prompts";
109
247
  import fs2 from "fs-extra";
110
- async function promptFormatter(config) {
111
- if (!config.formatterChoice) {
112
- const formatter = await select2({
248
+ import pc2 from "picocolors";
249
+ async function promptFormatter(config2) {
250
+ const formatterConfig = config2.get("formatter");
251
+ log2.message(pc2.bgBlue(pc2.black(" Formatter Configuration ")));
252
+ const formatter = await withCancelHandling(
253
+ async () => select2({
113
254
  message: "Select a formatter:",
114
- options: [
115
- { value: "prettier", label: "Prettier" },
116
- { value: "oxfmt", label: "Oxfmt" }
117
- ]
118
- });
119
- config.formatterChoice = formatter;
120
- }
255
+ options: FORMATTER_OPTIONS,
256
+ initialValue: formatterConfig.options.choice
257
+ })
258
+ );
259
+ formatterConfig.options = { choice: formatter };
121
260
  }
122
- async function installFormatter(config) {
123
- if (config.formatterChoice === "prettier") {
261
+ async function installFormatter(config2) {
262
+ const choice = config2.get("formatter").options.choice;
263
+ if (choice === "prettier") {
124
264
  await installPackages(["prettier"], true);
125
265
  const configContent = {
126
266
  semi: true,
@@ -130,34 +270,39 @@ async function installFormatter(config) {
130
270
  tabWidth: 2
131
271
  };
132
272
  await fs2.writeJson(".prettierrc", configContent, { spaces: 2 });
133
- } else if (config.formatterChoice === "oxfmt") {
273
+ } else if (choice === "oxfmt") {
134
274
  await installPackages(["oxfmt"], true);
135
275
  }
136
276
  }
137
277
  var init_formatter = __esm({
138
278
  "src/services/formatter.ts"() {
139
279
  "use strict";
280
+ init_esm_shims();
140
281
  init_pm();
282
+ init_options();
283
+ init_handle_cancel();
141
284
  }
142
285
  });
143
286
 
144
287
  // src/services/linter.ts
145
- import { select as select3 } from "@clack/prompts";
288
+ import { select as select3, log as log3 } from "@clack/prompts";
146
289
  import fs3 from "fs-extra";
147
- async function promptLinter(config) {
148
- if (!config.linterChoice) {
149
- const linter = await select3({
290
+ import pc3 from "picocolors";
291
+ async function promptLinter(config2) {
292
+ const linterConfig = config2.get("linter");
293
+ log3.message(pc3.bgYellow(pc3.black(" Linter Configuration ")));
294
+ const linter = await withCancelHandling(
295
+ async () => select3({
150
296
  message: "Select a linter:",
151
- options: [
152
- { value: "eslint", label: "ESLint" },
153
- { value: "oxlint", label: "Oxlint" }
154
- ]
155
- });
156
- config.linterChoice = linter;
157
- }
297
+ options: LINTER_OPTIONS,
298
+ initialValue: linterConfig.options.choice
299
+ })
300
+ );
301
+ linterConfig.options = { choice: linter };
158
302
  }
159
- async function installLinter(config) {
160
- if (config.linterChoice === "eslint") {
303
+ async function installLinter(config2) {
304
+ const choice = config2.get("linter").options.choice;
305
+ if (choice === "eslint") {
161
306
  await installPackages(["eslint"], true);
162
307
  const configContent = {
163
308
  extends: ["eslint:recommended"],
@@ -171,81 +316,72 @@ async function installLinter(config) {
171
316
  }
172
317
  };
173
318
  await fs3.writeJson(".eslintrc.json", configContent, { spaces: 2 });
174
- } else if (config.linterChoice === "oxlint") {
319
+ } else if (choice === "oxlint") {
175
320
  await installPackages(["oxlint"], true);
176
321
  }
177
322
  }
178
323
  var init_linter = __esm({
179
324
  "src/services/linter.ts"() {
180
325
  "use strict";
326
+ init_esm_shims();
181
327
  init_pm();
328
+ init_options();
329
+ init_handle_cancel();
182
330
  }
183
331
  });
184
332
 
185
333
  // src/services/lint-staged.ts
186
- import { multiselect } from "@clack/prompts";
334
+ import { multiselect, log as log4 } from "@clack/prompts";
187
335
  import fs4 from "fs-extra";
188
- async function promptLintStaged(config) {
189
- const lintExtensions = await multiselect({
190
- message: "Select extensions to lint:",
191
- options: [
192
- { value: "js", label: "js" },
193
- { value: "ts", label: "ts" },
194
- { value: "jsx", label: "jsx" },
195
- { value: "tsx", label: "tsx" },
196
- { value: "html", label: "html" },
197
- { value: "vue", label: "vue" },
198
- { value: "svelte", label: "svelte" }
199
- ],
200
- required: false
201
- });
202
- const formatExtensions = await multiselect({
203
- message: "Select extensions to format:",
204
- options: [
205
- { value: "md", label: "md" },
206
- { value: "css", label: "css" },
207
- { value: "scss", label: "scss" },
208
- { value: "json", label: "json" },
209
- { value: "yaml", label: "yaml" },
210
- { value: "html", label: "html" },
211
- { value: "js", label: "js" },
212
- { value: "ts", label: "ts" },
213
- { value: "jsx", label: "jsx" },
214
- { value: "tsx", label: "tsx" },
215
- { value: "vue", label: "vue" },
216
- { value: "svelte", label: "svelte" }
217
- ],
218
- required: false
219
- });
220
- config.lintStagedLintExtensions = lintExtensions;
221
- config.lintStagedFormatExtensions = formatExtensions;
222
- if (lintExtensions.length > 0 && !config.linterChoice) {
223
- await promptLinter(config);
224
- config.linter = true;
225
- }
226
- if (formatExtensions.length > 0 && !config.formatterChoice) {
227
- await promptFormatter(config);
228
- config.formatter = true;
336
+ import pc4 from "picocolors";
337
+ async function promptLintStaged(config2) {
338
+ log4.message(pc4.bgGreen(pc4.black(" Lint-staged Configuration ")));
339
+ const lintExtensions = await withCancelHandling(
340
+ async () => multiselect({
341
+ message: "Select extensions to lint:",
342
+ options: LINT_STAGED_EXTENSIONS,
343
+ required: false
344
+ })
345
+ );
346
+ const formatExtensions = await withCancelHandling(
347
+ async () => multiselect({
348
+ message: "Select extensions to format:",
349
+ options: LINT_STAGED_EXTENSIONS,
350
+ required: false
351
+ })
352
+ );
353
+ config2.get("lintStaged").options = {
354
+ lintExtensions,
355
+ formatExtensions
356
+ };
357
+ if (lintExtensions.length > 0 && !config2.get("linter").selected) {
358
+ await promptLinter(config2);
359
+ config2.enableTool("linter");
360
+ }
361
+ if (formatExtensions.length > 0 && !config2.get("formatter").selected) {
362
+ await promptFormatter(config2);
363
+ config2.enableTool("formatter");
229
364
  }
230
365
  }
231
- async function installLintStaged(config) {
366
+ async function installLintStaged(config2) {
232
367
  await installPackages(["lint-staged"], true);
233
368
  const lintStagedConfig = {};
234
- const lintExts = config.lintStagedLintExtensions || [];
235
- const formatExts = config.lintStagedFormatExtensions || [];
369
+ const lintStagedOptions = config2.get("lintStaged").options;
370
+ const lintExts = lintStagedOptions?.lintExtensions || [];
371
+ const formatExts = lintStagedOptions?.formatExtensions || [];
236
372
  if (lintExts.length > 0) {
237
- await installLinter(config);
373
+ await installLinter(config2);
238
374
  const glob = `*.{${lintExts.join(",")}}`;
239
- if (config.linterChoice === "oxlint") {
375
+ if (config2.get("linter").options.choice === "oxlint") {
240
376
  lintStagedConfig[glob] = ["npx oxlint --fix"];
241
377
  } else {
242
378
  lintStagedConfig[glob] = ["eslint --fix"];
243
379
  }
244
380
  }
245
381
  if (formatExts.length > 0) {
246
- await installFormatter(config);
382
+ await installFormatter(config2);
247
383
  const glob = `*.{${formatExts.join(",")}}`;
248
- if (config.formatterChoice === "oxfmt") {
384
+ if (config2.get("formatter").options.choice === "oxfmt") {
249
385
  lintStagedConfig[glob] = ["npx oxfmt"];
250
386
  } else {
251
387
  lintStagedConfig[glob] = ["prettier --write"];
@@ -256,92 +392,85 @@ async function installLintStaged(config) {
256
392
  var init_lint_staged = __esm({
257
393
  "src/services/lint-staged.ts"() {
258
394
  "use strict";
395
+ init_esm_shims();
259
396
  init_pm();
260
397
  init_formatter();
261
398
  init_linter();
399
+ init_options();
400
+ init_handle_cancel();
262
401
  }
263
402
  });
264
403
 
265
404
  // src/services/env.ts
266
- import { select as select5, confirm, text as text2, multiselect as multiselect2 } from "@clack/prompts";
405
+ import { select as select4, confirm as confirm2, text as text2, multiselect as multiselect2, log as log5 } from "@clack/prompts";
267
406
  import fs5 from "fs-extra";
268
- import path from "path";
269
- async function promptEnv(config) {
270
- const variant = await select5({
271
- message: "Which @t3-oss/env variant?",
272
- options: [
273
- { value: "@t3-oss/env-nextjs", label: "Next.js" },
274
- { value: "@t3-oss/env-nuxt", label: "Nuxt" },
275
- { value: "@t3-oss/env-core", label: "Core" }
276
- ]
277
- });
278
- config.envVariant = variant;
279
- const validator = await select5({
280
- message: "Which validator?",
281
- options: [
282
- { value: "zod", label: "Zod" },
283
- { value: "valibot", label: "Valibot" },
284
- { value: "arktype", label: "Arktype" }
285
- ]
286
- });
287
- config.envValidator = validator;
288
- const installPresets = await confirm({
289
- message: "Install presets?"
290
- });
291
- config.envInstallPresets = installPresets;
407
+ import path2 from "path";
408
+ import pc5 from "picocolors";
409
+ async function promptEnv(config2) {
410
+ log5.message(pc5.bgCyan(pc5.black(" Env Validation Configuration ")));
411
+ const variant = await withCancelHandling(
412
+ async () => select4({
413
+ message: "Which @t3-oss/env variant?",
414
+ options: ENV_VARIANT_OPTIONS
415
+ })
416
+ );
417
+ const validator = await withCancelHandling(
418
+ async () => select4({
419
+ message: "Which validator?",
420
+ options: ENV_VALIDATOR_OPTIONS
421
+ })
422
+ );
423
+ const installPresets = await withCancelHandling(
424
+ async () => confirm2({
425
+ message: "Install presets?"
426
+ })
427
+ );
428
+ let presets;
292
429
  if (installPresets) {
293
- const presets = await multiselect2({
294
- message: "Select preset to extend:",
295
- options: [
296
- { value: "netlify", label: "Netlify" },
297
- { value: "vercel", label: "Vercel" },
298
- { value: "neonVercel", label: "Neon (Vercel)" },
299
- { value: "supabaseVercel", label: "Supabase (Vercel)" },
300
- { value: "uploadThing", label: "UploadThing" },
301
- { value: "render", label: "Render" },
302
- { value: "railway", label: "Railway" },
303
- { value: "fly.io", label: "Fly.io" },
304
- { value: "upstashRedis", label: "Upstash Redis" },
305
- { value: "coolify", label: "Coolify" },
306
- { value: "vite", label: "Vite" },
307
- { value: "wxt", label: "WXT" }
308
- ],
309
- required: false
310
- });
311
- config.envPresets = presets;
430
+ presets = await withCancelHandling(
431
+ async () => multiselect2({
432
+ message: "Select preset to extend:",
433
+ options: ENV_PRESET_OPTIONS,
434
+ required: false
435
+ })
436
+ );
312
437
  }
313
- const split = await select5({
314
- message: "Split or Joined env files?",
315
- options: [
316
- { value: "split", label: "Split (env/server.ts, env/client.ts)" },
317
- { value: "joined", label: "Joined (env.ts)" }
318
- ]
319
- });
320
- config.envSplit = split;
321
- const location = await text2({
322
- message: "Where should the environment files be created?",
323
- initialValue: "src/lib",
324
- placeholder: "src/lib"
325
- });
326
- config.envLocation = location;
438
+ const split = await withCancelHandling(
439
+ async () => select4({
440
+ message: "Split or Joined env files?",
441
+ options: ENV_SPLIT_OPTIONS
442
+ })
443
+ );
444
+ const location = await withCancelHandling(
445
+ async () => text2({
446
+ message: "Where should the environment files be created?",
447
+ initialValue: config2.get("env").options.location || "src/lib",
448
+ placeholder: "src/lib"
449
+ })
450
+ );
451
+ config2.get("env").options = {
452
+ variant,
453
+ validator,
454
+ installPresets,
455
+ presets: presets || [],
456
+ split,
457
+ location
458
+ };
327
459
  }
328
- async function installEnv(config) {
329
- await installPackages([config.envVariant, config.envValidator], true);
330
- if (config.envInstallPresets) {
331
- const presetPackage = `@t3-oss/env-core/presets-${config.envValidator}`;
332
- await installPackages([presetPackage], true);
333
- }
334
- const targetDir = config.envLocation;
335
- await fs5.ensureDir(targetDir);
336
- const presetImport = config.envPresets && config.envPresets.length > 0 ? `// Presets: ${config.envPresets.join(", ")}
460
+ async function installEnv(config2) {
461
+ const envOptions = config2.get("env").options;
462
+ const { variant, validator, location, presets, split } = envOptions;
463
+ await installPackages([variant, validator], true);
464
+ await fs5.ensureDir(location);
465
+ const presetImport = presets && presets.length > 0 ? `// Presets: ${presets.join(", ")}
337
466
  ` : "";
338
- const content = `import { createEnv } from "${config.envVariant}";
339
- import { ${config.envValidator} } from "${config.envValidator}";
467
+ const content = `import { createEnv } from "${variant}";
468
+ import { ${validator} } from "${validator}";
340
469
 
341
470
  ${presetImport}`;
342
- if (config.envSplit === "split") {
471
+ if (split === "split") {
343
472
  await fs5.outputFile(
344
- path.join(targetDir, "env/server.ts"),
473
+ path2.join(location, "env/server.ts"),
345
474
  `${content}
346
475
  // Server env definition
347
476
  export const env = createEnv({
@@ -352,7 +481,7 @@ export const env = createEnv({
352
481
  });`
353
482
  );
354
483
  await fs5.outputFile(
355
- path.join(targetDir, "env/client.ts"),
484
+ path2.join(location, "env/client.ts"),
356
485
  `${content}
357
486
  // Client env definition
358
487
  export const env = createEnv({
@@ -366,7 +495,7 @@ export const env = createEnv({
366
495
  );
367
496
  } else {
368
497
  await fs5.outputFile(
369
- path.join(targetDir, "env.ts"),
498
+ path2.join(location, "env.ts"),
370
499
  `${content}
371
500
  // Joined env definition
372
501
  export const env = createEnv({
@@ -386,7 +515,385 @@ export const env = createEnv({
386
515
  var init_env = __esm({
387
516
  "src/services/env.ts"() {
388
517
  "use strict";
518
+ init_esm_shims();
519
+ init_pm();
520
+ init_options();
521
+ init_handle_cancel();
522
+ }
523
+ });
524
+
525
+ // src/services/test.ts
526
+ import { select as select5, log as log6 } from "@clack/prompts";
527
+ import fs6 from "fs-extra";
528
+ import pc6 from "picocolors";
529
+ async function promptTest(config2) {
530
+ log6.message(pc6.bgRed(pc6.black(" Test Runner Configuration ")));
531
+ const runner = await withCancelHandling(
532
+ async () => select5({
533
+ message: "Select a test runner:",
534
+ options: TEST_RUNNER_OPTIONS
535
+ })
536
+ );
537
+ config2.get("test").options = { runner };
538
+ }
539
+ async function installTest(config2) {
540
+ const runner = config2.get("test").options.runner;
541
+ if (runner === "vitest") {
542
+ await installPackages(["vitest"], true);
543
+ const configFile = "vitest.config.ts";
544
+ if (!await fs6.pathExists(configFile)) {
545
+ await fs6.outputFile(
546
+ configFile,
547
+ `import { defineConfig } from 'vitest/config';
548
+
549
+ export default defineConfig({
550
+ test: {
551
+ environment: 'node',
552
+ },
553
+ });
554
+ `
555
+ );
556
+ }
557
+ } else if (runner === "jest") {
558
+ await installPackages(["jest", "ts-jest", "@types/jest"], true);
559
+ const configFile = "jest.config.js";
560
+ if (!await fs6.pathExists(configFile)) {
561
+ await fs6.outputFile(
562
+ configFile,
563
+ `/** @type {import('ts-jest').JestConfigWithTsJest} */
564
+ module.exports = {
565
+ preset: 'ts-jest',
566
+ testEnvironment: 'node',
567
+ };
568
+ `
569
+ );
570
+ }
571
+ }
572
+ }
573
+ var init_test = __esm({
574
+ "src/services/test.ts"() {
575
+ "use strict";
576
+ init_esm_shims();
389
577
  init_pm();
578
+ init_options();
579
+ init_handle_cancel();
580
+ }
581
+ });
582
+
583
+ // src/services/editor-config.ts
584
+ import { select as select6, log as log7 } from "@clack/prompts";
585
+ import fs7 from "fs-extra";
586
+ import pc7 from "picocolors";
587
+ async function promptEditorConfig(config2) {
588
+ log7.message(pc7.bgWhite(pc7.black(" EditorConfig Configuration ")));
589
+ const currentPreset = config2.get("editorConfig").options.preset;
590
+ const preset = await withCancelHandling(
591
+ async () => select6({
592
+ message: "Select EditorConfig preset:",
593
+ options: EDITOR_CONFIG_OPTIONS,
594
+ initialValue: currentPreset
595
+ })
596
+ );
597
+ config2.get("editorConfig").options = { preset };
598
+ }
599
+ async function installEditorConfig(config2) {
600
+ let content = "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n";
601
+ const preset = config2.get("editorConfig").options.preset;
602
+ if (preset === "default") {
603
+ content += "indent_style = space\nindent_size = 2\n";
604
+ } else if (preset === "spaces4") {
605
+ content += "indent_style = space\nindent_size = 4\n";
606
+ } else if (preset === "tabs") {
607
+ content += "indent_style = tab\n";
608
+ }
609
+ await fs7.outputFile(".editorconfig", content);
610
+ }
611
+ var init_editor_config = __esm({
612
+ "src/services/editor-config.ts"() {
613
+ "use strict";
614
+ init_esm_shims();
615
+ init_options();
616
+ init_handle_cancel();
617
+ }
618
+ });
619
+
620
+ // src/services/license.ts
621
+ import { text as text3, select as select7, log as log8 } from "@clack/prompts";
622
+ import fs8 from "fs-extra";
623
+ import path3 from "path";
624
+ import pc8 from "picocolors";
625
+ async function promptLicense(config2) {
626
+ log8.message(pc8.bgGreen(pc8.black(" License Configuration ")));
627
+ const licenseOptions = config2.get("license").options;
628
+ licenseOptions.name = await withCancelHandling(
629
+ async () => text3({
630
+ message: "License Holder Name:",
631
+ placeholder: "John Doe",
632
+ initialValue: licenseOptions.name
633
+ })
634
+ );
635
+ licenseOptions.email = await withCancelHandling(
636
+ async () => text3({
637
+ message: "License Holder Email:",
638
+ placeholder: "john@example.com",
639
+ initialValue: licenseOptions.email
640
+ })
641
+ );
642
+ licenseOptions.website = await withCancelHandling(
643
+ async () => text3({
644
+ message: "License Holder Website:",
645
+ placeholder: "https://example.com",
646
+ initialValue: licenseOptions.website
647
+ })
648
+ );
649
+ licenseOptions.type = await withCancelHandling(
650
+ async () => select7({
651
+ message: "Select License Type:",
652
+ options: LICENSE_TYPE_OPTIONS
653
+ })
654
+ );
655
+ }
656
+ async function installLicense(config2) {
657
+ const licenseOptions = config2.get("license").options;
658
+ const { type, name, email, website } = licenseOptions;
659
+ if (type !== "UNLICENSED") {
660
+ const year = (/* @__PURE__ */ new Date()).getFullYear().toString();
661
+ const templatePath = path3.join(__dirname, "licenses", `${type}.txt`);
662
+ if (await fs8.pathExists(templatePath)) {
663
+ let licenseContent = await fs8.readFile(templatePath, "utf-8");
664
+ licenseContent = licenseContent.replace(/{YEAR}/g, year);
665
+ licenseContent = licenseContent.replace(/{HOLDER}/g, name || "");
666
+ licenseContent = licenseContent.replace(/{EMAIL}/g, email || "");
667
+ licenseContent = licenseContent.replace(/{WEBSITE}/g, website || "");
668
+ await fs8.outputFile("LICENSE", licenseContent);
669
+ } else {
670
+ const simpleContent = `Copyright (c) ${year} ${name}
671
+ Licensed under ${type}`;
672
+ await fs8.outputFile("LICENSE", simpleContent);
673
+ }
674
+ }
675
+ if (await fs8.pathExists("package.json")) {
676
+ const pkg = await fs8.readJson("package.json");
677
+ pkg.license = type;
678
+ if (name) {
679
+ pkg.author = { name, email, url: website };
680
+ }
681
+ await fs8.writeJson("package.json", pkg, { spaces: 2 });
682
+ }
683
+ }
684
+ var init_license = __esm({
685
+ "src/services/license.ts"() {
686
+ "use strict";
687
+ init_esm_shims();
688
+ init_options();
689
+ init_handle_cancel();
690
+ }
691
+ });
692
+
693
+ // src/config/config.ts
694
+ import pc9 from "picocolors";
695
+ var Config, config;
696
+ var init_config = __esm({
697
+ "src/config/config.ts"() {
698
+ "use strict";
699
+ init_esm_shims();
700
+ Config = class {
701
+ data;
702
+ constructor() {
703
+ this.data = {
704
+ husky: {
705
+ selected: false,
706
+ options: { hookType: "none", customScript: "npm run test" }
707
+ },
708
+ formatter: {
709
+ selected: false,
710
+ options: { choice: "prettier" }
711
+ },
712
+ linter: {
713
+ selected: false,
714
+ options: { choice: "eslint" }
715
+ },
716
+ lintStaged: {
717
+ selected: false,
718
+ options: { lintExtensions: [], formatExtensions: [] }
719
+ },
720
+ env: {
721
+ selected: false,
722
+ options: {
723
+ variant: "@t3-oss/env-nextjs",
724
+ validator: "zod",
725
+ installPresets: false,
726
+ presets: [],
727
+ split: "split",
728
+ location: "src/env"
729
+ }
730
+ },
731
+ test: {
732
+ selected: false,
733
+ options: { runner: "vitest" }
734
+ },
735
+ editorConfig: {
736
+ selected: false,
737
+ options: { preset: "default" }
738
+ },
739
+ license: {
740
+ selected: false,
741
+ options: { name: "", email: "", website: "", type: "MIT" }
742
+ }
743
+ };
744
+ }
745
+ get(tool) {
746
+ return this.data[tool];
747
+ }
748
+ enableTool(tool) {
749
+ this.data[tool].selected = true;
750
+ }
751
+ get summary() {
752
+ const lines = [];
753
+ lines.push(pc9.bold("The following actions will be performed:"));
754
+ lines.push("");
755
+ if (this.data.husky.selected) {
756
+ lines.push(pc9.magenta(`\u2022 Install and configure Husky`));
757
+ if (this.data.husky.options.hookType === "custom") {
758
+ lines.push(pc9.dim(` - Custom hook script`));
759
+ }
760
+ }
761
+ if (this.data.formatter.selected) {
762
+ const choice = this.data.formatter.options.choice;
763
+ lines.push(pc9.blue(`\u2022 Install and configure ${choice || "Formatter"}`));
764
+ }
765
+ if (this.data.linter.selected) {
766
+ const choice = this.data.linter.options.choice;
767
+ lines.push(pc9.yellow(`\u2022 Install and configure ${choice || "Linter"}`));
768
+ }
769
+ if (this.data.lintStaged.selected) {
770
+ lines.push(pc9.green(`\u2022 Install and configure Lint-staged`));
771
+ const lintExts = this.data.lintStaged.options.lintExtensions.join(", ");
772
+ const formatExts = this.data.lintStaged.options.formatExtensions.join(", ");
773
+ if (lintExts) lines.push(pc9.dim(` - Lint: ${lintExts}`));
774
+ if (formatExts) lines.push(pc9.dim(` - Format: ${formatExts}`));
775
+ }
776
+ if (this.data.env.selected) {
777
+ lines.push(pc9.cyan(`\u2022 Install and configure Env Validation`));
778
+ lines.push(pc9.dim(` - Variant: ${this.data.env.options.variant}`));
779
+ lines.push(pc9.dim(` - Validator: ${this.data.env.options.validator}`));
780
+ }
781
+ if (this.data.test.selected) {
782
+ const runner = this.data.test.options.runner;
783
+ lines.push(pc9.red(`\u2022 Install and configure Test Runner (${runner})`));
784
+ }
785
+ if (this.data.editorConfig.selected) {
786
+ const preset = this.data.editorConfig.options.preset;
787
+ lines.push(pc9.white(`\u2022 Create .editorconfig (${preset})`));
788
+ }
789
+ if (this.data.license.selected) {
790
+ const type = this.data.license.options.type;
791
+ const name = this.data.license.options.name;
792
+ lines.push(pc9.green(`\u2022 Create LICENSE (${type})`));
793
+ lines.push(pc9.dim(` - Holder: ${name}`));
794
+ }
795
+ return lines.join("\n");
796
+ }
797
+ };
798
+ config = new Config();
799
+ }
800
+ });
801
+
802
+ // src/steps/execution.ts
803
+ import { spinner } from "@clack/prompts";
804
+ async function execution(config2) {
805
+ const s = spinner();
806
+ if (config2.get("husky").selected) {
807
+ s.start("Setting up Husky...");
808
+ await installHusky(config2);
809
+ s.stop("Husky setup complete.");
810
+ }
811
+ if (config2.get("formatter").selected) {
812
+ const choice = config2.get("formatter").options.choice;
813
+ s.start(`Setting up ${choice}...`);
814
+ await installFormatter(config2);
815
+ s.stop(`${choice} setup complete.`);
816
+ }
817
+ if (config2.get("linter").selected) {
818
+ const choice = config2.get("linter").options.choice;
819
+ s.start(`Setting up ${choice}...`);
820
+ await installLinter(config2);
821
+ s.stop(`${choice} setup complete.`);
822
+ }
823
+ if (config2.get("lintStaged").selected) {
824
+ s.start("Setting up Lint-staged...");
825
+ await installLintStaged(config2);
826
+ s.stop("Lint-staged setup complete.");
827
+ }
828
+ if (config2.get("env").selected) {
829
+ s.start("Setting up Env Validation...");
830
+ await installEnv(config2);
831
+ s.stop("Env Validation setup complete.");
832
+ }
833
+ if (config2.get("test").selected) {
834
+ const runner = config2.get("test").options.runner;
835
+ s.start(`Setting up ${runner}...`);
836
+ await installTest(config2);
837
+ s.stop(`${runner} setup complete.`);
838
+ }
839
+ if (config2.get("editorConfig").selected) {
840
+ s.start("Creating .editorconfig...");
841
+ await installEditorConfig(config2);
842
+ s.stop(".editorconfig created.");
843
+ }
844
+ if (config2.get("license").selected) {
845
+ s.start("Creating LICENSE...");
846
+ await installLicense(config2);
847
+ s.stop("LICENSE created.");
848
+ }
849
+ }
850
+ var init_execution = __esm({
851
+ "src/steps/execution.ts"() {
852
+ "use strict";
853
+ init_esm_shims();
854
+ init_husky();
855
+ init_formatter();
856
+ init_linter();
857
+ init_lint_staged();
858
+ init_env();
859
+ init_test();
860
+ init_editor_config();
861
+ init_license();
862
+ }
863
+ });
864
+
865
+ // src/utils/logger.ts
866
+ import fs9 from "fs-extra";
867
+ import path4 from "path";
868
+ async function logError(error) {
869
+ try {
870
+ await fs9.ensureDir(ERRORS_DIR);
871
+ const gitignorePath = path4.join(LOG_DIR, ".gitignore");
872
+ if (!await fs9.pathExists(gitignorePath)) {
873
+ await fs9.outputFile(gitignorePath, "*\n");
874
+ }
875
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
876
+ const logFile = path4.join(ERRORS_DIR, `log-${timestamp}.txt`);
877
+ const errorMessage = error instanceof Error ? error.stack || error.message : String(error);
878
+ const logContent = `Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}
879
+
880
+ Error:
881
+ ${errorMessage}
882
+ `;
883
+ await fs9.outputFile(logFile, logContent);
884
+ return logFile;
885
+ } catch (e) {
886
+ console.error("Failed to log error:", e);
887
+ return "";
888
+ }
889
+ }
890
+ var LOG_DIR, ERRORS_DIR;
891
+ var init_logger = __esm({
892
+ "src/utils/logger.ts"() {
893
+ "use strict";
894
+ init_esm_shims();
895
+ LOG_DIR = ".mayrlabs/setup-project";
896
+ ERRORS_DIR = path4.join(LOG_DIR, "errors");
390
897
  }
391
898
  });
392
899
 
@@ -415,6 +922,41 @@ async function commitChanges(message) {
415
922
  var init_git = __esm({
416
923
  "src/utils/git.ts"() {
417
924
  "use strict";
925
+ init_esm_shims();
926
+ }
927
+ });
928
+
929
+ // src/steps/git-check.ts
930
+ import { confirm as confirm3, spinner as spinner2, text as text4 } from "@clack/prompts";
931
+ async function gitCheck() {
932
+ if (await isGitRepository()) {
933
+ if (await isGitDirty()) {
934
+ const shouldCommit = await confirm3({
935
+ message: "Your working directory is dirty. Would you like to commit changes before proceeding?"
936
+ });
937
+ if (shouldCommit) {
938
+ const message = text4({
939
+ message: "Enter commit message:",
940
+ placeholder: "wip: pre-setup commit",
941
+ validate(value) {
942
+ if (value.length === 0) return "Commit message is required";
943
+ }
944
+ });
945
+ if (typeof message === "string") {
946
+ const s = spinner2();
947
+ s.start("Committing changes...");
948
+ await commitChanges(message);
949
+ s.stop("Changes committed.");
950
+ }
951
+ }
952
+ }
953
+ }
954
+ }
955
+ var init_git_check = __esm({
956
+ "src/steps/git-check.ts"() {
957
+ "use strict";
958
+ init_esm_shims();
959
+ init_git();
418
960
  }
419
961
  });
420
962
 
@@ -424,7 +966,7 @@ var init_package = __esm({
424
966
  "package.json"() {
425
967
  package_default = {
426
968
  name: "@mayrlabs/setup-project",
427
- version: "0.1.3",
969
+ version: "0.1.5",
428
970
  description: "Interactive CLI to setup project tools",
429
971
  private: false,
430
972
  publishConfig: {
@@ -457,7 +999,11 @@ var init_package = __esm({
457
999
  directory: "packages/setup-project"
458
1000
  },
459
1001
  license: "MIT",
460
- author: "Aghogho Meyoron <youngmayor.dev@gmail.com>",
1002
+ author: {
1003
+ name: "Aghogho Meyoron",
1004
+ email: "youngmayor.dev@gmail.com",
1005
+ url: "https://mayrlabs.com"
1006
+ },
461
1007
  type: "commonjs",
462
1008
  main: "dist/index.js",
463
1009
  scripts: {
@@ -469,143 +1015,188 @@ var init_package = __esm({
469
1015
  "@clack/prompts": "^0.7.0",
470
1016
  commander: "^11.1.0",
471
1017
  execa: "^8.0.1",
1018
+ figlet: "^1.10.0",
472
1019
  "fs-extra": "^11.2.0",
473
1020
  picocolors: "^1.0.0",
474
1021
  zod: "^3.22.4"
475
1022
  },
476
1023
  devDependencies: {
1024
+ "@types/figlet": "^1.7.0",
477
1025
  "@types/fs-extra": "^11.0.4",
478
1026
  "@types/node": "^20.11.16",
479
1027
  tsup: "^8.5.1",
1028
+ tsx: "^4.21.0",
480
1029
  typescript: "^5.3.3"
481
1030
  }
482
1031
  };
483
1032
  }
484
1033
  });
485
1034
 
1035
+ // src/utils/display.ts
1036
+ import pc10 from "picocolors";
1037
+ import figlet from "figlet";
1038
+ function introScreen() {
1039
+ console.log();
1040
+ console.log(
1041
+ pc10.cyan(
1042
+ figlet.textSync("MayR\nLabs", {
1043
+ font: "Graceful",
1044
+ horizontalLayout: "default",
1045
+ verticalLayout: "default",
1046
+ width: 80,
1047
+ whitespaceBreak: true
1048
+ })
1049
+ )
1050
+ );
1051
+ console.log(pc10.cyan(`@mayrlabs/setup-project v${package_default.version}`));
1052
+ console.log();
1053
+ }
1054
+ function showAbout() {
1055
+ introScreen();
1056
+ console.log(pc10.bold("About:"));
1057
+ console.log(
1058
+ " Interactive CLI to setup project tools like Husky, Prettier, ESLint, etc."
1059
+ );
1060
+ console.log("");
1061
+ console.log(pc10.bold("How to use:"));
1062
+ console.log(
1063
+ " Run 'npx @mayrlabs/setup-project' and follow the interactive prompts."
1064
+ );
1065
+ console.log("");
1066
+ }
1067
+ function showVisit() {
1068
+ console.log(pc10.bold("Project Homepage:"));
1069
+ console.log(pc10.underline(pc10.cyan(package_default.homepage)));
1070
+ console.log("");
1071
+ }
1072
+ function showManual() {
1073
+ introScreen();
1074
+ console.log(pc10.bold("Usage:"));
1075
+ console.log(" npx @mayrlabs/setup-project [command] [options]");
1076
+ console.log("");
1077
+ console.log(pc10.bold("Commands:"));
1078
+ console.log(" about Show project details");
1079
+ console.log(" version Show version information");
1080
+ console.log(" visit Visit project homepage");
1081
+ console.log(" help Show this help message");
1082
+ console.log("");
1083
+ console.log(pc10.bold("Options:"));
1084
+ console.log(" -a, --about Show project details");
1085
+ console.log(" -v, --version Show version information");
1086
+ console.log(" -V, --visit Visit project homepage");
1087
+ console.log(" -h, --help Show this help message");
1088
+ console.log("");
1089
+ }
1090
+ var init_display = __esm({
1091
+ "src/utils/display.ts"() {
1092
+ "use strict";
1093
+ init_esm_shims();
1094
+ init_package();
1095
+ }
1096
+ });
1097
+
486
1098
  // src/index.ts
487
- import {
488
- intro,
489
- outro,
490
- multiselect as multiselect3,
491
- isCancel,
492
- cancel,
493
- note,
494
- confirm as confirm2,
495
- spinner
496
- } from "@clack/prompts";
497
- import pc from "picocolors";
1099
+ import { outro, multiselect as multiselect3, note, confirm as confirm4, intro } from "@clack/prompts";
1100
+ import pc11 from "picocolors";
498
1101
  import { program } from "commander";
499
1102
  var require_index = __commonJS({
500
1103
  "src/index.ts"() {
1104
+ init_esm_shims();
501
1105
  init_husky();
502
1106
  init_formatter();
503
1107
  init_linter();
504
1108
  init_lint_staged();
505
1109
  init_env();
506
- init_git();
507
- init_package();
1110
+ init_test();
1111
+ init_editor_config();
1112
+ init_license();
1113
+ init_config();
1114
+ init_handle_cancel();
1115
+ init_options();
1116
+ init_execution();
1117
+ init_logger();
1118
+ init_git_check();
1119
+ init_display();
508
1120
  async function main() {
509
- intro(pc.bgCyan(pc.black(" @mayrlabs/setup-project ")));
510
- if (await isGitRepository()) {
511
- if (await isGitDirty()) {
512
- const shouldCommit = await confirm2({
513
- message: "Your working directory is dirty. Would you like to commit changes before proceeding?"
514
- });
515
- if (shouldCommit) {
516
- const message = await import("@clack/prompts").then(
517
- (m) => m.text({
518
- message: "Enter commit message:",
519
- placeholder: "wip: pre-setup commit",
520
- validate(value) {
521
- if (value.length === 0) return "Commit message is required";
522
- }
523
- })
524
- );
525
- if (typeof message === "string") {
526
- const s2 = spinner();
527
- s2.start("Committing changes...");
528
- await commitChanges(message);
529
- s2.stop("Changes committed.");
530
- }
531
- }
1121
+ try {
1122
+ introScreen();
1123
+ intro(
1124
+ pc11.inverse(pc11.bold(pc11.cyan(" Welcome to the Project Setup Wizard ")))
1125
+ );
1126
+ await gitCheck();
1127
+ const tools = await withCancelHandling(
1128
+ async () => multiselect3({
1129
+ message: "Select tools to configure:",
1130
+ options: TOOL_OPTIONS,
1131
+ required: false
1132
+ })
1133
+ );
1134
+ tools.forEach((tool) => config.enableTool(tool));
1135
+ if (config.get("husky").selected) await promptHusky(config);
1136
+ if (config.get("formatter").selected) await promptFormatter(config);
1137
+ if (config.get("linter").selected) await promptLinter(config);
1138
+ if (config.get("lintStaged").selected) await promptLintStaged(config);
1139
+ if (config.get("env").selected) await promptEnv(config);
1140
+ if (config.get("test").selected) await promptTest(config);
1141
+ if (config.get("editorConfig").selected) await promptEditorConfig(config);
1142
+ if (config.get("license").selected) await promptLicense(config);
1143
+ note(config.summary, "Configuration Summary");
1144
+ const proceed = await withCancelHandling(
1145
+ async () => confirm4({
1146
+ message: "Do you want to proceed with the installation?"
1147
+ })
1148
+ );
1149
+ if (!proceed) {
1150
+ outro(pc11.yellow("Installation cancelled."));
1151
+ process.exit(0);
532
1152
  }
1153
+ await execution(config);
1154
+ outro(pc11.green("Setup complete!"));
1155
+ } catch (error) {
1156
+ const logPath = await logError(error);
1157
+ outro(pc11.red(`
1158
+ Something went wrong!
1159
+ Error log saved to: ${logPath}`));
1160
+ process.exit(1);
533
1161
  }
534
- const tools = await multiselect3({
535
- message: "Select tools to configure:",
536
- options: [
537
- { value: "husky", label: "Husky" },
538
- { value: "formatter", label: "Formatter (Prettier/Oxfmt)" },
539
- { value: "linter", label: "Linter (Eslint/Oxlint)" },
540
- { value: "lint-staged", label: "Lint-staged" },
541
- { value: "env", label: "Env Validation (@t3-oss/env)" }
542
- ],
543
- required: false
544
- });
545
- if (isCancel(tools)) {
546
- cancel("Operation cancelled.");
1162
+ }
1163
+ program.helpOption(false);
1164
+ program.name("setup-project").description("Interactive setup for common project tools").option("-a, --about", "Show project details").option("-v, --version", "Show version info").option("-V, --visit", "Visit project homepage").option("-h, --help", "Show help");
1165
+ program.command("about").action(() => {
1166
+ showAbout();
1167
+ process.exit(0);
1168
+ });
1169
+ program.command("version").action(() => {
1170
+ introScreen();
1171
+ process.exit(0);
1172
+ });
1173
+ program.command("visit").action(() => {
1174
+ showVisit();
1175
+ process.exit(0);
1176
+ });
1177
+ program.command("help").action(() => {
1178
+ showManual();
1179
+ process.exit(0);
1180
+ });
1181
+ program.action(async (options) => {
1182
+ if (options.about) {
1183
+ showAbout();
547
1184
  process.exit(0);
548
1185
  }
549
- const selectedTools = tools;
550
- const config = {
551
- husky: selectedTools.includes("husky"),
552
- formatter: selectedTools.includes("formatter"),
553
- linter: selectedTools.includes("linter"),
554
- lintStaged: selectedTools.includes("lint-staged"),
555
- env: selectedTools.includes("env")
556
- };
557
- if (config.husky) await promptHusky(config);
558
- if (config.formatter) await promptFormatter(config);
559
- if (config.linter) await promptLinter(config);
560
- if (config.lintStaged) await promptLintStaged(config);
561
- if (config.env) await promptEnv(config);
562
- let summary = "The following actions will be performed:\n\n";
563
- if (config.husky) summary += "- Install and configure Husky\n";
564
- if (config.formatter)
565
- summary += `- Install and configure ${config.formatterChoice}
566
- `;
567
- if (config.linter)
568
- summary += `- Install and configure ${config.linterChoice}
569
- `;
570
- if (config.lintStaged) summary += "- Install and configure Lint-staged\n";
571
- if (config.env) summary += "- Install and configure @t3-oss/env\n";
572
- note(summary, "Configuration Summary");
573
- const proceed = await confirm2({
574
- message: "Do you want to proceed with the installation?"
575
- });
576
- if (!proceed || isCancel(proceed)) {
577
- cancel("Installation cancelled. Configuration saved.");
1186
+ if (options.version) {
1187
+ introScreen();
578
1188
  process.exit(0);
579
1189
  }
580
- const s = spinner();
581
- if (config.husky) {
582
- s.start("Setting up Husky...");
583
- await installHusky(config);
584
- s.stop("Husky setup complete.");
585
- }
586
- if (config.formatter) {
587
- s.start(`Setting up ${config.formatterChoice}...`);
588
- await installFormatter(config);
589
- s.stop(`${config.formatterChoice} setup complete.`);
590
- }
591
- if (config.linter) {
592
- s.start(`Setting up ${config.linterChoice}...`);
593
- await installLinter(config);
594
- s.stop(`${config.linterChoice} setup complete.`);
595
- }
596
- if (config.lintStaged) {
597
- s.start("Setting up Lint-staged...");
598
- await installLintStaged(config);
599
- s.stop("Lint-staged setup complete.");
1190
+ if (options.visit) {
1191
+ showVisit();
1192
+ process.exit(0);
600
1193
  }
601
- if (config.env) {
602
- s.start("Setting up Env Validation...");
603
- await installEnv(config);
604
- s.stop("Env Validation setup complete.");
1194
+ if (options.help) {
1195
+ showManual();
1196
+ process.exit(0);
605
1197
  }
606
- outro(pc.green("Setup complete!"));
607
- }
608
- program.name("setup-project").description("Interactive setup for common project tools").version(package_default.version).action(main);
1198
+ await main();
1199
+ });
609
1200
  program.parse();
610
1201
  }
611
1202
  });
@@ -616,4 +1207,3 @@ export default require_index();
616
1207
  * Software should feel intentional.
617
1208
  */
618
1209
 
619
- //# sourceMappingURL=index.mjs.map