create-sprint 0.0.48 → 0.0.54
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 +133 -83
- package/dist/index.js +8 -3
- package/package.json +1 -1
- package/src/generators.ts +135 -83
- package/src/index.ts +9 -3
package/dist/generators.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as crypto from "node:crypto";
|
|
2
2
|
export function generateJWTKeys() {
|
|
3
|
-
const keys = crypto.generateKeyPairSync("
|
|
4
|
-
|
|
3
|
+
const keys = crypto.generateKeyPairSync("rsa", {
|
|
4
|
+
modulusLength: 4096,
|
|
5
5
|
publicKeyEncoding: { type: "spki", format: "pem" },
|
|
6
6
|
privateKeyEncoding: { type: "pkcs8", format: "pem" }
|
|
7
7
|
});
|
|
@@ -130,22 +130,24 @@ export function getHomeRoute(language) {
|
|
|
130
130
|
if (language === "typescript") {
|
|
131
131
|
return `import { Router } from "sprint-es";
|
|
132
132
|
import { homeSchema } from "@/schemas/home";
|
|
133
|
-
import { homeController } from "@/controllers/home";
|
|
133
|
+
import { homeController, jwtValidateController } from "@/controllers/home";
|
|
134
134
|
|
|
135
135
|
const router = Router();
|
|
136
136
|
|
|
137
137
|
router.get("/", homeSchema, homeController);
|
|
138
|
+
router.post("/jwt/validate", jwtValidateController);
|
|
138
139
|
|
|
139
140
|
export default router;
|
|
140
141
|
`;
|
|
141
142
|
}
|
|
142
143
|
return `import { Router } from "sprint-es";
|
|
143
144
|
import { homeSchema } from "../schemas/home.js";
|
|
144
|
-
import { homeController } from "../controllers/home.js";
|
|
145
|
+
import { homeController, jwtValidateController } from "../controllers/home.js";
|
|
145
146
|
|
|
146
147
|
const router = Router();
|
|
147
148
|
|
|
148
149
|
router.get("/", homeSchema, homeController);
|
|
150
|
+
router.post("/jwt/validate", jwtValidateController);
|
|
149
151
|
|
|
150
152
|
export default router;
|
|
151
153
|
`;
|
|
@@ -154,67 +156,109 @@ export function getAdminRoute(language) {
|
|
|
154
156
|
if (language === "typescript") {
|
|
155
157
|
return `import { Router } from "sprint-es";
|
|
156
158
|
import { adminSchema, jwtGenerateSchema } from "@/schemas/admin";
|
|
157
|
-
import { adminController, adminUsersController, jwtGenerateController
|
|
159
|
+
import { adminController, adminUsersController, jwtGenerateController } from "@/controllers/admin";
|
|
158
160
|
|
|
159
161
|
const router = Router();
|
|
160
162
|
|
|
161
163
|
router.get("/", adminSchema, adminController);
|
|
162
164
|
router.get("/users", adminSchema, adminUsersController);
|
|
163
165
|
router.post("/jwt/generate", jwtGenerateSchema, jwtGenerateController);
|
|
164
|
-
router.post("/jwt/validate", jwtValidateController);
|
|
165
166
|
|
|
166
167
|
export default router;
|
|
167
168
|
`;
|
|
168
169
|
}
|
|
169
170
|
return `import { Router } from "sprint-es";
|
|
170
171
|
import { adminSchema, jwtGenerateSchema } from "../schemas/admin.js";
|
|
171
|
-
import { adminController, adminUsersController, jwtGenerateController
|
|
172
|
+
import { adminController, adminUsersController, jwtGenerateController } from "../controllers/admin.js";
|
|
172
173
|
|
|
173
174
|
const router = Router();
|
|
174
175
|
|
|
175
176
|
router.get("/", adminSchema, adminController);
|
|
176
177
|
router.get("/users", adminSchema, adminUsersController);
|
|
177
178
|
router.post("/jwt/generate", jwtGenerateSchema, jwtGenerateController);
|
|
178
|
-
router.post("/jwt/validate", jwtValidateController);
|
|
179
179
|
|
|
180
180
|
export default router;
|
|
181
181
|
`;
|
|
182
182
|
}
|
|
183
183
|
export function getHomeController(language) {
|
|
184
184
|
if (language === "typescript") {
|
|
185
|
-
return `import { Handler } from "sprint-es";
|
|
185
|
+
return `import { Handler, SprintRequest, SprintResponse } from "sprint-es";
|
|
186
|
+
import { verifyEncrypted, getJwtFromEnv } from "sprint-es/jwt";
|
|
186
187
|
|
|
187
|
-
export const homeController: Handler = (req, res) => {
|
|
188
|
+
export const homeController: Handler = (req: SprintRequest, res: SprintResponse) => {
|
|
188
189
|
res.json({
|
|
189
190
|
message: "Hello World",
|
|
190
191
|
status: "ok"
|
|
191
192
|
});
|
|
192
193
|
};
|
|
194
|
+
|
|
195
|
+
export const jwtValidateController: Handler = (req: SprintRequest, res: SprintResponse) => {
|
|
196
|
+
const token = req.sprint?.getAuthorization() || req.headers.authorization;
|
|
197
|
+
|
|
198
|
+
if (!token) {
|
|
199
|
+
return res.status(401).json({ error: "No token provided" });
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
const { publicKey, encryptionSecret } = getJwtFromEnv();
|
|
204
|
+
const decoded = verifyEncrypted(token, publicKey, encryptionSecret);
|
|
205
|
+
|
|
206
|
+
if (!decoded) {
|
|
207
|
+
return res.status(401).json({ error: "Invalid token" });
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
res.json({ valid: true, payload: decoded });
|
|
211
|
+
} catch (error) {
|
|
212
|
+
return res.status(500).json({ error: "JWT not configured" });
|
|
213
|
+
}
|
|
214
|
+
};
|
|
193
215
|
`;
|
|
194
216
|
}
|
|
195
|
-
return `import { Handler } from "sprint-es";
|
|
217
|
+
return `import { Handler, SprintRequest, SprintResponse } from "sprint-es";
|
|
218
|
+
import { verifyEncrypted, getJwtFromEnv } from "sprint-es/jwt";
|
|
196
219
|
|
|
197
|
-
export const homeController = (req, res) => {
|
|
220
|
+
export const homeController = (req: SprintRequest, res: SprintResponse) => {
|
|
198
221
|
res.json({
|
|
199
222
|
message: "Hello World",
|
|
200
223
|
status: "ok"
|
|
201
224
|
});
|
|
202
225
|
};
|
|
226
|
+
|
|
227
|
+
export const jwtValidateController = (req: SprintRequest, res: SprintResponse) => {
|
|
228
|
+
const token = req.sprint?.getAuthorization() || req.headers.authorization;
|
|
229
|
+
|
|
230
|
+
if (!token) {
|
|
231
|
+
return res.status(401).json({ error: "No token provided" });
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
try {
|
|
235
|
+
const { publicKey, encryptionSecret } = getJwtFromEnv();
|
|
236
|
+
const decoded = verifyEncrypted(token, publicKey, encryptionSecret);
|
|
237
|
+
|
|
238
|
+
if (!decoded) {
|
|
239
|
+
return res.status(401).json({ error: "Invalid token" });
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
res.json({ valid: true, payload: decoded });
|
|
243
|
+
} catch (error) {
|
|
244
|
+
return res.status(500).json({ error: "JWT not configured" });
|
|
245
|
+
}
|
|
246
|
+
};
|
|
203
247
|
`;
|
|
204
248
|
}
|
|
205
249
|
export function getAdminController(language) {
|
|
206
250
|
if (language === "typescript") {
|
|
207
|
-
return `import { Handler } from "sprint-es";
|
|
208
|
-
import { signEncrypted,
|
|
251
|
+
return `import { Handler, SprintRequest, SprintResponse } from "sprint-es";
|
|
252
|
+
import { signEncrypted, getJwtFromEnv } from "sprint-es/jwt";
|
|
209
253
|
|
|
210
|
-
export const adminController: Handler = (req, res) => {
|
|
254
|
+
export const adminController: Handler = (req: SprintRequest, res: SprintResponse) => {
|
|
211
255
|
res.json({
|
|
212
256
|
message: "Admin Dashboard",
|
|
213
257
|
status: "ok"
|
|
214
258
|
});
|
|
215
259
|
};
|
|
216
260
|
|
|
217
|
-
export const adminUsersController: Handler = (req, res) => {
|
|
261
|
+
export const adminUsersController: Handler = (req: SprintRequest, res: SprintResponse) => {
|
|
218
262
|
res.json({
|
|
219
263
|
users: [
|
|
220
264
|
{ id: 1, name: "John Doe", role: "admin" },
|
|
@@ -223,52 +267,31 @@ export const adminUsersController: Handler = (req, res) => {
|
|
|
223
267
|
});
|
|
224
268
|
};
|
|
225
269
|
|
|
226
|
-
export const jwtGenerateController: Handler = (req, res) => {
|
|
270
|
+
export const jwtGenerateController: Handler = (req: SprintRequest, res: SprintResponse) => {
|
|
227
271
|
const { userId, role } = req.body || {};
|
|
228
272
|
|
|
229
273
|
try {
|
|
230
274
|
const { privateKey } = getJwtFromEnv();
|
|
231
275
|
const payload = { userId, role: role || "user" };
|
|
232
|
-
const token = signEncrypted(payload, privateKey, { expiresIn: "1h" });
|
|
276
|
+
const token = signEncrypted(payload, privateKey, encryptionSecret, { expiresIn: "1h" });
|
|
233
277
|
res.json({ token });
|
|
234
278
|
} catch (error) {
|
|
235
279
|
return res.status(500).json({ error: "JWT not configured" });
|
|
236
280
|
}
|
|
237
281
|
};
|
|
238
|
-
|
|
239
|
-
export const jwtValidateController: Handler = (req, res) => {
|
|
240
|
-
const token = req.sprint?.getAuthorization() || req.headers.authorization;
|
|
241
|
-
|
|
242
|
-
if (!token) {
|
|
243
|
-
return res.status(401).json({ error: "No token provided" });
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
try {
|
|
247
|
-
const { publicKey } = getJwtFromEnv();
|
|
248
|
-
const decoded = verifyEncrypted(token, publicKey);
|
|
249
|
-
|
|
250
|
-
if (!decoded) {
|
|
251
|
-
return res.status(401).json({ error: "Invalid token" });
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
res.json({ valid: true, payload: decoded });
|
|
255
|
-
} catch (error) {
|
|
256
|
-
return res.status(500).json({ error: "JWT not configured" });
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
282
|
`;
|
|
260
283
|
}
|
|
261
|
-
return `import { Handler } from "sprint-es";
|
|
262
|
-
import { signEncrypted,
|
|
284
|
+
return `import { Handler, SprintRequest, SprintResponse } from "sprint-es";
|
|
285
|
+
import { signEncrypted, getJwtFromEnv } from "sprint-es/jwt";
|
|
263
286
|
|
|
264
|
-
export const adminController = (req, res) => {
|
|
287
|
+
export const adminController = (req: SprintRequest, res: SprintResponse) => {
|
|
265
288
|
res.json({
|
|
266
289
|
message: "Admin Dashboard",
|
|
267
290
|
status: "ok"
|
|
268
291
|
});
|
|
269
292
|
};
|
|
270
293
|
|
|
271
|
-
export const adminUsersController = (req, res) => {
|
|
294
|
+
export const adminUsersController = (req: SprintRequest, res: SprintResponse) => {
|
|
272
295
|
res.json({
|
|
273
296
|
users: [
|
|
274
297
|
{ id: 1, name: "John Doe", role: "admin" },
|
|
@@ -277,39 +300,18 @@ export const adminUsersController = (req, res) => {
|
|
|
277
300
|
});
|
|
278
301
|
};
|
|
279
302
|
|
|
280
|
-
export const jwtGenerateController = (req, res) => {
|
|
303
|
+
export const jwtGenerateController = (req: SprintRequest, res: SprintResponse) => {
|
|
281
304
|
const { userId, role } = req.body || {};
|
|
282
305
|
|
|
283
306
|
try {
|
|
284
|
-
const { privateKey } = getJwtFromEnv();
|
|
307
|
+
const { privateKey, encryptionSecret } = getJwtFromEnv();
|
|
285
308
|
const payload = { userId, role: role || "user" };
|
|
286
|
-
const token = signEncrypted(payload, privateKey, { expiresIn: "1h" });
|
|
309
|
+
const token = signEncrypted(payload, privateKey, encryptionSecret, { expiresIn: "1h" });
|
|
287
310
|
res.json({ token });
|
|
288
311
|
} catch (error) {
|
|
289
312
|
return res.status(500).json({ error: "JWT not configured" });
|
|
290
313
|
}
|
|
291
314
|
};
|
|
292
|
-
|
|
293
|
-
export const jwtValidateController = (req, res) => {
|
|
294
|
-
const token = req.sprint?.getAuthorization() || req.headers.authorization;
|
|
295
|
-
|
|
296
|
-
if (!token) {
|
|
297
|
-
return res.status(401).json({ error: "No token provided" });
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
try {
|
|
301
|
-
const { publicKey } = getJwtFromEnv();
|
|
302
|
-
const decoded = verifyEncrypted(token, publicKey);
|
|
303
|
-
|
|
304
|
-
if (!decoded) {
|
|
305
|
-
return res.status(401).json({ error: "Invalid token" });
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
res.json({ valid: true, payload: decoded });
|
|
309
|
-
} catch (error) {
|
|
310
|
-
return res.status(500).json({ error: "JWT not configured" });
|
|
311
|
-
}
|
|
312
|
-
};
|
|
313
315
|
`;
|
|
314
316
|
}
|
|
315
317
|
export function getHomeSchema(language) {
|
|
@@ -366,26 +368,21 @@ export const jwtGenerateSchema = defineRouteSchema({
|
|
|
366
368
|
});
|
|
367
369
|
`;
|
|
368
370
|
}
|
|
369
|
-
export function
|
|
371
|
+
export function getInternalAuthMiddleware(language) {
|
|
370
372
|
if (language === "typescript") {
|
|
371
373
|
return `import { defineMiddleware } from "sprint-es";
|
|
372
374
|
|
|
373
375
|
export default defineMiddleware({
|
|
374
|
-
name: "
|
|
376
|
+
name: "adminAuth",
|
|
375
377
|
priority: 10,
|
|
376
378
|
include: "/admin/**",
|
|
377
379
|
handler: (req, res, next) => {
|
|
378
380
|
const auth = req.sprint.getAuthorization();
|
|
379
|
-
|
|
380
|
-
if (!auth) {
|
|
381
|
-
return res.status(401).json({ error: "No authorization header" });
|
|
382
|
-
}
|
|
381
|
+
if (!auth) return res.status(401).json({ error: "No authorization header" });
|
|
383
382
|
|
|
384
383
|
const token = auth.replace("Bearer ", "");
|
|
385
384
|
|
|
386
|
-
if (token !== "admin-token") {
|
|
387
|
-
return res.status(403).json({ error: "Invalid token" });
|
|
388
|
-
}
|
|
385
|
+
if (token !== "admin-token") return res.status(403).json({ error: "Invalid token" });
|
|
389
386
|
|
|
390
387
|
next();
|
|
391
388
|
}
|
|
@@ -395,21 +392,72 @@ export default defineMiddleware({
|
|
|
395
392
|
return `import { defineMiddleware } from "sprint-es";
|
|
396
393
|
|
|
397
394
|
export default defineMiddleware({
|
|
398
|
-
name: "
|
|
395
|
+
name: "adminAuth",
|
|
399
396
|
priority: 10,
|
|
400
397
|
include: "/admin/**",
|
|
401
398
|
handler: (req, res, next) => {
|
|
402
399
|
const auth = req.sprint.getAuthorization();
|
|
400
|
+
if (!auth) return res.status(401).json({ error: "No authorization header" });
|
|
401
|
+
|
|
402
|
+
const token = auth.replace("Bearer ", "");
|
|
403
403
|
|
|
404
|
-
if (
|
|
405
|
-
|
|
406
|
-
|
|
404
|
+
if (token !== "admin-token") return res.status(403).json({ error: "Invalid token" });
|
|
405
|
+
|
|
406
|
+
next();
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
`;
|
|
410
|
+
}
|
|
411
|
+
export function getUserAuthMiddleware(language) {
|
|
412
|
+
if (language === "typescript") {
|
|
413
|
+
return `import { defineMiddleware } from "sprint-es";
|
|
414
|
+
import { verifyEncrypted, getJwtFromEnv } from "sprint-es/jwt";
|
|
415
|
+
|
|
416
|
+
const { publicKey, encryptionSecret } = getJwtFromEnv();
|
|
417
|
+
|
|
418
|
+
export default defineMiddleware({
|
|
419
|
+
name: "userAuth",
|
|
420
|
+
priority: 10,
|
|
421
|
+
include: "/**",
|
|
422
|
+
exclude: "/admin/**",
|
|
423
|
+
handler: (req, res, next) => {
|
|
424
|
+
const auth = req.sprint.getAuthorization();
|
|
425
|
+
if (!auth) return res.status(401).json({ error: "No authorization header" });
|
|
407
426
|
|
|
408
427
|
const token = auth.replace("Bearer ", "");
|
|
409
428
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
}
|
|
429
|
+
const decoded = verifyEncrypted(token, publicKey, encryptionSecret);cd .
|
|
430
|
+
|
|
431
|
+
if (!decoded) return res.status(403).json({ error: "Invalid token" });
|
|
432
|
+
|
|
433
|
+
req.custom.user = decoded;
|
|
434
|
+
|
|
435
|
+
next();
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
`;
|
|
439
|
+
}
|
|
440
|
+
return `import { defineMiddleware } from "sprint-es";
|
|
441
|
+
import { verifyEncrypted, getJwtFromEnv } from "sprint-es/jwt";
|
|
442
|
+
|
|
443
|
+
const { publicKey, encryptionSecret } = getJwtFromEnv();
|
|
444
|
+
|
|
445
|
+
export default defineMiddleware({
|
|
446
|
+
name: "userAuth",
|
|
447
|
+
priority: 10,
|
|
448
|
+
include: "/**",
|
|
449
|
+
exclude: "/admin/**",
|
|
450
|
+
handler: (req, res, next) => {
|
|
451
|
+
const auth = req.sprint.getAuthorization();
|
|
452
|
+
if (!auth) return res.status(401).json({ error: "No authorization header" });
|
|
453
|
+
|
|
454
|
+
const token = auth.replace("Bearer ", "");
|
|
455
|
+
|
|
456
|
+
const decoded = verifyEncrypted(token, publicKey, encryptionSecret);
|
|
457
|
+
|
|
458
|
+
if (!decoded) return res.status(403).json({ error: "Invalid token" });
|
|
459
|
+
|
|
460
|
+
req.custom.user = decoded;
|
|
413
461
|
|
|
414
462
|
next();
|
|
415
463
|
}
|
|
@@ -614,6 +662,7 @@ export function getEnvDevelopment(telemetry) {
|
|
|
614
662
|
PORT=5000
|
|
615
663
|
JWT_PUBLIC_KEY='${keys.publicKey}'
|
|
616
664
|
JWT_PRIVATE_KEY='${keys.privateKey}'
|
|
665
|
+
JWT_ENCRYPTION_SECRET='${crypto.randomBytes(32).toString("hex")}'
|
|
617
666
|
`;
|
|
618
667
|
if (telemetry === "sentry" || telemetry === "glitchtip") {
|
|
619
668
|
env += `
|
|
@@ -635,6 +684,7 @@ export function getEnvProduction(telemetry) {
|
|
|
635
684
|
PORT=5000
|
|
636
685
|
JWT_PUBLIC_KEY='${keys.publicKey}'
|
|
637
686
|
JWT_PRIVATE_KEY='${keys.privateKey}'
|
|
687
|
+
JWT_ENCRYPTION_SECRET='${crypto.randomBytes(32).toString("hex")}'
|
|
638
688
|
`;
|
|
639
689
|
if (telemetry === "sentry" || telemetry === "glitchtip") {
|
|
640
690
|
env += `
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,10 @@ import { spawn } from "child_process";
|
|
|
2
2
|
import { existsSync } from "fs";
|
|
3
3
|
import { mkdir, writeFile as fsWriteFile } from "fs/promises";
|
|
4
4
|
import { join } from "path";
|
|
5
|
+
import color from "picocolors";
|
|
5
6
|
import * as p from "@clack/prompts";
|
|
6
7
|
import { validateProjectName } from "./validators.js";
|
|
7
|
-
import { getTypeScriptPackageJson, getJavaScriptPackageJson, getTsConfig, getViteConfig, getMainFile, getHomeRoute, getAdminRoute, getHomeController, getAdminController,
|
|
8
|
+
import { getTypeScriptPackageJson, getJavaScriptPackageJson, getTsConfig, getViteConfig, getMainFile, getHomeRoute, getAdminRoute, getHomeController, getAdminController, getInternalAuthMiddleware, getUserAuthMiddleware, getHomeSchema, getAdminSchema, getDockerfile, getDockerCompose, getGitignore, getDockerIgnore, getSprintConfigFile, getEnvDevelopment, getEnvProduction, getExampleCronJob } from "./generators.js";
|
|
8
9
|
export async function writeFile(path, content, options) {
|
|
9
10
|
if (typeof content === "string")
|
|
10
11
|
content = content.trimEnd();
|
|
@@ -14,6 +15,7 @@ export async function writeFile(path, content, options) {
|
|
|
14
15
|
export async function runCLI(args) {
|
|
15
16
|
const options = parseArgs(args);
|
|
16
17
|
p.intro("Sprint — Quickly API Framework");
|
|
18
|
+
p.intro(`${color.bgCyan(color.black(' create-sprint-app '))}`);
|
|
17
19
|
const config = await p.group({
|
|
18
20
|
projectName: () => p.text({
|
|
19
21
|
message: "Project name:",
|
|
@@ -49,12 +51,13 @@ export async function runCLI(args) {
|
|
|
49
51
|
await createProject(config.projectName, config.language, config.telemetry, config.docker);
|
|
50
52
|
s.stop("Project created");
|
|
51
53
|
const installDeps = await p.confirm({ message: "Install dependencies now?", initialValue: true });
|
|
54
|
+
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
52
55
|
if (installDeps) {
|
|
53
56
|
const s2 = p.spinner();
|
|
54
57
|
s2.start("Installing dependencies");
|
|
55
58
|
try {
|
|
56
59
|
await new Promise((resolve, reject) => {
|
|
57
|
-
const child = spawn(
|
|
60
|
+
const child = spawn(npmCmd, ["install"], {
|
|
58
61
|
cwd: targetDir,
|
|
59
62
|
stdio: "pipe"
|
|
60
63
|
});
|
|
@@ -64,6 +67,7 @@ export async function runCLI(args) {
|
|
|
64
67
|
else
|
|
65
68
|
reject(new Error(`npm install exited with code ${code}`));
|
|
66
69
|
});
|
|
70
|
+
child.on("error", reject);
|
|
67
71
|
});
|
|
68
72
|
s2.stop("Dependencies installed");
|
|
69
73
|
}
|
|
@@ -154,7 +158,8 @@ async function createProject(projectName, language, telemetry, useDocker) {
|
|
|
154
158
|
await writeFile(join(srcDir, "routes", "admin." + (language === "typescript" ? "ts" : "js")), getAdminRoute(language));
|
|
155
159
|
await writeFile(join(srcDir, "controllers", "home." + (language === "typescript" ? "ts" : "js")), getHomeController(language));
|
|
156
160
|
await writeFile(join(srcDir, "controllers", "admin." + (language === "typescript" ? "ts" : "js")), getAdminController(language));
|
|
157
|
-
await writeFile(join(srcDir, "middlewares", "auth." + (language === "typescript" ? "ts" : "js")),
|
|
161
|
+
await writeFile(join(srcDir, "middlewares", "auth.internal." + (language === "typescript" ? "ts" : "js")), getInternalAuthMiddleware(language));
|
|
162
|
+
await writeFile(join(srcDir, "middlewares", "auth.user." + (language === "typescript" ? "ts" : "js")), getUserAuthMiddleware(language));
|
|
158
163
|
await writeFile(join(srcDir, "schemas", "home." + (language === "typescript" ? "ts" : "js")), getHomeSchema(language));
|
|
159
164
|
await writeFile(join(srcDir, "schemas", "admin." + (language === "typescript" ? "ts" : "js")), getAdminSchema(language));
|
|
160
165
|
await writeFile(join(srcDir, "cronjobs", "example." + (language === "typescript" ? "ts" : "js")), getExampleCronJob(language));
|
package/package.json
CHANGED
package/src/generators.ts
CHANGED
|
@@ -6,8 +6,8 @@ export interface JWTKeys {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export function generateJWTKeys(): JWTKeys {
|
|
9
|
-
const keys = crypto.generateKeyPairSync("
|
|
10
|
-
|
|
9
|
+
const keys = crypto.generateKeyPairSync("rsa", {
|
|
10
|
+
modulusLength: 4096,
|
|
11
11
|
publicKeyEncoding: { type: "spki", format: "pem" },
|
|
12
12
|
privateKeyEncoding: { type: "pkcs8", format: "pem" }
|
|
13
13
|
}) as unknown as { publicKey: string; privateKey: string };
|
|
@@ -146,22 +146,24 @@ export function getHomeRoute(language: string) {
|
|
|
146
146
|
if (language === "typescript") {
|
|
147
147
|
return `import { Router } from "sprint-es";
|
|
148
148
|
import { homeSchema } from "@/schemas/home";
|
|
149
|
-
import { homeController } from "@/controllers/home";
|
|
149
|
+
import { homeController, jwtValidateController } from "@/controllers/home";
|
|
150
150
|
|
|
151
151
|
const router = Router();
|
|
152
152
|
|
|
153
153
|
router.get("/", homeSchema, homeController);
|
|
154
|
+
router.post("/jwt/validate", jwtValidateController);
|
|
154
155
|
|
|
155
156
|
export default router;
|
|
156
157
|
`;
|
|
157
158
|
}
|
|
158
159
|
return `import { Router } from "sprint-es";
|
|
159
160
|
import { homeSchema } from "../schemas/home.js";
|
|
160
|
-
import { homeController } from "../controllers/home.js";
|
|
161
|
+
import { homeController, jwtValidateController } from "../controllers/home.js";
|
|
161
162
|
|
|
162
163
|
const router = Router();
|
|
163
164
|
|
|
164
165
|
router.get("/", homeSchema, homeController);
|
|
166
|
+
router.post("/jwt/validate", jwtValidateController);
|
|
165
167
|
|
|
166
168
|
export default router;
|
|
167
169
|
`;
|
|
@@ -171,28 +173,26 @@ export function getAdminRoute(language: string) {
|
|
|
171
173
|
if (language === "typescript") {
|
|
172
174
|
return `import { Router } from "sprint-es";
|
|
173
175
|
import { adminSchema, jwtGenerateSchema } from "@/schemas/admin";
|
|
174
|
-
import { adminController, adminUsersController, jwtGenerateController
|
|
176
|
+
import { adminController, adminUsersController, jwtGenerateController } from "@/controllers/admin";
|
|
175
177
|
|
|
176
178
|
const router = Router();
|
|
177
179
|
|
|
178
180
|
router.get("/", adminSchema, adminController);
|
|
179
181
|
router.get("/users", adminSchema, adminUsersController);
|
|
180
182
|
router.post("/jwt/generate", jwtGenerateSchema, jwtGenerateController);
|
|
181
|
-
router.post("/jwt/validate", jwtValidateController);
|
|
182
183
|
|
|
183
184
|
export default router;
|
|
184
185
|
`;
|
|
185
186
|
}
|
|
186
187
|
return `import { Router } from "sprint-es";
|
|
187
188
|
import { adminSchema, jwtGenerateSchema } from "../schemas/admin.js";
|
|
188
|
-
import { adminController, adminUsersController, jwtGenerateController
|
|
189
|
+
import { adminController, adminUsersController, jwtGenerateController } from "../controllers/admin.js";
|
|
189
190
|
|
|
190
191
|
const router = Router();
|
|
191
192
|
|
|
192
193
|
router.get("/", adminSchema, adminController);
|
|
193
194
|
router.get("/users", adminSchema, adminUsersController);
|
|
194
195
|
router.post("/jwt/generate", jwtGenerateSchema, jwtGenerateController);
|
|
195
|
-
router.post("/jwt/validate", jwtValidateController);
|
|
196
196
|
|
|
197
197
|
export default router;
|
|
198
198
|
`;
|
|
@@ -200,40 +200,84 @@ export default router;
|
|
|
200
200
|
|
|
201
201
|
export function getHomeController(language: string) {
|
|
202
202
|
if (language === "typescript") {
|
|
203
|
-
return `import { Handler } from "sprint-es";
|
|
203
|
+
return `import { Handler, SprintRequest, SprintResponse } from "sprint-es";
|
|
204
|
+
import { verifyEncrypted, getJwtFromEnv } from "sprint-es/jwt";
|
|
204
205
|
|
|
205
|
-
export const homeController: Handler = (req, res) => {
|
|
206
|
+
export const homeController: Handler = (req: SprintRequest, res: SprintResponse) => {
|
|
206
207
|
res.json({
|
|
207
208
|
message: "Hello World",
|
|
208
209
|
status: "ok"
|
|
209
210
|
});
|
|
210
211
|
};
|
|
212
|
+
|
|
213
|
+
export const jwtValidateController: Handler = (req: SprintRequest, res: SprintResponse) => {
|
|
214
|
+
const token = req.sprint?.getAuthorization() || req.headers.authorization;
|
|
215
|
+
|
|
216
|
+
if (!token) {
|
|
217
|
+
return res.status(401).json({ error: "No token provided" });
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
const { publicKey, encryptionSecret } = getJwtFromEnv();
|
|
222
|
+
const decoded = verifyEncrypted(token, publicKey, encryptionSecret);
|
|
223
|
+
|
|
224
|
+
if (!decoded) {
|
|
225
|
+
return res.status(401).json({ error: "Invalid token" });
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
res.json({ valid: true, payload: decoded });
|
|
229
|
+
} catch (error) {
|
|
230
|
+
return res.status(500).json({ error: "JWT not configured" });
|
|
231
|
+
}
|
|
232
|
+
};
|
|
211
233
|
`;
|
|
212
234
|
}
|
|
213
|
-
return `import { Handler } from "sprint-es";
|
|
235
|
+
return `import { Handler, SprintRequest, SprintResponse } from "sprint-es";
|
|
236
|
+
import { verifyEncrypted, getJwtFromEnv } from "sprint-es/jwt";
|
|
214
237
|
|
|
215
|
-
export const homeController = (req, res) => {
|
|
238
|
+
export const homeController = (req: SprintRequest, res: SprintResponse) => {
|
|
216
239
|
res.json({
|
|
217
240
|
message: "Hello World",
|
|
218
241
|
status: "ok"
|
|
219
242
|
});
|
|
220
243
|
};
|
|
244
|
+
|
|
245
|
+
export const jwtValidateController = (req: SprintRequest, res: SprintResponse) => {
|
|
246
|
+
const token = req.sprint?.getAuthorization() || req.headers.authorization;
|
|
247
|
+
|
|
248
|
+
if (!token) {
|
|
249
|
+
return res.status(401).json({ error: "No token provided" });
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
try {
|
|
253
|
+
const { publicKey, encryptionSecret } = getJwtFromEnv();
|
|
254
|
+
const decoded = verifyEncrypted(token, publicKey, encryptionSecret);
|
|
255
|
+
|
|
256
|
+
if (!decoded) {
|
|
257
|
+
return res.status(401).json({ error: "Invalid token" });
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
res.json({ valid: true, payload: decoded });
|
|
261
|
+
} catch (error) {
|
|
262
|
+
return res.status(500).json({ error: "JWT not configured" });
|
|
263
|
+
}
|
|
264
|
+
};
|
|
221
265
|
`;
|
|
222
266
|
}
|
|
223
267
|
|
|
224
268
|
export function getAdminController(language: string) {
|
|
225
269
|
if (language === "typescript") {
|
|
226
|
-
return `import { Handler } from "sprint-es";
|
|
227
|
-
import { signEncrypted,
|
|
270
|
+
return `import { Handler, SprintRequest, SprintResponse } from "sprint-es";
|
|
271
|
+
import { signEncrypted, getJwtFromEnv } from "sprint-es/jwt";
|
|
228
272
|
|
|
229
|
-
export const adminController: Handler = (req, res) => {
|
|
273
|
+
export const adminController: Handler = (req: SprintRequest, res: SprintResponse) => {
|
|
230
274
|
res.json({
|
|
231
275
|
message: "Admin Dashboard",
|
|
232
276
|
status: "ok"
|
|
233
277
|
});
|
|
234
278
|
};
|
|
235
279
|
|
|
236
|
-
export const adminUsersController: Handler = (req, res) => {
|
|
280
|
+
export const adminUsersController: Handler = (req: SprintRequest, res: SprintResponse) => {
|
|
237
281
|
res.json({
|
|
238
282
|
users: [
|
|
239
283
|
{ id: 1, name: "John Doe", role: "admin" },
|
|
@@ -242,52 +286,31 @@ export const adminUsersController: Handler = (req, res) => {
|
|
|
242
286
|
});
|
|
243
287
|
};
|
|
244
288
|
|
|
245
|
-
export const jwtGenerateController: Handler = (req, res) => {
|
|
289
|
+
export const jwtGenerateController: Handler = (req: SprintRequest, res: SprintResponse) => {
|
|
246
290
|
const { userId, role } = req.body || {};
|
|
247
291
|
|
|
248
292
|
try {
|
|
249
293
|
const { privateKey } = getJwtFromEnv();
|
|
250
294
|
const payload = { userId, role: role || "user" };
|
|
251
|
-
const token = signEncrypted(payload, privateKey, { expiresIn: "1h" });
|
|
295
|
+
const token = signEncrypted(payload, privateKey, encryptionSecret, { expiresIn: "1h" });
|
|
252
296
|
res.json({ token });
|
|
253
297
|
} catch (error) {
|
|
254
298
|
return res.status(500).json({ error: "JWT not configured" });
|
|
255
299
|
}
|
|
256
300
|
};
|
|
257
|
-
|
|
258
|
-
export const jwtValidateController: Handler = (req, res) => {
|
|
259
|
-
const token = req.sprint?.getAuthorization() || req.headers.authorization;
|
|
260
|
-
|
|
261
|
-
if (!token) {
|
|
262
|
-
return res.status(401).json({ error: "No token provided" });
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
try {
|
|
266
|
-
const { publicKey } = getJwtFromEnv();
|
|
267
|
-
const decoded = verifyEncrypted(token, publicKey);
|
|
268
|
-
|
|
269
|
-
if (!decoded) {
|
|
270
|
-
return res.status(401).json({ error: "Invalid token" });
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
res.json({ valid: true, payload: decoded });
|
|
274
|
-
} catch (error) {
|
|
275
|
-
return res.status(500).json({ error: "JWT not configured" });
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
301
|
`;
|
|
279
302
|
}
|
|
280
|
-
return `import { Handler } from "sprint-es";
|
|
281
|
-
import { signEncrypted,
|
|
303
|
+
return `import { Handler, SprintRequest, SprintResponse } from "sprint-es";
|
|
304
|
+
import { signEncrypted, getJwtFromEnv } from "sprint-es/jwt";
|
|
282
305
|
|
|
283
|
-
export const adminController = (req, res) => {
|
|
306
|
+
export const adminController = (req: SprintRequest, res: SprintResponse) => {
|
|
284
307
|
res.json({
|
|
285
308
|
message: "Admin Dashboard",
|
|
286
309
|
status: "ok"
|
|
287
310
|
});
|
|
288
311
|
};
|
|
289
312
|
|
|
290
|
-
export const adminUsersController = (req, res) => {
|
|
313
|
+
export const adminUsersController = (req: SprintRequest, res: SprintResponse) => {
|
|
291
314
|
res.json({
|
|
292
315
|
users: [
|
|
293
316
|
{ id: 1, name: "John Doe", role: "admin" },
|
|
@@ -296,40 +319,20 @@ export const adminUsersController = (req, res) => {
|
|
|
296
319
|
});
|
|
297
320
|
};
|
|
298
321
|
|
|
299
|
-
export const jwtGenerateController = (req, res) => {
|
|
322
|
+
export const jwtGenerateController = (req: SprintRequest, res: SprintResponse) => {
|
|
300
323
|
const { userId, role } = req.body || {};
|
|
301
324
|
|
|
302
325
|
try {
|
|
303
|
-
const { privateKey } = getJwtFromEnv();
|
|
326
|
+
const { privateKey, encryptionSecret } = getJwtFromEnv();
|
|
304
327
|
const payload = { userId, role: role || "user" };
|
|
305
|
-
const token = signEncrypted(payload, privateKey, { expiresIn: "1h" });
|
|
328
|
+
const token = signEncrypted(payload, privateKey, encryptionSecret, { expiresIn: "1h" });
|
|
306
329
|
res.json({ token });
|
|
307
330
|
} catch (error) {
|
|
308
331
|
return res.status(500).json({ error: "JWT not configured" });
|
|
309
332
|
}
|
|
310
333
|
};
|
|
311
|
-
|
|
312
|
-
export const jwtValidateController = (req, res) => {
|
|
313
|
-
const token = req.sprint?.getAuthorization() || req.headers.authorization;
|
|
314
|
-
|
|
315
|
-
if (!token) {
|
|
316
|
-
return res.status(401).json({ error: "No token provided" });
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
try {
|
|
320
|
-
const { publicKey } = getJwtFromEnv();
|
|
321
|
-
const decoded = verifyEncrypted(token, publicKey);
|
|
322
|
-
|
|
323
|
-
if (!decoded) {
|
|
324
|
-
return res.status(401).json({ error: "Invalid token" });
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
res.json({ valid: true, payload: decoded });
|
|
328
|
-
} catch (error) {
|
|
329
|
-
return res.status(500).json({ error: "JWT not configured" });
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
334
|
`;
|
|
335
|
+
|
|
333
336
|
}
|
|
334
337
|
|
|
335
338
|
export function getHomeSchema(language: string) {
|
|
@@ -388,26 +391,21 @@ export const jwtGenerateSchema = defineRouteSchema({
|
|
|
388
391
|
`;
|
|
389
392
|
}
|
|
390
393
|
|
|
391
|
-
export function
|
|
394
|
+
export function getInternalAuthMiddleware(language: string) {
|
|
392
395
|
if (language === "typescript") {
|
|
393
396
|
return `import { defineMiddleware } from "sprint-es";
|
|
394
397
|
|
|
395
398
|
export default defineMiddleware({
|
|
396
|
-
name: "
|
|
399
|
+
name: "adminAuth",
|
|
397
400
|
priority: 10,
|
|
398
401
|
include: "/admin/**",
|
|
399
402
|
handler: (req, res, next) => {
|
|
400
403
|
const auth = req.sprint.getAuthorization();
|
|
401
|
-
|
|
402
|
-
if (!auth) {
|
|
403
|
-
return res.status(401).json({ error: "No authorization header" });
|
|
404
|
-
}
|
|
404
|
+
if (!auth) return res.status(401).json({ error: "No authorization header" });
|
|
405
405
|
|
|
406
406
|
const token = auth.replace("Bearer ", "");
|
|
407
407
|
|
|
408
|
-
if (token !== "admin-token") {
|
|
409
|
-
return res.status(403).json({ error: "Invalid token" });
|
|
410
|
-
}
|
|
408
|
+
if (token !== "admin-token") return res.status(403).json({ error: "Invalid token" });
|
|
411
409
|
|
|
412
410
|
next();
|
|
413
411
|
}
|
|
@@ -417,21 +415,73 @@ export default defineMiddleware({
|
|
|
417
415
|
return `import { defineMiddleware } from "sprint-es";
|
|
418
416
|
|
|
419
417
|
export default defineMiddleware({
|
|
420
|
-
name: "
|
|
418
|
+
name: "adminAuth",
|
|
421
419
|
priority: 10,
|
|
422
420
|
include: "/admin/**",
|
|
423
421
|
handler: (req, res, next) => {
|
|
424
422
|
const auth = req.sprint.getAuthorization();
|
|
423
|
+
if (!auth) return res.status(401).json({ error: "No authorization header" });
|
|
424
|
+
|
|
425
|
+
const token = auth.replace("Bearer ", "");
|
|
425
426
|
|
|
426
|
-
if (
|
|
427
|
-
|
|
428
|
-
|
|
427
|
+
if (token !== "admin-token") return res.status(403).json({ error: "Invalid token" });
|
|
428
|
+
|
|
429
|
+
next();
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
`;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export function getUserAuthMiddleware(language: string) {
|
|
436
|
+
if (language === "typescript") {
|
|
437
|
+
return `import { defineMiddleware } from "sprint-es";
|
|
438
|
+
import { verifyEncrypted, getJwtFromEnv } from "sprint-es/jwt";
|
|
439
|
+
|
|
440
|
+
const { publicKey, encryptionSecret } = getJwtFromEnv();
|
|
441
|
+
|
|
442
|
+
export default defineMiddleware({
|
|
443
|
+
name: "userAuth",
|
|
444
|
+
priority: 10,
|
|
445
|
+
include: "/**",
|
|
446
|
+
exclude: "/admin/**",
|
|
447
|
+
handler: (req, res, next) => {
|
|
448
|
+
const auth = req.sprint.getAuthorization();
|
|
449
|
+
if (!auth) return res.status(401).json({ error: "No authorization header" });
|
|
429
450
|
|
|
430
451
|
const token = auth.replace("Bearer ", "");
|
|
431
452
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
}
|
|
453
|
+
const decoded = verifyEncrypted(token, publicKey, encryptionSecret);cd .
|
|
454
|
+
|
|
455
|
+
if (!decoded) return res.status(403).json({ error: "Invalid token" });
|
|
456
|
+
|
|
457
|
+
req.custom.user = decoded;
|
|
458
|
+
|
|
459
|
+
next();
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
`;
|
|
463
|
+
}
|
|
464
|
+
return `import { defineMiddleware } from "sprint-es";
|
|
465
|
+
import { verifyEncrypted, getJwtFromEnv } from "sprint-es/jwt";
|
|
466
|
+
|
|
467
|
+
const { publicKey, encryptionSecret } = getJwtFromEnv();
|
|
468
|
+
|
|
469
|
+
export default defineMiddleware({
|
|
470
|
+
name: "userAuth",
|
|
471
|
+
priority: 10,
|
|
472
|
+
include: "/**",
|
|
473
|
+
exclude: "/admin/**",
|
|
474
|
+
handler: (req, res, next) => {
|
|
475
|
+
const auth = req.sprint.getAuthorization();
|
|
476
|
+
if (!auth) return res.status(401).json({ error: "No authorization header" });
|
|
477
|
+
|
|
478
|
+
const token = auth.replace("Bearer ", "");
|
|
479
|
+
|
|
480
|
+
const decoded = verifyEncrypted(token, publicKey, encryptionSecret);
|
|
481
|
+
|
|
482
|
+
if (!decoded) return res.status(403).json({ error: "Invalid token" });
|
|
483
|
+
|
|
484
|
+
req.custom.user = decoded;
|
|
435
485
|
|
|
436
486
|
next();
|
|
437
487
|
}
|
|
@@ -648,6 +698,7 @@ export function getEnvDevelopment(telemetry: string) {
|
|
|
648
698
|
PORT=5000
|
|
649
699
|
JWT_PUBLIC_KEY='${keys.publicKey}'
|
|
650
700
|
JWT_PRIVATE_KEY='${keys.privateKey}'
|
|
701
|
+
JWT_ENCRYPTION_SECRET='${crypto.randomBytes(32).toString("hex")}'
|
|
651
702
|
`;
|
|
652
703
|
|
|
653
704
|
if (telemetry === "sentry" || telemetry === "glitchtip") {
|
|
@@ -671,6 +722,7 @@ export function getEnvProduction(telemetry: string) {
|
|
|
671
722
|
PORT=5000
|
|
672
723
|
JWT_PUBLIC_KEY='${keys.publicKey}'
|
|
673
724
|
JWT_PRIVATE_KEY='${keys.privateKey}'
|
|
725
|
+
JWT_ENCRYPTION_SECRET='${crypto.randomBytes(32).toString("hex")}'
|
|
674
726
|
`;
|
|
675
727
|
|
|
676
728
|
if (telemetry === "sentry" || telemetry === "glitchtip") {
|
package/src/index.ts
CHANGED
|
@@ -2,9 +2,10 @@ import { spawn } from "child_process";
|
|
|
2
2
|
import { existsSync, writeFileSync } from "fs";
|
|
3
3
|
import { mkdir, writeFile as fsWriteFile } from "fs/promises";
|
|
4
4
|
import { join } from "path";
|
|
5
|
+
import color from "picocolors";
|
|
5
6
|
import * as p from "@clack/prompts";
|
|
6
7
|
import { validateProjectName } from "./validators.js";
|
|
7
|
-
import { getTypeScriptPackageJson, getJavaScriptPackageJson, getTsConfig, getViteConfig, getMainFile, getHomeRoute, getAdminRoute, getHomeController, getAdminController,
|
|
8
|
+
import { getTypeScriptPackageJson, getJavaScriptPackageJson, getTsConfig, getViteConfig, getMainFile, getHomeRoute, getAdminRoute, getHomeController, getAdminController, getInternalAuthMiddleware, getUserAuthMiddleware, getHomeSchema, getAdminSchema, getDockerfile, getDockerCompose, getGitignore, getDockerIgnore, getSprintConfigFile, getEnvDevelopment, getEnvProduction, getExampleCronJob } from "./generators.js";
|
|
8
9
|
|
|
9
10
|
export interface CLIOptions {
|
|
10
11
|
projectName?: string;
|
|
@@ -25,6 +26,8 @@ export async function runCLI(args: string[]) {
|
|
|
25
26
|
|
|
26
27
|
p.intro("Sprint — Quickly API Framework");
|
|
27
28
|
|
|
29
|
+
p.intro(`${color.bgCyan(color.black(' create-sprint-app '))}`);
|
|
30
|
+
|
|
28
31
|
const config = await p.group(
|
|
29
32
|
{
|
|
30
33
|
projectName: () =>
|
|
@@ -78,13 +81,14 @@ export async function runCLI(args: string[]) {
|
|
|
78
81
|
s.stop("Project created");
|
|
79
82
|
|
|
80
83
|
const installDeps = await p.confirm({ message: "Install dependencies now?", initialValue: true });
|
|
84
|
+
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
81
85
|
|
|
82
86
|
if (installDeps) {
|
|
83
87
|
const s2 = p.spinner();
|
|
84
88
|
s2.start("Installing dependencies");
|
|
85
89
|
try {
|
|
86
90
|
await new Promise<void>((resolve, reject) => {
|
|
87
|
-
const child = spawn(
|
|
91
|
+
const child = spawn(npmCmd, ["install"], {
|
|
88
92
|
cwd: targetDir,
|
|
89
93
|
stdio: "pipe"
|
|
90
94
|
});
|
|
@@ -92,6 +96,7 @@ export async function runCLI(args: string[]) {
|
|
|
92
96
|
if (code === 0) resolve();
|
|
93
97
|
else reject(new Error(`npm install exited with code ${code}`));
|
|
94
98
|
});
|
|
99
|
+
child.on("error", reject);
|
|
95
100
|
});
|
|
96
101
|
s2.stop("Dependencies installed");
|
|
97
102
|
} catch {
|
|
@@ -197,7 +202,8 @@ async function createProject(
|
|
|
197
202
|
await writeFile(join(srcDir, "controllers", "home." + (language === "typescript" ? "ts" : "js")), getHomeController(language));
|
|
198
203
|
await writeFile(join(srcDir, "controllers", "admin." + (language === "typescript" ? "ts" : "js")), getAdminController(language));
|
|
199
204
|
|
|
200
|
-
await writeFile(join(srcDir, "middlewares", "auth." + (language === "typescript" ? "ts" : "js")),
|
|
205
|
+
await writeFile(join(srcDir, "middlewares", "auth.internal." + (language === "typescript" ? "ts" : "js")), getInternalAuthMiddleware(language));
|
|
206
|
+
await writeFile(join(srcDir, "middlewares", "auth.user." + (language === "typescript" ? "ts" : "js")), getUserAuthMiddleware(language));
|
|
201
207
|
|
|
202
208
|
await writeFile(join(srcDir, "schemas", "home." + (language === "typescript" ? "ts" : "js")), getHomeSchema(language));
|
|
203
209
|
await writeFile(join(srcDir, "schemas", "admin." + (language === "typescript" ? "ts" : "js")), getAdminSchema(language));
|