@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.
- package/LICENSE +21 -0
- package/README.md +0 -0
- package/dist/cli-entry.d.ts +1 -0
- package/dist/cli-entry.mjs +5 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.mjs +92 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.mjs +7 -0
- package/dist/directory.d.ts +3 -0
- package/dist/directory.mjs +62 -0
- package/dist/index.d.ts +2446 -0
- package/dist/index.mjs +15 -0
- package/dist/logo.d.ts +1 -0
- package/dist/logo.mjs +28 -0
- package/dist/module.d.ts +67 -0
- package/dist/module.mjs +168 -0
- package/dist/modules/core/index.d.ts +1446 -0
- package/dist/modules/core/index.mjs +218 -0
- package/dist/modules/core/template/app/client.tsx +10 -0
- package/dist/modules/core/template/app/router.tsx +18 -0
- package/dist/modules/core/template/app/routes/__root.tsx +50 -0
- package/dist/modules/core/template/app/ssr.tsx +15 -0
- package/dist/modules/core/template/app.config.ts +5 -0
- package/dist/modules/core/template/tsconfig.json +10 -0
- package/dist/modules/git.d.ts +231 -0
- package/dist/modules/git.mjs +114 -0
- package/dist/modules/ide.d.ts +92 -0
- package/dist/modules/ide.mjs +70 -0
- package/dist/modules/packageJson.d.ts +541 -0
- package/dist/modules/packageJson.mjs +153 -0
- package/dist/modules/packageManager.d.ts +139 -0
- package/dist/modules/packageManager.mjs +89 -0
- package/dist/modules/vscode/index.d.ts +33 -0
- package/dist/modules/vscode/index.mjs +35 -0
- package/dist/modules/vscode/template/_dot_vscode/settings.json +11 -0
- package/dist/templates/barebones/index.d.ts +1507 -0
- package/dist/templates/barebones/index.mjs +60 -0
- package/dist/templates/barebones/template/app/routes/index.tsx +11 -0
- package/dist/templates/index.d.ts +13 -0
- package/dist/templates/index.mjs +60 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.mjs +0 -0
- package/dist/utils/debug.d.ts +11 -0
- package/dist/utils/debug.mjs +71 -0
- package/dist/utils/getPackageManager.d.ts +2 -0
- package/dist/utils/getPackageManager.mjs +11 -0
- package/dist/utils/helpers/helperFactory.d.ts +15 -0
- package/dist/utils/helpers/helperFactory.mjs +3 -0
- package/dist/utils/helpers/index.d.ts +51 -0
- package/dist/utils/helpers/index.mjs +227 -0
- package/dist/utils/runCmd.d.ts +1 -0
- package/dist/utils/runCmd.mjs +4 -0
- package/dist/utils/runPackageManagerCommand.d.ts +4 -0
- package/dist/utils/runPackageManagerCommand.mjs +17 -0
- package/dist/utils/spawnCmd.d.ts +1 -0
- package/dist/utils/spawnCmd.mjs +30 -0
- package/dist/utils/validateProjectName.d.ts +8 -0
- package/dist/utils/validateProjectName.mjs +14 -0
- package/index.js +3 -0
- 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,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
|
+
});
|