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.
@@ -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"}
@@ -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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"}