@flight-framework/cli 0.0.16 → 0.2.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 Flight Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -123,6 +123,76 @@ flight create my-app --ui solid --features forms,auth,i18n
123
123
  | `--no-git` | Skip git initialization |
124
124
  | `--install` | Install dependencies (default: true) |
125
125
  | `--no-install` | Skip dependency installation |
126
+ | `--raw` | Create raw project (100% Web Standards, zero dependencies) |
127
+ | `--empty` | Create empty project (just package.json) |
128
+ | `--minimal` | Create minimal project (single server file) |
129
+
130
+ ### Toolbox Mode (Zero Lock-in)
131
+
132
+ Start with the minimum and add what you need:
133
+
134
+ ```bash
135
+ # Raw project - 100% Web Standards, ZERO dependencies
136
+ # Works on Bun, Deno, Node 22+, Cloudflare Workers
137
+ flight create my-app --raw
138
+
139
+ # Empty project - just package.json
140
+ flight create my-app --empty
141
+
142
+ # Minimal project - single server file with Flight
143
+ flight create my-app --minimal
144
+
145
+ # Then add packages as needed
146
+ cd my-app
147
+ flight add http
148
+ flight add db
149
+ flight add cache
150
+ ```
151
+
152
+ The `--raw` mode generates code with **zero Flight dependencies**. You can run it on any runtime and add Flight packages later if you want.
153
+
154
+ ---
155
+
156
+ ## Adding Packages
157
+
158
+ Add Flight packages to an existing project:
159
+
160
+ ```bash
161
+ flight add [package]
162
+ ```
163
+
164
+ ### Available Packages
165
+
166
+ | Package | Description |
167
+ |---------|-------------|
168
+ | `http` | HTTP server with routing and middleware |
169
+ | `core` | File-based routing and configuration |
170
+ | `db` | Database abstraction layer |
171
+ | `cache` | Caching with multiple adapters |
172
+ | `auth` | Authentication adapters |
173
+ | `forms` | Type-safe form handling |
174
+ | `i18n` | Internationalization |
175
+ | `seo` | SEO utilities |
176
+ | `image` | Image optimization |
177
+ | `email` | Email sending |
178
+ | `realtime` | WebSocket and real-time features |
179
+ | `helpers` | Optional helper utilities |
180
+
181
+ ### Examples
182
+
183
+ ```bash
184
+ # Add HTTP server
185
+ flight add http
186
+
187
+ # Add database support
188
+ flight add db
189
+
190
+ # Add authentication
191
+ flight add auth
192
+
193
+ # See all packages
194
+ flight add
195
+ ```
126
196
 
127
197
  ---
128
198
 
package/dist/bin.js CHANGED
@@ -8,7 +8,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
8
8
 
9
9
  // src/index.ts
10
10
  import { cac } from "cac";
11
- import pc5 from "picocolors";
11
+ import pc6 from "picocolors";
12
12
 
13
13
  // src/version.ts
14
14
  var VERSION = "0.0.1";
@@ -61,6 +61,21 @@ async function createCommand(name, options) {
61
61
  console.log(pc.red("Project creation cancelled."));
62
62
  return;
63
63
  }
