A simple, folder-driven static-site engine.
bun ssg fs
at dev 135 lines 3.7 kB view raw
1#!/usr/bin/env bun 2 3/** 4 * Webette CLI entrypoint (`build` / `serve`). 5 */ 6 7import { build } from "./core/build"; 8import { serve } from "./core/serve"; 9import { createProjectLogger } from "./logging/logger"; 10import { getVersion } from "./version"; 11 12type CliOptions = { 13 verbose: boolean; 14 exportModel?: { 15 only?: boolean; 16 }; 17 readContent?: boolean; 18 includeDrafts?: boolean; // serve-only flag to show/hide draft entries 19}; 20 21function parseArgs(argv: string[]) { 22 // Remove the first 2 entries (bun + script) 23 const rawArgs = argv.slice(2); 24 25 let verbose = false; 26 const exportModel: CliOptions["exportModel"] = {}; 27 let readContent: boolean | undefined = undefined; 28 let includeDrafts: boolean | undefined = undefined; 29 30 const filtered: string[] = []; 31 32 for (let i = 0; i < rawArgs.length; i++) { 33 const arg = rawArgs[i]; 34 if (arg === undefined) continue; 35 36 if (arg === "--verbose" || arg === "-v") { 37 verbose = true; 38 continue; 39 } 40 41 if (arg === "--export-model-only") { 42 exportModel.only = true; 43 continue; 44 } 45 46 if (arg === "--skip-content") { 47 readContent = false; 48 continue; 49 } 50 51 if (arg === "--include-drafts") { 52 includeDrafts = true; 53 continue; 54 } 55 56 if (arg === "--no-include-drafts") { 57 includeDrafts = false; 58 continue; 59 } 60 61 filtered.push(arg); 62 } 63 64 // Remove flags from the "useful" args 65 66 const command = filtered[0]; // "build" or "serve" 67 const sitePath = filtered[1]; // path to the site folder 68 69 const options: CliOptions = { 70 verbose, 71 exportModel: Object.keys(exportModel).length ? exportModel : undefined, 72 readContent, 73 includeDrafts, 74 }; 75 76 return { command, sitePath, options }; 77} 78 79async function main() { 80 const { command, sitePath, options } = parseArgs(Bun.argv); 81 82 if (!command) { 83 console.log(`webette ${getVersion()}`); 84 console.log("Usage:"); 85 console.log(" webette build [site-folder]"); 86 console.log(" webette serve [site-folder]"); 87 console.log(""); 88 console.log("If no folder is provided, the current directory is used."); 89 console.log(""); 90 console.log("Options:"); 91 console.log(" -v, --verbose Show debug logs"); 92 console.log(" --export-model-only Export the model and skip HTML generation"); 93 console.log(" --skip-content Do not read/resolve block contents"); 94 console.log(" --include-drafts Serve draft entries (default in serve)"); 95 console.log(" --no-include-drafts Hide draft entries even in serve"); 96 return; 97 } 98 99 const rootDir = sitePath ?? process.cwd(); 100 101 // 🔹 NEW: create a logger for this project + this command 102 const logger = await createProjectLogger( 103 rootDir, 104 `webette.cli.${command}`, 105 options.verbose 106 ); 107 108 try { 109 switch (command) { 110 case "build": 111 await build(rootDir, options, logger); 112 break; 113 114 case "serve": 115 await serve(rootDir, options, logger); 116 break; 117 118 default: 119 logger.error("cli.unknownCommand", { command }); 120 console.log("Available commands: build, serve"); 121 console.log("Options:"); 122 console.log(" -v, --verbose Show debug logs"); 123 console.log(" --export-model-only Export the model and skip HTML generation"); 124 console.log(" --skip-content Do not read/resolve block contents"); 125 console.log(" --include-drafts Serve draft entries (default in serve)"); 126 console.log(" --no-include-drafts Hide draft entries even in serve"); 127 break; 128 } 129 } catch (error) { 130 logger.error("error.unexpected", { error: String(error) }); 131 process.exitCode = 1; 132 } 133} 134 135await main();