create-sprint 0.0.6 → 0.0.8
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 +221 -26
- package/dist/index.js +22 -11
- package/package.json +1 -1
- package/src/generators.ts +227 -26
- package/src/index.ts +26 -10
package/dist/generators.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export function getTypeScriptPackageJson(name, telemetry) {
|
|
2
2
|
const deps = {
|
|
3
|
-
"sprint-es": "^0.0.
|
|
3
|
+
"sprint-es": "^0.0.28",
|
|
4
|
+
"sprint": "^0.0.1",
|
|
4
5
|
dotenv: "^17.0.0",
|
|
5
6
|
};
|
|
6
7
|
const devDeps = {
|
|
7
8
|
"@types/node": "^22.0.0",
|
|
8
9
|
"tsx": "^4.19.0",
|
|
9
10
|
typescript: "^5.6.0",
|
|
10
|
-
vite: "^6.0.0",
|
|
11
11
|
};
|
|
12
12
|
if (telemetry === "sentry" || telemetry === "glitchtip") {
|
|
13
13
|
deps["@sentry/node"] = "^8.0.0";
|
|
@@ -21,9 +21,9 @@ export function getTypeScriptPackageJson(name, telemetry) {
|
|
|
21
21
|
description: "Sprint API",
|
|
22
22
|
main: "dist/index.js",
|
|
23
23
|
scripts: {
|
|
24
|
-
build: "
|
|
25
|
-
start: "
|
|
26
|
-
dev: "
|
|
24
|
+
build: "sprint build",
|
|
25
|
+
start: "sprint start",
|
|
26
|
+
dev: "sprint dev",
|
|
27
27
|
},
|
|
28
28
|
dependencies: deps,
|
|
29
29
|
devDependencies: devDeps,
|
|
@@ -31,7 +31,8 @@ export function getTypeScriptPackageJson(name, telemetry) {
|
|
|
31
31
|
}
|
|
32
32
|
export function getJavaScriptPackageJson(name, telemetry) {
|
|
33
33
|
const deps = {
|
|
34
|
-
"sprint-es": "^0.0.
|
|
34
|
+
"sprint-es": "^0.0.28",
|
|
35
|
+
"sprint": "^0.0.1",
|
|
35
36
|
dotenv: "^17.0.0",
|
|
36
37
|
};
|
|
37
38
|
if (telemetry === "sentry" || telemetry === "glitchtip") {
|
|
@@ -47,8 +48,9 @@ export function getJavaScriptPackageJson(name, telemetry) {
|
|
|
47
48
|
main: "src/index.js",
|
|
48
49
|
type: "module",
|
|
49
50
|
scripts: {
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
build: "sprint build",
|
|
52
|
+
start: "sprint start",
|
|
53
|
+
dev: "sprint dev",
|
|
52
54
|
},
|
|
53
55
|
dependencies: deps,
|
|
54
56
|
};
|
|
@@ -71,6 +73,10 @@ export function getTsConfig() {
|
|
|
71
73
|
declarationMap: true,
|
|
72
74
|
sourceMap: true,
|
|
73
75
|
tabWidth: 4,
|
|
76
|
+
baseUrl: ".",
|
|
77
|
+
paths: {
|
|
78
|
+
"@/*": ["./src/*"]
|
|
79
|
+
}
|
|
74
80
|
},
|
|
75
81
|
include: ["src/**/*"],
|
|
76
82
|
exclude: ["node_modules", "dist"],
|
|
@@ -104,51 +110,235 @@ export default defineConfig({
|
|
|
104
110
|
export function getMainFile(language) {
|
|
105
111
|
if (language === "typescript") {
|
|
106
112
|
return `import Sprint from "sprint-es";
|
|
107
|
-
import { config } from "./sprint.config";
|
|
108
|
-
import homeRouter from "./routes/home";
|
|
109
113
|
|
|
110
|
-
const app = new Sprint(
|
|
111
|
-
|
|
112
|
-
app.use(homeRouter);
|
|
114
|
+
const app = new Sprint();
|
|
113
115
|
`;
|
|
114
116
|
}
|
|
115
117
|
return `import Sprint from "sprint-es";
|
|
116
|
-
import { config } from "./sprint.config.js";
|
|
117
|
-
import homeRouter from "./routes/home.js";
|
|
118
|
-
|
|
119
|
-
const app = new Sprint(config);
|
|
120
118
|
|
|
121
|
-
app
|
|
119
|
+
const app = new Sprint();
|
|
122
120
|
`;
|
|
123
121
|
}
|
|
124
122
|
export function getHomeRoute(language) {
|
|
125
123
|
if (language === "typescript") {
|
|
126
124
|
return `import { Router } from "sprint-es";
|
|
125
|
+
import { homeSchema } from "@/schemas/home";
|
|
126
|
+
import { homeController } from "@/controllers/home";
|
|
127
127
|
|
|
128
128
|
const router = Router();
|
|
129
129
|
|
|
130
|
-
router.get("/",
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
}
|
|
130
|
+
router.get("/", homeSchema, homeController);
|
|
131
|
+
|
|
132
|
+
export default router;
|
|
133
|
+
`;
|
|
134
|
+
}
|
|
135
|
+
return `import { Router } from "sprint-es";
|
|
136
|
+
import { homeSchema } from "../schemas/home.js";
|
|
137
|
+
import { homeController } from "../controllers/home.js";
|
|
138
|
+
|
|
139
|
+
const router = Router();
|
|
140
|
+
|
|
141
|
+
router.get("/", homeSchema, homeController);
|
|
142
|
+
|
|
143
|
+
export default router;
|
|
144
|
+
`;
|
|
145
|
+
}
|
|
146
|
+
export function getAdminRoute(language) {
|
|
147
|
+
if (language === "typescript") {
|
|
148
|
+
return `import { Router } from "sprint-es";
|
|
149
|
+
import { adminSchema } from "@/schemas/admin";
|
|
150
|
+
import { adminController, adminUsersController } from "@/controllers/admin";
|
|
151
|
+
|
|
152
|
+
const router = Router();
|
|
153
|
+
|
|
154
|
+
router.get("/", adminSchema, adminController);
|
|
155
|
+
router.get("/users", adminSchema, adminUsersController);
|
|
136
156
|
|
|
137
157
|
export default router;
|
|
138
158
|
`;
|
|
139
159
|
}
|
|
140
160
|
return `import { Router } from "sprint-es";
|
|
161
|
+
import { adminSchema } from "../schemas/admin.js";
|
|
162
|
+
import { adminController, adminUsersController } from "../controllers/admin.js";
|
|
141
163
|
|
|
142
164
|
const router = Router();
|
|
143
165
|
|
|
144
|
-
router.get("/",
|
|
166
|
+
router.get("/", adminSchema, adminController);
|
|
167
|
+
router.get("/users", adminSchema, adminUsersController);
|
|
168
|
+
|
|
169
|
+
export default router;
|
|
170
|
+
`;
|
|
171
|
+
}
|
|
172
|
+
export function getHomeController(language) {
|
|
173
|
+
if (language === "typescript") {
|
|
174
|
+
return `import { Handler } from "sprint-es";
|
|
175
|
+
|
|
176
|
+
export const homeController: Handler = (req, res) => {
|
|
145
177
|
res.json({
|
|
146
178
|
message: "Hello World",
|
|
147
179
|
status: "ok"
|
|
148
180
|
});
|
|
181
|
+
};
|
|
182
|
+
`;
|
|
183
|
+
}
|
|
184
|
+
return `import { Handler } from "sprint-es";
|
|
185
|
+
|
|
186
|
+
export const homeController = (req, res) => {
|
|
187
|
+
res.json({
|
|
188
|
+
message: "Hello World",
|
|
189
|
+
status: "ok"
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
`;
|
|
193
|
+
}
|
|
194
|
+
export function getAdminController(language) {
|
|
195
|
+
if (language === "typescript") {
|
|
196
|
+
return `import { Handler } from "sprint-es";
|
|
197
|
+
|
|
198
|
+
export const adminController: Handler = (req, res) => {
|
|
199
|
+
res.json({
|
|
200
|
+
message: "Admin Dashboard",
|
|
201
|
+
status: "ok"
|
|
202
|
+
});
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export const adminUsersController: Handler = (req, res) => {
|
|
206
|
+
res.json({
|
|
207
|
+
users: [
|
|
208
|
+
{ id: 1, name: "John Doe", role: "admin" },
|
|
209
|
+
{ id: 2, name: "Jane Smith", role: "user" }
|
|
210
|
+
]
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
`;
|
|
214
|
+
}
|
|
215
|
+
return `import { Handler } from "sprint-es";
|
|
216
|
+
|
|
217
|
+
export const adminController = (req, res) => {
|
|
218
|
+
res.json({
|
|
219
|
+
message: "Admin Dashboard",
|
|
220
|
+
status: "ok"
|
|
221
|
+
});
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
export const adminUsersController = (req, res) => {
|
|
225
|
+
res.json({
|
|
226
|
+
users: [
|
|
227
|
+
{ id: 1, name: "John Doe", role: "admin" },
|
|
228
|
+
{ id: 2, name: "Jane Smith", role: "user" }
|
|
229
|
+
]
|
|
230
|
+
});
|
|
231
|
+
};
|
|
232
|
+
`;
|
|
233
|
+
}
|
|
234
|
+
export function getHomeSchema(language) {
|
|
235
|
+
if (language === "typescript") {
|
|
236
|
+
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
237
|
+
|
|
238
|
+
export const homeSchema = defineRouteSchema({
|
|
239
|
+
input: z.object({
|
|
240
|
+
message: z.string(),
|
|
241
|
+
status: z.string()
|
|
242
|
+
})
|
|
149
243
|
});
|
|
244
|
+
`;
|
|
245
|
+
}
|
|
246
|
+
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
150
247
|
|
|
151
|
-
export
|
|
248
|
+
export const homeSchema = defineRouteSchema({
|
|
249
|
+
input: z.object({
|
|
250
|
+
message: z.string(),
|
|
251
|
+
status: z.string()
|
|
252
|
+
})
|
|
253
|
+
});
|
|
254
|
+
`;
|
|
255
|
+
}
|
|
256
|
+
export function getAdminSchema(language) {
|
|
257
|
+
if (language === "typescript") {
|
|
258
|
+
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
259
|
+
|
|
260
|
+
export const adminSchema = defineRouteSchema({
|
|
261
|
+
params: z.object({
|
|
262
|
+
id: z.string().uuid()
|
|
263
|
+
}),
|
|
264
|
+
body: z.object({
|
|
265
|
+
name: z.string().min(1),
|
|
266
|
+
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
|
+
})
|
|
273
|
+
});
|
|
274
|
+
`;
|
|
275
|
+
}
|
|
276
|
+
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
277
|
+
|
|
278
|
+
export const adminSchema = defineRouteSchema({
|
|
279
|
+
params: z.object({
|
|
280
|
+
id: z.string().uuid()
|
|
281
|
+
}),
|
|
282
|
+
body: z.object({
|
|
283
|
+
name: z.string().min(1),
|
|
284
|
+
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
|
+
})
|
|
291
|
+
});
|
|
292
|
+
`;
|
|
293
|
+
}
|
|
294
|
+
export function getAuthMiddleware(language) {
|
|
295
|
+
if (language === "typescript") {
|
|
296
|
+
return `import { defineMiddleware } from "sprint-es";
|
|
297
|
+
|
|
298
|
+
export default defineMiddleware({
|
|
299
|
+
name: "auth",
|
|
300
|
+
priority: 10,
|
|
301
|
+
include: "/admin/**",
|
|
302
|
+
handler: (req, res, next) => {
|
|
303
|
+
const authHeader = req.headers.authorization;
|
|
304
|
+
|
|
305
|
+
if (!authHeader) {
|
|
306
|
+
return res.status(401).json({ error: "No authorization header" });
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const token = authHeader.replace("Bearer ", "");
|
|
310
|
+
|
|
311
|
+
if (token !== "admin-token") {
|
|
312
|
+
return res.status(403).json({ error: "Invalid token" });
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
next();
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
`;
|
|
319
|
+
}
|
|
320
|
+
return `import { defineMiddleware } from "sprint-es";
|
|
321
|
+
|
|
322
|
+
export default defineMiddleware({
|
|
323
|
+
name: "auth",
|
|
324
|
+
priority: 10,
|
|
325
|
+
include: "/admin/**",
|
|
326
|
+
handler: (req, res, next) => {
|
|
327
|
+
const authHeader = req.headers.authorization;
|
|
328
|
+
|
|
329
|
+
if (!authHeader) {
|
|
330
|
+
return res.status(401).json({ error: "No authorization header" });
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const token = authHeader.replace("Bearer ", "");
|
|
334
|
+
|
|
335
|
+
if (token !== "admin-token") {
|
|
336
|
+
return res.status(403).json({ error: "Invalid token" });
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
next();
|
|
340
|
+
}
|
|
341
|
+
});
|
|
152
342
|
`;
|
|
153
343
|
}
|
|
154
344
|
export function getDockerfile(language) {
|
|
@@ -266,6 +456,11 @@ export const config: SprintOptions = {
|
|
|
266
456
|
port: process.env.PORT ? parseInt(process.env.PORT) : 3000
|
|
267
457
|
};
|
|
268
458
|
|
|
459
|
+
// Add Vite config here if needed
|
|
460
|
+
// export const vite = {
|
|
461
|
+
// build: { ... }
|
|
462
|
+
// };
|
|
463
|
+
|
|
269
464
|
`;
|
|
270
465
|
if (telemetry === "sentry" || telemetry === "glitchtip") {
|
|
271
466
|
config += `import { initTelemetry } from "sprint-es/telemetry";
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { mkdir, writeFile } from "fs/promises";
|
|
|
4
4
|
import { join } from "path";
|
|
5
5
|
import { input, select, confirm } from "@inquirer/prompts";
|
|
6
6
|
import { validateProjectName } from "./validators.js";
|
|
7
|
-
import { getTypeScriptPackageJson, getJavaScriptPackageJson, getTsConfig, getViteConfig, getMainFile, getHomeRoute, getDockerfile, getDockerCompose, getGitignore, getDockerIgnore, getSprintConfigFile,
|
|
7
|
+
import { getTypeScriptPackageJson, getJavaScriptPackageJson, getTsConfig, getViteConfig, getMainFile, getHomeRoute, getAdminRoute, getHomeController, getAdminController, getAuthMiddleware, getHomeSchema, getAdminSchema, getDockerfile, getDockerCompose, getGitignore, getDockerIgnore, getSprintConfigFile, getEnvDevelopment, getEnvProduction } from "./generators.js";
|
|
8
8
|
export async function runCLI(args) {
|
|
9
9
|
const options = parseArgs(args);
|
|
10
10
|
console.log("\n🚀 Welcome to Sprint - Quickly API Framework\n");
|
|
@@ -30,7 +30,7 @@ export async function runCLI(args) {
|
|
|
30
30
|
if (options.skipInstall) {
|
|
31
31
|
installDeps = false;
|
|
32
32
|
}
|
|
33
|
-
else
|
|
33
|
+
else {
|
|
34
34
|
installDeps = await confirm({
|
|
35
35
|
message: "Do you want to install dependencies now?",
|
|
36
36
|
default: true,
|
|
@@ -63,13 +63,17 @@ function parseArgs(args) {
|
|
|
63
63
|
const telemetryArg = args.includes("--telemetry") ? args[args.indexOf("--telemetry") + 1] : null;
|
|
64
64
|
if (args.includes("--yes") || args.includes("-y")) {
|
|
65
65
|
options.skipPrompts = true;
|
|
66
|
-
options.language = "typescript";
|
|
67
66
|
}
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
if (!options.skipPrompts) {
|
|
68
|
+
if (hasTs) {
|
|
69
|
+
options.language = "typescript";
|
|
70
|
+
}
|
|
71
|
+
else if (hasJs) {
|
|
72
|
+
options.language = "javascript";
|
|
73
|
+
}
|
|
70
74
|
}
|
|
71
|
-
else
|
|
72
|
-
options.language = "
|
|
75
|
+
else {
|
|
76
|
+
options.language = "typescript";
|
|
73
77
|
}
|
|
74
78
|
if (hasName !== -1 && args[hasName + 1]) {
|
|
75
79
|
options.projectName = args[hasName + 1];
|
|
@@ -185,13 +189,20 @@ async function createProject(projectName, language, telemetryArg, useDockerArg)
|
|
|
185
189
|
await mkdir(join(srcDir, "middlewares"), { recursive: true });
|
|
186
190
|
await mkdir(join(srcDir, "routes"), { recursive: true });
|
|
187
191
|
await mkdir(join(srcDir, "controllers"), { recursive: true });
|
|
192
|
+
await mkdir(join(srcDir, "schemas"), { recursive: true });
|
|
188
193
|
await writeFile(join(srcDir, "middlewares", ".gitkeep"), "");
|
|
189
|
-
await writeFile(join(srcDir, "controllers", ".gitkeep"), "");
|
|
190
194
|
await writeFile(join(srcDir, "app." + (language === "typescript" ? "ts" : "js")), getMainFile(language));
|
|
191
195
|
await writeFile(join(srcDir, "routes", "home." + (language === "typescript" ? "ts" : "js")), getHomeRoute(language));
|
|
192
|
-
await writeFile(join(
|
|
193
|
-
await writeFile(join(
|
|
194
|
-
await writeFile(join(
|
|
196
|
+
await writeFile(join(srcDir, "routes", "admin." + (language === "typescript" ? "ts" : "js")), getAdminRoute(language));
|
|
197
|
+
await writeFile(join(srcDir, "controllers", "home." + (language === "typescript" ? "ts" : "js")), getHomeController(language));
|
|
198
|
+
await writeFile(join(srcDir, "controllers", "admin." + (language === "typescript" ? "ts" : "js")), getAdminController(language));
|
|
199
|
+
await writeFile(join(srcDir, "middlewares", "auth." + (language === "typescript" ? "ts" : "js")), getAuthMiddleware(language));
|
|
200
|
+
await writeFile(join(srcDir, "schemas", "home." + (language === "typescript" ? "ts" : "js")), getHomeSchema(language));
|
|
201
|
+
await writeFile(join(srcDir, "schemas", "admin." + (language === "typescript" ? "ts" : "js")), getAdminSchema(language));
|
|
202
|
+
await writeFile(join(targetDir, ".env.development.example"), getEnvDevelopment(telemetry));
|
|
203
|
+
await writeFile(join(targetDir, ".env.production.example"), getEnvProduction(telemetry));
|
|
204
|
+
await writeFile(join(targetDir, ".env.development"), "");
|
|
205
|
+
await writeFile(join(targetDir, ".env.production"), "");
|
|
195
206
|
await writeFile(join(targetDir, ".gitignore"), getGitignore());
|
|
196
207
|
if (useDocker) {
|
|
197
208
|
await writeFile(join(targetDir, "Dockerfile"), getDockerfile(language));
|
package/package.json
CHANGED
package/src/generators.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export function getTypeScriptPackageJson(name: string, telemetry: string) {
|
|
2
2
|
const deps: Record<string, string> = {
|
|
3
|
-
"sprint-es": "^0.0.
|
|
3
|
+
"sprint-es": "^0.0.28",
|
|
4
|
+
"sprint": "^0.0.1",
|
|
4
5
|
dotenv: "^17.0.0",
|
|
5
6
|
};
|
|
6
7
|
|
|
@@ -8,7 +9,6 @@ export function getTypeScriptPackageJson(name: string, telemetry: string) {
|
|
|
8
9
|
"@types/node": "^22.0.0",
|
|
9
10
|
"tsx": "^4.19.0",
|
|
10
11
|
typescript: "^5.6.0",
|
|
11
|
-
vite: "^6.0.0",
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
if (telemetry === "sentry" || telemetry === "glitchtip") {
|
|
@@ -23,9 +23,9 @@ export function getTypeScriptPackageJson(name: string, telemetry: string) {
|
|
|
23
23
|
description: "Sprint API",
|
|
24
24
|
main: "dist/index.js",
|
|
25
25
|
scripts: {
|
|
26
|
-
build: "
|
|
27
|
-
start: "
|
|
28
|
-
dev: "
|
|
26
|
+
build: "sprint build",
|
|
27
|
+
start: "sprint start",
|
|
28
|
+
dev: "sprint dev",
|
|
29
29
|
},
|
|
30
30
|
dependencies: deps,
|
|
31
31
|
devDependencies: devDeps,
|
|
@@ -34,7 +34,8 @@ export function getTypeScriptPackageJson(name: string, telemetry: string) {
|
|
|
34
34
|
|
|
35
35
|
export function getJavaScriptPackageJson(name: string, telemetry: string) {
|
|
36
36
|
const deps: Record<string, string> = {
|
|
37
|
-
"sprint-es": "^0.0.
|
|
37
|
+
"sprint-es": "^0.0.28",
|
|
38
|
+
"sprint": "^0.0.1",
|
|
38
39
|
dotenv: "^17.0.0",
|
|
39
40
|
};
|
|
40
41
|
|
|
@@ -51,8 +52,9 @@ export function getJavaScriptPackageJson(name: string, telemetry: string) {
|
|
|
51
52
|
main: "src/index.js",
|
|
52
53
|
type: "module",
|
|
53
54
|
scripts: {
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
build: "sprint build",
|
|
56
|
+
start: "sprint start",
|
|
57
|
+
dev: "sprint dev",
|
|
56
58
|
},
|
|
57
59
|
dependencies: deps,
|
|
58
60
|
};
|
|
@@ -76,6 +78,10 @@ export function getTsConfig() {
|
|
|
76
78
|
declarationMap: true,
|
|
77
79
|
sourceMap: true,
|
|
78
80
|
tabWidth: 4,
|
|
81
|
+
baseUrl: ".",
|
|
82
|
+
paths: {
|
|
83
|
+
"@/*": ["./src/*"]
|
|
84
|
+
}
|
|
79
85
|
},
|
|
80
86
|
include: ["src/**/*"],
|
|
81
87
|
exclude: ["node_modules", "dist"],
|
|
@@ -111,53 +117,243 @@ export default defineConfig({
|
|
|
111
117
|
export function getMainFile(language: string) {
|
|
112
118
|
if (language === "typescript") {
|
|
113
119
|
return `import Sprint from "sprint-es";
|
|
114
|
-
import { config } from "./sprint.config";
|
|
115
|
-
import homeRouter from "./routes/home";
|
|
116
120
|
|
|
117
|
-
const app = new Sprint(
|
|
118
|
-
|
|
119
|
-
app.use(homeRouter);
|
|
121
|
+
const app = new Sprint();
|
|
120
122
|
`;
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
return `import Sprint from "sprint-es";
|
|
124
|
-
import { config } from "./sprint.config.js";
|
|
125
|
-
import homeRouter from "./routes/home.js";
|
|
126
|
-
|
|
127
|
-
const app = new Sprint(config);
|
|
128
126
|
|
|
129
|
-
app
|
|
127
|
+
const app = new Sprint();
|
|
130
128
|
`;
|
|
131
129
|
}
|
|
132
130
|
|
|
133
131
|
export function getHomeRoute(language: string) {
|
|
134
132
|
if (language === "typescript") {
|
|
135
133
|
return `import { Router } from "sprint-es";
|
|
134
|
+
import { homeSchema } from "@/schemas/home";
|
|
135
|
+
import { homeController } from "@/controllers/home";
|
|
136
136
|
|
|
137
137
|
const router = Router();
|
|
138
138
|
|
|
139
|
-
router.get("/",
|
|
140
|
-
res.json({
|
|
141
|
-
message: "Hello World",
|
|
142
|
-
status: "ok"
|
|
143
|
-
});
|
|
144
|
-
});
|
|
139
|
+
router.get("/", homeSchema, homeController);
|
|
145
140
|
|
|
146
141
|
export default router;
|
|
147
142
|
`;
|
|
148
143
|
}
|
|
149
144
|
return `import { Router } from "sprint-es";
|
|
145
|
+
import { homeSchema } from "../schemas/home.js";
|
|
146
|
+
import { homeController } from "../controllers/home.js";
|
|
150
147
|
|
|
151
148
|
const router = Router();
|
|
152
149
|
|
|
153
|
-
router.get("/",
|
|
150
|
+
router.get("/", homeSchema, homeController);
|
|
151
|
+
|
|
152
|
+
export default router;
|
|
153
|
+
`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function getAdminRoute(language: string) {
|
|
157
|
+
if (language === "typescript") {
|
|
158
|
+
return `import { Router } from "sprint-es";
|
|
159
|
+
import { adminSchema } from "@/schemas/admin";
|
|
160
|
+
import { adminController, adminUsersController } from "@/controllers/admin";
|
|
161
|
+
|
|
162
|
+
const router = Router();
|
|
163
|
+
|
|
164
|
+
router.get("/", adminSchema, adminController);
|
|
165
|
+
router.get("/users", adminSchema, adminUsersController);
|
|
166
|
+
|
|
167
|
+
export default router;
|
|
168
|
+
`;
|
|
169
|
+
}
|
|
170
|
+
return `import { Router } from "sprint-es";
|
|
171
|
+
import { adminSchema } from "../schemas/admin.js";
|
|
172
|
+
import { adminController, adminUsersController } from "../controllers/admin.js";
|
|
173
|
+
|
|
174
|
+
const router = Router();
|
|
175
|
+
|
|
176
|
+
router.get("/", adminSchema, adminController);
|
|
177
|
+
router.get("/users", adminSchema, adminUsersController);
|
|
178
|
+
|
|
179
|
+
export default router;
|
|
180
|
+
`;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function getHomeController(language: string) {
|
|
184
|
+
if (language === "typescript") {
|
|
185
|
+
return `import { Handler } from "sprint-es";
|
|
186
|
+
|
|
187
|
+
export const homeController: Handler = (req, res) => {
|
|
188
|
+
res.json({
|
|
189
|
+
message: "Hello World",
|
|
190
|
+
status: "ok"
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
`;
|
|
194
|
+
}
|
|
195
|
+
return `import { Handler } from "sprint-es";
|
|
196
|
+
|
|
197
|
+
export const homeController = (req, res) => {
|
|
154
198
|
res.json({
|
|
155
199
|
message: "Hello World",
|
|
156
200
|
status: "ok"
|
|
157
201
|
});
|
|
202
|
+
};
|
|
203
|
+
`;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function getAdminController(language: string) {
|
|
207
|
+
if (language === "typescript") {
|
|
208
|
+
return `import { Handler } from "sprint-es";
|
|
209
|
+
|
|
210
|
+
export const adminController: Handler = (req, res) => {
|
|
211
|
+
res.json({
|
|
212
|
+
message: "Admin Dashboard",
|
|
213
|
+
status: "ok"
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
export const adminUsersController: Handler = (req, res) => {
|
|
218
|
+
res.json({
|
|
219
|
+
users: [
|
|
220
|
+
{ id: 1, name: "John Doe", role: "admin" },
|
|
221
|
+
{ id: 2, name: "Jane Smith", role: "user" }
|
|
222
|
+
]
|
|
223
|
+
});
|
|
224
|
+
};
|
|
225
|
+
`;
|
|
226
|
+
}
|
|
227
|
+
return `import { Handler } from "sprint-es";
|
|
228
|
+
|
|
229
|
+
export const adminController = (req, res) => {
|
|
230
|
+
res.json({
|
|
231
|
+
message: "Admin Dashboard",
|
|
232
|
+
status: "ok"
|
|
233
|
+
});
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
export const adminUsersController = (req, res) => {
|
|
237
|
+
res.json({
|
|
238
|
+
users: [
|
|
239
|
+
{ id: 1, name: "John Doe", role: "admin" },
|
|
240
|
+
{ id: 2, name: "Jane Smith", role: "user" }
|
|
241
|
+
]
|
|
242
|
+
});
|
|
243
|
+
};
|
|
244
|
+
`;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function getHomeSchema(language: string) {
|
|
248
|
+
if (language === "typescript") {
|
|
249
|
+
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
250
|
+
|
|
251
|
+
export const homeSchema = defineRouteSchema({
|
|
252
|
+
input: z.object({
|
|
253
|
+
message: z.string(),
|
|
254
|
+
status: z.string()
|
|
255
|
+
})
|
|
158
256
|
});
|
|
257
|
+
`;
|
|
258
|
+
}
|
|
259
|
+
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
159
260
|
|
|
160
|
-
export
|
|
261
|
+
export const homeSchema = defineRouteSchema({
|
|
262
|
+
input: z.object({
|
|
263
|
+
message: z.string(),
|
|
264
|
+
status: z.string()
|
|
265
|
+
})
|
|
266
|
+
});
|
|
267
|
+
`;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export function getAdminSchema(language: string) {
|
|
271
|
+
if (language === "typescript") {
|
|
272
|
+
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
273
|
+
|
|
274
|
+
export const adminSchema = defineRouteSchema({
|
|
275
|
+
params: z.object({
|
|
276
|
+
id: z.string().uuid()
|
|
277
|
+
}),
|
|
278
|
+
body: z.object({
|
|
279
|
+
name: z.string().min(1),
|
|
280
|
+
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
|
+
})
|
|
287
|
+
});
|
|
288
|
+
`;
|
|
289
|
+
}
|
|
290
|
+
return `import { z, defineRouteSchema } from "sprint-es/schemas";
|
|
291
|
+
|
|
292
|
+
export const adminSchema = defineRouteSchema({
|
|
293
|
+
params: z.object({
|
|
294
|
+
id: z.string().uuid()
|
|
295
|
+
}),
|
|
296
|
+
body: z.object({
|
|
297
|
+
name: z.string().min(1),
|
|
298
|
+
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
|
+
})
|
|
305
|
+
});
|
|
306
|
+
`;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export function getAuthMiddleware(language: string) {
|
|
310
|
+
if (language === "typescript") {
|
|
311
|
+
return `import { defineMiddleware } from "sprint-es";
|
|
312
|
+
|
|
313
|
+
export default defineMiddleware({
|
|
314
|
+
name: "auth",
|
|
315
|
+
priority: 10,
|
|
316
|
+
include: "/admin/**",
|
|
317
|
+
handler: (req, res, next) => {
|
|
318
|
+
const authHeader = req.headers.authorization;
|
|
319
|
+
|
|
320
|
+
if (!authHeader) {
|
|
321
|
+
return res.status(401).json({ error: "No authorization header" });
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const token = authHeader.replace("Bearer ", "");
|
|
325
|
+
|
|
326
|
+
if (token !== "admin-token") {
|
|
327
|
+
return res.status(403).json({ error: "Invalid token" });
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
next();
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
`;
|
|
334
|
+
}
|
|
335
|
+
return `import { defineMiddleware } from "sprint-es";
|
|
336
|
+
|
|
337
|
+
export default defineMiddleware({
|
|
338
|
+
name: "auth",
|
|
339
|
+
priority: 10,
|
|
340
|
+
include: "/admin/**",
|
|
341
|
+
handler: (req, res, next) => {
|
|
342
|
+
const authHeader = req.headers.authorization;
|
|
343
|
+
|
|
344
|
+
if (!authHeader) {
|
|
345
|
+
return res.status(401).json({ error: "No authorization header" });
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const token = authHeader.replace("Bearer ", "");
|
|
349
|
+
|
|
350
|
+
if (token !== "admin-token") {
|
|
351
|
+
return res.status(403).json({ error: "Invalid token" });
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
next();
|
|
355
|
+
}
|
|
356
|
+
});
|
|
161
357
|
`;
|
|
162
358
|
}
|
|
163
359
|
|
|
@@ -280,6 +476,11 @@ export const config: SprintOptions = {
|
|
|
280
476
|
port: process.env.PORT ? parseInt(process.env.PORT) : 3000
|
|
281
477
|
};
|
|
282
478
|
|
|
479
|
+
// Add Vite config here if needed
|
|
480
|
+
// export const vite = {
|
|
481
|
+
// build: { ... }
|
|
482
|
+
// };
|
|
483
|
+
|
|
283
484
|
`;
|
|
284
485
|
|
|
285
486
|
if (telemetry === "sentry" || telemetry === "glitchtip") {
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { mkdir, writeFile } from "fs/promises";
|
|
|
4
4
|
import { join } from "path";
|
|
5
5
|
import { input, select, confirm } from "@inquirer/prompts";
|
|
6
6
|
import { validateProjectName } from "./validators.js";
|
|
7
|
-
import { getTypeScriptPackageJson, getJavaScriptPackageJson, getTsConfig, getViteConfig, getMainFile, getHomeRoute, getDockerfile, getDockerCompose, getGitignore, getDockerIgnore, getSprintConfigFile,
|
|
7
|
+
import { getTypeScriptPackageJson, getJavaScriptPackageJson, getTsConfig, getViteConfig, getMainFile, getHomeRoute, getAdminRoute, getHomeController, getAdminController, getAuthMiddleware, getHomeSchema, getAdminSchema, getDockerfile, getDockerCompose, getGitignore, getDockerIgnore, getSprintConfigFile, getEnvDevelopment, getEnvProduction } from "./generators.js";
|
|
8
8
|
|
|
9
9
|
export interface CLIOptions {
|
|
10
10
|
projectName?: string;
|
|
@@ -48,7 +48,7 @@ export async function runCLI(args: string[]) {
|
|
|
48
48
|
let installDeps = true;
|
|
49
49
|
if (options.skipInstall) {
|
|
50
50
|
installDeps = false;
|
|
51
|
-
} else
|
|
51
|
+
} else {
|
|
52
52
|
installDeps = await confirm({
|
|
53
53
|
message: "Do you want to install dependencies now?",
|
|
54
54
|
default: true,
|
|
@@ -85,11 +85,16 @@ function parseArgs(args: string[]): CLIOptions {
|
|
|
85
85
|
|
|
86
86
|
if (args.includes("--yes") || args.includes("-y")) {
|
|
87
87
|
options.skipPrompts = true;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (!options.skipPrompts) {
|
|
91
|
+
if (hasTs) {
|
|
92
|
+
options.language = "typescript";
|
|
93
|
+
} else if (hasJs) {
|
|
94
|
+
options.language = "javascript";
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
88
97
|
options.language = "typescript";
|
|
89
|
-
} else if (hasTs) {
|
|
90
|
-
options.language = "typescript";
|
|
91
|
-
} else if (hasJs) {
|
|
92
|
-
options.language = "javascript";
|
|
93
98
|
}
|
|
94
99
|
|
|
95
100
|
if (hasName !== -1 && args[hasName + 1]) {
|
|
@@ -230,17 +235,28 @@ async function createProject(
|
|
|
230
235
|
await mkdir(join(srcDir, "middlewares"), { recursive: true });
|
|
231
236
|
await mkdir(join(srcDir, "routes"), { recursive: true });
|
|
232
237
|
await mkdir(join(srcDir, "controllers"), { recursive: true });
|
|
238
|
+
await mkdir(join(srcDir, "schemas"), { recursive: true });
|
|
233
239
|
|
|
234
240
|
await writeFile(join(srcDir, "middlewares", ".gitkeep"), "");
|
|
235
|
-
await writeFile(join(srcDir, "controllers", ".gitkeep"), "");
|
|
236
241
|
|
|
237
242
|
await writeFile(join(srcDir, "app." + (language === "typescript" ? "ts" : "js")), getMainFile(language));
|
|
238
243
|
|
|
239
244
|
await writeFile(join(srcDir, "routes", "home." + (language === "typescript" ? "ts" : "js")), getHomeRoute(language));
|
|
245
|
+
await writeFile(join(srcDir, "routes", "admin." + (language === "typescript" ? "ts" : "js")), getAdminRoute(language));
|
|
246
|
+
|
|
247
|
+
await writeFile(join(srcDir, "controllers", "home." + (language === "typescript" ? "ts" : "js")), getHomeController(language));
|
|
248
|
+
await writeFile(join(srcDir, "controllers", "admin." + (language === "typescript" ? "ts" : "js")), getAdminController(language));
|
|
249
|
+
|
|
250
|
+
await writeFile(join(srcDir, "middlewares", "auth." + (language === "typescript" ? "ts" : "js")), getAuthMiddleware(language));
|
|
251
|
+
|
|
252
|
+
await writeFile(join(srcDir, "schemas", "home." + (language === "typescript" ? "ts" : "js")), getHomeSchema(language));
|
|
253
|
+
await writeFile(join(srcDir, "schemas", "admin." + (language === "typescript" ? "ts" : "js")), getAdminSchema(language));
|
|
254
|
+
|
|
255
|
+
await writeFile(join(targetDir, ".env.development.example"), getEnvDevelopment(telemetry));
|
|
256
|
+
await writeFile(join(targetDir, ".env.production.example"), getEnvProduction(telemetry));
|
|
240
257
|
|
|
241
|
-
await writeFile(join(targetDir, ".env.
|
|
242
|
-
await writeFile(join(targetDir, ".env.
|
|
243
|
-
await writeFile(join(targetDir, ".env.production"), getEnvProduction(telemetry));
|
|
258
|
+
await writeFile(join(targetDir, ".env.development"), "");
|
|
259
|
+
await writeFile(join(targetDir, ".env.production"), "");
|
|
244
260
|
|
|
245
261
|
await writeFile(join(targetDir, ".gitignore"), getGitignore());
|
|
246
262
|
|