@tanstack/create-start 1.92.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +0 -0
  3. package/dist/cli-entry.d.ts +1 -0
  4. package/dist/cli-entry.mjs +5 -0
  5. package/dist/cli.d.ts +1 -0
  6. package/dist/cli.mjs +92 -0
  7. package/dist/constants.d.ts +3 -0
  8. package/dist/constants.mjs +7 -0
  9. package/dist/directory.d.ts +3 -0
  10. package/dist/directory.mjs +62 -0
  11. package/dist/index.d.ts +2446 -0
  12. package/dist/index.mjs +15 -0
  13. package/dist/logo.d.ts +1 -0
  14. package/dist/logo.mjs +28 -0
  15. package/dist/module.d.ts +67 -0
  16. package/dist/module.mjs +168 -0
  17. package/dist/modules/core/index.d.ts +1446 -0
  18. package/dist/modules/core/index.mjs +218 -0
  19. package/dist/modules/core/template/app/client.tsx +10 -0
  20. package/dist/modules/core/template/app/router.tsx +18 -0
  21. package/dist/modules/core/template/app/routes/__root.tsx +50 -0
  22. package/dist/modules/core/template/app/ssr.tsx +15 -0
  23. package/dist/modules/core/template/app.config.ts +5 -0
  24. package/dist/modules/core/template/tsconfig.json +10 -0
  25. package/dist/modules/git.d.ts +231 -0
  26. package/dist/modules/git.mjs +114 -0
  27. package/dist/modules/ide.d.ts +92 -0
  28. package/dist/modules/ide.mjs +70 -0
  29. package/dist/modules/packageJson.d.ts +541 -0
  30. package/dist/modules/packageJson.mjs +153 -0
  31. package/dist/modules/packageManager.d.ts +139 -0
  32. package/dist/modules/packageManager.mjs +89 -0
  33. package/dist/modules/vscode/index.d.ts +33 -0
  34. package/dist/modules/vscode/index.mjs +35 -0
  35. package/dist/modules/vscode/template/_dot_vscode/settings.json +11 -0
  36. package/dist/templates/barebones/index.d.ts +1507 -0
  37. package/dist/templates/barebones/index.mjs +60 -0
  38. package/dist/templates/barebones/template/app/routes/index.tsx +11 -0
  39. package/dist/templates/index.d.ts +13 -0
  40. package/dist/templates/index.mjs +60 -0
  41. package/dist/types.d.ts +2 -0
  42. package/dist/types.mjs +0 -0
  43. package/dist/utils/debug.d.ts +11 -0
  44. package/dist/utils/debug.mjs +71 -0
  45. package/dist/utils/getPackageManager.d.ts +2 -0
  46. package/dist/utils/getPackageManager.mjs +11 -0
  47. package/dist/utils/helpers/helperFactory.d.ts +15 -0
  48. package/dist/utils/helpers/helperFactory.mjs +3 -0
  49. package/dist/utils/helpers/index.d.ts +51 -0
  50. package/dist/utils/helpers/index.mjs +227 -0
  51. package/dist/utils/runCmd.d.ts +1 -0
  52. package/dist/utils/runCmd.mjs +4 -0
  53. package/dist/utils/runPackageManagerCommand.d.ts +4 -0
  54. package/dist/utils/runPackageManagerCommand.mjs +17 -0
  55. package/dist/utils/spawnCmd.d.ts +1 -0
  56. package/dist/utils/spawnCmd.mjs +30 -0
  57. package/dist/utils/validateProjectName.d.ts +8 -0
  58. package/dist/utils/validateProjectName.mjs +14 -0
  59. package/index.js +3 -0
  60. package/package.json +66 -0
