tagliatelle 1.0.0-beta.1
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/README.md +488 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +609 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-runtime.d.ts +31 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +46 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/router.d.ts +59 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +487 -0
- package/dist/router.js.map +1 -0
- package/dist/security.d.ts +84 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +233 -0
- package/dist/security.js.map +1 -0
- package/dist/tagliatelle.d.ts +90 -0
- package/dist/tagliatelle.d.ts.map +1 -0
- package/dist/tagliatelle.js +684 -0
- package/dist/tagliatelle.js.map +1 -0
- package/dist/types.d.ts +144 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +32 -0
- package/dist/types.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🔒 <Tag>liatelle.js - Security Utilities
|
|
3
|
+
*
|
|
4
|
+
* Additional security on top of Fastify's built-in protections:
|
|
5
|
+
* - Error message sanitization (no stack trace leakage)
|
|
6
|
+
* - Input validation helpers
|
|
7
|
+
* - Middleware timeout wrapper
|
|
8
|
+
* - Auth failure rate limiting
|
|
9
|
+
*
|
|
10
|
+
* Note: Fastify handles prototype pollution at JSON parse level
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Sanitizes an error message for safe external exposure
|
|
14
|
+
* Removes stack traces, sensitive data, and internal paths
|
|
15
|
+
*/
|
|
16
|
+
export declare function sanitizeErrorMessage(error: unknown, fallback?: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Creates a safe error response object
|
|
19
|
+
*/
|
|
20
|
+
export declare function safeErrorResponse(error: unknown, isDevelopment?: boolean): {
|
|
21
|
+
error: string;
|
|
22
|
+
details?: unknown;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Safely merges source into target
|
|
26
|
+
* Note: Fastify already handles prototype pollution at JSON parse level
|
|
27
|
+
*/
|
|
28
|
+
export declare function safeMerge<T extends object>(target: T, source: unknown): T;
|
|
29
|
+
/**
|
|
30
|
+
* Validates that a value is a non-empty string
|
|
31
|
+
*/
|
|
32
|
+
export declare function isNonEmptyString(value: unknown): value is string;
|
|
33
|
+
/**
|
|
34
|
+
* Validates that a value is a safe string (no null bytes, control chars)
|
|
35
|
+
*/
|
|
36
|
+
export declare function isSafeString(value: unknown): value is string;
|
|
37
|
+
/**
|
|
38
|
+
* Validates that a value is a positive integer
|
|
39
|
+
*/
|
|
40
|
+
export declare function isPositiveInt(value: unknown): value is number;
|
|
41
|
+
/**
|
|
42
|
+
* Validates an ID string (alphanumeric, dashes, underscores)
|
|
43
|
+
*/
|
|
44
|
+
export declare function isValidId(value: unknown): value is string;
|
|
45
|
+
/**
|
|
46
|
+
* Sanitizes a string for safe logging (prevents log injection)
|
|
47
|
+
*/
|
|
48
|
+
export declare function sanitizeForLog(value: string, maxLength?: number): string;
|
|
49
|
+
/**
|
|
50
|
+
* Wraps an async function with a timeout
|
|
51
|
+
*/
|
|
52
|
+
export declare function withTimeout<T>(fn: () => Promise<T>, timeoutMs: number, timeoutError?: string): Promise<T>;
|
|
53
|
+
/**
|
|
54
|
+
* Tracks authentication failures per IP to prevent brute force attacks
|
|
55
|
+
*/
|
|
56
|
+
export declare class AuthFailureTracker {
|
|
57
|
+
private failures;
|
|
58
|
+
private readonly maxFailures;
|
|
59
|
+
private readonly windowMs;
|
|
60
|
+
private readonly blockDurationMs;
|
|
61
|
+
constructor(options?: {
|
|
62
|
+
maxFailures?: number;
|
|
63
|
+
windowMs?: number;
|
|
64
|
+
blockDurationMs?: number;
|
|
65
|
+
});
|
|
66
|
+
/**
|
|
67
|
+
* Records an auth failure. Returns true if IP should be blocked.
|
|
68
|
+
*/
|
|
69
|
+
recordFailure(ip: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Checks if an IP is currently blocked
|
|
72
|
+
*/
|
|
73
|
+
isBlocked(ip: string): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Clears failures for an IP (on successful auth)
|
|
76
|
+
*/
|
|
77
|
+
clearFailures(ip: string): void;
|
|
78
|
+
/**
|
|
79
|
+
* Cleanup expired records
|
|
80
|
+
*/
|
|
81
|
+
cleanup(): void;
|
|
82
|
+
}
|
|
83
|
+
export declare const authFailureTracker: AuthFailureTracker;
|
|
84
|
+
//# sourceMappingURL=security.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAwBH;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,SAAsB,GAAG,MAAM,CAgC3F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,aAAa,UAAQ,GACpB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CActC;AAMD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,GAAG,CAAC,CAQzE;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEhE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAM5D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAE7D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAGzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAM,GAAG,MAAM,CAKrE;AAMD;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC3B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,SAAS,EAAE,MAAM,EACjB,YAAY,SAAwB,GACnC,OAAO,CAAC,CAAC,CAAC,CAgBZ;AAMD;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAA8D;IAC9E,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAE7B,OAAO,GAAE;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,eAAe,CAAC,EAAE,MAAM,CAAC;KACrB;IAMN;;OAEG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAmBlC;;OAEG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAc9B;;OAEG;IACH,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,OAAO,IAAI,IAAI;CAUhB;AAGD,eAAO,MAAM,kBAAkB,oBAA2B,CAAC"}
|
package/dist/security.js
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🔒 <Tag>liatelle.js - Security Utilities
|
|
3
|
+
*
|
|
4
|
+
* Additional security on top of Fastify's built-in protections:
|
|
5
|
+
* - Error message sanitization (no stack trace leakage)
|
|
6
|
+
* - Input validation helpers
|
|
7
|
+
* - Middleware timeout wrapper
|
|
8
|
+
* - Auth failure rate limiting
|
|
9
|
+
*
|
|
10
|
+
* Note: Fastify handles prototype pollution at JSON parse level
|
|
11
|
+
*/
|
|
12
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
13
|
+
// 🛡️ ERROR SANITIZATION
|
|
14
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
15
|
+
/**
|
|
16
|
+
* Sensitive patterns that should never appear in error messages
|
|
17
|
+
*/
|
|
18
|
+
const SENSITIVE_PATTERNS = [
|
|
19
|
+
/password/i,
|
|
20
|
+
/secret/i,
|
|
21
|
+
/token/i,
|
|
22
|
+
/api[_-]?key/i,
|
|
23
|
+
/authorization/i,
|
|
24
|
+
/credential/i,
|
|
25
|
+
/private/i,
|
|
26
|
+
/\.env/i,
|
|
27
|
+
/database/i,
|
|
28
|
+
/connection/i,
|
|
29
|
+
/node_modules/i,
|
|
30
|
+
/at\s+\w+\s+\(/i, // Stack trace patterns
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* Sanitizes an error message for safe external exposure
|
|
34
|
+
* Removes stack traces, sensitive data, and internal paths
|
|
35
|
+
*/
|
|
36
|
+
export function sanitizeErrorMessage(error, fallback = 'An error occurred') {
|
|
37
|
+
if (!error)
|
|
38
|
+
return fallback;
|
|
39
|
+
let message;
|
|
40
|
+
if (error instanceof Error) {
|
|
41
|
+
message = error.message;
|
|
42
|
+
}
|
|
43
|
+
else if (typeof error === 'string') {
|
|
44
|
+
message = error;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
return fallback;
|
|
48
|
+
}
|
|
49
|
+
// Remove stack traces (take first line only)
|
|
50
|
+
message = message.split('\n')[0];
|
|
51
|
+
// Check for sensitive patterns
|
|
52
|
+
for (const pattern of SENSITIVE_PATTERNS) {
|
|
53
|
+
if (pattern.test(message)) {
|
|
54
|
+
return fallback;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Remove file paths
|
|
58
|
+
message = message.replace(/\/[\w/.-]+\.(js|ts|tsx|jsx)/g, '[path]');
|
|
59
|
+
// Limit length
|
|
60
|
+
if (message.length > 200) {
|
|
61
|
+
message = message.slice(0, 200) + '...';
|
|
62
|
+
}
|
|
63
|
+
return message || fallback;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Creates a safe error response object
|
|
67
|
+
*/
|
|
68
|
+
export function safeErrorResponse(error, isDevelopment = false) {
|
|
69
|
+
const response = {
|
|
70
|
+
error: sanitizeErrorMessage(error, 'Internal server error'),
|
|
71
|
+
};
|
|
72
|
+
// Only include stack in development
|
|
73
|
+
if (isDevelopment && error instanceof Error) {
|
|
74
|
+
response.details = {
|
|
75
|
+
message: error.message,
|
|
76
|
+
stack: error.stack?.replace(/\(\/[^)]+\)/g, '([path])'),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return response;
|
|
80
|
+
}
|
|
81
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
82
|
+
// 🛡️ SAFE OBJECT MERGE
|
|
83
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
84
|
+
/**
|
|
85
|
+
* Safely merges source into target
|
|
86
|
+
* Note: Fastify already handles prototype pollution at JSON parse level
|
|
87
|
+
*/
|
|
88
|
+
export function safeMerge(target, source) {
|
|
89
|
+
if (!source || typeof source !== 'object' || Array.isArray(source)) {
|
|
90
|
+
return target;
|
|
91
|
+
}
|
|
92
|
+
// Use Object.assign - Fastify has already sanitized the input
|
|
93
|
+
Object.assign(target, source);
|
|
94
|
+
return target;
|
|
95
|
+
}
|
|
96
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
97
|
+
// 🛡️ INPUT VALIDATION
|
|
98
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
99
|
+
/**
|
|
100
|
+
* Validates that a value is a non-empty string
|
|
101
|
+
*/
|
|
102
|
+
export function isNonEmptyString(value) {
|
|
103
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Validates that a value is a safe string (no null bytes, control chars)
|
|
107
|
+
*/
|
|
108
|
+
export function isSafeString(value) {
|
|
109
|
+
if (typeof value !== 'string')
|
|
110
|
+
return false;
|
|
111
|
+
if (value.includes('\0'))
|
|
112
|
+
return false;
|
|
113
|
+
// eslint-disable-next-line no-control-regex
|
|
114
|
+
if (/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/.test(value))
|
|
115
|
+
return false;
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Validates that a value is a positive integer
|
|
120
|
+
*/
|
|
121
|
+
export function isPositiveInt(value) {
|
|
122
|
+
return typeof value === 'number' && Number.isInteger(value) && value > 0;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Validates an ID string (alphanumeric, dashes, underscores)
|
|
126
|
+
*/
|
|
127
|
+
export function isValidId(value) {
|
|
128
|
+
if (typeof value !== 'string')
|
|
129
|
+
return false;
|
|
130
|
+
return /^[a-zA-Z0-9_-]{1,128}$/.test(value);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Sanitizes a string for safe logging (prevents log injection)
|
|
134
|
+
*/
|
|
135
|
+
export function sanitizeForLog(value, maxLength = 100) {
|
|
136
|
+
return value
|
|
137
|
+
.replace(/[\r\n]/g, ' ')
|
|
138
|
+
.replace(/[\x00-\x1F\x7F]/g, '')
|
|
139
|
+
.slice(0, maxLength);
|
|
140
|
+
}
|
|
141
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
142
|
+
// 🛡️ MIDDLEWARE TIMEOUT
|
|
143
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
144
|
+
/**
|
|
145
|
+
* Wraps an async function with a timeout
|
|
146
|
+
*/
|
|
147
|
+
export function withTimeout(fn, timeoutMs, timeoutError = 'Operation timed out') {
|
|
148
|
+
return new Promise((resolve, reject) => {
|
|
149
|
+
const timer = setTimeout(() => {
|
|
150
|
+
reject(new Error(timeoutError));
|
|
151
|
+
}, timeoutMs);
|
|
152
|
+
fn()
|
|
153
|
+
.then((result) => {
|
|
154
|
+
clearTimeout(timer);
|
|
155
|
+
resolve(result);
|
|
156
|
+
})
|
|
157
|
+
.catch((error) => {
|
|
158
|
+
clearTimeout(timer);
|
|
159
|
+
reject(error);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
164
|
+
// 🛡️ AUTH FAILURE RATE LIMITING
|
|
165
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
166
|
+
/**
|
|
167
|
+
* Tracks authentication failures per IP to prevent brute force attacks
|
|
168
|
+
*/
|
|
169
|
+
export class AuthFailureTracker {
|
|
170
|
+
failures = new Map();
|
|
171
|
+
maxFailures;
|
|
172
|
+
windowMs;
|
|
173
|
+
blockDurationMs;
|
|
174
|
+
constructor(options = {}) {
|
|
175
|
+
this.maxFailures = options.maxFailures ?? 5;
|
|
176
|
+
this.windowMs = options.windowMs ?? 15 * 60 * 1000; // 15 min
|
|
177
|
+
this.blockDurationMs = options.blockDurationMs ?? 60 * 60 * 1000; // 1 hour
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Records an auth failure. Returns true if IP should be blocked.
|
|
181
|
+
*/
|
|
182
|
+
recordFailure(ip) {
|
|
183
|
+
const now = Date.now();
|
|
184
|
+
const record = this.failures.get(ip);
|
|
185
|
+
if (!record || now - record.firstFailure > this.windowMs) {
|
|
186
|
+
this.failures.set(ip, { count: 1, firstFailure: now });
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
record.count++;
|
|
190
|
+
if (record.count >= this.maxFailures) {
|
|
191
|
+
record.firstFailure = now - this.windowMs + this.blockDurationMs;
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Checks if an IP is currently blocked
|
|
198
|
+
*/
|
|
199
|
+
isBlocked(ip) {
|
|
200
|
+
const record = this.failures.get(ip);
|
|
201
|
+
if (!record)
|
|
202
|
+
return false;
|
|
203
|
+
const now = Date.now();
|
|
204
|
+
if (now - record.firstFailure > this.windowMs + this.blockDurationMs) {
|
|
205
|
+
this.failures.delete(ip);
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
return record.count >= this.maxFailures;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Clears failures for an IP (on successful auth)
|
|
212
|
+
*/
|
|
213
|
+
clearFailures(ip) {
|
|
214
|
+
this.failures.delete(ip);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Cleanup expired records
|
|
218
|
+
*/
|
|
219
|
+
cleanup() {
|
|
220
|
+
const now = Date.now();
|
|
221
|
+
const maxAge = this.windowMs + this.blockDurationMs;
|
|
222
|
+
for (const [ip, record] of this.failures) {
|
|
223
|
+
if (now - record.firstFailure > maxAge) {
|
|
224
|
+
this.failures.delete(ip);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Global auth failure tracker instance
|
|
230
|
+
export const authFailureTracker = new AuthFailureTracker();
|
|
231
|
+
// Auto-cleanup every 10 minutes
|
|
232
|
+
setInterval(() => authFailureTracker.cleanup(), 10 * 60 * 1000);
|
|
233
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.js","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🍝 <Tag>liatelle.js - The Declarative Backend Framework
|
|
3
|
+
*
|
|
4
|
+
* This is the secret sauce that makes JSX work for backend routing.
|
|
5
|
+
* It transforms your beautiful component tree into a blazing-fast Fastify server.
|
|
6
|
+
*/
|
|
7
|
+
import { FastifyInstance } from 'fastify';
|
|
8
|
+
import { TagliatelleElement, TagliatelleNode, TagliatelleComponent, ServerProps, RouteProps, MiddlewareProps, DBProps, LoggerProps, GroupProps, CorsProps, RateLimiterProps, RoutesProps, ResponseProps, StatusProps, BodyProps, HeadersProps, ErrProps } from './types.js';
|
|
9
|
+
export * from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* JSX factory function - creates virtual elements from JSX
|
|
12
|
+
* This is called by TypeScript when it transforms JSX
|
|
13
|
+
*/
|
|
14
|
+
export declare function h(type: string | Function, props: Record<string, unknown> | null, ...children: TagliatelleNode[]): TagliatelleElement;
|
|
15
|
+
/**
|
|
16
|
+
* Fragment support for grouping elements without a wrapper
|
|
17
|
+
*/
|
|
18
|
+
export declare function Fragment({ children }: {
|
|
19
|
+
children?: TagliatelleNode[];
|
|
20
|
+
}): TagliatelleNode[];
|
|
21
|
+
export declare class Context {
|
|
22
|
+
private values;
|
|
23
|
+
set<T>(key: string, value: T): void;
|
|
24
|
+
get<T>(key: string): T | undefined;
|
|
25
|
+
clone(): Context;
|
|
26
|
+
}
|
|
27
|
+
export declare function Server({ port, host, children }: ServerProps): TagliatelleComponent;
|
|
28
|
+
export declare function Get<TParams, TBody, TQuery, TResponse>(props: RouteProps<TParams, TBody, TQuery, TResponse>): TagliatelleComponent;
|
|
29
|
+
export declare function Post<TParams, TBody, TQuery, TResponse>(props: RouteProps<TParams, TBody, TQuery, TResponse>): TagliatelleComponent;
|
|
30
|
+
export declare function Put<TParams, TBody, TQuery, TResponse>(props: RouteProps<TParams, TBody, TQuery, TResponse>): TagliatelleComponent;
|
|
31
|
+
export declare function Delete<TParams, TBody, TQuery, TResponse>(props: RouteProps<TParams, TBody, TQuery, TResponse>): TagliatelleComponent;
|
|
32
|
+
export declare function Patch<TParams, TBody, TQuery, TResponse>(props: RouteProps<TParams, TBody, TQuery, TResponse>): TagliatelleComponent;
|
|
33
|
+
export declare function Middleware({ use, children }: MiddlewareProps): TagliatelleComponent;
|
|
34
|
+
export declare function DB({ provider, children }: DBProps): TagliatelleComponent;
|
|
35
|
+
export declare function Logger({ level }: LoggerProps): TagliatelleComponent;
|
|
36
|
+
export declare function Group({ prefix, children }: GroupProps): TagliatelleComponent;
|
|
37
|
+
export declare function Cors({ origin, methods, children }: CorsProps): TagliatelleComponent;
|
|
38
|
+
export declare function RateLimiter({ max, timeWindow, children }: RateLimiterProps): TagliatelleComponent;
|
|
39
|
+
/**
|
|
40
|
+
* File-based routing - Next.js style!
|
|
41
|
+
* Usage: <Routes dir="./routes" prefix="/api" />
|
|
42
|
+
*/
|
|
43
|
+
export declare function Routes({ dir, prefix }: RoutesProps): TagliatelleComponent;
|
|
44
|
+
/**
|
|
45
|
+
* Response wrapper - contains status, headers, and body
|
|
46
|
+
* Usage: <Response><Status code={201} /><Body data={{...}} /></Response>
|
|
47
|
+
*/
|
|
48
|
+
export declare function Response({ children }: ResponseProps): TagliatelleComponent;
|
|
49
|
+
/**
|
|
50
|
+
* Set HTTP status code
|
|
51
|
+
* Usage: <Status code={201} />
|
|
52
|
+
*/
|
|
53
|
+
export declare function Status({ code }: StatusProps): TagliatelleComponent;
|
|
54
|
+
/**
|
|
55
|
+
* Set response body (JSON)
|
|
56
|
+
* Usage: <Body data={{ success: true, data: [...] }} />
|
|
57
|
+
*/
|
|
58
|
+
export declare function Body<T>({ data }: BodyProps<T>): TagliatelleComponent;
|
|
59
|
+
/**
|
|
60
|
+
* Set response headers
|
|
61
|
+
* Usage: <Headers headers={{ 'X-Custom': 'value' }} />
|
|
62
|
+
*/
|
|
63
|
+
export declare function Headers({ headers }: HeadersProps): TagliatelleComponent;
|
|
64
|
+
/**
|
|
65
|
+
* Return an error response
|
|
66
|
+
* Usage: <Err code={404} message="Not found" />
|
|
67
|
+
*/
|
|
68
|
+
export declare function Err({ code, message, details }: ErrProps): TagliatelleComponent;
|
|
69
|
+
import type { AugmentProps, HaltProps } from './types.js';
|
|
70
|
+
/**
|
|
71
|
+
* Augment handler props with additional data (e.g., user from auth)
|
|
72
|
+
* Usage: <Augment user={{ id: 1, name: "John" }} />
|
|
73
|
+
*/
|
|
74
|
+
export declare function Augment(props: AugmentProps): TagliatelleComponent;
|
|
75
|
+
/**
|
|
76
|
+
* Halt the middleware chain (optionally with error)
|
|
77
|
+
* Usage: <Halt /> or <Halt code={401} message="Unauthorized" />
|
|
78
|
+
*/
|
|
79
|
+
export declare function Halt({ code, message }: HaltProps): TagliatelleComponent;
|
|
80
|
+
/**
|
|
81
|
+
* The main render function - turns your JSX tree into a running server
|
|
82
|
+
*/
|
|
83
|
+
export declare function render(element: TagliatelleNode): Promise<FastifyInstance>;
|
|
84
|
+
declare const Tagliatelle: {
|
|
85
|
+
h: typeof h;
|
|
86
|
+
Fragment: typeof Fragment;
|
|
87
|
+
render: typeof render;
|
|
88
|
+
};
|
|
89
|
+
export default Tagliatelle;
|
|
90
|
+
//# sourceMappingURL=tagliatelle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tagliatelle.d.ts","sourceRoot":"","sources":["../src/tagliatelle.ts"],"names":[],"mappings":"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"}
|