create-sprint 0.0.8 → 0.0.32
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/generators.js +12 -34
- package/dist/index.js +24 -33
- package/dist/validators.js +7 -12
- package/package.json +4 -3
- package/src/cli.ts +1 -1
- package/src/generators.ts +12 -34
- package/src/index.ts +29 -55
- package/src/validators.ts +10 -21
package/dist/generators.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export function getTypeScriptPackageJson(name, telemetry) {
|
|
2
2
|
const deps = {
|
|
3
|
-
"sprint-es": "^0.0.
|
|
4
|
-
"sprint": "^0.0.1",
|
|
3
|
+
"sprint-es": "^0.0.29",
|
|
5
4
|
dotenv: "^17.0.0",
|
|
6
5
|
};
|
|
7
6
|
const devDeps = {
|
|
@@ -21,9 +20,9 @@ export function getTypeScriptPackageJson(name, telemetry) {
|
|
|
21
20
|
description: "Sprint API",
|
|
22
21
|
main: "dist/index.js",
|
|
23
22
|
scripts: {
|
|
24
|
-
build: "sprint build",
|
|
25
|
-
start: "sprint start",
|
|
26
|
-
dev: "sprint dev",
|
|
23
|
+
build: "sprint-es build",
|
|
24
|
+
start: "sprint-es start",
|
|
25
|
+
dev: "sprint-es dev",
|
|
27
26
|
},
|
|
28
27
|
dependencies: deps,
|
|
29
28
|
devDependencies: devDeps,
|
|
@@ -31,8 +30,7 @@ export function getTypeScriptPackageJson(name, telemetry) {
|
|
|
31
30
|
}
|
|
32
31
|
export function getJavaScriptPackageJson(name, telemetry) {
|
|
33
32
|
const deps = {
|
|
34
|
-
"sprint-es": "^0.0.
|
|
35
|
-
"sprint": "^0.0.1",
|
|
33
|
+
"sprint-es": "^0.0.29",
|
|
36
34
|
dotenv: "^17.0.0",
|
|
37
35
|
};
|
|
38
36
|
if (telemetry === "sentry" || telemetry === "glitchtip") {
|
|
@@ -48,9 +46,9 @@ export function getJavaScriptPackageJson(name, telemetry) {
|
|
|
48
46
|
main: "src/index.js",
|
|
49
47
|
type: "module",
|
|
50
48
|
scripts: {
|
|
51
|
-
build: "sprint build",
|
|
52
|
-
start: "sprint start",
|
|
53
|
-
dev: "sprint dev",
|
|
49
|
+
build: "sprint-es build",
|
|
50
|
+
start: "sprint-es start",
|
|
51
|
+
dev: "sprint-es dev",
|
|
54
52
|
},
|
|
55
53
|
dependencies: deps,
|
|
56
54
|
};
|
|
@@ -235,22 +233,12 @@ export function getHomeSchema(language) {
|
|
|
235
233
|
if (language === "typescript") {
|
|
236
234
|
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
237
235
|
|
|
238
|
-
export const homeSchema = defineRouteSchema({
|
|
239
|
-
input: z.object({
|
|
240
|
-
message: z.string(),
|
|
241
|
-
status: z.string()
|
|
242
|
-
})
|
|
243
|
-
});
|
|
236
|
+
export const homeSchema = defineRouteSchema({});
|
|
244
237
|
`;
|
|
245
238
|
}
|
|
246
239
|
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
247
240
|
|
|
248
|
-
export const homeSchema = defineRouteSchema({
|
|
249
|
-
input: z.object({
|
|
250
|
-
message: z.string(),
|
|
251
|
-
status: z.string()
|
|
252
|
-
})
|
|
253
|
-
});
|
|
241
|
+
export const homeSchema = defineRouteSchema({});
|
|
254
242
|
`;
|
|
255
243
|
}
|
|
256
244
|
export function getAdminSchema(language) {
|
|
@@ -258,17 +246,12 @@ export function getAdminSchema(language) {
|
|
|
258
246
|
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
259
247
|
|
|
260
248
|
export const adminSchema = defineRouteSchema({
|
|
261
|
-
|
|
249
|
+
queryParams: z.object({
|
|
262
250
|
id: z.string().uuid()
|
|
263
251
|
}),
|
|
264
252
|
body: z.object({
|
|
265
253
|
name: z.string().min(1),
|
|
266
254
|
email: z.email().optional()
|
|
267
|
-
}),
|
|
268
|
-
input: z.object({
|
|
269
|
-
id: z.string().uuid(),
|
|
270
|
-
name: z.string(),
|
|
271
|
-
email: z.string().email().optional()
|
|
272
255
|
})
|
|
273
256
|
});
|
|
274
257
|
`;
|
|
@@ -276,17 +259,12 @@ export const adminSchema = defineRouteSchema({
|
|
|
276
259
|
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
277
260
|
|
|
278
261
|
export const adminSchema = defineRouteSchema({
|
|
279
|
-
|
|
262
|
+
queryParams: z.object({
|
|
280
263
|
id: z.string().uuid()
|
|
281
264
|
}),
|
|
282
265
|
body: z.object({
|
|
283
266
|
name: z.string().min(1),
|
|
284
267
|
email: z.email().optional()
|
|
285
|
-
}),
|
|
286
|
-
input: z.object({
|
|
287
|
-
id: z.string().uuid(),
|
|
288
|
-
name: z.string(),
|
|
289
|
-
email: z.string().email().optional()
|
|
290
268
|
})
|
|
291
269
|
});
|
|
292
270
|
`;
|
package/dist/index.js
CHANGED
|
@@ -61,46 +61,39 @@ function parseArgs(args) {
|
|
|
61
61
|
const hasJs = args.includes("--js") || args.includes("--javascript");
|
|
62
62
|
const hasName = args.indexOf("--name");
|
|
63
63
|
const telemetryArg = args.includes("--telemetry") ? args[args.indexOf("--telemetry") + 1] : null;
|
|
64
|
-
if (args.includes("--yes") || args.includes("-y"))
|
|
64
|
+
if (args.includes("--yes") || args.includes("-y"))
|
|
65
65
|
options.skipPrompts = true;
|
|
66
|
-
}
|
|
67
66
|
if (!options.skipPrompts) {
|
|
68
|
-
if (hasTs)
|
|
67
|
+
if (hasTs)
|
|
69
68
|
options.language = "typescript";
|
|
70
|
-
|
|
71
|
-
else if (hasJs) {
|
|
69
|
+
else if (hasJs)
|
|
72
70
|
options.language = "javascript";
|
|
73
|
-
}
|
|
74
71
|
}
|
|
75
|
-
else
|
|
72
|
+
else
|
|
76
73
|
options.language = "typescript";
|
|
77
|
-
|
|
78
|
-
if (hasName !== -1 && args[hasName + 1]) {
|
|
74
|
+
if (hasName !== -1 && args[hasName + 1])
|
|
79
75
|
options.projectName = args[hasName + 1];
|
|
80
|
-
|
|
81
|
-
if (args.includes("--current")) {
|
|
76
|
+
if (args.includes("--current"))
|
|
82
77
|
options.projectName = ".";
|
|
83
|
-
|
|
84
|
-
if (args.includes("--docker")) {
|
|
78
|
+
if (args.includes("--docker"))
|
|
85
79
|
options.docker = true;
|
|
86
|
-
|
|
87
|
-
if (args.includes("--no-install")) {
|
|
80
|
+
if (args.includes("--no-install"))
|
|
88
81
|
options.skipInstall = true;
|
|
89
|
-
|
|
90
|
-
if (telemetryArg && ["sentry", "glitchtip", "discord", "none"].includes(telemetryArg)) {
|
|
82
|
+
if (telemetryArg && ["sentry", "glitchtip", "discord", "none"].includes(telemetryArg))
|
|
91
83
|
options.telemetry = telemetryArg;
|
|
92
|
-
}
|
|
93
84
|
return options;
|
|
94
85
|
}
|
|
86
|
+
;
|
|
95
87
|
async function getProjectName() {
|
|
96
88
|
const name = await input({
|
|
97
89
|
message: "Enter project name:",
|
|
98
90
|
validate: (value) => {
|
|
99
91
|
return validateProjectName(value) || true;
|
|
100
|
-
}
|
|
92
|
+
}
|
|
101
93
|
});
|
|
102
94
|
return name;
|
|
103
95
|
}
|
|
96
|
+
;
|
|
104
97
|
async function selectLanguage() {
|
|
105
98
|
const language = await select({
|
|
106
99
|
message: "Select your preferred language:",
|
|
@@ -114,11 +107,12 @@ async function selectLanguage() {
|
|
|
114
107
|
name: "JavaScript",
|
|
115
108
|
value: "javascript",
|
|
116
109
|
description: "Vanilla JavaScript for simpler projects",
|
|
117
|
-
}
|
|
118
|
-
]
|
|
110
|
+
}
|
|
111
|
+
]
|
|
119
112
|
});
|
|
120
113
|
return language;
|
|
121
114
|
}
|
|
115
|
+
;
|
|
122
116
|
async function selectTelemetry() {
|
|
123
117
|
const telemetry = await select({
|
|
124
118
|
message: "Select error tracking/telemetry solution:",
|
|
@@ -142,11 +136,12 @@ async function selectTelemetry() {
|
|
|
142
136
|
name: "Discord Webhook",
|
|
143
137
|
value: "discord",
|
|
144
138
|
description: "Send error notifications to Discord channel",
|
|
145
|
-
}
|
|
146
|
-
]
|
|
139
|
+
}
|
|
140
|
+
]
|
|
147
141
|
});
|
|
148
142
|
return telemetry;
|
|
149
143
|
}
|
|
144
|
+
;
|
|
150
145
|
async function createProject(projectName, language, telemetryArg, useDockerArg) {
|
|
151
146
|
const isCurrentDir = projectName === ".";
|
|
152
147
|
const targetDir = isCurrentDir ? process.cwd() : join(process.cwd(), projectName);
|
|
@@ -154,13 +149,11 @@ async function createProject(projectName, language, telemetryArg, useDockerArg)
|
|
|
154
149
|
console.error(`Error: Directory ${projectName} already exists`);
|
|
155
150
|
process.exit(1);
|
|
156
151
|
}
|
|
157
|
-
if (!isCurrentDir)
|
|
152
|
+
if (!isCurrentDir)
|
|
158
153
|
await mkdir(targetDir, { recursive: true });
|
|
159
|
-
}
|
|
160
154
|
let telemetry = telemetryArg || "none";
|
|
161
|
-
if (!telemetryArg)
|
|
155
|
+
if (!telemetryArg)
|
|
162
156
|
telemetry = await selectTelemetry();
|
|
163
|
-
}
|
|
164
157
|
let useDocker = useDockerArg || false;
|
|
165
158
|
if (!useDockerArg) {
|
|
166
159
|
useDocker = await confirm({
|
|
@@ -169,21 +162,18 @@ async function createProject(projectName, language, telemetryArg, useDockerArg)
|
|
|
169
162
|
});
|
|
170
163
|
}
|
|
171
164
|
let pkgJson;
|
|
172
|
-
if (language === "typescript")
|
|
165
|
+
if (language === "typescript")
|
|
173
166
|
pkgJson = getTypeScriptPackageJson(projectName, telemetry);
|
|
174
|
-
|
|
175
|
-
else {
|
|
167
|
+
else
|
|
176
168
|
pkgJson = getJavaScriptPackageJson(projectName, telemetry);
|
|
177
|
-
}
|
|
178
169
|
await writeFile(join(targetDir, "package.json"), JSON.stringify(pkgJson, null, 2));
|
|
179
170
|
if (language === "typescript") {
|
|
180
171
|
await writeFile(join(targetDir, "tsconfig.json"), getTsConfig());
|
|
181
172
|
await writeFile(join(targetDir, "vite.config.ts"), getViteConfig());
|
|
182
173
|
await writeFile(join(targetDir, "sprint.config.ts"), getSprintConfigFile(language, telemetry));
|
|
183
174
|
}
|
|
184
|
-
else
|
|
175
|
+
else
|
|
185
176
|
await writeFile(join(targetDir, "sprint.config.js"), getSprintConfigFile(language, telemetry));
|
|
186
|
-
}
|
|
187
177
|
const srcDir = join(targetDir, "src");
|
|
188
178
|
await mkdir(srcDir, { recursive: true });
|
|
189
179
|
await mkdir(join(srcDir, "middlewares"), { recursive: true });
|
|
@@ -210,3 +200,4 @@ async function createProject(projectName, language, telemetryArg, useDockerArg)
|
|
|
210
200
|
await writeFile(join(targetDir, ".dockerignore"), getDockerIgnore());
|
|
211
201
|
}
|
|
212
202
|
}
|
|
203
|
+
;
|
package/dist/validators.js
CHANGED
|
@@ -2,24 +2,19 @@ export function validateProjectName(name) {
|
|
|
2
2
|
if (!name.trim())
|
|
3
3
|
return "Please enter a project name";
|
|
4
4
|
const n = name.trim();
|
|
5
|
-
if (n !== n.toLowerCase())
|
|
5
|
+
if (n !== n.toLowerCase())
|
|
6
6
|
return "Project name must be lowercase";
|
|
7
|
-
|
|
8
|
-
if (n.length > 214) {
|
|
7
|
+
if (n.length > 214)
|
|
9
8
|
return "Project name must be less than 214 characters";
|
|
10
|
-
|
|
11
|
-
if (n.startsWith("-") || n.startsWith(".")) {
|
|
9
|
+
if (n.startsWith("-") || n.startsWith("."))
|
|
12
10
|
return "Project name cannot start with - or .";
|
|
13
|
-
}
|
|
14
|
-
if (/[~!@#$%^&*(){}[\]<>?:]/.test(n)) {
|
|
11
|
+
if (/[~!@#$%^&*(){}[\]<>?:]/.test(n))
|
|
15
12
|
return "Project name cannot contain special characters (only letters, numbers, - and _)";
|
|
16
|
-
|
|
17
|
-
if (n !== encodeURIComponent(n)) {
|
|
13
|
+
if (n !== encodeURIComponent(n))
|
|
18
14
|
return "Project name must be URL-safe";
|
|
19
|
-
}
|
|
20
15
|
const reserved = ["node_modules", "favicon.ico"];
|
|
21
|
-
if (reserved.includes(n.toLowerCase()))
|
|
16
|
+
if (reserved.includes(n.toLowerCase()))
|
|
22
17
|
return `Cannot use "${n}" as project name`;
|
|
23
|
-
}
|
|
24
18
|
return null;
|
|
25
19
|
}
|
|
20
|
+
;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-sprint",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.32",
|
|
4
4
|
"description": "Create a new Sprint API project",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
15
|
"build": "tsc && node -e \"const fs=require('fs');const p='dist/cli.js';let c=fs.readFileSync(p,'utf8');if(!c.startsWith('#!')){fs.writeFileSync(p,'#!/usr/bin/env node\\n'+c)}\"",
|
|
16
|
-
"prepublishOnly": "npm run build",
|
|
16
|
+
"prepublishOnly": "npm version patch && npm run build",
|
|
17
17
|
"start": "node dist/cli.js"
|
|
18
18
|
},
|
|
19
19
|
"keywords": [
|
|
@@ -29,10 +29,11 @@
|
|
|
29
29
|
"@inquirer/prompts": "^7.10.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
+
"@types/node": "^25.3.3",
|
|
32
33
|
"tsx": "^4.19.0",
|
|
33
34
|
"typescript": "^5.9.3"
|
|
34
35
|
},
|
|
35
36
|
"engines": {
|
|
36
37
|
"node": ">=18.0.0"
|
|
37
38
|
}
|
|
38
|
-
}
|
|
39
|
+
}
|
package/src/cli.ts
CHANGED
package/src/generators.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export function getTypeScriptPackageJson(name: string, telemetry: string) {
|
|
2
2
|
const deps: Record<string, string> = {
|
|
3
|
-
"sprint-es": "^0.0.
|
|
4
|
-
"sprint": "^0.0.1",
|
|
3
|
+
"sprint-es": "^0.0.29",
|
|
5
4
|
dotenv: "^17.0.0",
|
|
6
5
|
};
|
|
7
6
|
|
|
@@ -23,9 +22,9 @@ export function getTypeScriptPackageJson(name: string, telemetry: string) {
|
|
|
23
22
|
description: "Sprint API",
|
|
24
23
|
main: "dist/index.js",
|
|
25
24
|
scripts: {
|
|
26
|
-
build: "sprint build",
|
|
27
|
-
start: "sprint start",
|
|
28
|
-
dev: "sprint dev",
|
|
25
|
+
build: "sprint-es build",
|
|
26
|
+
start: "sprint-es start",
|
|
27
|
+
dev: "sprint-es dev",
|
|
29
28
|
},
|
|
30
29
|
dependencies: deps,
|
|
31
30
|
devDependencies: devDeps,
|
|
@@ -34,8 +33,7 @@ export function getTypeScriptPackageJson(name: string, telemetry: string) {
|
|
|
34
33
|
|
|
35
34
|
export function getJavaScriptPackageJson(name: string, telemetry: string) {
|
|
36
35
|
const deps: Record<string, string> = {
|
|
37
|
-
"sprint-es": "^0.0.
|
|
38
|
-
"sprint": "^0.0.1",
|
|
36
|
+
"sprint-es": "^0.0.29",
|
|
39
37
|
dotenv: "^17.0.0",
|
|
40
38
|
};
|
|
41
39
|
|
|
@@ -52,9 +50,9 @@ export function getJavaScriptPackageJson(name: string, telemetry: string) {
|
|
|
52
50
|
main: "src/index.js",
|
|
53
51
|
type: "module",
|
|
54
52
|
scripts: {
|
|
55
|
-
build: "sprint build",
|
|
56
|
-
start: "sprint start",
|
|
57
|
-
dev: "sprint dev",
|
|
53
|
+
build: "sprint-es build",
|
|
54
|
+
start: "sprint-es start",
|
|
55
|
+
dev: "sprint-es dev",
|
|
58
56
|
},
|
|
59
57
|
dependencies: deps,
|
|
60
58
|
};
|
|
@@ -248,22 +246,12 @@ export function getHomeSchema(language: string) {
|
|
|
248
246
|
if (language === "typescript") {
|
|
249
247
|
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
250
248
|
|
|
251
|
-
export const homeSchema = defineRouteSchema({
|
|
252
|
-
input: z.object({
|
|
253
|
-
message: z.string(),
|
|
254
|
-
status: z.string()
|
|
255
|
-
})
|
|
256
|
-
});
|
|
249
|
+
export const homeSchema = defineRouteSchema({});
|
|
257
250
|
`;
|
|
258
251
|
}
|
|
259
252
|
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
260
253
|
|
|
261
|
-
export const homeSchema = defineRouteSchema({
|
|
262
|
-
input: z.object({
|
|
263
|
-
message: z.string(),
|
|
264
|
-
status: z.string()
|
|
265
|
-
})
|
|
266
|
-
});
|
|
254
|
+
export const homeSchema = defineRouteSchema({});
|
|
267
255
|
`;
|
|
268
256
|
}
|
|
269
257
|
|
|
@@ -272,17 +260,12 @@ export function getAdminSchema(language: string) {
|
|
|
272
260
|
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
273
261
|
|
|
274
262
|
export const adminSchema = defineRouteSchema({
|
|
275
|
-
|
|
263
|
+
queryParams: z.object({
|
|
276
264
|
id: z.string().uuid()
|
|
277
265
|
}),
|
|
278
266
|
body: z.object({
|
|
279
267
|
name: z.string().min(1),
|
|
280
268
|
email: z.email().optional()
|
|
281
|
-
}),
|
|
282
|
-
input: z.object({
|
|
283
|
-
id: z.string().uuid(),
|
|
284
|
-
name: z.string(),
|
|
285
|
-
email: z.string().email().optional()
|
|
286
269
|
})
|
|
287
270
|
});
|
|
288
271
|
`;
|
|
@@ -290,17 +273,12 @@ export const adminSchema = defineRouteSchema({
|
|
|
290
273
|
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
291
274
|
|
|
292
275
|
export const adminSchema = defineRouteSchema({
|
|
293
|
-
|
|
276
|
+
queryParams: z.object({
|
|
294
277
|
id: z.string().uuid()
|
|
295
278
|
}),
|
|
296
279
|
body: z.object({
|
|
297
280
|
name: z.string().min(1),
|
|
298
281
|
email: z.email().optional()
|
|
299
|
-
}),
|
|
300
|
-
input: z.object({
|
|
301
|
-
id: z.string().uuid(),
|
|
302
|
-
name: z.string(),
|
|
303
|
-
email: z.string().email().optional()
|
|
304
282
|
})
|
|
305
283
|
});
|
|
306
284
|
`;
|
package/src/index.ts
CHANGED
|
@@ -83,53 +83,36 @@ function parseArgs(args: string[]): CLIOptions {
|
|
|
83
83
|
const hasName = args.indexOf("--name");
|
|
84
84
|
const telemetryArg = args.includes("--telemetry") ? args[args.indexOf("--telemetry") + 1] : null;
|
|
85
85
|
|
|
86
|
-
if (args.includes("--yes") || args.includes("-y"))
|
|
87
|
-
options.skipPrompts = true;
|
|
88
|
-
}
|
|
86
|
+
if (args.includes("--yes") || args.includes("-y")) options.skipPrompts = true;
|
|
89
87
|
|
|
90
88
|
if (!options.skipPrompts) {
|
|
91
|
-
if (hasTs)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
} else {
|
|
97
|
-
options.language = "typescript";
|
|
98
|
-
}
|
|
89
|
+
if (hasTs) options.language = "typescript";
|
|
90
|
+
else if (hasJs) options.language = "javascript";
|
|
91
|
+
} else options.language = "typescript";
|
|
92
|
+
|
|
93
|
+
if (hasName !== -1 && args[hasName + 1]) options.projectName = args[hasName + 1];
|
|
99
94
|
|
|
100
|
-
if (
|
|
101
|
-
options.projectName = args[hasName + 1];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (args.includes("--current")) {
|
|
105
|
-
options.projectName = ".";
|
|
106
|
-
}
|
|
95
|
+
if (args.includes("--current")) options.projectName = ".";
|
|
107
96
|
|
|
108
|
-
if (args.includes("--docker"))
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (args.includes("--no-install")) {
|
|
113
|
-
options.skipInstall = true;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (telemetryArg && ["sentry", "glitchtip", "discord", "none"].includes(telemetryArg)) {
|
|
117
|
-
options.telemetry = telemetryArg as CLIOptions["telemetry"];
|
|
118
|
-
}
|
|
97
|
+
if (args.includes("--docker")) options.docker = true;
|
|
98
|
+
|
|
99
|
+
if (args.includes("--no-install")) options.skipInstall = true;
|
|
119
100
|
|
|
101
|
+
if (telemetryArg && ["sentry", "glitchtip", "discord", "none"].includes(telemetryArg)) options.telemetry = telemetryArg as CLIOptions["telemetry"];
|
|
102
|
+
|
|
120
103
|
return options;
|
|
121
|
-
}
|
|
104
|
+
};
|
|
122
105
|
|
|
123
106
|
async function getProjectName(): Promise<string> {
|
|
124
107
|
const name = await input({
|
|
125
108
|
message: "Enter project name:",
|
|
126
109
|
validate: (value) => {
|
|
127
110
|
return validateProjectName(value) || true;
|
|
128
|
-
}
|
|
111
|
+
}
|
|
129
112
|
});
|
|
130
113
|
|
|
131
114
|
return name;
|
|
132
|
-
}
|
|
115
|
+
};
|
|
133
116
|
|
|
134
117
|
async function selectLanguage(): Promise<"typescript" | "javascript"> {
|
|
135
118
|
const language = await select({
|
|
@@ -144,12 +127,12 @@ async function selectLanguage(): Promise<"typescript" | "javascript"> {
|
|
|
144
127
|
name: "JavaScript",
|
|
145
128
|
value: "javascript",
|
|
146
129
|
description: "Vanilla JavaScript for simpler projects",
|
|
147
|
-
}
|
|
148
|
-
]
|
|
130
|
+
}
|
|
131
|
+
]
|
|
149
132
|
});
|
|
150
133
|
|
|
151
134
|
return language as "typescript" | "javascript";
|
|
152
|
-
}
|
|
135
|
+
};
|
|
153
136
|
|
|
154
137
|
async function selectTelemetry(): Promise<"none" | "sentry" | "glitchtip" | "discord"> {
|
|
155
138
|
const telemetry = await select({
|
|
@@ -174,12 +157,12 @@ async function selectTelemetry(): Promise<"none" | "sentry" | "glitchtip" | "dis
|
|
|
174
157
|
name: "Discord Webhook",
|
|
175
158
|
value: "discord",
|
|
176
159
|
description: "Send error notifications to Discord channel",
|
|
177
|
-
}
|
|
178
|
-
]
|
|
160
|
+
}
|
|
161
|
+
]
|
|
179
162
|
});
|
|
180
163
|
|
|
181
164
|
return telemetry as "none" | "sentry" | "glitchtip" | "discord";
|
|
182
|
-
}
|
|
165
|
+
};
|
|
183
166
|
|
|
184
167
|
async function createProject(
|
|
185
168
|
projectName: string,
|
|
@@ -195,14 +178,10 @@ async function createProject(
|
|
|
195
178
|
process.exit(1);
|
|
196
179
|
}
|
|
197
180
|
|
|
198
|
-
if (!isCurrentDir) {
|
|
199
|
-
await mkdir(targetDir, { recursive: true });
|
|
200
|
-
}
|
|
181
|
+
if (!isCurrentDir) await mkdir(targetDir, { recursive: true });
|
|
201
182
|
|
|
202
183
|
let telemetry = telemetryArg || "none";
|
|
203
|
-
if (!telemetryArg)
|
|
204
|
-
telemetry = await selectTelemetry();
|
|
205
|
-
}
|
|
184
|
+
if (!telemetryArg) telemetry = await selectTelemetry();
|
|
206
185
|
|
|
207
186
|
let useDocker = useDockerArg || false;
|
|
208
187
|
if (!useDockerArg) {
|
|
@@ -213,22 +192,17 @@ async function createProject(
|
|
|
213
192
|
}
|
|
214
193
|
|
|
215
194
|
let pkgJson;
|
|
216
|
-
if (language === "typescript")
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
pkgJson = getJavaScriptPackageJson(projectName, telemetry);
|
|
220
|
-
}
|
|
221
|
-
|
|
195
|
+
if (language === "typescript") pkgJson = getTypeScriptPackageJson(projectName, telemetry);
|
|
196
|
+
else pkgJson = getJavaScriptPackageJson(projectName, telemetry);
|
|
197
|
+
|
|
222
198
|
await writeFile(join(targetDir, "package.json"), JSON.stringify(pkgJson, null, 2));
|
|
223
199
|
|
|
224
200
|
if (language === "typescript") {
|
|
225
201
|
await writeFile(join(targetDir, "tsconfig.json"), getTsConfig());
|
|
226
202
|
await writeFile(join(targetDir, "vite.config.ts"), getViteConfig());
|
|
227
203
|
await writeFile(join(targetDir, "sprint.config.ts"), getSprintConfigFile(language, telemetry));
|
|
228
|
-
} else
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
|
|
204
|
+
} else await writeFile(join(targetDir, "sprint.config.js"), getSprintConfigFile(language, telemetry));
|
|
205
|
+
|
|
232
206
|
const srcDir = join(targetDir, "src");
|
|
233
207
|
await mkdir(srcDir, { recursive: true });
|
|
234
208
|
|
|
@@ -265,4 +239,4 @@ async function createProject(
|
|
|
265
239
|
await writeFile(join(targetDir, "docker-compose.yml"), getDockerCompose(language));
|
|
266
240
|
await writeFile(join(targetDir, ".dockerignore"), getDockerIgnore());
|
|
267
241
|
}
|
|
268
|
-
}
|
|
242
|
+
};
|
package/src/validators.ts
CHANGED
|
@@ -3,30 +3,19 @@ export function validateProjectName(name: string): string | null {
|
|
|
3
3
|
|
|
4
4
|
const n = name.trim();
|
|
5
5
|
|
|
6
|
-
if (n !== n.toLowerCase())
|
|
7
|
-
return "Project name must be lowercase";
|
|
8
|
-
}
|
|
6
|
+
if (n !== n.toLowerCase()) return "Project name must be lowercase";
|
|
9
7
|
|
|
10
|
-
if (n.length > 214)
|
|
11
|
-
return "Project name must be less than 214 characters";
|
|
12
|
-
}
|
|
8
|
+
if (n.length > 214) return "Project name must be less than 214 characters";
|
|
13
9
|
|
|
14
|
-
if (n.startsWith("-") || n.startsWith("."))
|
|
15
|
-
return "Project name cannot start with - or .";
|
|
16
|
-
}
|
|
10
|
+
if (n.startsWith("-") || n.startsWith(".")) return "Project name cannot start with - or .";
|
|
17
11
|
|
|
18
|
-
if (/[~!@#$%^&*(){}[\]<>?:]/.test(n))
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (n !== encodeURIComponent(n)) {
|
|
23
|
-
return "Project name must be URL-safe";
|
|
24
|
-
}
|
|
12
|
+
if (/[~!@#$%^&*(){}[\]<>?:]/.test(n)) return "Project name cannot contain special characters (only letters, numbers, - and _)";
|
|
13
|
+
|
|
14
|
+
if (n !== encodeURIComponent(n)) return "Project name must be URL-safe";
|
|
15
|
+
|
|
25
16
|
|
|
26
17
|
const reserved = ["node_modules", "favicon.ico"];
|
|
27
|
-
if (reserved.includes(n.toLowerCase())) {
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
18
|
+
if (reserved.includes(n.toLowerCase())) return `Cannot use "${n}" as project name`;
|
|
19
|
+
|
|
31
20
|
return null;
|
|
32
|
-
}
|
|
21
|
+
};
|