create-tinny-backend 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,668 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" data-theme="light">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
6
+ <title>404 | Page Not Found</title>
7
+ <link rel="shortcut icon" href="/imgs/logo.png" type="image/x-icon">
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
10
+
11
+ <style>
12
+ :root {
13
+ --bg: #f4f6fa;
14
+ --text: #1e293b;
15
+ --text-secondary: #475569;
16
+ --text-muted: #64748b;
17
+ --border: #e2e8f0;
18
+ --card-bg: #ffffff;
19
+ --card-border: #e9eef3;
20
+ --input-focus: #2563eb;
21
+ --heading: #0f172a;
22
+ --shadow-lg: 0 12px 40px rgba(0,0,0,0.1);
23
+ --toggle-bg: #f1f5f9;
24
+ --badge-bg: #dbeafe;
25
+ --badge-text: #1e40af;
26
+ --error-bg: #fee2e2;
27
+ --error-text: #991b1b;
28
+ --success-bg: #dcfce7;
29
+ --success-text: #166534;
30
+ --terminal-bg: #0f172a;
31
+ --terminal-text: #e2e8f0;
32
+ --terminal-border: #1e293b;
33
+ --icon-bg: #f8fafc;
34
+ --code-color: #6d8ecc;
35
+ --path-color: #f56565;
36
+ }
37
+
38
+ [data-theme="dark"] {
39
+ --bg: #1a1a1a;
40
+ --text: #d4d4d4;
41
+ --text-secondary: #a0a0a0;
42
+ --text-muted: #808080;
43
+ --border: #3a3a3a;
44
+ --card-bg: #2a2a2a;
45
+ --card-border: #3a3a3a;
46
+ --input-focus: #60a5fa;
47
+ --heading: #e0e0e0;
48
+ --shadow-lg: 0 12px 40px rgba(0,0,0,0.5);
49
+ --toggle-bg: #333333;
50
+ --badge-bg: #2a2a2a;
51
+ --badge-text: #a0a0a0;
52
+ --error-bg: #3a1a1a;
53
+ --error-text: #fc8181;
54
+ --success-bg: #1a3a2a;
55
+ --success-text: #48bb78;
56
+ --terminal-bg: #0a0a0a;
57
+ --terminal-text: #d4d4d4;
58
+ --terminal-border: #2a2a2a;
59
+ --icon-bg: #222222;
60
+ --code-color: #60a5fa;
61
+ --path-color: #fc8181;
62
+ }
63
+
64
+ * {
65
+ margin: 0;
66
+ padding: 0;
67
+ box-sizing: border-box;
68
+ }
69
+
70
+ body {
71
+ background: var(--bg);
72
+ font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
73
+ min-height: 100vh;
74
+ display: flex;
75
+ justify-content: center;
76
+ align-items: center;
77
+ padding: 2rem;
78
+ color: var(--text);
79
+ transition: background 0.3s ease, color 0.3s ease;
80
+ }
81
+
82
+ .container {
83
+ width: 100%;
84
+ max-width: 800px;
85
+ animation: fadeIn 0.6s ease;
86
+ }
87
+
88
+ @keyframes fadeIn {
89
+ from {
90
+ opacity: 0;
91
+ transform: translateY(20px);
92
+ }
93
+ to {
94
+ opacity: 1;
95
+ transform: translateY(0);
96
+ }
97
+ }
98
+
99
+ .error-card {
100
+ background: var(--card-bg);
101
+ border: 1px solid var(--card-border);
102
+ border-radius: 1.5rem;
103
+ padding: 3rem;
104
+ text-align: center;
105
+ box-shadow: var(--shadow-lg);
106
+ transition: background 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
107
+ position: relative;
108
+ overflow: hidden;
109
+ }
110
+
111
+ .error-card::before {
112
+ content: '';
113
+ position: absolute;
114
+ top: 0;
115
+ left: 0;
116
+ right: 0;
117
+ height: 4px;
118
+ background: linear-gradient(90deg, var(--input-focus), var(--badge-bg));
119
+ opacity: 0.5;
120
+ }
121
+
122
+ .error-card:hover {
123
+ border-color: var(--input-focus);
124
+ box-shadow: var(--shadow-lg), 0 0 0 1px var(--input-focus);
125
+ }
126
+
127
+ /* Theme Toggle */
128
+ .theme-toggle-wrapper {
129
+ display: flex;
130
+ justify-content: flex-end;
131
+ margin-bottom: 1.5rem;
132
+ }
133
+
134
+ .theme-toggle {
135
+ background: var(--toggle-bg);
136
+ border: 1px solid var(--border);
137
+ color: var(--text);
138
+ width: 40px;
139
+ height: 40px;
140
+ border-radius: 0.8rem;
141
+ display: flex;
142
+ align-items: center;
143
+ justify-content: center;
144
+ cursor: pointer;
145
+ font-size: 1.1rem;
146
+ transition: all 0.2s ease;
147
+ }
148
+
149
+ .theme-toggle:hover {
150
+ background: var(--input-focus);
151
+ color: white;
152
+ border-color: var(--input-focus);
153
+ }
154
+
155
+ /* Icon */
156
+ .error-icon {
157
+ width: 120px;
158
+ height: 120px;
159
+ margin: 0 auto 1.5rem;
160
+ border-radius: 50%;
161
+ background: var(--icon-bg);
162
+ border: 2px solid var(--border);
163
+ display: flex;
164
+ align-items: center;
165
+ justify-content: center;
166
+ transition: all 0.3s ease;
167
+ }
168
+
169
+ .error-icon:hover {
170
+ border-color: var(--input-focus);
171
+ box-shadow: 0 0 40px rgba(37, 99, 235, 0.1);
172
+ }
173
+
174
+ .error-icon i {
175
+ font-size: 3.25rem;
176
+ color: var(--input-focus);
177
+ }
178
+
179
+ /* Code */
180
+ .error-code {
181
+ font-size: 5rem;
182
+ font-weight: 700;
183
+ line-height: 1;
184
+ letter-spacing: -3px;
185
+ color: var(--heading);
186
+ margin-bottom: 0.75rem;
187
+ }
188
+
189
+ .error-code span {
190
+ background: linear-gradient(135deg, var(--input-focus), var(--badge-text));
191
+ -webkit-background-clip: text;
192
+ -webkit-text-fill-color: transparent;
193
+ background-clip: text;
194
+ }
195
+
196
+ /* Title */
197
+ .error-title {
198
+ font-size: 1.8rem;
199
+ font-weight: 600;
200
+ color: var(--heading);
201
+ margin-bottom: 0.75rem;
202
+ }
203
+
204
+ .error-title i {
205
+ color: var(--input-focus);
206
+ margin-right: 0.5rem;
207
+ }
208
+
209
+ /* Description */
210
+ .error-description {
211
+ color: var(--text-secondary);
212
+ font-size: 1rem;
213
+ line-height: 1.7;
214
+ max-width: 520px;
215
+ margin: 0 auto 2rem;
216
+ }
217
+
218
+ .error-description .badge {
219
+ display: inline-block;
220
+ background: var(--badge-bg);
221
+ color: var(--badge-text);
222
+ padding: 0.2rem 0.6rem;
223
+ border-radius: 30px;
224
+ font-size: 0.7rem;
225
+ font-weight: 700;
226
+ border: 1px solid var(--border);
227
+ }
228
+
229
+ /* Actions */
230
+ .actions {
231
+ display: flex;
232
+ justify-content: center;
233
+ gap: 1rem;
234
+ flex-wrap: wrap;
235
+ margin-bottom: 2rem;
236
+ }
237
+
238
+ .btn {
239
+ text-decoration: none;
240
+ padding: 0.85rem 2rem;
241
+ border-radius: 2.5rem;
242
+ font-size: 0.9rem;
243
+ font-weight: 600;
244
+ transition: all 0.3s ease;
245
+ display: flex;
246
+ align-items: center;
247
+ gap: 0.6rem;
248
+ font-family: 'Inter', sans-serif;
249
+ border: none;
250
+ cursor: pointer;
251
+ }
252
+
253
+ .btn-primary {
254
+ background: var(--input-focus);
255
+ color: #fff;
256
+ }
257
+
258
+ .btn-primary:hover {
259
+ background: var(--badge-text);
260
+ transform: translateY(-2px);
261
+ box-shadow: 0 8px 24px rgba(37, 99, 235, 0.3);
262
+ }
263
+
264
+ .btn-secondary {
265
+ background: var(--toggle-bg);
266
+ border: 1px solid var(--border);
267
+ color: var(--text);
268
+ }
269
+
270
+ .btn-secondary:hover {
271
+ background: var(--border);
272
+ transform: translateY(-2px);
273
+ }
274
+
275
+ /* Terminal */
276
+ .terminal {
277
+ margin-top: 0.5rem;
278
+ background: var(--terminal-bg);
279
+ border: 1px solid var(--terminal-border);
280
+ border-radius: 1rem;
281
+ overflow: hidden;
282
+ transition: background 0.3s ease, border-color 0.3s ease;
283
+ text-align: left;
284
+ }
285
+
286
+ .terminal-header {
287
+ background: var(--border);
288
+ padding: 0.7rem 1rem;
289
+ display: flex;
290
+ align-items: center;
291
+ gap: 0.5rem;
292
+ border-bottom: 1px solid var(--terminal-border);
293
+ transition: background 0.3s ease, border-color 0.3s ease;
294
+ }
295
+
296
+ .dot {
297
+ width: 10px;
298
+ height: 10px;
299
+ border-radius: 50%;
300
+ display: inline-block;
301
+ }
302
+
303
+ .red { background: #f56565; }
304
+ .yellow { background: #ecc94b; }
305
+ .green { background: #48bb78; }
306
+
307
+ .terminal-title {
308
+ margin-left: 0.5rem;
309
+ color: var(--text-muted);
310
+ font-size: 0.8rem;
311
+ font-weight: 500;
312
+ letter-spacing: 0.3px;
313
+ }
314
+
315
+ .terminal-body {
316
+ padding: 1.2rem 1.2rem;
317
+ font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
318
+ font-size: 0.85rem;
319
+ color: var(--terminal-text);
320
+ background: var(--terminal-bg);
321
+ min-height: 150px;
322
+ }
323
+
324
+ .line {
325
+ margin-bottom: 0.5rem;
326
+ display: flex;
327
+ align-items: baseline;
328
+ gap: 0.6rem;
329
+ flex-wrap: wrap;
330
+ }
331
+
332
+ .line:last-child {
333
+ margin-bottom: 0;
334
+ }
335
+
336
+ .prompt {
337
+ color: var(--code-color);
338
+ user-select: none;
339
+ }
340
+
341
+ .error {
342
+ color: var(--path-color);
343
+ }
344
+
345
+ .success {
346
+ color: #48bb78;
347
+ }
348
+
349
+ .info {
350
+ color: var(--code-color);
351
+ }
352
+
353
+ .dim {
354
+ color: var(--text-muted);
355
+ }
356
+
357
+ .path-highlight {
358
+ color: var(--path-color);
359
+ font-weight: 600;
360
+ }
361
+
362
+ .cursor-blink {
363
+ display: inline-block;
364
+ width: 8px;
365
+ height: 16px;
366
+ background: var(--code-color);
367
+ animation: blink 1s step-end infinite;
368
+ vertical-align: text-bottom;
369
+ margin-left: 2px;
370
+ }
371
+
372
+ @keyframes blink {
373
+ 0%, 100% { opacity: 1; }
374
+ 50% { opacity: 0; }
375
+ }
376
+
377
+ /* Decorative line */
378
+ .decorative-line {
379
+ display: flex;
380
+ align-items: center;
381
+ gap: 1rem;
382
+ margin: 1.5rem 0;
383
+ }
384
+
385
+ .decorative-line::before,
386
+ .decorative-line::after {
387
+ content: '';
388
+ flex: 1;
389
+ height: 1px;
390
+ background: linear-gradient(to right, transparent, var(--border), transparent);
391
+ }
392
+
393
+ .decorative-line span {
394
+ color: var(--text-muted);
395
+ font-size: 0.7rem;
396
+ text-transform: uppercase;
397
+ letter-spacing: 0.5px;
398
+ font-weight: 600;
399
+ }
400
+
401
+ /* Footer */
402
+ .footer {
403
+ margin-top: 2rem;
404
+ text-align: center;
405
+ color: var(--text-muted);
406
+ font-size: 0.8rem;
407
+ }
408
+
409
+ .footer a {
410
+ color: var(--input-focus);
411
+ text-decoration: none;
412
+ font-weight: 500;
413
+ transition: color 0.3s ease;
414
+ }
415
+
416
+ .footer a:hover {
417
+ color: var(--badge-text);
418
+ text-decoration: underline;
419
+ }
420
+
421
+ .footer i {
422
+ margin: 0 0.3rem;
423
+ font-size: 0.7rem;
424
+ }
425
+
426
+ @media (max-width: 600px) {
427
+ body {
428
+ padding: 1rem;
429
+ }
430
+
431
+ .error-card {
432
+ padding: 2rem 1.5rem;
433
+ }
434
+
435
+ .error-code {
436
+ font-size: 3.5rem;
437
+ }
438
+
439
+ .error-title {
440
+ font-size: 1.4rem;
441
+ }
442
+
443
+ .error-icon {
444
+ width: 90px;
445
+ height: 90px;
446
+ }
447
+
448
+ .error-icon i {
449
+ font-size: 2.5rem;
450
+ }
451
+
452
+ .btn {
453
+ padding: 0.7rem 1.5rem;
454
+ font-size: 0.85rem;
455
+ width: 100%;
456
+ justify-content: center;
457
+ }
458
+
459
+ .actions {
460
+ flex-direction: column;
461
+ gap: 0.8rem;
462
+ }
463
+
464
+ .terminal-body {
465
+ font-size: 0.75rem;
466
+ padding: 1rem;
467
+ }
468
+
469
+ .line {
470
+ flex-wrap: wrap;
471
+ gap: 0.3rem;
472
+ }
473
+ }
474
+
475
+ /* Scrollbar */
476
+ ::-webkit-scrollbar {
477
+ width: 6px;
478
+ height: 6px;
479
+ }
480
+
481
+ ::-webkit-scrollbar-track {
482
+ background: var(--bg);
483
+ }
484
+
485
+ ::-webkit-scrollbar-thumb {
486
+ background: var(--border);
487
+ border-radius: 10px;
488
+ }
489
+
490
+ ::-webkit-scrollbar-thumb:hover {
491
+ background: var(--text-muted);
492
+ }
493
+ </style>
494
+ </head>
495
+ <body>
496
+
497
+ <div class="container">
498
+
499
+ <div class="error-card">
500
+
501
+ <!-- Theme Toggle -->
502
+ <div class="theme-toggle-wrapper">
503
+ <button class="theme-toggle" id="themeToggle" title="Toggle dark/light mode">
504
+ <i class="fas fa-moon"></i>
505
+ </button>
506
+ </div>
507
+
508
+ <!-- Icon -->
509
+ <div class="error-icon">
510
+ <i class="fas fa-cube"></i>
511
+ </div>
512
+
513
+ <!-- Code -->
514
+ <div class="error-code">
515
+ <span>404</span>
516
+ </div>
517
+
518
+ <!-- Title -->
519
+ <h1 class="error-title">
520
+ <i class="fas fa-compass"></i>
521
+ Page Not Found
522
+ </h1>
523
+
524
+ <!-- Description -->
525
+ <p class="error-description">
526
+ The page you requested could not be found.
527
+ It may have been moved, deleted, or the URL may be incorrect.
528
+ <br><br>
529
+ <span class="badge"><i class="fas fa-search"></i> Check the URL for typos</span>
530
+ </p>
531
+
532
+ <!-- Actions -->
533
+ <div class="actions">
534
+ <a href="/" class="btn btn-primary">
535
+ <i class="fas fa-house"></i>
536
+ Return Home
537
+ </a>
538
+ <a href="javascript:history.back()" class="btn btn-secondary">
539
+ <i class="fas fa-arrow-left"></i>
540
+ Go Back
541
+ </a>
542
+ <a href="/docs" class="btn btn-secondary">
543
+ <i class="fa-regular fa-newspaper"></i>
544
+ Documentation
545
+ </a>
546
+ </div>
547
+
548
+ <!-- Decorative Line -->
549
+ <div class="decorative-line">
550
+ <span>resource not found</span>
551
+ </div>
552
+
553
+ <!-- Terminal -->
554
+ <div class="terminal">
555
+ <div class="terminal-header">
556
+ <span class="dot red"></span>
557
+ <span class="dot yellow"></span>
558
+ <span class="dot green"></span>
559
+ <span class="terminal-title"><i class="fas fa-terminal"></i> system.log</span>
560
+ </div>
561
+
562
+ <div class="terminal-body">
563
+ <div class="line">
564
+ <span class="prompt">❯</span>
565
+ <span class="info">[REQUEST]</span>
566
+ <span>GET</span>
567
+ <span class="path-highlight" id="requested-path">/page-not-found</span>
568
+ </div>
569
+
570
+ <div class="line">
571
+ <span class="prompt">❯</span>
572
+ <span class="error">[ERROR]</span>
573
+ <span>Status: 404 Not Found</span>
574
+ </div>
575
+
576
+ <div class="line">
577
+ <span class="prompt">❯</span>
578
+ <span class="info">[INFO]</span>
579
+ <span>Resource does not exist in routing table</span>
580
+ </div>
581
+
582
+ <div class="line">
583
+ <span class="prompt">❯</span>
584
+ <span class="info">[INFO]</span>
585
+ <span>Available routes: <span class="dim">/admin, /login, /docs</span></span>
586
+ </div>
587
+
588
+ <div class="line success">
589
+ <span class="prompt">❯</span>
590
+ <span class="success">[SUGGESTION]</span>
591
+ <span>Redirect user to a valid route... <span class="cursor-blink"></span></span>
592
+ </div>
593
+ </div>
594
+ </div>
595
+
596
+ <!-- Footer -->
597
+ <div class="footer">
598
+ <i class="fas fa-map-signs"></i>
599
+ Check the
600
+ <a href="/docs">documentation</a>
601
+ for available routes
602
+ <i class="fas fa-chevron-right"></i>
603
+ <a href="/">back to home</a>
604
+ </div>
605
+
606
+ </div>
607
+
608
+ </div>
609
+
610
+ <script>
611
+ (function() {
612
+ // ===== THEME TOGGLE =====
613
+ const html = document.documentElement;
614
+ const themeToggle = document.getElementById('themeToggle');
615
+ const savedTheme = localStorage.getItem('tinnybackend-theme');
616
+
617
+ if (savedTheme) {
618
+ html.setAttribute('data-theme', savedTheme);
619
+ } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
620
+ html.setAttribute('data-theme', 'dark');
621
+ }
622
+
623
+ function updateThemeUI(theme) {
624
+ const icon = themeToggle.querySelector('i');
625
+ if (theme === 'dark') {
626
+ icon.classList.remove('fa-moon');
627
+ icon.classList.add('fa-sun');
628
+ } else {
629
+ icon.classList.remove('fa-sun');
630
+ icon.classList.add('fa-moon');
631
+ }
632
+ }
633
+
634
+ updateThemeUI(html.getAttribute('data-theme'));
635
+
636
+ themeToggle.addEventListener('click', () => {
637
+ const currentTheme = html.getAttribute('data-theme');
638
+ const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
639
+ html.setAttribute('data-theme', newTheme);
640
+ localStorage.setItem('tinnybackend-theme', newTheme);
641
+ updateThemeUI(newTheme);
642
+ });
643
+
644
+ if (window.matchMedia) {
645
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
646
+ if (!localStorage.getItem('tinnybackend-theme')) {
647
+ const newTheme = e.matches ? 'dark' : 'light';
648
+ html.setAttribute('data-theme', newTheme);
649
+ updateThemeUI(newTheme);
650
+ }
651
+ });
652
+ }
653
+
654
+ // ===== DISPLAY REQUESTED PATH =====
655
+ const pathElement = document.getElementById('requested-path');
656
+ const currentPath = window.location.pathname || '/unknown';
657
+ pathElement.textContent = currentPath;
658
+
659
+ // ===== AUTO-REDIRECT AFTER 15 SECONDS =====
660
+ setTimeout(() => {
661
+ window.location.href = '/';
662
+ }, 15000);
663
+
664
+ })();
665
+ </script>
666
+
667
+ </body>
668
+ </html>
@@ -0,0 +1,44 @@
1
+ {
2
+ // Visit https://aka.ms/tsconfig to read more about this file
3
+ "compilerOptions": {
4
+ // File Layout
5
+ "rootDir": "./",
6
+ "outDir": "./dist",
7
+
8
+ // Environment Settings
9
+ // See also https://aka.ms/tsconfig/module
10
+ "module": "nodenext",
11
+ "target": "esnext",
12
+ "types": [],
13
+ // For nodejs:
14
+ // "lib": ["esnext"],
15
+ // "types": ["node"],
16
+ // and npm install -D @types/node
17
+
18
+ // Other Outputs
19
+ "sourceMap": false,
20
+ "declaration": true,
21
+ "declarationMap": true,
22
+
23
+ // Stricter Typechecking Options
24
+ "noUncheckedIndexedAccess": true,
25
+ "exactOptionalPropertyTypes": true,
26
+
27
+ // Style Options
28
+ // "noImplicitReturns": true,
29
+ // "noImplicitOverride": true,
30
+ // "noUnusedLocals": true,
31
+ // "noUnusedParameters": true,
32
+ // "noFallthroughCasesInSwitch": true,
33
+ // "noPropertyAccessFromIndexSignature": true,
34
+
35
+ // Recommended Options
36
+ "strict": true,
37
+ "jsx": "react-jsx",
38
+ "verbatimModuleSyntax": true,
39
+ "isolatedModules": true,
40
+ "noUncheckedSideEffectImports": true,
41
+ "moduleDetection": "force",
42
+ "skipLibCheck": true,
43
+ }
44
+ }