@@ -0,0 +1,218 @@
1
+ import { dirname } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { z } from "zod";
4
+ import { packageJsonModule } from "../packageJson.mjs";
5
+ import { createModule, runWithSpinner } from "../../module.mjs";
6
+ import { ideModule } from "../ide.mjs";
7
+ import packageJson from "../../../package.json" assert { type: "json" };
8
+ import { packageManagerModule } from "../packageManager.mjs";
9
+ import { initHelpers } from "../../utils/helpers/index.mjs";
10
+ import { gitModule } from "../git.mjs";
11
+ import { createDebugger } from "../../utils/debug.mjs";
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = dirname(__filename);
14
+ const debug = createDebugger("core-module");
15
+ export const coreModule = createModule(
16
+ z.object({
17
+ packageJson: packageJsonModule._initSchema.optional(),
18
+ ide: ideModule._initSchema.optional(),
19
+ packageManager: packageManagerModule._initSchema.optional(),
20
+ git: gitModule._initSchema.optional()
21
+ })
22
+ ).init(
23
+ (schema) => schema.transform(async (vals, ctx) => {
24
+ debug.verbose("Initializing core module schema", { vals });
25
+ const gitignore = [
26
+ {
27
+ sectionName: "Dependencies",
28
+ lines: ["node_modules/"]
29
+ },
30
+ {
31
+ sectionName: "Env",
32
+ lines: [
33
+ ".env",
34
+ ".env.local",
35
+ ".env.development",
36
+ ".env.test",
37
+ ".env.production",
38
+ ".env.staging"
39
+ ]
40
+ },
41
+ {
42
+ sectionName: "System Files",
43
+ lines: [".DS_Store", "Thumbs.db"]
44
+ }
45
+ ];
46
+ vals.git = {
47
+ ...vals.git,
48
+ gitIgnore: [...vals.git?.gitIgnore ?? [], ...gitignore]
49
+ };
50
+ const packageJson2 = {
51
+ type: "new",
52
+ dependencies: await deps([
53
+ "@tanstack/react-router",
54
+ "@tanstack/start",
55
+ "react",
56
+ "react-dom",
57
+ "vinxi"
58
+ ]),
59
+ devDependencies: await deps(["@types/react", "@types/react"]),
60
+ scripts: [
61
+ {
62
+ name: "dev",
63
+ script: "vinxi dev"
64
+ },
65
+ {
66
+ name: "build",
67
+ script: "vinxi build"
68
+ },
69
+ {
70
+ name: "start",
71
+ script: "vinxi start"
72
+ }
73
+ ],
74
+ ...vals.packageJson
75
+ };
76
+ debug.verbose("Parsing package manager schema");
77
+ const packageManager = await packageManagerModule._initSchema.safeParseAsync(
78
+ vals.packageManager,
79
+ {
80
+ path: ["packageManager"]
81
+ }
82
+ );
83
+ debug.verbose("Parsing IDE schema");
84
+ const ide = await ideModule._initSchema.safeParseAsync(vals.ide, {
85
+ path: ["ide"]
86
+ });
87
+ debug.verbose("Parsing git schema");
88
+ const git = await gitModule._initSchema.safeParseAsync(vals.git, {
89
+ path: ["git"]
90
+ });
91
+ if (!ide.success || !packageManager.success || !git.success) {
92
+ debug.error("Schema validation failed", null, {
93
+ ide: ide.success,
94
+ packageManager: packageManager.success,
95
+ git: git.success
96
+ });
97
+ ide.error?.issues.forEach((i) => ctx.addIssue(i));
98
+ packageManager.error?.issues.forEach((i) => ctx.addIssue(i));
99
+ git.error?.issues.forEach((i) => ctx.addIssue(i));
100
+ throw Error("Failed validation");
101
+ }
102
+ debug.verbose("Schema transformation complete");
103
+ return {
104
+ ...vals,
105
+ packageManager: packageManager.data,
106
+ ide: ide.data,
107
+ git: git.data,
108
+ packageJson: packageJson2
109
+ };
110
+ })
111
+ ).prompt(
112
+ (schema) => schema.transform(async (vals, ctx) => {
113
+ debug.verbose("Running prompt transformations", { vals });
114
+ debug.verbose("Parsing IDE prompt schema");
115
+ const ide = await ideModule._promptSchema.safeParseAsync(vals.ide, {
116
+ path: ["ide"]
117
+ });
118
+ debug.verbose("Parsing package manager prompt schema");
119
+ const packageManager = await packageManagerModule._promptSchema.safeParseAsync(
120
+ vals.packageManager,
121
+ { path: ["packageManager"] }
122
+ );
123
+ debug.verbose("Parsing git prompt schema");
124
+ const git = await gitModule._promptSchema.safeParseAsync(vals.git, {
125
+ path: ["git"]
126
+ });
127
+ debug.verbose("Parsing package.json prompt schema");
128
+ const packageJson2 = await packageJsonModule._promptSchema.safeParseAsync(
129
+ vals.packageJson,
130
+ {
131
+ path: ["packageJson"]
132
+ }
133
+ );
134
+ if (!ide.success || !packageManager.success || !git.success || !packageJson2.success) {
135
+ debug.error("Prompt validation failed", null, {
136
+ ide: ide.success,
137
+ packageManager: packageManager.success,
138
+ git: git.success,
139
+ packageJson: packageJson2.success
140
+ });
141
+ ide.error?.issues.forEach((i) => ctx.addIssue(i));
142
+ packageManager.error?.issues.forEach((i) => ctx.addIssue(i));
143
+ git.error?.issues.forEach((i) => ctx.addIssue(i));
144
+ throw Error("Failed validation");
145
+ }
146
+ debug.verbose("Prompt transformations complete");
147
+ return {
148
+ packageJson: packageJson2.data,
149
+ ide: ide.data,
150
+ packageManager: packageManager.data,
151
+ git: git.data
152
+ };
153
+ })
154
+ ).validateAndApply({
155
+ validate: async ({ cfg, targetPath }) => {
156
+ debug.verbose("Validating core module", { targetPath });
157
+ const _ = initHelpers(__dirname, targetPath);
158
+ const issues = await _.getTemplateFilesThatWouldBeOverwritten({
159
+ file: "**/*",
160
+ templateFolder: "./template",
161
+ targetFolder: targetPath,
162
+ overwrite: false
163
+ });
164
+ if (ideModule._validateFn) {
165
+ debug.verbose("Running IDE validation");
166
+ const ideIssues = await ideModule._validateFn({
167
+ cfg: cfg.ide,
168
+ targetPath
169
+ });
170
+ issues.push(...ideIssues);
171
+ }
172
+ debug.info("Validation complete", { issueCount: issues.length });
173
+ return issues;
174
+ },
175
+ apply: async ({ cfg, targetPath }) => {
176
+ debug.info("Applying core module", { targetPath });
177
+ const _ = initHelpers(__dirname, targetPath);
178
+ debug.verbose("Copying core template files");
179
+ await runWithSpinner({
180
+ spinnerOptions: {
181
+ inProgress: "Copying core template files",
182
+ error: "Failed to copy core template files",
183
+ success: "Copied core template files"
184
+ },
185
+ fn: async () => await _.copyTemplateFiles({
186
+ file: "**/*",
187
+ templateFolder: "./template",
188
+ targetFolder: ".",
189
+ overwrite: false
190
+ })
191
+ });
192
+ debug.verbose("Applying package.json module");
193
+ await packageJsonModule.apply({ cfg: cfg.packageJson, targetPath });
194
+ debug.verbose("Applying IDE module");
195
+ await ideModule.apply({ cfg: cfg.ide, targetPath });
196
+ debug.verbose("Applying git module");
197
+ await gitModule._applyFn({ cfg: cfg.git, targetPath });
198
+ debug.verbose("Applying package manager module");
199
+ await packageManagerModule.apply({
200
+ cfg: cfg.packageManager,
201
+ targetPath
202
+ });
203
+ debug.info("Core module application complete");
204
+ }
205
+ });
206
+ const deps = async (depsArray) => {
207
+ debug.verbose("Resolving dependencies", { deps: depsArray });
208
+ const result = await Promise.all(
209
+ depsArray.map((d) => {
210
+ const version = packageJson["peerDependencies"][d] === "workspace:^" ? "latest" : packageJson["peerDependencies"][d];
211
+ return {
212
+ name: d,
213
+ version
214
+ };
215
+ })
216
+ );
217
+ return result;
218
+ };
@@ -0,0 +1,10 @@
1
+ // @ts-nocheck
2
+
3
+ /// <reference types="vinxi/types/client" />
4
+ import { hydrateRoot } from 'react-dom/client'
5
+ import { StartClient } from '@tanstack/start'
6
+ import { createRouter } from './router'
7
+
8
+ const router = createRouter()
9
+
10
+ hydrateRoot(document, <StartClient router={router} />)
@@ -0,0 +1,18 @@
1
+ // @ts-nocheck
2
+
3
+ import { createRouter as createTanStackRouter } from '@tanstack/react-router'
4
+ import { routeTree } from './routeTree.gen'
5
+
6
+ export function createRouter() {
7
+ const router = createTanStackRouter({
8
+ routeTree,
9
+ })
10
+
11
+ return router
12
+ }
13
+
14
+ declare module '@tanstack/react-router' {
15
+ interface Register {
16
+ router: ReturnType<typeof createRouter>
17
+ }
18
+ }
@@ -0,0 +1,50 @@
1
+ // @ts-nocheck
2
+
3
+ import {
4
+ Outlet,
5
+ ScrollRestoration,
6
+ createRootRoute,
7
+ } from '@tanstack/react-router'
8
+ import { Meta, Scripts } from '@tanstack/start'
9
+ import type { ReactNode } from 'react'
10
+
11
+ export const Route = createRootRoute({
12
+ head: () => ({
13
+ meta: [
14
+ {
15
+ charSet: 'utf-8',
16
+ },
17
+ {
18
+ name: 'viewport',
19
+ content: 'width=device-width, initial-scale=1',
20
+ },
21
+ {
22
+ title: 'TanStack Start Starter',
23
+ },
24
+ ],
25
+ }),
26
+ component: RootComponent,
27
+ })
28
+
29
+ function RootComponent() {
30
+ return (
31
+ <RootDocument>
32
+ <Outlet />
33
+ </RootDocument>
34
+ )
35
+ }
36
+
37
+ function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
38
+ return (
39
+ <html>
40
+ <head>
41
+ <Meta />
42
+ </head>
43
+ <body>
44
+ {children}
45
+ <ScrollRestoration />
46
+ <Scripts />
47
+ </body>
48
+ </html>
49
+ )
50
+ }
@@ -0,0 +1,15 @@
1
+ // @ts-nocheck
2
+
3
+ /// <reference types="vinxi/types/server" />
4
+ import {
5
+ createStartHandler,
6
+ defaultStreamHandler,
7
+ } from '@tanstack/start/server'
8
+ import { getRouterManifest } from '@tanstack/start/router-manifest'
9
+
10
+ import { createRouter } from './router'
11
+
12
+ export default createStartHandler({
13
+ createRouter,
14
+ getRouterManifest,
15
+ })(defaultStreamHandler)
@@ -0,0 +1,5 @@
1
+ // @ts-nocheck
2
+
3
+ import { defineConfig } from '@tanstack/start/config'
4
+
5
+ export default defineConfig({})
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "jsx": "react-jsx",
4
+ "moduleResolution": "Bundler",
5
+ "module": "ESNext",
6
+ "target": "ES2022",
7
+ "skipLibCheck": true,
8
+ "strictNullChecks": true
9
+ }
10
+ }
@@ -0,0 +1,231 @@
1
+ import { z } from 'zod';
2
+ export declare const gitModule: {
3
+ _baseSchema: z.ZodObject<{
4
+ setupGit: z.ZodOptional<z.ZodBoolean>;
5
+ gitIgnore: z.ZodOptional<z.ZodArray<z.ZodObject<{
6
+ sectionName: z.ZodString;
7
+ lines: z.ZodArray<z.ZodString, "many">;
8
+ }, "strip", z.ZodTypeAny, {
9
+ sectionName: string;
10
+ lines: string[];
11
+ }, {
12
+ sectionName: string;
13
+ lines: string[];
14
+ }>, "many">>;
15
+ }, "strip", z.ZodTypeAny, {
16
+ setupGit?: boolean | undefined;
17
+ gitIgnore?: {
18
+ sectionName: string;
19
+ lines: string[];
20
+ }[] | undefined;
21
+ }, {
22
+ setupGit?: boolean | undefined;
23
+ gitIgnore?: {
24
+ sectionName: string;
25
+ lines: string[];
26
+ }[] | undefined;
27
+ }>;
28
+ _initSchema: z.ZodObject<{
29
+ setupGit: z.ZodOptional<z.ZodBoolean>;
30
+ gitIgnore: z.ZodOptional<z.ZodArray<z.ZodObject<{
31
+ sectionName: z.ZodString;
32
+ lines: z.ZodArray<z.ZodString, "many">;
33
+ }, "strip", z.ZodTypeAny, {
34
+ sectionName: string;
35
+ lines: string[];
36
+ }, {
37
+ sectionName: string;
38
+ lines: string[];
39
+ }>, "many">>;
40
+ }, "strip", z.ZodTypeAny, {
41
+ setupGit?: boolean | undefined;
42
+ gitIgnore?: {
43
+ sectionName: string;
44
+ lines: string[];
45
+ }[] | undefined;
46
+ }, {
47
+ setupGit?: boolean | undefined;
48
+ gitIgnore?: {
49
+ sectionName: string;
50
+ lines: string[];
51
+ }[] | undefined;
52
+ }>;
53
+ _promptSchema: z.ZodEffects<z.ZodObject<{
54
+ setupGit: z.ZodOptional<z.ZodBoolean>;
55
+ gitIgnore: z.ZodOptional<z.ZodArray<z.ZodObject<{
56
+ sectionName: z.ZodString;
57
+ lines: z.ZodArray<z.ZodString, "many">;
58
+ }, "strip", z.ZodTypeAny, {
59
+ sectionName: string;
60
+ lines: string[];
61
+ }, {
62
+ sectionName: string;
63
+ lines: string[];
64
+ }>, "many">>;
65
+ }, "strip", z.ZodTypeAny, {
66
+ setupGit?: boolean | undefined;
67
+ gitIgnore?: {
68
+ sectionName: string;
69
+ lines: string[];
70
+ }[] | undefined;
71
+ }, {
72
+ setupGit?: boolean | undefined;
73
+ gitIgnore?: {
74
+ sectionName: string;
75
+ lines: string[];
76
+ }[] | undefined;
77
+ }>, {
78
+ setupGit: boolean;
79
+ gitIgnore: {
80
+ sectionName: string;
81
+ lines: string[];
82
+ }[] | undefined;
83
+ }, {
84
+ setupGit?: boolean | undefined;
85
+ gitIgnore?: {
86
+ sectionName: string;
87
+ lines: string[];
88
+ }[] | undefined;
89
+ }>;
90
+ _applyFn: ({ cfg, targetPath }: {
91
+ targetPath: string;
92
+ cfg: {
93
+ setupGit: boolean;
94
+ gitIgnore: {
95
+ sectionName: string;
96
+ lines: string[];
97
+ }[] | undefined;
98
+ };
99
+ }) => Promise<void>;
100
+ _validateFn: ((opts: {
101
+ targetPath: string;
102
+ cfg: {
103
+ setupGit: boolean;
104
+ gitIgnore: {
105
+ sectionName: string;
106
+ lines: string[];
107
+ }[] | undefined;
108
+ };
109
+ }) => Promise<Array<string>> | Array<string>) | undefined;
110
+ _spinnerConfigFn: ((cfg: {
111
+ setupGit: boolean;
112
+ gitIgnore: {
113
+ sectionName: string;
114
+ lines: string[];
115
+ }[] | undefined;
116
+ }) => {
117
+ success: string;
118
+ error: string;
119
+ inProgress: string;
120
+ } | undefined) | undefined;
121
+ init(cfg: {
122
+ setupGit?: boolean | undefined;
123
+ gitIgnore?: {
124
+ sectionName: string;
125
+ lines: string[];
126
+ }[] | undefined;
127
+ }): Promise<z.ParseReturnType<z.ZodObject<{
128
+ setupGit: z.ZodOptional<z.ZodBoolean>;
129
+ gitIgnore: z.ZodOptional<z.ZodArray<z.ZodObject<{
130
+ sectionName: z.ZodString;
131
+ lines: z.ZodArray<z.ZodString, "many">;
132
+ }, "strip", z.ZodTypeAny, {
133
+ sectionName: string;
134
+ lines: string[];
135
+ }, {
136
+ sectionName: string;
137
+ lines: string[];
138
+ }>, "many">>;
139
+ }, "strip", z.ZodTypeAny, {
140
+ setupGit?: boolean | undefined;
141
+ gitIgnore?: {
142
+ sectionName: string;
143
+ lines: string[];
144
+ }[] | undefined;
145
+ }, {
146
+ setupGit?: boolean | undefined;
147
+ gitIgnore?: {
148
+ sectionName: string;
149
+ lines: string[];
150
+ }[] | undefined;
151
+ }>>>;
152
+ initSafe(cfg: {
153
+ setupGit?: boolean | undefined;
154
+ gitIgnore?: {
155
+ sectionName: string;
156
+ lines: string[];
157
+ }[] | undefined;
158
+ }): Promise<z.SafeParseReturnType<{
159
+ setupGit?: boolean | undefined;
160
+ gitIgnore?: {
161
+ sectionName: string;
162
+ lines: string[];
163
+ }[] | undefined;
164
+ }, {
165
+ setupGit?: boolean | undefined;
166
+ gitIgnore?: {
167
+ sectionName: string;
168
+ lines: string[];
169
+ }[] | undefined;
170
+ }>>;
171
+ prompt(cfg: {
172
+ setupGit?: boolean | undefined;
173
+ gitIgnore?: {
174
+ sectionName: string;
175
+ lines: string[];
176
+ }[] | undefined;
177
+ }): Promise<z.SafeParseReturnType<{
178
+ setupGit?: boolean | undefined;
179
+ gitIgnore?: {
180
+ sectionName: string;
181
+ lines: string[];
182
+ }[] | undefined;
183
+ }, {
184
+ setupGit: boolean;
185
+ gitIgnore: {
186
+ sectionName: string;
187
+ lines: string[];
188
+ }[] | undefined;
189
+ }>>;
190
+ validate(cfg: {
191
+ setupGit?: boolean | undefined;
192
+ gitIgnore?: {
193
+ sectionName: string;
194
+ lines: string[];
195
+ }[] | undefined;
196
+ }): Promise<z.SafeParseReturnType<{
197
+ setupGit?: boolean | undefined;
198
+ gitIgnore?: {
199
+ sectionName: string;
200
+ lines: string[];
201
+ }[] | undefined;
202
+ }, {
203
+ setupGit: boolean;
204
+ gitIgnore: {
205
+ sectionName: string;
206
+ lines: string[];
207
+ }[] | undefined;
208
+ }>>;
209
+ apply({ cfg, targetPath, }: {
210
+ cfg: {
211
+ setupGit: boolean;
212
+ gitIgnore: {
213
+ sectionName: string;
214
+ lines: string[];
215
+ }[] | undefined;
216
+ };
217
+ targetPath: string;
218
+ }): Promise<void>;
219
+ execute({ cfg, targetPath, type, applyingMessage, }: {
220
+ cfg: {
221
+ setupGit?: boolean | undefined;
222
+ gitIgnore?: {
223
+ sectionName: string;
224
+ lines: string[];
225
+ }[] | undefined;
226
+ };
227
+ targetPath: string;
228
+ type: "new-project" | "update";
229
+ applyingMessage?: string;
230
+ }): Promise<void>;
231
+ };
@@ -0,0 +1,114 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { fileURLToPath } from "node:url";
3
+ import { dirname, resolve } from "node:path";
4
+ import { z } from "zod";
5
+ import { select } from "@inquirer/prompts";
6
+ import { createModule } from "../module.mjs";
7
+ import { runCmd } from "../utils/runCmd.mjs";
8
+ import { createDebugger } from "../utils/debug.mjs";
9
+ import { checkFileExists, initHelpers } from "../utils/helpers/index.mjs";
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+ const debug = createDebugger("git-module");
13
+ async function appendToGitignore(targetPath, newEntries, sectionName) {
14
+ const gitignorePath = resolve(targetPath, ".gitignore");
15
+ debug.verbose("Handling gitignore", { gitignorePath });
16
+ let existingContent = "";
17
+ const exists = await checkFileExists(gitignorePath);
18
+ if (exists) {
19
+ existingContent = await readFile(gitignorePath, "utf-8");
20
+ const lines = existingContent.split("\n");
21
+ const sectionStart = lines.findIndex(
22
+ (line) => line.trim() === `# ${sectionName}`
23
+ );
24
+ if (sectionStart !== -1) {
25
+ let sectionEnd = lines.findIndex(
26
+ (line, i) => i > sectionStart && line.trim().startsWith("#")
27
+ );
28
+ if (sectionEnd === -1) sectionEnd = lines.length;
29
+ const sectionEntries = lines.slice(sectionStart + 1, sectionEnd).map((line) => line.trim()).filter((line) => line !== "");
30
+ newEntries = newEntries.filter(
31
+ (entry) => !sectionEntries.some(
32
+ (existing) => existing.toLowerCase() === entry.trim().toLowerCase()
33
+ )
34
+ );
35
+ if (newEntries.length > 0) {
36
+ lines.splice(sectionEnd, 0, ...newEntries);
37
+ await writeFile(gitignorePath, lines.join("\n"));
38
+ debug.info("Updated existing section in gitignore file");
39
+ }
40
+ } else {
41
+ const newContent = `${existingContent}
42
+
43
+ # ${sectionName}
44
+ ${newEntries.join("\n")}`;
45
+ await writeFile(gitignorePath, newContent);
46
+ debug.info("Added new section to gitignore file");
47
+ }
48
+ } else {
49
+ const content = `# ${sectionName}
50
+ ${newEntries.join("\n")}`;
51
+ await writeFile(gitignorePath, content);
52
+ debug.info("Created new gitignore file");
53
+ }
54
+ }
55
+ export const gitModule = createModule(
56
+ z.object({
57
+ setupGit: z.boolean().optional(),
58
+ gitIgnore: z.object({
59
+ sectionName: z.string(),
60
+ lines: z.string().array()
61
+ }).array().optional()
62
+ })
63
+ ).init((schema) => schema).prompt(
64
+ (schema) => schema.transform(async (vals) => {
65
+ debug.verbose("Transforming git prompt schema", { vals });
66
+ const setupGit = vals.setupGit != void 0 ? vals.setupGit : await select({
67
+ message: "Initialize git",
68
+ choices: [
69
+ { name: "yes", value: true },
70
+ { name: "no", value: false }
71
+ ],
72
+ default: "yes"
73
+ });
74
+ debug.info("Git initialization choice made", { setupGit });
75
+ return {
76
+ setupGit,
77
+ gitIgnore: vals.gitIgnore
78
+ };
79
+ })
80
+ ).validateAndApply({
81
+ apply: async ({ cfg, targetPath }) => {
82
+ const _ = initHelpers(__dirname, targetPath);
83
+ debug.verbose("Applying git module", { cfg, targetPath });
84
+ if (cfg.gitIgnore && cfg.gitIgnore.length > 0) {
85
+ for (const gitIgnore of cfg.gitIgnore) {
86
+ await appendToGitignore(
87
+ _.getFullTargetPath(""),
88
+ gitIgnore.lines,
89
+ gitIgnore.sectionName
90
+ );
91
+ }
92
+ debug.info("Created / updated .gitignore");
93
+ }
94
+ if (cfg.setupGit) {
95
+ debug.info("Initializing git repository");
96
+ try {
97
+ await runCmd("git", ["init"], {}, targetPath);
98
+ debug.info("Git repository initialized successfully");
99
+ } catch (error) {
100
+ debug.error("Failed to initialize git repository", error);
101
+ throw error;
102
+ }
103
+ } else {
104
+ debug.info("Skipping git initialization");
105
+ }
106
+ },
107
+ spinnerConfigFn: () => {
108
+ return {
109
+ success: "Git initalized",
110
+ error: "Failed to initialize git",
111
+ inProgress: "Initializing git"
112
+ };
113
+ }
114
+ });