create-sprint 0.0.62 → 0.0.64

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/src/generators.ts CHANGED
@@ -1,742 +1,3 @@
1
- import * as crypto from "node:crypto";
1
+ // Re-export all templates for backward compatibility.
2
2
 
3
- export interface JWTKeys {
4
- publicKey: string;
5
- privateKey: string;
6
- }
7
-
8
- export function generateJWTKeys(): JWTKeys {
9
- const keys = crypto.generateKeyPairSync("rsa", {
10
- modulusLength: 4096,
11
- publicKeyEncoding: { type: "spki", format: "pem" },
12
- privateKeyEncoding: { type: "pkcs8", format: "pem" }
13
- }) as unknown as { publicKey: string; privateKey: string };
14
- return keys;
15
- }
16
-
17
- export function getTypeScriptPackageJson(name: string, telemetry: string) {
18
- const deps: Record<string, string> = {
19
- "sprint-es": "^0.0.54"
20
- };
21
-
22
- const devDeps: Record<string, string> = {
23
- "@types/node": "^22.0.0",
24
- "tsx": "^4.19.0",
25
- typescript: "^5.6.0",
26
- };
27
-
28
- if (telemetry === "sentry" || telemetry === "glitchtip") {
29
- deps["@sentry/node"] = "^8.0.0";
30
- } else if (telemetry === "discord") {
31
- deps["axios"] = "^1.6.0";
32
- }
33
-
34
- return {
35
- name: name === "." ? "sprint-app" : name,
36
- version: "0.0.1",
37
- description: "Sprint API",
38
- main: "dist/index.js",
39
- scripts: {
40
- build: "sprint-es build",
41
- start: "sprint-es start",
42
- dev: "sprint-es dev",
43
- "generate:keys": "sprint-es generate-keys"
44
- },
45
- dependencies: deps,
46
- devDependencies: devDeps,
47
- };
48
- }
49
-
50
- export function getJavaScriptPackageJson(name: string, telemetry: string) {
51
- const deps: Record<string, string> = {
52
- "sprint-es": "^0.0.54"
53
- };
54
-
55
- if (telemetry === "sentry" || telemetry === "glitchtip") {
56
- deps["@sentry/node"] = "^8.0.0";
57
- } else if (telemetry === "discord") {
58
- deps["axios"] = "^1.6.0";
59
- }
60
-
61
- return {
62
- name: name === "." ? "sprint-app" : name,
63
- version: "0.0.1",
64
- description: "Sprint API",
65
- main: "src/index.js",
66
- type: "module",
67
- scripts: {
68
- build: "sprint-es build",
69
- start: "sprint-es start",
70
- dev: "sprint-es dev",
71
- "generate:keys": "sprint-es generate-keys"
72
- },
73
- dependencies: deps
74
- };
75
- }
76
-
77
- export function getTsConfig() {
78
- return JSON.stringify({
79
- compilerOptions: {
80
- target: "ES2022",
81
- module: "NodeNext",
82
- moduleResolution: "NodeNext",
83
- lib: ["ES2022"],
84
- types: ["node"],
85
- outDir: "./dist",
86
- rootDir: "./src",
87
- strict: true,
88
- esModuleInterop: true,
89
- skipLibCheck: true,
90
- forceConsistentCasingInFileNames: true,
91
- resolveJsonModule: true,
92
- declaration: true,
93
- declarationMap: true,
94
- sourceMap: true,
95
- baseUrl: ".",
96
- paths: {
97
- "@/*": ["./src/*"]
98
- }
99
- },
100
- include: ["src/**/*"],
101
- exclude: ["node_modules", "dist"],
102
- }, null, 2);
103
- }
104
-
105
- export function getViteConfig() {
106
- return `import { defineConfig } from "vite";
107
- import { resolve } from "path";
108
-
109
- export default defineConfig({
110
- build: {
111
- lib: {
112
- entry: resolve(__dirname, "src/index.ts"),
113
- formats: ["es"],
114
- fileName: "index",
115
- },
116
- outDir: "dist",
117
- rollupOptions: {
118
- external: ["sprint-es", "express", "cors", "morgan", "serve-favicon", "dotenv"],
119
- },
120
- target: "ES2020",
121
- },
122
- resolve: {
123
- alias: {
124
- "@": resolve(__dirname, "src"),
125
- },
126
- },
127
- });
128
- `;
129
- }
130
-
131
- export function getMainFile(language: string) {
132
- if (language === "typescript") {
133
- return `import Sprint from "sprint-es";
134
-
135
- const app = new Sprint();
136
- `;
137
- }
138
-
139
- return `import Sprint from "sprint-es";
140
-
141
- const app = new Sprint();
142
- `;
143
- }
144
-
145
- export function getHomeRoute(language: string) {
146
- if (language === "typescript") {
147
- return `import { Router } from "sprint-es";
148
- import { homeSchema } from "@/schemas/home";
149
- import { homeController, jwtValidateController } from "@/controllers/home";
150
-
151
- const router = Router();
152
-
153
- router.get("/", homeSchema, homeController);
154
- router.post("/me", jwtValidateController);
155
-
156
- export default router;
157
- `;
158
- }
159
- return `import { Router } from "sprint-es";
160
- import { homeSchema } from "../schemas/home.js";
161
- import { homeController, jwtValidateController } from "../controllers/home.js";
162
-
163
- const router = Router();
164
-
165
- router.get("/", homeSchema, homeController);
166
- router.post("/me", jwtValidateController);
167
-
168
- export default router;
169
- `;
170
- }
171
-
172
- export function getAdminRoute(language: string) {
173
- if (language === "typescript") {
174
- return `import { Router } from "sprint-es";
175
- import { adminSchema, jwtGenerateSchema } from "@/schemas/admin";
176
- import { adminController, adminUsersController, jwtGenerateController } from "@/controllers/admin";
177
-
178
- const router = Router();
179
-
180
- router.get("/", adminSchema, adminController);
181
- router.get("/users", adminSchema, adminUsersController);
182
- router.post("/jwt/generate", jwtGenerateSchema, jwtGenerateController);
183
-
184
- export default router;
185
- `;
186
- }
187
- return `import { Router } from "sprint-es";
188
- import { adminSchema, jwtGenerateSchema } from "../schemas/admin.js";
189
- import { adminController, adminUsersController, jwtGenerateController } from "../controllers/admin.js";
190
-
191
- const router = Router();
192
-
193
- router.get("/", adminSchema, adminController);
194
- router.get("/users", adminSchema, adminUsersController);
195
- router.post("/jwt/generate", jwtGenerateSchema, jwtGenerateController);
196
-
197
- export default router;
198
- `;
199
- }
200
-
201
- export function getHomeController(language: string) {
202
- if (language === "typescript") {
203
- return `import { Handler, SprintRequest, SprintResponse } from "sprint-es";
204
- import { verifyEncrypted, getJwtFromEnv } from "sprint-es/jwt";
205
-
206
- export const homeController: Handler = (req: SprintRequest, res: SprintResponse) => {
207
- res.json({
208
- message: "Hello World",
209
- status: "ok"
210
- });
211
- };
212
-
213
- export const jwtValidateController: Handler = (req: SprintRequest, res: SprintResponse) => {
214
- return res.json(req.custom.user);
215
- };
216
- `;
217
- }
218
- return `import { Handler, SprintRequest, SprintResponse } from "sprint-es";
219
- import { verifyEncrypted, getJwtFromEnv } from "sprint-es/jwt";
220
-
221
- export const homeController = (req: SprintRequest, res: SprintResponse) => {
222
- res.json({
223
- message: "Hello World",
224
- status: "ok"
225
- });
226
- };
227
-
228
- export const jwtValidateController = (req: SprintRequest, res: SprintResponse) => {
229
- return res.json(req.custom.user);
230
- };
231
- `;
232
- }
233
-
234
- export function getAdminController(language: string) {
235
- if (language === "typescript") {
236
- return `import { Handler, SprintRequest, SprintResponse } from "sprint-es";
237
- import { signEncrypted, getJwtFromEnv } from "sprint-es/jwt";
238
-
239
- export const adminController: Handler = (req: SprintRequest, res: SprintResponse) => {
240
- res.json({
241
- message: "Admin Dashboard",
242
- status: "ok"
243
- });
244
- };
245
-
246
- export const adminUsersController: Handler = (req: SprintRequest, res: SprintResponse) => {
247
- res.json({
248
- users: [
249
- { id: 1, name: "John Doe", role: "admin" },
250
- { id: 2, name: "Jane Smith", role: "user" }
251
- ]
252
- });
253
- };
254
-
255
- const { privateKey, encryptionSecret } = getJwtFromEnv();
256
-
257
- export const jwtGenerateController: Handler = (req: SprintRequest, res: SprintResponse) => {
258
- const { userId, role } = req.body || {};
259
-
260
- try {
261
- const payload = { userId, role: role || "user" };
262
- const token = signEncrypted(payload, privateKey, encryptionSecret, { expiresIn: "1h" });
263
- res.json({ token });
264
- } catch (error) {
265
- return res.status(500).json({ error: "JWT not configured" });
266
- }
267
- };
268
- `;
269
- } else {
270
- return `import { Handler, SprintRequest, SprintResponse } from "sprint-es";
271
- import { signEncrypted, getJwtFromEnv } from "sprint-es/jwt";
272
-
273
- export const adminController = (req: SprintRequest, res: SprintResponse) => {
274
- res.json({
275
- message: "Admin Dashboard",
276
- status: "ok"
277
- });
278
- };
279
-
280
- export const adminUsersController = (req: SprintRequest, res: SprintResponse) => {
281
- res.json({
282
- users: [
283
- { id: 1, name: "John Doe", role: "admin" },
284
- { id: 2, name: "Jane Smith", role: "user" }
285
- ]
286
- });
287
- };
288
-
289
- const { privateKey, encryptionSecret } = getJwtFromEnv();
290
-
291
- export const jwtGenerateController = (req: SprintRequest, res: SprintResponse) => {
292
- const { userId, role } = req.body || {};
293
-
294
- try {
295
- const payload = { userId, role: role || "user" };
296
- const token = signEncrypted(payload, privateKey, encryptionSecret, { expiresIn: "1h" });
297
- res.json({ token });
298
- } catch (error) {
299
- return res.status(500).json({ error: "JWT not configured" });
300
- }
301
- };
302
- `;
303
- }
304
- }
305
-
306
- export function getHomeSchema(language: string) {
307
- if (language === "typescript") {
308
- return `import { z, defineRouteSchema } from "sprint-es/schemas";
309
-
310
- export const homeSchema = defineRouteSchema({});
311
- `;
312
- }
313
- return `import { z, defineRouteSchema } from "sprint-es/schemas";
314
-
315
- export const homeSchema = defineRouteSchema({});
316
- `;
317
- }
318
-
319
- export function getAdminSchema(language: string) {
320
- if (language === "typescript") {
321
- return `import { z, defineRouteSchema } from "sprint-es/schemas";
322
-
323
- export const adminSchema = defineRouteSchema({
324
- queryParams: z.object({
325
- id: z.string().uuid()
326
- }),
327
- body: z.object({
328
- name: z.string().min(1),
329
- email: z.string().email().optional()
330
- })
331
- });
332
-
333
- export const jwtGenerateSchema = defineRouteSchema({
334
- body: z.object({
335
- userId: z.string().min(1),
336
- role: z.string().optional()
337
- })
338
- });
339
- `;
340
- }
341
- return `import { z, defineRouteSchema } from "sprint-es/schemas";
342
-
343
- export const adminSchema = defineRouteSchema({
344
- queryParams: z.object({
345
- id: z.string().uuid()
346
- }),
347
- body: z.object({
348
- name: z.string().min(1),
349
- email: z.string().email().optional()
350
- })
351
- });
352
-
353
- export const jwtGenerateSchema = defineRouteSchema({
354
- body: z.object({
355
- userId: z.string().min(1),
356
- role: z.string().optional()
357
- })
358
- });
359
- `;
360
- }
361
-
362
- export function getInternalAuthMiddleware(language: string) {
363
- if (language === "typescript") {
364
- return `import { defineMiddleware, SprintRequest, SprintResponse, NextFunction } from "sprint-es";
365
-
366
- export default defineMiddleware({
367
- name: "adminAuth",
368
- priority: 10,
369
- include: "/admin/**",
370
- handler: (req: SprintRequest, res: SprintResponse, next: NextFunction) => {
371
- const auth = req.sprint.getAuthorization();
372
- if (!auth) return res.status(401).json({ error: "No authorization header" });
373
-
374
- const token = auth.replace("Bearer ", "");
375
-
376
- if (token !== "admin-token") return res.status(403).json({ error: "Invalid token" });
377
-
378
- next();
379
- }
380
- });
381
- `;
382
- }
383
- return `import { defineMiddleware } from "sprint-es";
384
-
385
- export default defineMiddleware({
386
- name: "adminAuth",
387
- priority: 10,
388
- include: "/admin/**",
389
- handler: (req, res, next) => {
390
- const auth = req.sprint.getAuthorization();
391
- if (!auth) return res.status(401).json({ error: "No authorization header" });
392
-
393
- const token = auth.replace("Bearer ", "");
394
-
395
- if (token !== "admin-token") return res.status(403).json({ error: "Invalid token" });
396
-
397
- next();
398
- }
399
- });
400
- `;
401
- }
402
-
403
- export function getUserAuthMiddleware(language: string) {
404
- if (language === "typescript") {
405
- return `import { defineMiddleware, SprintRequest, SprintResponse, NextFunction } from "sprint-es";
406
- import { verifyEncrypted, getJwtFromEnv } from "sprint-es/jwt";
407
-
408
- const { publicKey, encryptionSecret } = getJwtFromEnv();
409
-
410
- export default defineMiddleware({
411
- name: "userAuth",
412
- priority: 10,
413
- include: "/**",
414
- exclude: "/admin/**",
415
- handler: (req: SprintRequest, res: SprintResponse, next: NextFunction) => {
416
- const auth = req.sprint.getAuthorization();
417
- if (!auth) return res.status(401).json({ error: "No authorization header" });
418
-
419
- const token = auth.replace("Bearer ", "");
420
-
421
- const decoded = verifyEncrypted(token, publicKey, encryptionSecret);
422
-
423
- if (!decoded) return res.status(403).json({ error: "Invalid token" });
424
-
425
- req.custom.user = decoded;
426
-
427
- next();
428
- }
429
- });
430
- `;
431
- }
432
- return `import { defineMiddleware } from "sprint-es";
433
- import { verifyEncrypted, getJwtFromEnv } from "sprint-es/jwt";
434
-
435
- const { publicKey, encryptionSecret } = getJwtFromEnv();
436
-
437
- export default defineMiddleware({
438
- name: "userAuth",
439
- priority: 10,
440
- include: "/**",
441
- exclude: "/admin/**",
442
- handler: (req, res, next) => {
443
- const auth = req.sprint.getAuthorization();
444
- if (!auth) return res.status(401).json({ error: "No authorization header" });
445
-
446
- const token = auth.replace("Bearer ", "");
447
-
448
- const decoded = verifyEncrypted(token, publicKey, encryptionSecret);
449
-
450
- if (!decoded) return res.status(403).json({ error: "Invalid token" });
451
-
452
- req.custom.user = decoded;
453
-
454
- next();
455
- }
456
- });
457
- `;
458
- }
459
-
460
- export function getDockerfile(language: string) {
461
- if (language === "typescript") {
462
- return `FROM node:20-alpine
463
-
464
- WORKDIR /app
465
-
466
- COPY package*.json ./
467
-
468
- RUN npm ci
469
-
470
- COPY . .
471
-
472
- RUN npm run build
473
-
474
- EXPOSE 3000
475
-
476
- CMD ["npm", "start"]
477
- `;
478
- }
479
- return `FROM node:20-alpine
480
-
481
- WORKDIR /app
482
-
483
- COPY package*.json ./
484
-
485
- RUN npm ci
486
-
487
- COPY . .
488
-
489
- EXPOSE 3000
490
-
491
- CMD ["npm", "start"]
492
- `;
493
- }
494
-
495
- export function getDockerCompose(language: string) {
496
- return `
497
- services:
498
- app:
499
- build: .
500
- ports:
501
- - "3000:3000"
502
- environment:
503
- - NODE_ENV=production
504
- - PORT=5000
505
- restart: unless-stopped
506
- `;
507
- }
508
-
509
- export function getGitignore() {
510
- return `# Dependencies
511
- node_modules/
512
- npm-debug.log*
513
- yarn-debug.log*
514
- yarn-error.log*
515
-
516
- # Build
517
- dist/
518
- build/
519
- *.tsbuildinfo
520
-
521
- # Environment
522
- .env.development
523
- .env.production
524
- .env.local
525
- .env.*.local
526
-
527
- # IDE
528
- .vscode/
529
- .idea/
530
- *.swp
531
- *.swo
532
- *~
533
-
534
- # OS
535
- .DS_Store
536
- Thumbs.db
537
-
538
- # Logs
539
- logs/
540
- *.log
541
-
542
- # Test
543
- coverage/
544
-
545
- # Temporary
546
- tmp/
547
- temp/
548
- `;
549
- }
550
-
551
- export function getDockerIgnore() {
552
- return `node_modules
553
- npm-debug.log
554
- .env
555
- .env.*
556
- .git
557
- .gitignore
558
- README.md
559
- dist
560
- build
561
- coverage
562
- .vscode
563
- .idea
564
- *.log
565
- tmp
566
- temp
567
- `;
568
- }
569
-
570
- export function getSprintConfigFile(language: string, telemetry: string) {
571
- if (language === "typescript") {
572
- let config = `import type { SprintOptions } from "sprint-es";
573
-
574
- export const config: SprintOptions = {
575
- openapi: {
576
- /* Generate OpenAPI spec on build - Coming Soon */
577
- generateOnBuild: false
578
- }
579
- };
580
-
581
- // Add Vite config here if needed
582
- // export const vite = {
583
- // build: { ... }
584
- // };
585
- `;
586
-
587
- if (telemetry === "sentry" || telemetry === "glitchtip") {
588
- config += `import { initTelemetry } from "sprint-es/telemetry";
589
-
590
- initTelemetry({
591
- provider: "${telemetry}",
592
- dsn: process.env.SENTRY_DSN || "",
593
- environment: process.env.NODE_ENV || "development"
594
- });
595
- `;
596
- } else if (telemetry === "discord") {
597
- config += `import { initTelemetry } from "sprint-es/telemetry";
598
-
599
- initTelemetry({
600
- provider: "discord",
601
- webhookUrl: process.env.DISCORD_TELEMETRY_WEBHOOK_URL || ""
602
- });
603
- `;
604
- }
605
-
606
- return config;
607
- }
608
-
609
- let config = `export const config = {
610
- openapi: {
611
- /* Generate OpenAPI spec on build - Coming Soon */
612
- generateOnBuild: false
613
- }
614
- };
615
- `;
616
-
617
- if (telemetry === "sentry" || telemetry === "glitchtip") {
618
- config += `
619
- import { initTelemetry } from "sprint-es/telemetry";
620
-
621
- initTelemetry({
622
- provider: "${telemetry}",
623
- dsn: process.env.SENTRY_DSN || "",
624
- environment: process.env.NODE_ENV || "development"
625
- });
626
- `;
627
- } else if (telemetry === "discord") {
628
- config += `
629
- import { initTelemetry } from "sprint-es/telemetry";
630
-
631
- initTelemetry({
632
- provider: "discord",
633
- webhookUrl: process.env.DISCORD_TELEMETRY_WEBHOOK_URL || ""
634
- });
635
- `;
636
- }
637
-
638
- return config;
639
- }
640
-
641
- export function getEnvExample(telemetry: string) {
642
- let env = `PORT=5000
643
-
644
- JWT_PUBLIC_KEY=""
645
- JWT_PRIVATE_KEY=""
646
- JWT_ENCRYPTION_SECRET=""
647
-
648
- # Development: npm run dev (NODE_ENV=development)
649
- # Production: npm start (NODE_ENV=production)
650
- `;
651
-
652
- if (telemetry === "sentry" || telemetry === "glitchtip") {
653
- env += `
654
- # Sentry / GlitchTip (use GlitchTip DSN for self-hosted)
655
- SENTRY_DSN=""
656
- `;
657
- } else if (telemetry === "discord") {
658
- env += `
659
- # Discord Webhook URL for error notifications
660
- DISCORD_TELEMETRY_WEBHOOK_URL=""
661
- `;
662
- }
663
-
664
- return env;
665
- }
666
-
667
- function envKey(key: any): string {
668
- return key;
669
- }
670
-
671
- export function getEnvDevelopment(telemetry: string) {
672
- const keys = generateJWTKeys();
673
- let env = `NODE_ENV=development
674
- PORT=5000
675
- JWT_PUBLIC_KEY='${keys.publicKey}'
676
- JWT_PRIVATE_KEY='${keys.privateKey}'
677
- JWT_ENCRYPTION_SECRET='${crypto.randomBytes(32).toString("hex")}'
678
- `;
679
-
680
- if (telemetry === "sentry" || telemetry === "glitchtip") {
681
- env += `
682
- # Sentry / GlitchTip
683
- SENTRY_DSN=""
684
- `;
685
- } else if (telemetry === "discord") {
686
- env += `
687
- # Discord Webhook URL
688
- DISCORD_TELEMETRY_WEBHOOK_URL=""
689
- `;
690
- }
691
-
692
- return env;
693
- }
694
-
695
- export function getEnvProduction(telemetry: string) {
696
- const keys = generateJWTKeys();
697
- let env = `NODE_ENV=production
698
- PORT=5000
699
- JWT_PUBLIC_KEY='${keys.publicKey}'
700
- JWT_PRIVATE_KEY='${keys.privateKey}'
701
- JWT_ENCRYPTION_SECRET='${crypto.randomBytes(32).toString("hex")}'
702
- `;
703
-
704
- if (telemetry === "sentry" || telemetry === "glitchtip") {
705
- env += `
706
- # Sentry / GlitchTip
707
- SENTRY_DSN=
708
- `;
709
- } else if (telemetry === "discord") {
710
- env += `
711
- # Discord Webhook URL
712
- DISCORD_TELEMETRY_WEBHOOK_URL=
713
- `;
714
- }
715
-
716
- return env;
717
- }
718
-
719
- export function getExampleCronJob(language: string) {
720
- if (language === "typescript") {
721
- return `import { defineCronJob } from "sprint-es/cronjobs";
722
-
723
- export default defineCronJob({
724
- name: "daily-task",
725
- cronExpression: "0 21 * * *",
726
- handler: () => {
727
- console.log("Hello World from cronjob!");
728
- }
729
- });
730
- `;
731
- }
732
- return `import { defineCronJob } from "sprint-es/cronjobs";
733
-
734
- export default defineCronJob({
735
- name: "daily-task",
736
- cronExpression: "0 21 * * *",
737
- handler: () => {
738
- console.log("Hello World from cronjob!");
739
- }
740
- });
741
- `;
742
- }
3
+ export * from "./templates/index.js";