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/dist/cli.js ADDED
@@ -0,0 +1,609 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * 🍝 Tagliatelle CLI
4
+ *
5
+ * Create new Tagliatelle projects with a single command!
6
+ *
7
+ * Usage:
8
+ * npx tagliatelle init my-api
9
+ * npx tagliatelle init my-api --skip-install
10
+ */
11
+ import fs from 'node:fs';
12
+ import path from 'node:path';
13
+ import { execSync } from 'node:child_process';
14
+ import { fileURLToPath } from 'node:url';
15
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
16
+ // ═══════════════════════════════════════════════════════════════════════════
17
+ // 🎨 COLORS
18
+ // ═══════════════════════════════════════════════════════════════════════════
19
+ const c = {
20
+ reset: '\x1b[0m',
21
+ bold: '\x1b[1m',
22
+ dim: '\x1b[2m',
23
+ green: '\x1b[32m',
24
+ yellow: '\x1b[33m',
25
+ blue: '\x1b[34m',
26
+ magenta: '\x1b[35m',
27
+ cyan: '\x1b[36m',
28
+ red: '\x1b[31m',
29
+ };
30
+ // ═══════════════════════════════════════════════════════════════════════════
31
+ // 📦 TEMPLATE FILES
32
+ // ═══════════════════════════════════════════════════════════════════════════
33
+ const templates = {
34
+ 'package.json': `{
35
+ "name": "{{PROJECT_NAME}}",
36
+ "version": "0.1.0",
37
+ "type": "module",
38
+ "scripts": {
39
+ "dev": "tsx watch server.tsx",
40
+ "start": "tsx server.tsx",
41
+ "build": "tsc",
42
+ "serve": "node dist/server.js"
43
+ },
44
+ "dependencies": {
45
+ "tagliatelle": "^1.0.0"
46
+ },
47
+ "devDependencies": {
48
+ "typescript": "^5.3.0",
49
+ "tsx": "^4.6.0",
50
+ "@types/node": "^20.10.0"
51
+ }
52
+ }`,
53
+ 'tsconfig.json': `{
54
+ "compilerOptions": {
55
+ "target": "ES2022",
56
+ "module": "ESNext",
57
+ "moduleResolution": "bundler",
58
+ "lib": ["ES2022"],
59
+ "types": ["node"],
60
+ "outDir": "./dist",
61
+ "strict": true,
62
+ "esModuleInterop": true,
63
+ "skipLibCheck": true,
64
+ "forceConsistentCasingInFileNames": true,
65
+ "declaration": true,
66
+
67
+ "jsx": "react-jsx",
68
+ "jsxImportSource": "tagliatelle"
69
+ },
70
+ "include": ["**/*.ts", "**/*.tsx"],
71
+ "exclude": ["node_modules", "dist"]
72
+ }`,
73
+ 'server.tsx': `/**
74
+ * 🍝 {{PROJECT_NAME}} - Powered by Tagliatelle
75
+ *
76
+ * Start your server:
77
+ * npm run dev - Development with hot reload
78
+ * npm run start - Production mode
79
+ */
80
+
81
+ import path from 'node:path';
82
+ import { fileURLToPath } from 'node:url';
83
+ import { render, Server, Logger, Cors, Routes, DB } from 'tagliatelle';
84
+ import { dbPlugin } from './plugins/db.js';
85
+
86
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
87
+
88
+ const App = () => (
89
+ <Server port={3000}>
90
+ <Logger level="info" />
91
+ <DB provider={dbPlugin}>
92
+ <Cors origin="*">
93
+ <Routes dir={path.join(__dirname, 'routes')} />
94
+ </Cors>
95
+ </DB>
96
+ </Server>
97
+ );
98
+
99
+ render(<App />);
100
+ `,
101
+ 'routes/index.tsx': `/**
102
+ * 🍝 Root Route
103
+ *
104
+ * GET /
105
+ */
106
+
107
+ import { Response, Status, Body } from 'tagliatelle';
108
+ import type { HandlerProps } from 'tagliatelle';
109
+
110
+ export async function GET({ log }: HandlerProps) {
111
+ log.info('API info request');
112
+
113
+ return (
114
+ <Response>
115
+ <Status code={200} />
116
+ <Body data={{
117
+ name: '{{PROJECT_NAME}}',
118
+ version: '0.1.0',
119
+ powered_by: 'Tagliatelle 🍝'
120
+ }} />
121
+ </Response>
122
+ );
123
+ }
124
+ `,
125
+ 'routes/health.tsx': `/**
126
+ * 🍝 Health Check Route
127
+ *
128
+ * GET /health
129
+ */
130
+
131
+ import { Response, Status, Body } from 'tagliatelle';
132
+ import type { HandlerProps } from 'tagliatelle';
133
+
134
+ export async function GET({ log }: HandlerProps) {
135
+ log.info('Health check');
136
+
137
+ return (
138
+ <Response>
139
+ <Status code={200} />
140
+ <Body data={{
141
+ status: 'Al Dente 🍝',
142
+ timestamp: new Date().toISOString()
143
+ }} />
144
+ </Response>
145
+ );
146
+ }
147
+ `,
148
+ 'routes/posts/_config.tsx': `/**
149
+ * 🍝 Posts Routes Config
150
+ *
151
+ * This config applies to all routes in /posts/*
152
+ */
153
+
154
+ import { Logger, RateLimiter } from 'tagliatelle';
155
+
156
+ export default () => (
157
+ <>
158
+ <Logger level="debug" />
159
+ <RateLimiter max={100} timeWindow="1 minute" />
160
+ </>
161
+ );
162
+ `,
163
+ 'routes/posts/_data.ts': `/**
164
+ * 🍝 Posts Data Store
165
+ *
166
+ * In-memory data store for demo purposes.
167
+ * Replace with your actual database!
168
+ */
169
+
170
+ export interface Post {
171
+ id: string;
172
+ title: string;
173
+ content: string;
174
+ author: string;
175
+ createdAt: Date;
176
+ }
177
+
178
+ export const posts: Post[] = [
179
+ {
180
+ id: '1',
181
+ title: 'Welcome to Tagliatelle',
182
+ content: 'The most delicious backend framework ever made.',
183
+ author: 'Chef de Code',
184
+ createdAt: new Date()
185
+ },
186
+ {
187
+ id: '2',
188
+ title: 'File-Based Routing is Here!',
189
+ content: 'Just like Next.js, but for your API. Bellissimo!',
190
+ author: 'The Pasta Architect',
191
+ createdAt: new Date()
192
+ }
193
+ ];
194
+ `,
195
+ 'routes/posts/index.tsx': `/**
196
+ * 🍝 Posts Collection Route
197
+ *
198
+ * GET /posts - List all posts
199
+ * POST /posts - Create a new post
200
+ */
201
+
202
+ import { Response, Status, Body, Err } from 'tagliatelle';
203
+ import type { HandlerProps } from 'tagliatelle';
204
+ import { posts } from './_data.js';
205
+
206
+ interface CreatePostBody {
207
+ title: string;
208
+ content: string;
209
+ author?: string;
210
+ }
211
+
212
+ export async function GET({ log }: HandlerProps) {
213
+ log.info('Fetching all posts');
214
+
215
+ return (
216
+ <Response>
217
+ <Status code={200} />
218
+ <Body data={{
219
+ success: true,
220
+ count: posts.length,
221
+ data: posts
222
+ }} />
223
+ </Response>
224
+ );
225
+ }
226
+
227
+ export async function POST({ body, log }: HandlerProps<unknown, CreatePostBody>) {
228
+ log.info('Creating new post');
229
+
230
+ if (!body.title || !body.content) {
231
+ return (
232
+ <Err
233
+ code={400}
234
+ message="Missing required fields"
235
+ details={{ required: ['title', 'content'] }}
236
+ />
237
+ );
238
+ }
239
+
240
+ const newPost = {
241
+ id: String(posts.length + 1),
242
+ title: body.title,
243
+ content: body.content,
244
+ author: body.author || 'Anonymous',
245
+ createdAt: new Date()
246
+ };
247
+
248
+ posts.push(newPost);
249
+
250
+ return (
251
+ <Response>
252
+ <Status code={201} />
253
+ <Body data={{
254
+ success: true,
255
+ message: 'Post created successfully! 🍝',
256
+ data: newPost
257
+ }} />
258
+ </Response>
259
+ );
260
+ }
261
+ `,
262
+ 'routes/posts/[id].tsx': `/**
263
+ * 🍝 Single Post Route
264
+ *
265
+ * GET /posts/:id - Get a post
266
+ * PUT /posts/:id - Update a post
267
+ * DELETE /posts/:id - Delete a post
268
+ */
269
+
270
+ import { Response, Status, Body, Err } from 'tagliatelle';
271
+ import type { HandlerProps } from 'tagliatelle';
272
+ import { posts } from './_data.js';
273
+
274
+ interface PostParams {
275
+ id: string;
276
+ }
277
+
278
+ interface UpdatePostBody {
279
+ title?: string;
280
+ content?: string;
281
+ author?: string;
282
+ }
283
+
284
+ export async function GET({ params, log }: HandlerProps<PostParams>) {
285
+ log.info(\`Fetching post \${params.id}\`);
286
+
287
+ const post = posts.find(p => p.id === params.id);
288
+
289
+ if (!post) {
290
+ return <Err code={404} message="Post not found" />;
291
+ }
292
+
293
+ return (
294
+ <Response>
295
+ <Status code={200} />
296
+ <Body data={{ success: true, data: post }} />
297
+ </Response>
298
+ );
299
+ }
300
+
301
+ export async function PUT({ params, body, log }: HandlerProps<PostParams, UpdatePostBody>) {
302
+ log.info(\`Updating post \${params.id}\`);
303
+
304
+ const postIndex = posts.findIndex(p => p.id === params.id);
305
+
306
+ if (postIndex === -1) {
307
+ return <Err code={404} message="Post not found" />;
308
+ }
309
+
310
+ posts[postIndex] = { ...posts[postIndex], ...body };
311
+
312
+ return (
313
+ <Response>
314
+ <Status code={200} />
315
+ <Body data={{
316
+ success: true,
317
+ message: 'Post updated!',
318
+ data: posts[postIndex]
319
+ }} />
320
+ </Response>
321
+ );
322
+ }
323
+
324
+ export async function DELETE({ params, log }: HandlerProps<PostParams>) {
325
+ log.info(\`Deleting post \${params.id}\`);
326
+
327
+ const postIndex = posts.findIndex(p => p.id === params.id);
328
+
329
+ if (postIndex === -1) {
330
+ return <Err code={404} message="Post not found" />;
331
+ }
332
+
333
+ const deleted = posts.splice(postIndex, 1)[0];
334
+
335
+ return (
336
+ <Response>
337
+ <Status code={200} />
338
+ <Body data={{
339
+ success: true,
340
+ message: 'Post deleted!',
341
+ data: deleted
342
+ }} />
343
+ </Response>
344
+ );
345
+ }
346
+ `,
347
+ 'plugins/db.ts': `/**
348
+ * 🗄️ Database Plugin
349
+ *
350
+ * Example database provider for Tagliatelle.
351
+ * Replace with your actual database connection (PostgreSQL, MongoDB, etc.)
352
+ */
353
+
354
+ // ═══════════════════════════════════════════════════════════════════════════
355
+ // 📦 TYPES
356
+ // ═══════════════════════════════════════════════════════════════════════════
357
+
358
+ export interface Database {
359
+ query: <T>(sql: string, params?: unknown[]) => Promise<T[]>;
360
+ insert: <T>(table: string, data: Record<string, unknown>) => Promise<T>;
361
+ update: (table: string, id: string, data: Record<string, unknown>) => Promise<boolean>;
362
+ delete: (table: string, id: string) => Promise<boolean>;
363
+ close: () => Promise<void>;
364
+ }
365
+
366
+ // ═══════════════════════════════════════════════════════════════════════════
367
+ // 🍝 DATABASE PROVIDER
368
+ // ═══════════════════════════════════════════════════════════════════════════
369
+
370
+ /**
371
+ * Creates a mock database connection
372
+ * Replace this with your actual database connection logic
373
+ *
374
+ * Examples:
375
+ * - PostgreSQL: pg or postgres
376
+ * - MongoDB: mongoose or mongodb
377
+ * - SQLite: better-sqlite3
378
+ * - Prisma: @prisma/client
379
+ */
380
+ export async function dbPlugin(): Promise<Database> {
381
+ // Simulate connection delay
382
+ await new Promise(resolve => setTimeout(resolve, 50));
383
+
384
+ console.log('🗄️ Database connected');
385
+
386
+ // In-memory storage (replace with real DB)
387
+ const storage: Record<string, Record<string, unknown>[]> = {};
388
+
389
+ return {
390
+ async query<T>(sql: string, _params?: unknown[]): Promise<T[]> {
391
+ console.log(\`🗄️ Query: \${sql}\`);
392
+ const table = sql.match(/FROM\\s+(\\w+)/i)?.[1] || 'default';
393
+ return (storage[table] || []) as T[];
394
+ },
395
+
396
+ async insert<T>(table: string, data: Record<string, unknown>): Promise<T> {
397
+ console.log(\`🗄️ Insert into \${table}:\`, data);
398
+ if (!storage[table]) storage[table] = [];
399
+ const record = { id: String(storage[table].length + 1), ...data };
400
+ storage[table].push(record);
401
+ return record as T;
402
+ },
403
+
404
+ async update(table: string, id: string, data: Record<string, unknown>): Promise<boolean> {
405
+ console.log(\`🗄️ Update \${table}/\${id}:\`, data);
406
+ if (!storage[table]) return false;
407
+ const index = storage[table].findIndex(r => r.id === id);
408
+ if (index === -1) return false;
409
+ storage[table][index] = { ...storage[table][index], ...data };
410
+ return true;
411
+ },
412
+
413
+ async delete(table: string, id: string): Promise<boolean> {
414
+ console.log(\`🗄️ Delete \${table}/\${id}\`);
415
+ if (!storage[table]) return false;
416
+ const index = storage[table].findIndex(r => r.id === id);
417
+ if (index === -1) return false;
418
+ storage[table].splice(index, 1);
419
+ return true;
420
+ },
421
+
422
+ async close(): Promise<void> {
423
+ console.log('🗄️ Database connection closed');
424
+ }
425
+ };
426
+ }
427
+ `,
428
+ '.gitignore': `node_modules/
429
+ dist/
430
+ .env
431
+ .env.local
432
+ *.log
433
+ .DS_Store
434
+ `,
435
+ 'README.md': `# {{PROJECT_NAME}}
436
+
437
+ A delicious API powered by [Tagliatelle](https://github.com/malekabdelkader/Tagliatelle.js) 🍝
438
+
439
+ ## Getting Started
440
+
441
+ \`\`\`bash
442
+ # Development with hot reload
443
+ npm run dev
444
+
445
+ # Production
446
+ npm run start
447
+ \`\`\`
448
+
449
+ ## API Endpoints
450
+
451
+ | Method | Path | Description |
452
+ |--------|------|-------------|
453
+ | GET | \`/\` | API info |
454
+ | GET | \`/health\` | Health check |
455
+ | GET | \`/posts\` | List all posts |
456
+ | POST | \`/posts\` | Create a post |
457
+ | GET | \`/posts/:id\` | Get a post |
458
+ | PUT | \`/posts/:id\` | Update a post |
459
+ | DELETE | \`/posts/:id\` | Delete a post |
460
+
461
+ ## Project Structure
462
+
463
+ \`\`\`
464
+ {{PROJECT_NAME}}/
465
+ ├── server.tsx # Entry point
466
+ ├── plugins/
467
+ │ └── db.ts # Database provider
468
+ ├── routes/
469
+ │ ├── index.tsx # GET /
470
+ │ ├── health.tsx # GET /health
471
+ │ └── posts/
472
+ │ ├── _config.tsx # Route group config
473
+ │ ├── _data.ts # Data store
474
+ │ ├── index.tsx # GET/POST /posts
475
+ │ └── [id].tsx # GET/PUT/DELETE /posts/:id
476
+ ├── package.json
477
+ └── tsconfig.json
478
+ \`\`\`
479
+
480
+ ## Learn More
481
+
482
+ - [Tagliatelle Docs](https://github.com/malekabdelkader/Tagliatelle.js)
483
+ - [File-Based Routing](https://github.com/malekabdelkader/Tagliatelle.js#routing)
484
+ - [JSX Components](https://github.com/malekabdelkader/Tagliatelle.js#components)
485
+ `,
486
+ };
487
+ // ═══════════════════════════════════════════════════════════════════════════
488
+ // 🛠️ HELPERS
489
+ // ═══════════════════════════════════════════════════════════════════════════
490
+ function printBanner() {
491
+ console.log(`
492
+ ${c.yellow} ╔══════════════════════════════════════════════════════════════╗
493
+ ║ ${c.bold}🍝 Tagliatelle${c.reset}${c.yellow} ║
494
+ ║ ${c.dim}The Declarative Backend Framework${c.reset}${c.yellow} ║
495
+ ╚══════════════════════════════════════════════════════════════╝${c.reset}
496
+ `);
497
+ }
498
+ function printHelp() {
499
+ printBanner();
500
+ console.log(`${c.bold}Usage:${c.reset}
501
+ ${c.cyan}npx tagliatelle init${c.reset} <project-name> [options]
502
+
503
+ ${c.bold}Commands:${c.reset}
504
+ ${c.green}init${c.reset} <name> Create a new Tagliatelle project
505
+
506
+ ${c.bold}Options:${c.reset}
507
+ ${c.yellow}--skip-install${c.reset} Skip npm install after scaffolding
508
+ ${c.yellow}--help, -h${c.reset} Show this help message
509
+
510
+ ${c.bold}Examples:${c.reset}
511
+ ${c.dim}# Create a new project${c.reset}
512
+ ${c.cyan}npx tagliatelle init my-api${c.reset}
513
+
514
+ ${c.dim}# Create without installing dependencies${c.reset}
515
+ ${c.cyan}npx tagliatelle init my-api --skip-install${c.reset}
516
+ `);
517
+ }
518
+ function createDir(dir) {
519
+ if (!fs.existsSync(dir)) {
520
+ fs.mkdirSync(dir, { recursive: true });
521
+ }
522
+ }
523
+ function writeFile(filePath, content) {
524
+ const dir = path.dirname(filePath);
525
+ createDir(dir);
526
+ fs.writeFileSync(filePath, content);
527
+ }
528
+ function scaffold(projectName, targetDir) {
529
+ console.log(`\n${c.cyan}Creating project:${c.reset} ${c.bold}${projectName}${c.reset}\n`);
530
+ // Create all files from templates
531
+ for (const [relativePath, template] of Object.entries(templates)) {
532
+ const content = template.replace(/\{\{PROJECT_NAME\}\}/g, projectName);
533
+ const filePath = path.join(targetDir, relativePath);
534
+ writeFile(filePath, content);
535
+ console.log(` ${c.green}✓${c.reset} ${relativePath}`);
536
+ }
537
+ }
538
+ function runNpmInstall(targetDir) {
539
+ console.log(`\n${c.cyan}Installing dependencies...${c.reset}\n`);
540
+ try {
541
+ execSync('npm install', { cwd: targetDir, stdio: 'inherit' });
542
+ return true;
543
+ }
544
+ catch {
545
+ console.log(`\n${c.yellow}⚠${c.reset} Failed to install dependencies. Run ${c.cyan}npm install${c.reset} manually.\n`);
546
+ return false;
547
+ }
548
+ }
549
+ function printSuccess(projectName, skipInstall) {
550
+ console.log(`
551
+ ${c.green}✓ Project created successfully!${c.reset}
552
+
553
+ ${c.bold}Next steps:${c.reset}
554
+
555
+ ${c.cyan}cd${c.reset} ${projectName}${skipInstall ? `
556
+ ${c.cyan}npm install${c.reset}` : ''}
557
+ ${c.cyan}npm run dev${c.reset}
558
+
559
+ ${c.dim}Your API will be running at ${c.cyan}http://localhost:3000${c.reset}
560
+
561
+ ${c.yellow}🍝 Buon appetito!${c.reset}
562
+ `);
563
+ }
564
+ // ═══════════════════════════════════════════════════════════════════════════
565
+ // 🚀 MAIN
566
+ // ═══════════════════════════════════════════════════════════════════════════
567
+ function main() {
568
+ const args = process.argv.slice(2);
569
+ // Handle help
570
+ if (args.includes('--help') || args.includes('-h') || args.length === 0) {
571
+ printHelp();
572
+ process.exit(0);
573
+ }
574
+ const command = args[0];
575
+ if (command !== 'init') {
576
+ console.log(`${c.red}Unknown command:${c.reset} ${command}\n`);
577
+ printHelp();
578
+ process.exit(1);
579
+ }
580
+ const projectName = args[1];
581
+ if (!projectName) {
582
+ console.log(`${c.red}Error:${c.reset} Please provide a project name\n`);
583
+ console.log(` ${c.cyan}npx tagliatelle init my-api${c.reset}\n`);
584
+ process.exit(1);
585
+ }
586
+ // Validate project name
587
+ if (!/^[a-zA-Z0-9-_]+$/.test(projectName)) {
588
+ console.log(`${c.red}Error:${c.reset} Invalid project name. Use only letters, numbers, dashes, and underscores.\n`);
589
+ process.exit(1);
590
+ }
591
+ const skipInstall = args.includes('--skip-install');
592
+ const targetDir = path.resolve(process.cwd(), projectName);
593
+ // Check if directory exists
594
+ if (fs.existsSync(targetDir)) {
595
+ console.log(`${c.red}Error:${c.reset} Directory ${c.bold}${projectName}${c.reset} already exists.\n`);
596
+ process.exit(1);
597
+ }
598
+ printBanner();
599
+ // Scaffold project
600
+ scaffold(projectName, targetDir);
601
+ // Install dependencies
602
+ if (!skipInstall) {
603
+ runNpmInstall(targetDir);
604
+ }
605
+ // Success message
606
+ printSuccess(projectName, skipInstall);
607
+ }
608
+ main();
609
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 🍝 <Tag>liatelle.js - Main Export
3
+ *
4
+ * The Declarative Backend Framework
5
+ */
6
+ export { h, Fragment, render, Context, Server, Get, Post, Put, Delete, Patch, Middleware, DB, Logger, Group, Cors, RateLimiter, Routes, Response, Status, Body, Headers, Err, Augment, Halt, COMPONENT_TYPES, } from './tagliatelle.js';
7
+ export type { TagliatelleElement, TagliatelleNode, TagliatelleComponent, ComponentType, Handler, HandlerProps, MiddlewareFunction, MiddlewareResult, ServerProps, RouteProps, MiddlewareProps, DBProps, LoggerProps, GroupProps, CorsProps, RateLimiterProps, RoutesProps, ResponseProps, StatusProps, BodyProps, HeadersProps, ErrProps, AugmentProps, HaltProps, } from './types.js';
8
+ export type { ParsedConfig, RouteModule, HTTPMethod } from './router.js';
9
+ export { sanitizeErrorMessage, safeErrorResponse, safeMerge, isNonEmptyString, isSafeString, isPositiveInt, isValidId, sanitizeForLog, withTimeout, AuthFailureTracker, authFailureTracker, } from './security.js';
10
+ export { default } from './tagliatelle.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAEL,CAAC,EACD,QAAQ,EAGR,MAAM,EACN,OAAO,EAGP,MAAM,EACN,GAAG,EACH,IAAI,EACJ,GAAG,EACH,MAAM,EACN,KAAK,EACL,UAAU,EACV,EAAE,EACF,MAAM,EACN,KAAK,EACL,IAAI,EACJ,WAAW,EACX,MAAM,EAGN,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,OAAO,EACP,GAAG,EAGH,OAAO,EACP,IAAI,EAGJ,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,OAAO,EACP,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,eAAe,EACf,OAAO,EACP,WAAW,EACX,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,WAAW,EACX,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,SAAS,GACV,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzE,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,SAAS,EACT,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * 🍝 <Tag>liatelle.js - Main Export
3
+ *
4
+ * The Declarative Backend Framework
5
+ */
6
+ export {
7
+ // JSX Factory
8
+ h, Fragment,
9
+ // Core
10
+ render, Context,
11
+ // Server Components
12
+ Server, Get, Post, Put, Delete, Patch, Middleware, DB, Logger, Group, Cors, RateLimiter, Routes,
13
+ // Response Components
14
+ Response, Status, Body, Headers, Err,
15
+ // Middleware Components
16
+ Augment, Halt,
17
+ // Types
18
+ COMPONENT_TYPES, } from './tagliatelle.js';
19
+ // Security exports
20
+ export { sanitizeErrorMessage, safeErrorResponse, safeMerge, isNonEmptyString, isSafeString, isPositiveInt, isValidId, sanitizeForLog, withTimeout, AuthFailureTracker, authFailureTracker, } from './security.js';
21
+ // Default export
22
+ export { default } from './tagliatelle.js';
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO;AACL,cAAc;AACd,CAAC,EACD,QAAQ;AAER,OAAO;AACP,MAAM,EACN,OAAO;AAEP,oBAAoB;AACpB,MAAM,EACN,GAAG,EACH,IAAI,EACJ,GAAG,EACH,MAAM,EACN,KAAK,EACL,UAAU,EACV,EAAE,EACF,MAAM,EACN,KAAK,EACL,IAAI,EACJ,WAAW,EACX,MAAM;AAEN,sBAAsB;AACtB,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,OAAO,EACP,GAAG;AAEH,wBAAwB;AACxB,OAAO,EACP,IAAI;AAEJ,QAAQ;AACR,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAgC1B,mBAAmB;AACnB,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,SAAS,EACT,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAEvB,iBAAiB;AACjB,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * 🍝 JSX Runtime for <Tag>liatelle.js
3
+ *
4
+ * This provides the modern JSX transform runtime (React 17+ style).
5
+ * TypeScript/esbuild/tsx will automatically import from here when using:
6
+ * { "jsx": "react-jsx", "jsxImportSource": "tagliatelle" }
7
+ */
8
+ import type { TagliatelleElement, TagliatelleNode } from './types.js';
9
+ /**
10
+ * Fragment component - groups children without a wrapper
11
+ */
12
+ export declare const Fragment: unique symbol;
13
+ /**
14
+ * JSX runtime function for production
15
+ * Called for elements with a single child or no children
16
+ */
17
+ export declare function jsx(type: string | Function | symbol, props: Record<string, unknown> & {
18
+ children?: TagliatelleNode;
19
+ }, _key?: string): TagliatelleElement;
20
+ /**
21
+ * JSX runtime function for elements with multiple static children
22
+ * Same as jsx but called when there are multiple children
23
+ */
24
+ export declare function jsxs(type: string | Function | symbol, props: Record<string, unknown> & {
25
+ children?: TagliatelleNode[];
26
+ }, _key?: string): TagliatelleElement;
27
+ /**
28
+ * JSX dev runtime function (same as jsx for our purposes)
29
+ */
30
+ export declare const jsxDEV: typeof jsx;
31
+ //# sourceMappingURL=jsx-runtime.d.ts.map