@lambertkeith/spec-go 0.2.4

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 (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +163 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +850 -0
  5. package/dist/index.js.map +1 -0
  6. package/package.json +46 -0
  7. package/templates/django/README.md +27 -0
  8. package/templates/django/_gitignore +20 -0
  9. package/templates/django/_template.json +14 -0
  10. package/templates/django/manage.py +22 -0
  11. package/templates/django/project_name/__init__.py +1 -0
  12. package/templates/django/project_name/asgi.py +11 -0
  13. package/templates/django/project_name/settings.py +75 -0
  14. package/templates/django/project_name/urls.py +16 -0
  15. package/templates/django/project_name/wsgi.py +11 -0
  16. package/templates/django/pyproject.toml +20 -0
  17. package/templates/empty/README.md +3 -0
  18. package/templates/empty/_gitignore +6 -0
  19. package/templates/empty/_template.json +6 -0
  20. package/templates/express-ts/README.md +27 -0
  21. package/templates/express-ts/_gitignore +7 -0
  22. package/templates/express-ts/_template.json +13 -0
  23. package/templates/express-ts/package.json +23 -0
  24. package/templates/express-ts/src/index.ts +17 -0
  25. package/templates/express-ts/src/middleware/error-handler.ts +14 -0
  26. package/templates/express-ts/src/routes/index.ts +11 -0
  27. package/templates/express-ts/tsconfig.json +17 -0
  28. package/templates/express-ts/tsup.config.ts +9 -0
  29. package/templates/fastapi/README.md +21 -0
  30. package/templates/fastapi/_gitignore +16 -0
  31. package/templates/fastapi/_template.json +14 -0
  32. package/templates/fastapi/pyproject.toml +21 -0
  33. package/templates/fastapi/src/project_name/__init__.py +1 -0
  34. package/templates/fastapi/src/project_name/main.py +20 -0
  35. package/templates/fastapi/src/project_name/routes/__init__.py +8 -0
  36. package/templates/flask/README.md +15 -0
  37. package/templates/flask/_gitignore +17 -0
  38. package/templates/flask/_template.json +14 -0
  39. package/templates/flask/pyproject.toml +19 -0
  40. package/templates/flask/src/project_name/__init__.py +1 -0
  41. package/templates/flask/src/project_name/app.py +15 -0
  42. package/templates/flask/src/project_name/routes/__init__.py +8 -0
  43. package/templates/fullstack-react-node/README.md +35 -0
  44. package/templates/fullstack-react-node/_gitignore +7 -0
  45. package/templates/fullstack-react-node/_template.json +14 -0
  46. package/templates/fullstack-react-node/backend/package.json +22 -0
  47. package/templates/fullstack-react-node/backend/src/index.ts +20 -0
  48. package/templates/fullstack-react-node/backend/tsconfig.json +17 -0
  49. package/templates/fullstack-react-node/backend/tsup.config.ts +9 -0
  50. package/templates/fullstack-react-node/frontend/index.html +12 -0
  51. package/templates/fullstack-react-node/frontend/package.json +22 -0
  52. package/templates/fullstack-react-node/frontend/src/App.css +16 -0
  53. package/templates/fullstack-react-node/frontend/src/App.tsx +22 -0
  54. package/templates/fullstack-react-node/frontend/src/main.tsx +9 -0
  55. package/templates/fullstack-react-node/frontend/tsconfig.json +20 -0
  56. package/templates/fullstack-react-node/frontend/vite.config.ts +14 -0
  57. package/templates/fullstack-react-node/package.json +10 -0
  58. package/templates/fullstack-react-node/pnpm-workspace.yaml +3 -0
  59. package/templates/fullstack-react-python/Makefile +35 -0
  60. package/templates/fullstack-react-python/README.md +43 -0
  61. package/templates/fullstack-react-python/_gitignore +18 -0
  62. package/templates/fullstack-react-python/_template.json +25 -0
  63. package/templates/fullstack-react-python/backend/pyproject.toml +21 -0
  64. package/templates/fullstack-react-python/backend/src/project_name/__init__.py +1 -0
  65. package/templates/fullstack-react-python/backend/src/project_name/main.py +29 -0
  66. package/templates/fullstack-react-python/backend/src/project_name/routes/__init__.py +8 -0
  67. package/templates/fullstack-react-python/frontend/index.html +12 -0
  68. package/templates/fullstack-react-python/frontend/package.json +22 -0
  69. package/templates/fullstack-react-python/frontend/src/App.css +16 -0
  70. package/templates/fullstack-react-python/frontend/src/App.tsx +22 -0
  71. package/templates/fullstack-react-python/frontend/src/main.tsx +9 -0
  72. package/templates/fullstack-react-python/frontend/tsconfig.json +20 -0
  73. package/templates/fullstack-react-python/frontend/vite.config.ts +14 -0
  74. package/templates/fullstack-vue-node/README.md +35 -0
  75. package/templates/fullstack-vue-node/_gitignore +7 -0
  76. package/templates/fullstack-vue-node/_template.json +14 -0
  77. package/templates/fullstack-vue-node/backend/package.json +22 -0
  78. package/templates/fullstack-vue-node/backend/src/index.ts +20 -0
  79. package/templates/fullstack-vue-node/backend/tsconfig.json +17 -0
  80. package/templates/fullstack-vue-node/backend/tsup.config.ts +9 -0
  81. package/templates/fullstack-vue-node/frontend/index.html +12 -0
  82. package/templates/fullstack-vue-node/frontend/package.json +20 -0
  83. package/templates/fullstack-vue-node/frontend/src/App.vue +41 -0
  84. package/templates/fullstack-vue-node/frontend/src/main.ts +4 -0
  85. package/templates/fullstack-vue-node/frontend/src/vite-env.d.ts +1 -0
  86. package/templates/fullstack-vue-node/frontend/tsconfig.json +20 -0
  87. package/templates/fullstack-vue-node/frontend/vite.config.ts +14 -0
  88. package/templates/fullstack-vue-node/package.json +10 -0
  89. package/templates/fullstack-vue-node/pnpm-workspace.yaml +3 -0
  90. package/templates/next-ts/README.md +26 -0
  91. package/templates/next-ts/_gitignore +34 -0
  92. package/templates/next-ts/_template.json +13 -0
  93. package/templates/next-ts/next.config.ts +7 -0
  94. package/templates/next-ts/package.json +22 -0
  95. package/templates/next-ts/src/app/globals.css +21 -0
  96. package/templates/next-ts/src/app/layout.tsx +19 -0
  97. package/templates/next-ts/src/app/page.tsx +10 -0
  98. package/templates/next-ts/tsconfig.json +27 -0
  99. package/templates/node-ts/README.md +21 -0
  100. package/templates/node-ts/_gitignore +7 -0
  101. package/templates/node-ts/_template.json +16 -0
  102. package/templates/node-ts/package.json +19 -0
  103. package/templates/node-ts/src/index.ts +1 -0
  104. package/templates/node-ts/tsconfig.json +17 -0
  105. package/templates/node-ts/tsup.config.ts +9 -0
  106. package/templates/python-uv/README.md +22 -0
  107. package/templates/python-uv/_gitignore +30 -0
  108. package/templates/python-uv/_template.json +14 -0
  109. package/templates/python-uv/pyproject.toml +20 -0
  110. package/templates/python-uv/src/project_name/__init__.py +10 -0
  111. package/templates/python-uv/src/project_name/__main__.py +4 -0
  112. package/templates/react-ts/_gitignore +6 -0
  113. package/templates/react-ts/_template.json +13 -0
  114. package/templates/react-ts/index.html +13 -0
  115. package/templates/react-ts/package.json +23 -0
  116. package/templates/react-ts/src/App.css +14 -0
  117. package/templates/react-ts/src/App.tsx +12 -0
  118. package/templates/react-ts/src/index.css +11 -0
  119. package/templates/react-ts/src/main.tsx +10 -0
  120. package/templates/react-ts/tsconfig.json +20 -0
  121. package/templates/react-ts/vite.config.ts +6 -0
  122. package/templates/springboot/.mvn/wrapper/maven-wrapper.properties +2 -0
  123. package/templates/springboot/README.md +27 -0
  124. package/templates/springboot/_gitignore +36 -0
  125. package/templates/springboot/_template.json +14 -0
  126. package/templates/springboot/mvnw +19 -0
  127. package/templates/springboot/mvnw.cmd +13 -0
  128. package/templates/springboot/pom.xml +46 -0
  129. package/templates/springboot/src/main/java/com/example/project_name/Application.java +12 -0
  130. package/templates/springboot/src/main/java/com/example/project_name/controller/HelloController.java +25 -0
  131. package/templates/springboot/src/main/resources/application.yml +6 -0
  132. package/templates/springboot/src/test/java/com/example/project_name/ApplicationTests.java +12 -0
  133. package/templates/template.config.json +102 -0
  134. package/templates/vue-ts/_gitignore +6 -0
  135. package/templates/vue-ts/_template.json +13 -0
  136. package/templates/vue-ts/index.html +13 -0
  137. package/templates/vue-ts/package.json +20 -0
  138. package/templates/vue-ts/src/App.vue +37 -0
  139. package/templates/vue-ts/src/main.ts +5 -0
  140. package/templates/vue-ts/src/style.css +11 -0
  141. package/templates/vue-ts/src/vite-env.d.ts +7 -0
  142. package/templates/vue-ts/tsconfig.json +20 -0
  143. package/templates/vue-ts/vite.config.ts +6 -0
package/dist/index.js ADDED
@@ -0,0 +1,850 @@
1
+ #!/usr/bin/env node
2
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
+ }) : x)(function(x) {
5
+ if (typeof require !== "undefined") return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
8
+
9
+ // src/cli.ts
10
+ import path7 from "path";
11
+ import fs5 from "fs";
12
+ import { Command } from "commander";
13
+ import pc6 from "picocolors";
14
+
15
+ // package.json
16
+ var version = "0.2.4";
17
+
18
+ // src/prompts.ts
19
+ import path2 from "path";
20
+ import fs from "fs";
21
+ import { input, select, confirm, Separator } from "@inquirer/prompts";
22
+ import pc from "picocolors";
23
+
24
+ // src/utils.ts
25
+ import path from "path";
26
+ import { fileURLToPath } from "url";
27
+ import { spawn } from "child_process";
28
+ var __filename = fileURLToPath(import.meta.url);
29
+ var __dirname = path.dirname(__filename);
30
+ function getTemplatesDir() {
31
+ return path.resolve(__dirname, "..", "templates");
32
+ }
33
+ function isValidPackageName(name) {
34
+ return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name);
35
+ }
36
+ function toValidPackageName(name) {
37
+ return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9-~]+/g, "-");
38
+ }
39
+ function isEmpty(dirPath) {
40
+ const fs6 = __require("fs");
41
+ if (!fs6.existsSync(dirPath)) {
42
+ return true;
43
+ }
44
+ const files = fs6.readdirSync(dirPath);
45
+ return files.length === 0 || files.length === 1 && files[0] === ".git";
46
+ }
47
+ function execAsync(command, args, options = {}) {
48
+ return new Promise((resolve) => {
49
+ const proc = spawn(command, args, {
50
+ cwd: options.cwd,
51
+ stdio: options.stdio === "inherit" ? "inherit" : "pipe",
52
+ shell: true
53
+ });
54
+ let stdout = "";
55
+ let stderr = "";
56
+ if (proc.stdout) {
57
+ proc.stdout.on("data", (data) => {
58
+ stdout += data.toString();
59
+ });
60
+ }
61
+ if (proc.stderr) {
62
+ proc.stderr.on("data", (data) => {
63
+ stderr += data.toString();
64
+ });
65
+ }
66
+ proc.on("close", (code) => {
67
+ resolve({ code: code ?? 1, stdout, stderr });
68
+ });
69
+ proc.on("error", () => {
70
+ resolve({ code: 1, stdout, stderr });
71
+ });
72
+ });
73
+ }
74
+
75
+ // src/prompts.ts
76
+ async function runPrompts(argProjectName, options, userConfig = {}) {
77
+ const defaults = userConfig.defaults ?? {};
78
+ const templatesDir = getTemplatesDir();
79
+ const registryPath = path2.join(templatesDir, "template.config.json");
80
+ const registry = JSON.parse(
81
+ fs.readFileSync(registryPath, "utf-8")
82
+ );
83
+ let projectName = argProjectName;
84
+ if (!projectName) {
85
+ projectName = await input({
86
+ message: "\u9879\u76EE\u540D\u79F0:",
87
+ default: "my-project",
88
+ validate: (value) => {
89
+ if (!value.trim()) {
90
+ return "\u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A";
91
+ }
92
+ if (!isValidPackageName(toValidPackageName(value))) {
93
+ return "\u65E0\u6548\u7684\u9879\u76EE\u540D\u79F0";
94
+ }
95
+ return true;
96
+ }
97
+ });
98
+ }
99
+ const validName = toValidPackageName(projectName);
100
+ const targetDir = path2.resolve(process.cwd(), validName);
101
+ if (fs.existsSync(targetDir) && !isEmpty(targetDir)) {
102
+ const overwrite = await confirm({
103
+ message: `\u76EE\u6807\u76EE\u5F55 "${validName}" \u975E\u7A7A\uFF0C\u662F\u5426\u7EE7\u7EED? (\u5C06\u8986\u76D6\u5DF2\u6709\u6587\u4EF6)`,
104
+ default: false
105
+ });
106
+ if (!overwrite) {
107
+ const error = new Error("PROMPT_CANCELLED");
108
+ throw error;
109
+ }
110
+ }
111
+ let template = options.template;
112
+ if (!template) {
113
+ const defaultTemplate = defaults.template;
114
+ const singleTemplates = registry.templates.filter((t) => t.category !== "fullstack");
115
+ const fullstackTemplates = registry.templates.filter((t) => t.category === "fullstack");
116
+ const templateChoices = [];
117
+ templateChoices.push(new Separator("\u2500\u2500 \u5355\u4F53\u9879\u76EE \u2500\u2500"));
118
+ for (const t of singleTemplates) {
119
+ templateChoices.push({
120
+ name: `${t.displayName} ${pc.dim(`- ${t.description}`)}`,
121
+ value: t.name
122
+ });
123
+ }
124
+ if (fullstackTemplates.length > 0) {
125
+ templateChoices.push(new Separator("\u2500\u2500 \u524D\u540E\u7AEF\u5206\u79BB \u2500\u2500"));
126
+ for (const t of fullstackTemplates) {
127
+ templateChoices.push({
128
+ name: `${t.displayName} ${pc.dim(`- ${t.description}`)}`,
129
+ value: t.name
130
+ });
131
+ }
132
+ }
133
+ template = await select({
134
+ message: "\u9009\u62E9\u6A21\u677F:",
135
+ choices: templateChoices,
136
+ default: defaultTemplate && registry.templates.some((t) => t.name === defaultTemplate) ? defaultTemplate : void 0
137
+ });
138
+ } else {
139
+ const found = registry.templates.find((t) => t.name === template);
140
+ if (!found) {
141
+ console.log(pc.red(`\u9519\u8BEF: \u672A\u627E\u5230\u6A21\u677F "${template}"`));
142
+ console.log(pc.dim(`\u53EF\u7528\u6A21\u677F: ${registry.templates.map((t) => t.name).join(", ")}`));
143
+ process.exit(1);
144
+ }
145
+ }
146
+ let initGit2 = options.git !== false;
147
+ if (options.git === void 0) {
148
+ initGit2 = await confirm({
149
+ message: "\u521D\u59CB\u5316 Git \u4ED3\u5E93?",
150
+ default: true
151
+ });
152
+ }
153
+ let createGithub = options.github ?? false;
154
+ if (initGit2 && options.github === void 0) {
155
+ createGithub = await confirm({
156
+ message: "\u5728 GitHub \u521B\u5EFA\u8FDC\u7A0B\u4ED3\u5E93?",
157
+ default: defaults.github ?? false
158
+ });
159
+ }
160
+ let isPublic = options.public ?? false;
161
+ if (createGithub && options.public === void 0) {
162
+ const publicDefault = defaults.public ?? false;
163
+ isPublic = await select({
164
+ message: "\u4ED3\u5E93\u53EF\u89C1\u6027:",
165
+ choices: [
166
+ { name: "private (\u79C1\u6709)", value: false },
167
+ { name: "public (\u516C\u5F00)", value: true }
168
+ ],
169
+ default: publicDefault
170
+ });
171
+ }
172
+ return {
173
+ projectName: validName,
174
+ template,
175
+ targetDir,
176
+ initGit: initGit2,
177
+ createGithub,
178
+ isPublic,
179
+ noInstall: options.install === false
180
+ };
181
+ }
182
+
183
+ // src/scaffold.ts
184
+ import path3 from "path";
185
+ import fs2 from "fs-extra";
186
+ async function scaffoldProject(options) {
187
+ const templatesDir = getTemplatesDir();
188
+ const registryPath = path3.join(templatesDir, "template.config.json");
189
+ const registry = await fs2.readJson(registryPath);
190
+ const templateEntry = registry.templates.find((t) => t.name === options.template);
191
+ if (!templateEntry) {
192
+ throw new Error(`\u672A\u627E\u5230\u6A21\u677F: ${options.template}`);
193
+ }
194
+ const templateDir = path3.join(templatesDir, templateEntry.dir);
195
+ const templateConfigPath = path3.join(templateDir, "_template.json");
196
+ let templateConfig = null;
197
+ if (await fs2.pathExists(templateConfigPath)) {
198
+ templateConfig = await fs2.readJson(templateConfigPath);
199
+ }
200
+ await fs2.ensureDir(options.targetDir);
201
+ const files = await fs2.readdir(templateDir);
202
+ for (const file of files) {
203
+ if (file === "_template.json") {
204
+ continue;
205
+ }
206
+ const srcPath = path3.join(templateDir, file);
207
+ let destFileName = file;
208
+ if (templateConfig?.fileRenames?.[file]) {
209
+ destFileName = templateConfig.fileRenames[file];
210
+ if (destFileName === "{{projectName}}") {
211
+ destFileName = options.projectName;
212
+ }
213
+ }
214
+ const destPath = path3.join(options.targetDir, destFileName);
215
+ const stat = await fs2.stat(srcPath);
216
+ if (stat.isDirectory()) {
217
+ await copyDirectory(srcPath, destPath, options.projectName, templateConfig);
218
+ } else {
219
+ await copyFile(srcPath, destPath, options.projectName, templateConfig);
220
+ }
221
+ }
222
+ return templateConfig;
223
+ }
224
+ async function copyDirectory(srcDir, destDir, projectName, config) {
225
+ await fs2.ensureDir(destDir);
226
+ const files = await fs2.readdir(srcDir);
227
+ for (const file of files) {
228
+ const srcPath = path3.join(srcDir, file);
229
+ let destFileName = file;
230
+ if (config?.fileRenames?.[file]) {
231
+ destFileName = config.fileRenames[file];
232
+ if (destFileName === "{{projectName}}") {
233
+ destFileName = projectName;
234
+ }
235
+ }
236
+ const destPath = path3.join(destDir, destFileName);
237
+ const stat = await fs2.stat(srcPath);
238
+ if (stat.isDirectory()) {
239
+ await copyDirectory(srcPath, destPath, projectName, config);
240
+ } else {
241
+ await copyFile(srcPath, destPath, projectName, config);
242
+ }
243
+ }
244
+ }
245
+ async function copyFile(srcPath, destPath, projectName, config) {
246
+ const binaryExtensions = [
247
+ ".png",
248
+ ".jpg",
249
+ ".jpeg",
250
+ ".gif",
251
+ ".ico",
252
+ ".webp",
253
+ ".woff",
254
+ ".woff2",
255
+ ".ttf",
256
+ ".eot",
257
+ ".zip",
258
+ ".tar",
259
+ ".gz"
260
+ ];
261
+ const ext = path3.extname(srcPath).toLowerCase();
262
+ if (binaryExtensions.includes(ext)) {
263
+ await fs2.copy(srcPath, destPath);
264
+ return;
265
+ }
266
+ let content = await fs2.readFile(srcPath, "utf-8");
267
+ content = content.replace(/\{\{projectName\}\}/g, projectName);
268
+ if (config?.variables) {
269
+ for (const [key, value] of Object.entries(config.variables)) {
270
+ const placeholder = `{{${key}}}`;
271
+ const replacement = value === "{{projectName}}" ? projectName : value;
272
+ content = content.replace(new RegExp(placeholder.replace(/[{}]/g, "\\$&"), "g"), replacement);
273
+ }
274
+ }
275
+ await fs2.writeFile(destPath, content, "utf-8");
276
+ }
277
+
278
+ // src/git.ts
279
+ import pc2 from "picocolors";
280
+
281
+ // src/config.ts
282
+ import fs3 from "fs";
283
+ import path4 from "path";
284
+ import os from "os";
285
+ var CONFIG_PATH = path4.join(os.homedir(), ".spec-go.json");
286
+ var DEFAULT_CONFIG = {
287
+ defaults: {
288
+ github: false,
289
+ public: false,
290
+ template: ""
291
+ },
292
+ github: {
293
+ token: "",
294
+ defaultOrg: ""
295
+ }
296
+ };
297
+ function ensureConfigExists() {
298
+ if (!fs3.existsSync(CONFIG_PATH)) {
299
+ saveConfig(DEFAULT_CONFIG);
300
+ }
301
+ }
302
+ function loadConfig() {
303
+ try {
304
+ if (fs3.existsSync(CONFIG_PATH)) {
305
+ const content = fs3.readFileSync(CONFIG_PATH, "utf-8");
306
+ return JSON.parse(content);
307
+ }
308
+ } catch {
309
+ }
310
+ return {};
311
+ }
312
+ function saveConfig(config) {
313
+ fs3.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), "utf-8");
314
+ fs3.chmodSync(CONFIG_PATH, 384);
315
+ }
316
+ function getConfigPath() {
317
+ return CONFIG_PATH;
318
+ }
319
+
320
+ // src/github-api.ts
321
+ var GITHUB_API_BASE = "https://api.github.com";
322
+ async function githubFetch(endpoint, token, options = {}) {
323
+ const url = `${GITHUB_API_BASE}${endpoint}`;
324
+ try {
325
+ const response = await fetch(url, {
326
+ ...options,
327
+ headers: {
328
+ "Accept": "application/vnd.github+json",
329
+ "Authorization": `Bearer ${token}`,
330
+ "X-GitHub-Api-Version": "2022-11-28",
331
+ "User-Agent": "spec-go",
332
+ ...options.headers
333
+ }
334
+ });
335
+ if (response.status === 403) {
336
+ const rateLimitRemaining = response.headers.get("x-ratelimit-remaining");
337
+ const rateLimitReset = response.headers.get("x-ratelimit-reset");
338
+ if (rateLimitRemaining === "0" && rateLimitReset) {
339
+ const resetDate = new Date(parseInt(rateLimitReset) * 1e3);
340
+ return {
341
+ success: false,
342
+ error: "API \u8BF7\u6C42\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650",
343
+ statusCode: 403,
344
+ rateLimitReset: resetDate
345
+ };
346
+ }
347
+ }
348
+ if (response.status === 401) {
349
+ return {
350
+ success: false,
351
+ error: "Token \u65E0\u6548\u6216\u5DF2\u8FC7\u671F",
352
+ statusCode: 401
353
+ };
354
+ }
355
+ if (!response.ok) {
356
+ const errorData = await response.json();
357
+ return {
358
+ success: false,
359
+ error: errorData.message || `\u8BF7\u6C42\u5931\u8D25: ${response.status}`,
360
+ statusCode: response.status
361
+ };
362
+ }
363
+ const data = await response.json();
364
+ return { success: true, data };
365
+ } catch (err) {
366
+ return {
367
+ success: false,
368
+ error: err instanceof Error ? err.message : "\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25"
369
+ };
370
+ }
371
+ }
372
+ async function validateToken(token) {
373
+ return githubFetch("/user", token);
374
+ }
375
+ async function createRepository(token, options) {
376
+ const endpoint = options.org ? `/orgs/${options.org}/repos` : "/user/repos";
377
+ const body = {
378
+ name: options.name,
379
+ description: options.description || `Created with spec-go`,
380
+ private: options.isPrivate,
381
+ auto_init: false
382
+ };
383
+ return githubFetch(endpoint, token, {
384
+ method: "POST",
385
+ body: JSON.stringify(body)
386
+ });
387
+ }
388
+
389
+ // src/git.ts
390
+ async function initGit(targetDir) {
391
+ await execAsync("git", ["init"], { cwd: targetDir });
392
+ await execAsync("git", ["add", "-A"], { cwd: targetDir });
393
+ await execAsync("git", ["commit", "-m", "Initial commit"], { cwd: targetDir });
394
+ }
395
+ async function createGithubRepo(repoName, targetDir, isPublic) {
396
+ const config = loadConfig();
397
+ if (!config.github?.token) {
398
+ console.log(pc2.yellow("\u26A0 \u672A\u914D\u7F6E GitHub Token\uFF0C\u8DF3\u8FC7\u4ED3\u5E93\u521B\u5EFA"));
399
+ console.log(pc2.dim(` \u8FD0\u884C ${pc2.cyan("spec-go config --setup-github")} \u914D\u7F6E Token`));
400
+ console.log(pc2.dim(` \u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84: ${getConfigPath()}`));
401
+ return null;
402
+ }
403
+ const token = config.github.token;
404
+ const defaultOrg = config.github.defaultOrg;
405
+ const validateResult = await validateToken(token);
406
+ if (!validateResult.success) {
407
+ console.log(pc2.yellow(`\u26A0 GitHub Token \u65E0\u6548: ${validateResult.error}`));
408
+ if (validateResult.rateLimitReset) {
409
+ console.log(pc2.dim(` Rate limit \u5C06\u5728 ${validateResult.rateLimitReset.toLocaleString()} \u91CD\u7F6E`));
410
+ }
411
+ console.log(pc2.dim(` \u8FD0\u884C ${pc2.cyan("spec-go config --setup-github")} \u91CD\u65B0\u914D\u7F6E`));
412
+ return null;
413
+ }
414
+ const username = validateResult.data.login;
415
+ const createResult = await createRepository(token, {
416
+ name: repoName,
417
+ isPrivate: !isPublic,
418
+ org: defaultOrg
419
+ });
420
+ if (!createResult.success) {
421
+ if (createResult.statusCode === 422) {
422
+ console.log(pc2.yellow(`\u26A0 \u4ED3\u5E93 "${repoName}" \u5DF2\u5B58\u5728\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6\u540D\u79F0`));
423
+ } else if (createResult.rateLimitReset) {
424
+ console.log(pc2.yellow(`\u26A0 API \u8BF7\u6C42\u6B21\u6570\u5DF2\u8FBE\u4E0A\u9650`));
425
+ console.log(pc2.dim(` \u5C06\u5728 ${createResult.rateLimitReset.toLocaleString()} \u91CD\u7F6E`));
426
+ } else {
427
+ console.log(pc2.yellow(`\u26A0 \u521B\u5EFA\u4ED3\u5E93\u5931\u8D25: ${createResult.error}`));
428
+ }
429
+ return null;
430
+ }
431
+ const repo = createResult.data;
432
+ const remoteResult = await execAsync(
433
+ "git",
434
+ ["remote", "add", "origin", repo.clone_url],
435
+ { cwd: targetDir }
436
+ );
437
+ if (remoteResult.code !== 0) {
438
+ await execAsync(
439
+ "git",
440
+ ["remote", "set-url", "origin", repo.clone_url],
441
+ { cwd: targetDir }
442
+ );
443
+ }
444
+ const pushResult = await execAsync(
445
+ "git",
446
+ ["push", "-u", "origin", "main"],
447
+ { cwd: targetDir }
448
+ );
449
+ if (pushResult.code !== 0) {
450
+ const pushMaster = await execAsync(
451
+ "git",
452
+ ["push", "-u", "origin", "master"],
453
+ { cwd: targetDir }
454
+ );
455
+ if (pushMaster.code !== 0) {
456
+ console.log(pc2.yellow(`\u26A0 \u63A8\u9001\u5931\u8D25: ${pushResult.stderr || pushMaster.stderr}`));
457
+ console.log(pc2.dim(` \u4ED3\u5E93\u5DF2\u521B\u5EFA: ${repo.html_url}`));
458
+ console.log(pc2.dim(" \u8BF7\u624B\u52A8\u63A8\u9001\u4EE3\u7801"));
459
+ return repo.html_url;
460
+ }
461
+ }
462
+ return repo.html_url;
463
+ }
464
+
465
+ // src/post-init.ts
466
+ import path5 from "path";
467
+ import pc3 from "picocolors";
468
+ async function runPostInit(targetDir, commands) {
469
+ for (const cmd of commands) {
470
+ console.log(pc3.dim(` ${cmd.description}...`));
471
+ const [command, ...args] = cmd.command.split(" ");
472
+ const result = await execAsync(command, args, {
473
+ cwd: targetDir,
474
+ stdio: "pipe"
475
+ });
476
+ if (result.code !== 0) {
477
+ console.log(pc3.yellow(`\u26A0 ${cmd.description} \u5931\u8D25`));
478
+ if (result.stderr) {
479
+ console.log(pc3.dim(result.stderr.slice(0, 200)));
480
+ }
481
+ }
482
+ }
483
+ }
484
+ async function runWorkspacePostInit(targetDir, config) {
485
+ if (config.postInit && config.postInit.length > 0) {
486
+ await runPostInit(targetDir, config.postInit);
487
+ }
488
+ if (config.workspaces) {
489
+ for (const ws of config.workspaces) {
490
+ if (ws.postInit && ws.postInit.length > 0) {
491
+ const wsDir = path5.join(targetDir, ws.name);
492
+ console.log(pc3.dim(` [${ws.name}]`));
493
+ await runPostInit(wsDir, ws.postInit);
494
+ }
495
+ }
496
+ }
497
+ }
498
+
499
+ // src/update-check.ts
500
+ import fs4 from "fs";
501
+ import path6 from "path";
502
+ import os2 from "os";
503
+ import { execSync } from "child_process";
504
+ import pc4 from "picocolors";
505
+ var CACHE_PATH = path6.join(os2.homedir(), ".spec-go-update-check");
506
+ var CACHE_TTL = 24 * 60 * 60 * 1e3;
507
+ var PACKAGE_NAME = "@lambertkeith/spec-go";
508
+ function readCache() {
509
+ try {
510
+ if (fs4.existsSync(CACHE_PATH)) {
511
+ const content = fs4.readFileSync(CACHE_PATH, "utf-8");
512
+ return JSON.parse(content);
513
+ }
514
+ } catch {
515
+ }
516
+ return null;
517
+ }
518
+ function writeCache(cache) {
519
+ try {
520
+ fs4.writeFileSync(CACHE_PATH, JSON.stringify(cache), "utf-8");
521
+ } catch {
522
+ }
523
+ }
524
+ async function fetchLatestVersion() {
525
+ try {
526
+ const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`);
527
+ if (!response.ok) {
528
+ return null;
529
+ }
530
+ const data = await response.json();
531
+ return data.version;
532
+ } catch {
533
+ return null;
534
+ }
535
+ }
536
+ function compareVersions(current, latest) {
537
+ const currentParts = current.split(".").map(Number);
538
+ const latestParts = latest.split(".").map(Number);
539
+ for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
540
+ const c = currentParts[i] || 0;
541
+ const l = latestParts[i] || 0;
542
+ if (c < l) return -1;
543
+ if (c > l) return 1;
544
+ }
545
+ return 0;
546
+ }
547
+ async function checkForUpdates(currentVersion) {
548
+ const cache = readCache();
549
+ const now = Date.now();
550
+ let latestVersion = null;
551
+ if (cache && now - cache.lastCheck < CACHE_TTL) {
552
+ latestVersion = cache.latestVersion;
553
+ } else {
554
+ latestVersion = await fetchLatestVersion();
555
+ if (latestVersion) {
556
+ writeCache({ lastCheck: now, latestVersion });
557
+ }
558
+ }
559
+ if (latestVersion && compareVersions(currentVersion, latestVersion) < 0) {
560
+ console.log();
561
+ console.log(
562
+ pc4.yellow(` \u26A0 \u53D1\u73B0\u65B0\u7248\u672C ${pc4.bold(latestVersion)}\uFF0C\u5F53\u524D ${currentVersion}`)
563
+ );
564
+ console.log(pc4.cyan(` \u8FD0\u884C ${pc4.bold(`npm update -g ${PACKAGE_NAME}`)} \u66F4\u65B0`));
565
+ console.log();
566
+ }
567
+ }
568
+ function detectPackageManager() {
569
+ const execPath = process.argv[1] || "";
570
+ if (execPath.includes("pnpm")) return "pnpm";
571
+ if (execPath.includes("yarn")) return "yarn";
572
+ return "npm";
573
+ }
574
+ function getUpdateCommand(pm) {
575
+ switch (pm) {
576
+ case "pnpm":
577
+ return `pnpm update -g ${PACKAGE_NAME}`;
578
+ case "yarn":
579
+ return `yarn global upgrade ${PACKAGE_NAME}`;
580
+ default:
581
+ return `npm update -g ${PACKAGE_NAME}`;
582
+ }
583
+ }
584
+ async function runUpdate(currentVersion, checkOnly) {
585
+ const latestVersion = await fetchLatestVersion();
586
+ if (!latestVersion) {
587
+ console.log(pc4.red("\u2717 \u65E0\u6CD5\u83B7\u53D6\u6700\u65B0\u7248\u672C\u4FE1\u606F"));
588
+ process.exit(1);
589
+ }
590
+ const comparison = compareVersions(currentVersion, latestVersion);
591
+ if (comparison >= 0) {
592
+ console.log(pc4.green(`\u2714 \u5DF2\u662F\u6700\u65B0\u7248\u672C (${currentVersion})`));
593
+ return;
594
+ }
595
+ console.log(pc4.cyan(`\u53D1\u73B0\u65B0\u7248\u672C: ${currentVersion} \u2192 ${latestVersion}`));
596
+ if (checkOnly) {
597
+ console.log(pc4.dim(`\u8FD0\u884C spec-go update \u66F4\u65B0`));
598
+ return;
599
+ }
600
+ const pm = detectPackageManager();
601
+ const updateCmd = getUpdateCommand(pm);
602
+ console.log(pc4.dim(`\u6B63\u5728\u6267\u884C: ${updateCmd}`));
603
+ try {
604
+ execSync(updateCmd, { stdio: "inherit" });
605
+ console.log(pc4.green(`\u2714 \u66F4\u65B0\u5B8C\u6210`));
606
+ } catch {
607
+ console.log(pc4.red("\u2717 \u66F4\u65B0\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u6267\u884C\u66F4\u65B0\u547D\u4EE4"));
608
+ process.exit(1);
609
+ }
610
+ }
611
+
612
+ // src/github-setup.ts
613
+ import { input as input2, confirm as confirm2 } from "@inquirer/prompts";
614
+ import pc5 from "picocolors";
615
+ var TOKEN_HELP_URL = "https://github.com/settings/tokens/new?scopes=repo&description=spec-go";
616
+ function isUserCancelled(err) {
617
+ const error = err;
618
+ return error.message === "PROMPT_CANCELLED" || error.name === "ExitPromptError" || error.message.includes("User force closed");
619
+ }
620
+ async function runGitHubSetup() {
621
+ console.log();
622
+ console.log(pc5.cyan("\u914D\u7F6E GitHub Token"));
623
+ console.log();
624
+ console.log("\u9700\u8981\u4E00\u4E2A\u5177\u6709 repo \u6743\u9650\u7684 Personal Access Token (Classic) \u6765\u521B\u5EFA\u4ED3\u5E93\u3002");
625
+ console.log();
626
+ console.log(pc5.dim("\u83B7\u53D6\u6B65\u9AA4:"));
627
+ console.log(pc5.dim("1. \u8BBF\u95EE GitHub Settings > Developer settings > Personal access tokens"));
628
+ console.log(pc5.dim('2. \u70B9\u51FB "Generate new token (classic)"'));
629
+ console.log(pc5.dim('3. \u52FE\u9009 "repo" \u6743\u9650'));
630
+ console.log(pc5.dim("4. \u751F\u6210\u5E76\u590D\u5236 Token"));
631
+ console.log();
632
+ console.log(pc5.dim(`\u5FEB\u6377\u94FE\u63A5: ${TOKEN_HELP_URL}`));
633
+ console.log();
634
+ try {
635
+ const token = await input2({
636
+ message: "\u8BF7\u8F93\u5165 GitHub Token:",
637
+ validate: (value) => {
638
+ if (!value.trim()) {
639
+ return "Token \u4E0D\u80FD\u4E3A\u7A7A";
640
+ }
641
+ if (!value.startsWith("ghp_") && !value.startsWith("github_pat_")) {
642
+ return "Token \u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u5E94\u4EE5 ghp_ \u6216 github_pat_ \u5F00\u5934";
643
+ }
644
+ return true;
645
+ }
646
+ });
647
+ console.log();
648
+ console.log(pc5.dim("\u6B63\u5728\u9A8C\u8BC1 Token..."));
649
+ const result = await validateToken(token.trim());
650
+ if (!result.success) {
651
+ console.log(pc5.red(`\u2717 Token \u9A8C\u8BC1\u5931\u8D25: ${result.error}`));
652
+ if (result.rateLimitReset) {
653
+ console.log(pc5.dim(` Rate limit \u5C06\u5728 ${result.rateLimitReset.toLocaleString()} \u91CD\u7F6E`));
654
+ }
655
+ return false;
656
+ }
657
+ const user = result.data;
658
+ console.log(pc5.green(`\u2714 Token \u6709\u6548\uFF0C\u5DF2\u767B\u5F55\u4E3A: ${user.login}${user.name ? ` (${user.name})` : ""}`));
659
+ console.log();
660
+ const setOrg = await confirm2({
661
+ message: "\u662F\u5426\u8BBE\u7F6E\u9ED8\u8BA4\u7EC4\u7EC7? (\u5426\u5219\u4ED3\u5E93\u5C06\u521B\u5EFA\u5728\u4E2A\u4EBA\u8D26\u6237\u4E0B)",
662
+ default: false
663
+ });
664
+ let defaultOrg;
665
+ if (setOrg) {
666
+ defaultOrg = await input2({
667
+ message: "\u9ED8\u8BA4\u7EC4\u7EC7\u540D\u79F0:",
668
+ validate: (value) => {
669
+ if (!value.trim()) {
670
+ return "\u7EC4\u7EC7\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A";
671
+ }
672
+ return true;
673
+ }
674
+ });
675
+ defaultOrg = defaultOrg.trim();
676
+ }
677
+ const config = loadConfig();
678
+ config.github = {
679
+ token: token.trim(),
680
+ ...defaultOrg && { defaultOrg }
681
+ };
682
+ saveConfig(config);
683
+ console.log();
684
+ console.log(pc5.green("\u2714 GitHub \u914D\u7F6E\u5DF2\u4FDD\u5B58"));
685
+ console.log(pc5.dim(" \u914D\u7F6E\u6587\u4EF6\u5DF2\u8BBE\u7F6E\u4E3A\u4EC5\u5F53\u524D\u7528\u6237\u53EF\u8BFB"));
686
+ return true;
687
+ } catch (err) {
688
+ if (isUserCancelled(err)) {
689
+ console.log(pc5.yellow("\n\u64CD\u4F5C\u5DF2\u53D6\u6D88"));
690
+ return false;
691
+ }
692
+ throw err;
693
+ }
694
+ }
695
+ function showConfig() {
696
+ const config = loadConfig();
697
+ console.log();
698
+ console.log(pc5.cyan("\u5F53\u524D\u914D\u7F6E:"));
699
+ console.log();
700
+ if (config.defaults) {
701
+ console.log(pc5.dim("defaults:"));
702
+ if (config.defaults.github !== void 0) {
703
+ console.log(` github: ${config.defaults.github}`);
704
+ }
705
+ if (config.defaults.public !== void 0) {
706
+ console.log(` public: ${config.defaults.public}`);
707
+ }
708
+ if (config.defaults.template !== void 0) {
709
+ console.log(` template: ${config.defaults.template}`);
710
+ }
711
+ }
712
+ if (config.github) {
713
+ console.log(pc5.dim("github:"));
714
+ if (config.github.token) {
715
+ const masked = config.github.token.slice(0, 8) + "..." + config.github.token.slice(-4);
716
+ console.log(` token: ${masked}`);
717
+ }
718
+ if (config.github.defaultOrg) {
719
+ console.log(` defaultOrg: ${config.github.defaultOrg}`);
720
+ }
721
+ }
722
+ if (!config.defaults && !config.github) {
723
+ console.log(pc5.dim("(\u65E0\u914D\u7F6E)"));
724
+ }
725
+ console.log();
726
+ }
727
+
728
+ // src/cli.ts
729
+ async function createCli() {
730
+ const program = new Command();
731
+ program.name("spec-go").description("CLI \u811A\u624B\u67B6\u5DE5\u5177\uFF0C\u5FEB\u901F\u521B\u5EFA\u9879\u76EE\u5E76\u53EF\u9009\u521D\u59CB\u5316 GitHub \u4ED3\u5E93").version(version).argument("[project-name]", "\u9879\u76EE\u540D\u79F0").option("-t, --template <template>", "\u4F7F\u7528\u6307\u5B9A\u6A21\u677F").option("--github", "\u5728 GitHub \u521B\u5EFA\u8FDC\u7A0B\u4ED3\u5E93").option("--public", "\u521B\u5EFA\u516C\u5F00\u4ED3\u5E93 (\u9ED8\u8BA4\u79C1\u6709)").option("--no-git", "\u8DF3\u8FC7 Git \u521D\u59CB\u5316").option("--no-install", "\u8DF3\u8FC7\u4F9D\u8D56\u5B89\u88C5").action(async (projectName, options) => {
732
+ console.log();
733
+ console.log(` ${pc6.cyan("spec-go")} ${pc6.dim(`v${version}`)}`);
734
+ console.log();
735
+ checkForUpdates(version).catch(() => {
736
+ });
737
+ const userConfig = loadConfig();
738
+ try {
739
+ const projectOptions = await runPrompts(projectName, options, userConfig);
740
+ await executeProject(projectOptions);
741
+ } catch (err) {
742
+ const error = err;
743
+ if (error.message === "PROMPT_CANCELLED" || error.name === "ExitPromptError" || error.message.includes("User force closed")) {
744
+ console.log(pc6.yellow("\n\u64CD\u4F5C\u5DF2\u53D6\u6D88"));
745
+ process.exit(0);
746
+ }
747
+ throw err;
748
+ }
749
+ });
750
+ program.command("list").description("\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u677F").action(() => {
751
+ const templatesDir = getTemplatesDir();
752
+ const registryPath = path7.join(templatesDir, "template.config.json");
753
+ const registry = JSON.parse(
754
+ fs5.readFileSync(registryPath, "utf-8")
755
+ );
756
+ const singleTemplates = registry.templates.filter((t) => t.category !== "fullstack");
757
+ const fullstackTemplates = registry.templates.filter((t) => t.category === "fullstack");
758
+ console.log();
759
+ console.log(pc6.cyan(" \u5355\u4F53\u9879\u76EE:"));
760
+ for (const t of singleTemplates) {
761
+ console.log(` ${pc6.green(t.name.padEnd(24))} ${pc6.dim(t.displayName)}`);
762
+ }
763
+ if (fullstackTemplates.length > 0) {
764
+ console.log();
765
+ console.log(pc6.cyan(" \u524D\u540E\u7AEF\u5206\u79BB:"));
766
+ for (const t of fullstackTemplates) {
767
+ console.log(` ${pc6.green(t.name.padEnd(24))} ${pc6.dim(t.displayName)}`);
768
+ }
769
+ }
770
+ console.log();
771
+ });
772
+ program.command("config").description("\u7BA1\u7406\u914D\u7F6E").option("--setup-github", "\u914D\u7F6E GitHub Token").option("--show", "\u663E\u793A\u5F53\u524D\u914D\u7F6E").option("--path", "\u663E\u793A\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84").action(async (options) => {
773
+ if (options.setupGithub) {
774
+ const success = await runGitHubSetup();
775
+ process.exit(success ? 0 : 1);
776
+ } else if (options.show) {
777
+ showConfig();
778
+ } else if (options.path) {
779
+ console.log(getConfigPath());
780
+ } else {
781
+ console.log();
782
+ console.log(pc6.cyan("\u914D\u7F6E\u7BA1\u7406\u547D\u4EE4:"));
783
+ console.log();
784
+ console.log(` ${pc6.dim("spec-go config --setup-github")} \u914D\u7F6E GitHub Token`);
785
+ console.log(` ${pc6.dim("spec-go config --show")} \u663E\u793A\u5F53\u524D\u914D\u7F6E`);
786
+ console.log(` ${pc6.dim("spec-go config --path")} \u663E\u793A\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84`);
787
+ console.log();
788
+ }
789
+ });
790
+ program.command("update").description("\u68C0\u67E5\u5E76\u66F4\u65B0\u5230\u6700\u65B0\u7248\u672C").option("--check", "\u4EC5\u68C0\u67E5\u7248\u672C\uFF0C\u4E0D\u6267\u884C\u66F4\u65B0").action(async (options) => {
791
+ await runUpdate(version, options.check ?? false);
792
+ });
793
+ return program;
794
+ }
795
+ async function executeProject(options) {
796
+ const templateConfig = await scaffoldProject(options);
797
+ console.log(pc6.green("\u2714 \u9879\u76EE\u6587\u4EF6\u5DF2\u751F\u6210"));
798
+ if (!options.noInstall && templateConfig) {
799
+ if (templateConfig.type === "workspace") {
800
+ await runWorkspacePostInit(options.targetDir, templateConfig);
801
+ console.log(pc6.green("\u2714 \u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210"));
802
+ } else if (templateConfig.postInit) {
803
+ await runPostInit(options.targetDir, templateConfig.postInit);
804
+ console.log(pc6.green("\u2714 \u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210"));
805
+ }
806
+ }
807
+ if (options.initGit) {
808
+ await initGit(options.targetDir);
809
+ console.log(pc6.green("\u2714 Git \u4ED3\u5E93\u5DF2\u521D\u59CB\u5316"));
810
+ }
811
+ if (options.createGithub) {
812
+ const repoUrl = await createGithubRepo(
813
+ options.projectName,
814
+ options.targetDir,
815
+ options.isPublic
816
+ );
817
+ if (repoUrl) {
818
+ console.log(pc6.green(`\u2714 GitHub \u4ED3\u5E93\u5DF2\u521B\u5EFA: ${pc6.cyan(repoUrl)}`));
819
+ }
820
+ }
821
+ console.log();
822
+ const pm = templateConfig?.packageManager ?? "pnpm";
823
+ const cdCmd = options.targetDir !== process.cwd() ? `cd ${options.projectName} && ` : "";
824
+ if (templateConfig?.type === "workspace") {
825
+ if (pm === "pnpm") {
826
+ console.log(pc6.dim(` ${cdCmd}pnpm dev`));
827
+ } else {
828
+ console.log(pc6.dim(` ${cdCmd}make dev`));
829
+ }
830
+ } else if (pm === "maven") {
831
+ console.log(pc6.dim(` ${cdCmd}./mvnw spring-boot:run`));
832
+ } else if (pm === "gradle") {
833
+ console.log(pc6.dim(` ${cdCmd}./gradlew bootRun`));
834
+ } else {
835
+ console.log(pc6.dim(` ${cdCmd}${pm} dev`));
836
+ }
837
+ console.log();
838
+ }
839
+
840
+ // src/index.ts
841
+ async function main() {
842
+ ensureConfigExists();
843
+ const program = await createCli();
844
+ await program.parseAsync(process.argv);
845
+ }
846
+ main().catch((err) => {
847
+ console.error(err);
848
+ process.exit(1);
849
+ });
850
+ //# sourceMappingURL=index.js.map