create-oven 0.3.1 → 0.5.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.
Files changed (2) hide show
  1. package/index.js +58 -141
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -88,14 +88,14 @@ async function main() {
88
88
  }
89
89
 
90
90
  if (args.includes('--version') || args.includes('-v')) {
91
- console.log('create-oven v0.3.1');
91
+ console.log('create-oven v0.5.0');
92
92
  process.exit(0);
93
93
  }
94
94
 
95
95
  console.log(`
96
96
  ${c.bold}${c.cyan} ╔═══════════════════════════════════════╗
97
97
  ║ ║
98
- ║ 🔥 Create Oven App v0.3.1
98
+ ║ 🔥 Create Oven App v0.5.0
99
99
  ║ ║
100
100
  ║ Next.js-style framework for Bun ║
101
101
  ║ ║
@@ -174,12 +174,14 @@ ${c.bold}${c.cyan} ╔═══════════════════
174
174
  version: '0.1.0',
175
175
  private: true,
176
176
  scripts: {
177
- dev: 'bun run --hot server.tsx',
178
- build: 'bun build ./server.tsx --outdir ./dist --target bun',
179
- start: 'bun run dist/server.js',
177
+ dev: 'oven dev',
178
+ build: 'oven build',
179
+ start: 'oven start',
180
180
  ...(useEslint && { lint: 'eslint .' }),
181
181
  },
182
- dependencies: {},
182
+ dependencies: {
183
+ 'oven-bun': 'latest',
184
+ },
183
185
  devDependencies: {
184
186
  ...(useTypescript && { '@types/bun': 'latest', 'typescript': '^5' }),
185
187
  ...(useTailwind && { '@tailwindcss/postcss': '^4', 'tailwindcss': '^4' }),
@@ -293,7 +295,7 @@ body {
293
295
  const spin6 = spinner(`Creating app/layout.${ext}...`);
294
296
  const layoutContent = useTypescript ? `import "./globals.css";
295
297
 
296
- export const metadata${useTypescript ? ': { title: string; description: string }' : ''} = {
298
+ export const metadata = {
297
299
  title: "Create Oven App",
298
300
  description: "Generated by create-oven",
299
301
  };
@@ -301,25 +303,24 @@ export const metadata${useTypescript ? ': { title: string; description: string }
301
303
  export default function RootLayout({
302
304
  children,
303
305
  }: Readonly<{
304
- children: string;
306
+ children: React.ReactNode;
305
307
  }>) {
306
308
  return (
307
- \`<!DOCTYPE html>
308
309
  <html lang="en">
309
310
  <head>
310
- <meta charset="UTF-8" />
311
+ <meta charSet="UTF-8" />
311
312
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
312
- <title>\${metadata.title}</title>
313
- <meta name="description" content="\${metadata.description}" />
313
+ <title>{metadata.title}</title>
314
+ <meta name="description" content={metadata.description} />
314
315
  <link rel="icon" href="/favicon.ico" />
315
316
  <link rel="preconnect" href="https://fonts.googleapis.com" />
316
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
317
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
317
318
  <link href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Geist+Mono&display=swap" rel="stylesheet" />
318
319
  </head>
319
- <body class="antialiased" style="font-family: 'Geist', sans-serif;">
320
- \${children}
320
+ <body className="antialiased" style={{ fontFamily: "'Geist', sans-serif" }}>
321
+ {children}
321
322
  </body>
322
- </html>\`
323
+ </html>
323
324
  );
324
325
  }
325
326
  ` : `import "./globals.css";
@@ -331,22 +332,21 @@ export const metadata = {
331
332
 
332
333
  export default function RootLayout({ children }) {
333
334
  return (
334
- \`<!DOCTYPE html>
335
335
  <html lang="en">
336
336
  <head>
337
- <meta charset="UTF-8" />
337
+ <meta charSet="UTF-8" />
338
338
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
339
- <title>\${metadata.title}</title>
340
- <meta name="description" content="\${metadata.description}" />
339
+ <title>{metadata.title}</title>
340
+ <meta name="description" content={metadata.description} />
341
341
  <link rel="icon" href="/favicon.ico" />
342
342
  <link rel="preconnect" href="https://fonts.googleapis.com" />
343
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
343
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
344
344
  <link href="https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Geist+Mono&display=swap" rel="stylesheet" />
345
345
  </head>
346
- <body class="antialiased" style="font-family: 'Geist', sans-serif;">
347
- \${children}
346
+ <body className="antialiased" style={{ fontFamily: "'Geist', sans-serif" }}>
347
+ {children}
348
348
  </body>
349
- </html>\`
349
+ </html>
350
350
  );
351
351
  }
352
352
  `;
@@ -357,55 +357,55 @@ export default function RootLayout({ children }) {
357
357
  const spin7 = spinner(`Creating app/page.${ext}...`);
358
358
  const pageContent = useTailwind ? `export default function Home() {
359
359
  return (
360
- \`<div class="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
361
- <main class="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
360
+ <div className="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
361
+ <main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
362
362
  <img
363
- class="dark:invert"
363
+ className="dark:invert"
364
364
  src="/oven.svg"
365
365
  alt="Oven logo"
366
- width="100"
367
- height="24"
366
+ width={100}
367
+ height={24}
368
368
  />
369
- <div class="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
370
- <h1 class="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
369
+ <div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
370
+ <h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
371
371
  Get started by editing app/page.${ext}
372
372
  </h1>
373
- <p class="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
373
+ <p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
374
374
  Looking for a starting point? Head over to the{" "}
375
375
  <a
376
376
  href="https://github.com/oven-ttta/oven-framework"
377
- class="font-medium text-zinc-950 dark:text-zinc-50"
377
+ className="font-medium text-zinc-950 dark:text-zinc-50"
378
378
  >
379
379
  Documentation
380
380
  </a>{" "}
381
381
  or{" "}
382
382
  <a
383
383
  href="https://bun.sh/docs"
384
- class="font-medium text-zinc-950 dark:text-zinc-50"
384
+ className="font-medium text-zinc-950 dark:text-zinc-50"
385
385
  >
386
386
  Bun Docs
387
387
  </a>.
388
388
  </p>
389
389
  </div>
390
- <div class="flex flex-col gap-4 text-base font-medium sm:flex-row">
390
+ <div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
391
391
  <a
392
- class="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
392
+ className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
393
393
  href="https://github.com/oven-ttta/oven-framework"
394
394
  target="_blank"
395
395
  rel="noopener noreferrer"
396
- style="background: #171717; color: white;"
396
+ style={{ background: "#171717", color: "white" }}
397
397
  >
398
398
  <img
399
- class="dark:invert"
399
+ className="dark:invert"
400
400
  src="/github.svg"
401
401
  alt="GitHub"
402
- width="16"
403
- height="16"
402
+ width={16}
403
+ height={16}
404
404
  />
405
405
  GitHub
406
406
  </a>
407
407
  <a
408
- class="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
408
+ className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
409
409
  href="https://bun.sh/docs"
410
410
  target="_blank"
411
411
  rel="noopener noreferrer"
@@ -414,134 +414,51 @@ export default function RootLayout({ children }) {
414
414
  </a>
415
415
  </div>
416
416
  </main>
417
- </div>\`
417
+ </div>
418
418
  );
419
419
  }
420
420
  ` : `export default function Home() {
421
421
  return (
422
- \`<div style="display: flex; min-height: 100vh; align-items: center; justify-content: center; background: #fafafa;">
423
- <main style="display: flex; flex-direction: column; align-items: center; justify-content: space-between; max-width: 48rem; padding: 8rem 4rem; background: white;">
424
- <div style="font-size: 4rem; margin-bottom: 2rem;">🔥</div>
425
- <div style="display: flex; flex-direction: column; align-items: center; gap: 1.5rem; text-align: center;">
426
- <h1 style="font-size: 1.875rem; font-weight: 600; line-height: 2.5rem; color: black;">
422
+ <div style={{ display: "flex", minHeight: "100vh", alignItems: "center", justifyContent: "center", background: "#fafafa" }}>
423
+ <main style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "space-between", maxWidth: "48rem", padding: "8rem 4rem", background: "white" }}>
424
+ <div style={{ fontSize: "4rem", marginBottom: "2rem" }}>🔥</div>
425
+ <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: "1.5rem", textAlign: "center" }}>
426
+ <h1 style={{ fontSize: "1.875rem", fontWeight: 600, lineHeight: "2.5rem", color: "black" }}>
427
427
  Get started by editing app/page.${ext}
428
428
  </h1>
429
- <p style="max-width: 28rem; font-size: 1.125rem; line-height: 2rem; color: #666;">
430
- Looking for a starting point? Head over to the
431
- <a href="https://github.com/oven-ttta/oven-framework" style="font-weight: 500; color: black;">Documentation</a>
432
- or
433
- <a href="https://bun.sh/docs" style="font-weight: 500; color: black;">Bun Docs</a>.
429
+ <p style={{ maxWidth: "28rem", fontSize: "1.125rem", lineHeight: "2rem", color: "#666" }}>
430
+ Looking for a starting point? Head over to the{" "}
431
+ <a href="https://github.com/oven-ttta/oven-framework" style={{ fontWeight: 500, color: "black" }}>Documentation</a>
432
+ {" "}or{" "}
433
+ <a href="https://bun.sh/docs" style={{ fontWeight: 500, color: "black" }}>Bun Docs</a>.
434
434
  </p>
435
435
  </div>
436
- <div style="display: flex; gap: 1rem; margin-top: 2rem;">
436
+ <div style={{ display: "flex", gap: "1rem", marginTop: "2rem" }}>
437
437
  <a
438
438
  href="https://github.com/oven-ttta/oven-framework"
439
439
  target="_blank"
440
- style="display: flex; height: 3rem; align-items: center; justify-content: center; gap: 0.5rem; border-radius: 9999px; background: black; color: white; padding: 0 1.5rem; text-decoration: none;"
440
+ rel="noopener noreferrer"
441
+ style={{ display: "flex", height: "3rem", alignItems: "center", justifyContent: "center", gap: "0.5rem", borderRadius: "9999px", background: "black", color: "white", padding: "0 1.5rem", textDecoration: "none" }}
441
442
  >
442
443
  GitHub
443
444
  </a>
444
445
  <a
445
446
  href="https://bun.sh/docs"
446
447
  target="_blank"
447
- style="display: flex; height: 3rem; align-items: center; justify-content: center; border-radius: 9999px; border: 1px solid #e5e5e5; padding: 0 1.5rem; text-decoration: none; color: inherit;"
448
+ rel="noopener noreferrer"
449
+ style={{ display: "flex", height: "3rem", alignItems: "center", justifyContent: "center", borderRadius: "9999px", border: "1px solid #e5e5e5", padding: "0 1.5rem", textDecoration: "none", color: "inherit" }}
448
450
  >
449
451
  Bun Docs
450
452
  </a>
451
453
  </div>
452
454
  </main>
453
- </div>\`
455
+ </div>
454
456
  );
455
457
  }
456
458
  `;
457
459
  fs.writeFileSync(path.join(projectDir, 'app', `page.${ext}`), pageContent);
458
460
  spin7.stop(`Created app/page.${ext}`);
459
461
 
460
- // ============ server.tsx ============
461
- const spin8 = spinner(`Creating server.${ext}...`);
462
- const serverContent = `/**
463
- * Oven Server
464
- * Powered by Bun
465
- */
466
-
467
- const PORT = parseInt(process.env.PORT || "3000");
468
-
469
- // Simple router
470
- const routes = new Map${useTypescript ? '<string, (req: Request) => Promise<Response>>' : ''}();
471
-
472
- async function scanRoutes() {
473
- const appDir = "./app";
474
-
475
- // Scan for page files
476
- const glob = new Bun.Glob("**/page.{tsx,jsx,ts,js}");
477
-
478
- for await (const file of glob.scan({ cwd: appDir })) {
479
- const routePath = "/" + file
480
- .replace(/\\/page\\.(tsx|jsx|ts|js)$/, "")
481
- .replace(/^page\\.(tsx|jsx|ts|js)$/, "")
482
- .replace(/\\/$/, "") || "/";
483
-
484
- routes.set(routePath === "" ? "/" : routePath, async (req${useTypescript ? ': Request' : ''}) => {
485
- const module = await import(\`\${appDir}/\${file}\`);
486
- const content = await module.default();
487
-
488
- // Wrap with layout
489
- let html = content;
490
- try {
491
- const layout = await import(\`\${appDir}/layout.tsx\`);
492
- html = await layout.default({ children: content });
493
- } catch {}
494
-
495
- return new Response(html, {
496
- headers: { "Content-Type": "text/html; charset=utf-8" },
497
- });
498
- });
499
- }
500
- }
501
-
502
- async function main() {
503
- await scanRoutes();
504
-
505
- Bun.serve({
506
- port: PORT,
507
- async fetch(req${useTypescript ? ': Request' : ''}) {
508
- const url = new URL(req.url);
509
- let pathname = url.pathname;
510
-
511
- if (pathname !== "/" && pathname.endsWith("/")) {
512
- pathname = pathname.slice(0, -1);
513
- }
514
-
515
- // Check routes
516
- const handler = routes.get(pathname);
517
- if (handler) {
518
- return handler(req);
519
- }
520
-
521
- // Static files
522
- const publicPath = "./public" + pathname;
523
- const file = Bun.file(publicPath);
524
- if (await file.exists()) {
525
- return new Response(file);
526
- }
527
-
528
- return new Response("Not Found", { status: 404 });
529
- },
530
- });
531
-
532
- console.log(\`
533
- ${c.green}▲${c.reset} Ready in \${Date.now() - start}ms
534
-
535
- ${c.dim}➜${c.reset} Local: ${c.cyan}http://localhost:\${PORT}${c.reset}
536
- \`);
537
- }
538
-
539
- const start = Date.now();
540
- main();
541
- `;
542
- fs.writeFileSync(path.join(projectDir, `server.${ext}`), serverContent);
543
- spin8.stop(`Created server.${ext}`);
544
-
545
462
  // ============ .gitignore ============
546
463
  const spin9 = spinner('Creating .gitignore...');
547
464
  fs.writeFileSync(path.join(projectDir, '.gitignore'), `# Dependencies
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-oven",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "Create a new Oven project - Next.js-style framework for Bun",
5
5
  "type": "module",
6
6
  "bin": {