64
+ if (options.raw) {
65
+ const projectPath2 = resolve(process.cwd(), projectName);
66
+ createRawProject(projectPath2, projectName, options);
67
+ return;
68
+ }
69
+ if (options.empty) {
70
+ const projectPath2 = resolve(process.cwd(), projectName);
71
+ createEmptyProject(projectPath2, projectName, options);
72
+ return;
73
+ }
74
+ if (options.minimal) {
75
+ const projectPath2 = resolve(process.cwd(), projectName);
76
+ createMinimalProject(projectPath2, projectName, options);
77
+ return;
78
+ }
64
79
  if (!uiFramework) {
65
80
  const response = await prompts({
66
81
  type: "select",
@@ -75,6 +90,9 @@ async function createCommand(name, options) {
75
90
  console.log(pc.red("Project creation cancelled."));
76
91
  return;
77
92
  }
93
+ let useCase = options.useCase;
94
+ const useCaseDir = join(TEMPLATES_DIR, "use-cases", useCase || "");
95
+ const isUseCase = useCase && existsSync(useCaseDir);
78
96
  let bundler = options.bundler;
79
97
  if (!bundler) {
80
98
  const response = await prompts({
@@ -110,8 +128,12 @@ async function createCommand(name, options) {
110
128
  Creating project in ${projectPath}...
111
129
  `));
112
130
  try {
113
- copyTemplate(projectPath, uiFramework, bundler, projectName);
114
- console.log(pc.green("\u2713") + " Project structure created");
131
+ if (isUseCase && useCase) {
132
+ copyUseCaseTemplate(projectPath, useCase, projectName);
133
+ } else {
134
+ copyTemplate(projectPath, uiFramework, bundler, projectName);
135
+ }
136
+ console.log(pc.green("[OK]") + " Project structure created");
115
137
  if (options.git) {
116
138
  try {
117
139
  execSync("git init", { cwd: projectPath, stdio: "ignore" });
@@ -179,6 +201,15 @@ function copyTemplate(projectPath, ui, bundler, projectName) {
179
201
  unlinkSync(gitignoreSrc);
180
202
  }
181
203
  }
204
+ function copyUseCaseTemplate(projectPath, useCase, projectName) {
205
+ const useCaseDir = join(TEMPLATES_DIR, "use-cases", useCase);
206
+ mkdirSync(projectPath, { recursive: true });
207
+ const vars = {
208
+ "{{PROJECT_NAME}}": projectName,
209
+ "{{USE_CASE}}": useCase
210
+ };
211
+ copyDirWithTemplates(useCaseDir, projectPath, vars);
212
+ }
182
213
  function copyDirWithTemplates(srcDir, destDir, vars) {
183
214
  if (!existsSync(srcDir)) return;
184
215
  const entries = readdirSync(srcDir, { withFileTypes: true });
@@ -205,6 +236,277 @@ function copyDirWithTemplates(srcDir, destDir, vars) {
205
236
  }
206
237
  }
207
238
  }
239
+ function createRawProject(projectPath, projectName, options) {
240
+ mkdirSync(projectPath, { recursive: true });
241
+ const packageJson = {
242
+ name: projectName,
243
+ version: "0.0.1",
244
+ type: "module",
245
+ scripts: {
246
+ // Works with Bun, Node 22+, or Deno
247
+ "dev": "node --watch server.js",
248
+ "dev:bun": "bun --watch server.js",
249
+ "dev:deno": "deno run --allow-net server.js",
250
+ "start": "node server.js"
251
+ },
252
+ dependencies: {},
253
+ devDependencies: {}
254
+ };
255
+ writeFileSync(
256
+ join(projectPath, "package.json"),
257
+ JSON.stringify(packageJson, null, 2)
258
+ );
259
+ const serverCode = `/**
260
+ * ${projectName}
261
+ *
262
+ * 100% Web Standards server. Zero dependencies. Zero lock-in.
263
+ * Works on: Bun, Deno, Node 22+, Cloudflare Workers
264
+ *
265
+ * Run:
266
+ * bun server.js
267
+ * deno run --allow-net server.js
268
+ * node server.js (Node 22+)
269
+ */
270
+
271
+ /**
272
+ * Handle incoming requests using Web Standard APIs
273
+ * @param {Request} request
274
+ * @returns {Response}
275
+ */
276
+ function handleRequest(request) {
277
+ const url = new URL(request.url);
278
+ const method = request.method;
279
+
280
+ // Router
281
+ if (method === 'GET' && url.pathname === '/') {
282
+ return Response.json({
283
+ message: 'Hello World!',
284
+ runtime: detectRuntime(),
285
+ docs: 'https://flight.dev/docs/quickstart-http',
286
+ });
287
+ }
288
+
289
+ if (method === 'GET' && url.pathname === '/health') {
290
+ return Response.json({
291
+ status: 'ok',
292
+ timestamp: Date.now(),
293
+ });
294
+ }
295
+
296
+ if (method === 'GET' && url.pathname.startsWith('/api/')) {
297
+ return Response.json({
298
+ path: url.pathname,
299
+ query: Object.fromEntries(url.searchParams),
300
+ });
301
+ }
302
+
303
+ // 404
304
+ return Response.json(
305
+ { error: 'Not Found', path: url.pathname },
306
+ { status: 404 }
307
+ );
308
+ }
309
+
310
+ /**
311
+ * Detect which runtime we're running on
312
+ */
313
+ function detectRuntime() {
314
+ if (typeof Bun !== 'undefined') return 'bun';
315
+ if (typeof Deno !== 'undefined') return 'deno';
316
+ return 'node';
317
+ }
318
+
319
+ // Export for different runtimes
320
+ const port = process.env.PORT || 3000;
321
+
322
+ // Bun / Cloudflare Workers style
323
+ export default {
324
+ port,
325
+ fetch: handleRequest,
326
+ };
327
+
328
+ // Also start server for Node.js
329
+ if (detectRuntime() === 'node') {
330
+ const { serve } = await import('node:http');
331
+ serve({ port }, (req, res) => {
332
+ const url = 'http://localhost' + req.url;
333
+ const request = new Request(url, { method: req.method });
334
+ handleRequest(request).then(response => {
335
+ res.writeHead(response.status, Object.fromEntries(response.headers));
336
+ response.text().then(body => res.end(body));
337
+ });
338
+ });
339
+ console.log(\`Server running at http://localhost:\${port}\`);
340
+ }
341
+ `;
342
+ writeFileSync(join(projectPath, "server.js"), serverCode);
343
+ if (options.git) {
344
+ writeFileSync(
345
+ join(projectPath, ".gitignore"),
346
+ "node_modules\ndist\n.env\n.env.local\n"
347
+ );
348
+ try {
349
+ execSync("git init", { cwd: projectPath, stdio: "ignore" });
350
+ } catch {
351
+ }
352
+ }
353
+ console.log(`
354
+ ${pc.green("[OK] Raw project created!")}
355
+
356
+ ${pc.bold("ZERO dependencies. ZERO lock-in. 100% Web Standards.")}
357
+
358
+ ${pc.cyan("Run with any runtime:")}
359
+
360
+ ${pc.dim("# Bun (fastest)")}
361
+ bun server.js
362
+
363
+ ${pc.dim("# Deno")}
364
+ deno run --allow-net server.js
365
+
366
+ ${pc.dim("# Node.js 22+")}
367
+ node server.js
368
+
369
+ ${pc.dim("Want to add Flight later? Just run:")}
370
+ flight add http ${pc.dim("# HTTP server with routing")}
371
+ flight add db ${pc.dim("# Database abstraction")}
372
+ flight add cache ${pc.dim("# Caching layer")}
373
+
374
+ ${pc.dim("Path:")} ${projectPath}
375
+ `);
376
+ }
377
+ function createEmptyProject(projectPath, projectName, options) {
378
+ mkdirSync(projectPath, { recursive: true });
379
+ const packageJson = {
380
+ name: projectName,
381
+ version: "0.0.1",
382
+ type: "module",
383
+ scripts: {
384
+ dev: "node server.js"
385
+ },
386
+ dependencies: {},
387
+ devDependencies: {}
388
+ };
389
+ writeFileSync(
390
+ join(projectPath, "package.json"),
391
+ JSON.stringify(packageJson, null, 2)
392
+ );
393
+ if (options.git) {
394
+ writeFileSync(
395
+ join(projectPath, ".gitignore"),
396
+ "node_modules\ndist\n.env\n.env.local\n"
397
+ );
398
+ try {
399
+ execSync("git init", { cwd: projectPath, stdio: "ignore" });
400
+ } catch {
401
+ }
402
+ }
403
+ console.log(`
404
+ ${pc.green("[OK] Empty project created!")}
405
+
406
+ ${pc.cyan("Your project is a blank canvas.")} Add what you need:
407
+
408
+ ${pc.dim("# HTTP server")}
409
+ npm install @flight-framework/http
410
+
411
+ ${pc.dim("# Database")}
412
+ npm install @flight-framework/db
413
+
414
+ ${pc.dim("# Cache")}
415
+ npm install @flight-framework/cache
416
+
417
+ ${pc.dim("# Authentication")}
418
+ npm install @flight-framework/auth
419
+
420
+ ${pc.dim("Path:")} ${projectPath}
421
+ `);
422
+ }
423
+ function createMinimalProject(projectPath, projectName, options) {
424
+ mkdirSync(projectPath, { recursive: true });
425
+ const packageJson = {
426
+ name: projectName,
427
+ version: "0.0.1",
428
+ type: "module",
429
+ scripts: {
430
+ dev: "node --watch server.js",
431
+ start: "node server.js"
432
+ },
433
+ dependencies: {
434
+ "@flight-framework/http": "^0.0.1"
435
+ }
436
+ };
437
+ writeFileSync(
438
+ join(projectPath, "package.json"),
439
+ JSON.stringify(packageJson, null, 2)
440
+ );
441
+ const serverCode = `/**
442
+ * ${projectName} - Built with Flight
443
+ *
444
+ * This is a minimal Flight server. Add more as you need.
445
+ * Run: npm run dev
446
+ */
447
+
448
+ import { createServer } from '@flight-framework/http';
449
+
450
+ const app = createServer();
451
+
452
+ // Your routes
453
+ app.get('/', (c) => c.json({
454
+ message: 'Hello from Flight!',
455
+ docs: 'https://flight.dev/docs/quickstart-http'
456
+ }));
457
+
458
+ app.get('/health', (c) => c.json({
459
+ status: 'ok',
460
+ timestamp: Date.now()
461
+ }));
462
+
463
+ // Start server
464
+ const port = process.env.PORT || 3000;
465
+ console.log(\`Server running at http://localhost:\${port}\`);
466
+
467
+ export default { port, fetch: app.fetch };
468
+ `;
469
+ writeFileSync(join(projectPath, "server.js"), serverCode);
470
+ if (options.git) {
471
+ writeFileSync(
472
+ join(projectPath, ".gitignore"),
473
+ "node_modules\ndist\n.env\n.env.local\n"
474
+ );
475
+ try {
476
+ execSync("git init", { cwd: projectPath, stdio: "ignore" });
477
+ } catch {
478
+ }
479
+ }
480
+ if (options.install) {
481
+ console.log(pc.dim("\\nInstalling dependencies...\\n"));
482
+ try {
483
+ const pm = detectPackageManager();
484
+ execSync(`${pm} install`, { cwd: projectPath, stdio: "inherit" });
485
+ } catch {
486
+ }
487
+ }
488
+ console.log(`
489
+ ${pc.green("[OK] Minimal project created!")}
490
+
491
+ ${pc.cyan("Next steps:")}
492
+
493
+ ${pc.dim("$")} cd ${projectName}
494
+ ${pc.dim("$")} ${options.install ? "" : "npm install && "}npm run dev
495
+
496
+ ${pc.dim("Add more features as needed:")}
497
+
498
+ ${pc.dim("# File-based routing")}
499
+ npm install @flight-framework/core
500
+
501
+ ${pc.dim("# Database")}
502
+ npm install @flight-framework/db pg
503
+
504
+ ${pc.dim("# Caching")}
505
+ npm install @flight-framework/cache
506
+
507
+ ${pc.cyan("Happy flying!")}
508
+ `);
509
+ }
208
510
 
209
511
  // src/commands/dev.ts
210
512
  import { resolve as resolve2, join as join2 } from "path";
@@ -1294,25 +1596,234 @@ async function typesGenerateCommand(options = {}) {
1294
1596
  }
1295
1597
  }
1296
1598
 
1599
+ // src/commands/add.ts
1600
+ import { existsSync as existsSync6 } from "fs";
1601
+ import { join as join5 } from "path";
1602
+ import { execSync as execSync2 } from "child_process";
1603
+ import pc5 from "picocolors";
1604
+ var PACKAGES = {
1605
+ // Core
1606
+ "http": {
1607
+ name: "@flight-framework/http",
1608
+ description: "HTTP server with routing and middleware",
1609
+ category: "core"
1610
+ },
1611
+ "core": {
1612
+ name: "@flight-framework/core",
1613
+ description: "File-based routing and configuration",
1614
+ category: "core"
1615
+ },
1616
+ // Data
1617
+ "db": {
1618
+ name: "@flight-framework/db",
1619
+ description: "Database abstraction layer",
1620
+ category: "data",
1621
+ drivers: ["pg", "@libsql/client", "@neondatabase/serverless", "@supabase/supabase-js"]
1622
+ },
1623
+ "cache": {
1624
+ name: "@flight-framework/cache",
1625
+ description: "Caching with multiple adapters",
1626
+ category: "data"
1627
+ },
1628
+ // Auth
1629
+ "auth": {
1630
+ name: "@flight-framework/auth",
1631
+ description: "Authentication adapters",
1632
+ category: "auth"
1633
+ },
1634
+ // Frontend
1635
+ "forms": {
1636
+ name: "@flight-framework/forms",
1637
+ description: "Type-safe form handling",
1638
+ category: "frontend"
1639
+ },
1640
+ "i18n": {
1641
+ name: "@flight-framework/i18n",
1642
+ description: "Internationalization",
1643
+ category: "frontend"
1644
+ },
1645
+ "seo": {
1646
+ name: "@flight-framework/seo",
1647
+ description: "SEO utilities",
1648
+ category: "frontend"
1649
+ },
1650
+ "image": {
1651
+ name: "@flight-framework/image",
1652
+ description: "Image optimization",
1653
+ category: "frontend"
1654
+ },
1655
+ // Communication
1656
+ "email": {
1657
+ name: "@flight-framework/email",
1658
+ description: "Email sending",
1659
+ category: "communication"
1660
+ },
1661
+ "realtime": {
1662
+ name: "@flight-framework/realtime",
1663
+ description: "WebSocket and real-time features",
1664
+ category: "communication"
1665
+ },
1666
+ // Deployment
1667
+ "helpers": {
1668
+ name: "@flight-framework/helpers",
1669
+ description: "Optional helper utilities (detection, suggestions)",
1670
+ category: "utilities"
1671
+ }
1672
+ };
1673
+ async function addCommand(packageName) {
1674
+ const cwd = process.cwd();
1675
+ if (!existsSync6(join5(cwd, "package.json"))) {
1676
+ console.log(pc5.red("No package.json found. Run this command from your project directory."));
1677
+ process.exit(1);
1678
+ }
1679
+ if (!packageName) {
1680
+ showAvailablePackages();
1681
+ return;
1682
+ }
1683
+ const pkg = PACKAGES[packageName];
1684
+ if (!pkg) {
1685
+ console.log(pc5.red(`Unknown package: ${packageName}`));
1686
+ console.log(pc5.dim("Run `flight add` to see available packages."));
1687
+ process.exit(1);
1688
+ }
1689
+ console.log(`
1690
+ ${pc5.cyan("Adding")} ${pc5.bold(pkg.name)}...`);
1691
+ console.log(pc5.dim(pkg.description));
1692
+ console.log();
1693
+ const pm = detectPackageManager2();
1694
+ try {
1695
+ const installCmd = pm === "npm" ? "npm install" : `${pm} add`;
1696
+ execSync2(`${installCmd} ${pkg.name}`, { cwd, stdio: "inherit" });
1697
+ console.log(`
1698
+ ${pc5.green("[OK]")} ${pkg.name} added successfully!`);
1699
+ showNextSteps(packageName, pkg);
1700
+ } catch (error) {
1701
+ console.log(pc5.red(`
1702
+ Failed to install ${pkg.name}`));
1703
+ process.exit(1);
1704
+ }
1705
+ }
1706
+ function detectPackageManager2() {
1707
+ const cwd = process.cwd();
1708
+ if (existsSync6(join5(cwd, "pnpm-lock.yaml"))) return "pnpm";
1709
+ if (existsSync6(join5(cwd, "yarn.lock"))) return "yarn";
1710
+ if (existsSync6(join5(cwd, "bun.lockb"))) return "bun";
1711
+ return "npm";
1712
+ }
1713
+ function showAvailablePackages() {
1714
+ console.log(`
1715
+ ${pc5.cyan("Available Flight packages:")}
1716
+
1717
+ ${pc5.bold("Core")}
1718
+ ${pc5.green("http")} ${pc5.dim("HTTP server with routing and middleware")}
1719
+ ${pc5.green("core")} ${pc5.dim("File-based routing and configuration")}
1720
+
1721
+ ${pc5.bold("Data")}
1722
+ ${pc5.green("db")} ${pc5.dim("Database abstraction layer")}
1723
+ ${pc5.green("cache")} ${pc5.dim("Caching with multiple adapters")}
1724
+
1725
+ ${pc5.bold("Auth")}
1726
+ ${pc5.green("auth")} ${pc5.dim("Authentication adapters")}
1727
+
1728
+ ${pc5.bold("Frontend")}
1729
+ ${pc5.green("forms")} ${pc5.dim("Type-safe form handling")}
1730
+ ${pc5.green("i18n")} ${pc5.dim("Internationalization")}
1731
+ ${pc5.green("seo")} ${pc5.dim("SEO utilities")}
1732
+ ${pc5.green("image")} ${pc5.dim("Image optimization")}
1733
+
1734
+ ${pc5.bold("Communication")}
1735
+ ${pc5.green("email")} ${pc5.dim("Email sending")}
1736
+ ${pc5.green("realtime")} ${pc5.dim("WebSocket and real-time features")}
1737
+
1738
+ ${pc5.bold("Utilities")}
1739
+ ${pc5.green("helpers")} ${pc5.dim("Optional helper utilities")}
1740
+
1741
+ ${pc5.cyan("Usage:")}
1742
+ flight add http
1743
+ flight add db
1744
+ flight add auth
1745
+ `);
1746
+ }
1747
+ function showNextSteps(packageName, pkg) {
1748
+ const examples = {
1749
+ "http": `
1750
+ ${pc5.cyan("Quick example:")}
1751
+
1752
+ import { createServer } from '@flight-framework/http';
1753
+
1754
+ const app = createServer();
1755
+ app.get('/', (c) => c.json({ hello: 'world' }));
1756
+
1757
+ export default { port: 3000, fetch: app.fetch };
1758
+ `,
1759
+ "db": `
1760
+ ${pc5.cyan("Quick example:")}
1761
+
1762
+ import { createDb } from '@flight-framework/db';
1763
+ import { postgres } from '@flight-framework/db/postgres';
1764
+
1765
+ const db = createDb(postgres({ connectionString: process.env.DATABASE_URL }));
1766
+ const users = await db.query('SELECT * FROM users');
1767
+
1768
+ ${pc5.dim("You may also need a driver:")}
1769
+ npm install pg ${pc5.dim("# PostgreSQL")}
1770
+ npm install @libsql/client ${pc5.dim("# Turso/SQLite")}
1771
+ npm install @neondatabase/serverless ${pc5.dim("# Neon")}
1772
+ `,
1773
+ "cache": `
1774
+ ${pc5.cyan("Quick example:")}
1775
+
1776
+ import { createCache, lru } from '@flight-framework/cache';
1777
+
1778
+ const cache = createCache(lru({ max: 1000 }));
1779
+ await cache.set('key', { data: 'value' });
1780
+ const value = await cache.get('key');
1781
+ `,
1782
+ "auth": `
1783
+ ${pc5.cyan("Quick example:")}
1784
+
1785
+ import { createAuth } from '@flight-framework/auth';
1786
+ import { betterAuth } from '@flight-framework/auth/better-auth';
1787
+
1788
+ const auth = createAuth(betterAuth({ db }));
1789
+ const user = await auth.getUser(request);
1790
+ `,
1791
+ "forms": `
1792
+ ${pc5.cyan("Quick example:")}
1793
+
1794
+ import { createForm } from '@flight-framework/forms';
1795
+ import { zodAdapter } from '@flight-framework/forms/adapters/zod';
1796
+
1797
+ const form = createForm({ schema: zodAdapter(schema) });
1798
+ const result = form.validate(data);
1799
+ `
1800
+ };
1801
+ if (examples[packageName]) {
1802
+ console.log(examples[packageName]);
1803
+ }
1804
+ console.log(`${pc5.dim("Docs:")} https://flight.dev/docs/packages/${packageName}`);
1805
+ }
1806
+
1297
1807
  // src/index.ts
1298
1808
  var cli = cac("flight");
1299
1809
  var LOGO = `
1300
- ${pc5.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557")}
1301
- ${pc5.cyan(" \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D")}
1302
- ${pc5.cyan(" \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 ")}
1303
- ${pc5.cyan(" \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 ")}
1304
- ${pc5.cyan(" \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 ")}
1305
- ${pc5.cyan(" \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D ")}
1810
+ ${pc6.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557")}
1811
+ ${pc6.cyan(" \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D")}
1812
+ ${pc6.cyan(" \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 ")}
1813
+ ${pc6.cyan(" \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 ")}
1814
+ ${pc6.cyan(" \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 ")}
1815
+ ${pc6.cyan(" \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D ")}
1306
1816
 
1307
- ${pc5.dim("The Agnostic Full-Stack Framework")}
1308
- ${pc5.dim("Maximum Flexibility. Zero Lock-in.")}
1817
+ ${pc6.dim("The Agnostic Full-Stack Framework")}
1818
+ ${pc6.dim("Maximum Flexibility. Zero Lock-in.")}
1309
1819
  `;
1310
1820
  function printLogo() {
1311
1821
  console.log(LOGO);
1312
1822
  }
1313
1823
  cli.version(VERSION);
1314
1824
  cli.help();
1315
- cli.command("create [name]", "Create a new Flight project").option("-t, --template <template>", "Project template to use", { default: "basic" }).option("--ui <framework>", "UI framework (react, vue, svelte, solid, vanilla)").option("--ts", "Use TypeScript", { default: true }).option("--git", "Initialize git repository", { default: true }).option("--install", "Install dependencies", { default: true }).action(createCommand);
1825
+ cli.command("create [name]", "Create a new Flight project").option("-t, --template <template>", "Project template to use", { default: "basic" }).option("--ui <framework>", "UI framework (react, vue, svelte, solid, vanilla)").option("--use-case <useCase>", "Use-case template (blog, ecommerce, saas, api, docs)").option("--ts", "Use TypeScript", { default: true }).option("--git", "Initialize git repository", { default: true }).option("--install", "Install dependencies", { default: true }).option("--raw", "Create raw project (100% Web Standards, zero dependencies)").option("--empty", "Create empty project (just package.json)").option("--minimal", "Create minimal project (single server file with Flight)").action(createCommand);
1826
+ cli.command("add [package]", "Add a Flight package to your project").action(addCommand);
1316
1827
  cli.command("dev", "Start development server").option("-p, --port <port>", "Port to listen on").option("-h, --host <host>", "Host to bind to").option("--open", "Open browser on start").option("--https", "Enable HTTPS").option("--ssr", "Enable Server-Side Rendering").action(devCommand);
1317
1828
  cli.command("build", "Build for production").option("--outDir <dir>", "Output directory").option("--sourcemap", "Generate source maps").option("--minify", "Minify output", { default: true }).action(buildCommand);
1318
1829
  cli.command("preview", "Preview production build").option("-p, --port <port>", "Port to listen on").option("-h, --host <host>", "Host to bind to").option("--open", "Open browser on start").action(previewCommand);
@@ -1326,7 +1837,7 @@ function run() {
1326
1837
  }
1327
1838
  cli.runMatchedCommand();
1328
1839
  } catch (error) {
1329
- console.error(pc5.red("Error:"), error instanceof Error ? error.message : error);
1840
+ console.error(pc6.red("Error:"), error instanceof Error ? error.message : error);
1330
1841
  process.exit(1);
1331
1842
  }
1332
1843
  }