vantris 0.2.0 → 0.3.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/dist/chunk-LRSN7SF4.js +1117 -0
- package/dist/chunk-LRSN7SF4.js.map +1 -0
- package/dist/cli/index.js +1 -1
- package/dist/index.d.ts +152 -2
- package/dist/index.js +1 -1
- package/package.json +20 -2
- package/dist/chunk-OFLPPG2U.js +0 -600
- package/dist/chunk-OFLPPG2U.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/constants.ts","../src/shared/errors.ts","../src/utils/fs.ts","../src/utils/paths.ts","../src/config/load.ts","../src/config/resolve.ts","../src/html/parse.ts","../src/html/detect.ts","../src/html/client.ts","../src/server/websocket.ts","../src/server/mime.ts","../src/server/transform.ts","../src/server/static.ts","../src/server/index.ts","../src/shared/logger.ts","../src/shared/context.ts","../src/shared/watcher.ts","../src/commands/support.ts","../src/commands/dev.ts","../src/build/index.ts","../src/commands/build.ts","../src/preview/index.ts","../src/commands/preview.ts","../src/commands/index.ts","../src/cli/help.ts","../src/cli/run.ts"],"names":["dev","extname","resolve","relative","readFile"],"mappings":"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","file":"chunk-OFLPPG2U.js","sourcesContent":["/** Product name, used in CLI banners and logs. */\nexport const APP_NAME = \"vantris\";\n\n/** Current Vantris version. Kept in sync with package.json at release time. */\nexport const VERSION = \"0.2.0\";\n\n/** The HTML entry filename Vantris looks for at the project root. */\nexport const HTML_ENTRY_FILENAME = \"index.html\";\n\n/** Default directory values, relative to the project root. */\nexport const DEFAULTS = {\n root: \".\",\n rootDir: \"./src\",\n publicDir: \"./public\",\n outDir: \"./dist\",\n} as const;\n\n/** Default dev-server options. */\nexport const DEV_DEFAULTS = {\n port: 3000,\n host: \"localhost\",\n} as const;\n\n/**\n * Message the dev server pushes over the WebSocket to ask the client to\n * reload. A typed string (rather than an empty frame) keeps room for richer\n * HMR messages in v1.x without breaking the v0.2 client.\n */\nexport const RELOAD_MESSAGE = \"reload\";\n\n/** Config filenames Vantris will look for, in priority order. */\nexport const CONFIG_FILENAMES = [\n \"vantris.config.ts\",\n \"vantris.config.js\",\n \"vantris.config.mjs\",\n] as const;\n","/**\n * Base class for all errors thrown intentionally by Vantris. The CLI layer can\n * recognise these and render them cleanly (without a stack trace), while\n * unexpected errors keep their full trace.\n */\nexport class VantrisError extends Error {\n override readonly name: string = \"VantrisError\";\n\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n }\n}\n\n/** Thrown when configuration is missing, malformed, or fails to load. */\nexport class ConfigError extends VantrisError {\n override readonly name = \"ConfigError\";\n}\n\n/** Thrown when the project's HTML entry cannot be found. */\nexport class HtmlEntryError extends VantrisError {\n override readonly name = \"HtmlEntryError\";\n}\n\n/** Thrown for functionality declared but not yet implemented in this version. */\nexport class NotImplementedError extends VantrisError {\n override readonly name = \"NotImplementedError\";\n}\n\n/** Narrowing helper. */\nexport function isVantrisError(error: unknown): error is VantrisError {\n return error instanceof VantrisError;\n}\n","import { mkdir, readFile, stat } from \"node:fs/promises\";\n\n/** Returns `true` if `path` exists and is a regular file. */\nexport async function isFile(path: string): Promise<boolean> {\n try {\n return (await stat(path)).isFile();\n } catch {\n return false;\n }\n}\n\n/** Reads a UTF-8 text file. */\nexport function readTextFile(path: string): Promise<string> {\n return readFile(path, \"utf8\");\n}\n\n/** Creates a directory (and any missing parents) if it does not exist. */\nexport async function ensureDir(path: string): Promise<void> {\n await mkdir(path, { recursive: true });\n}\n","import { isAbsolute, resolve } from \"node:path\";\n\n/**\n * Resolves `target` against `base`, returning an absolute path.\n * Absolute targets are returned untouched.\n */\nexport function resolveFrom(base: string, target: string): string {\n return isAbsolute(target) ? target : resolve(base, target);\n}\n","import { pathToFileURL } from \"node:url\";\nimport type { Config, ConfigInput } from \"../types/config.js\";\nimport type { Logger } from \"../types/logger.js\";\nimport { CONFIG_FILENAMES } from \"../shared/constants.js\";\nimport { ConfigError } from \"../shared/errors.js\";\nimport { isFile } from \"../utils/fs.js\";\nimport { resolveFrom } from \"../utils/paths.js\";\n\nexport interface LoadConfigOptions {\n /** Directory to search for a config file. */\n cwd: string;\n /** Logger for diagnostics. */\n logger: Logger;\n /** Explicit config file path; bypasses filename discovery. */\n configFile?: string;\n}\n\nexport interface LoadedConfig {\n /** Parsed configuration. Empty object when no config file is present. */\n config: Config;\n /** Absolute path of the file that was loaded, or `null` when none. */\n file: string | null;\n}\n\n/**\n * Locates and loads a `vantris.config.*` file from `cwd`.\n *\n * The actual module evaluation is isolated here so the loading strategy\n * (native TS stripping today; a bundled loader such as esbuild/jiti later)\n * can change without affecting any caller. A missing config is not an error —\n * defaults take over downstream.\n */\nexport async function loadConfig(\n options: LoadConfigOptions,\n): Promise<LoadedConfig> {\n const { cwd, logger } = options;\n\n const file = options.configFile\n ? resolveFrom(cwd, options.configFile)\n : await findConfigFile(cwd);\n\n if (!file) {\n logger.debug(\"No config file found; using defaults.\");\n return { config: {}, file: null };\n }\n\n logger.debug(`Loading config from ${file}`);\n const config = await importConfig(file);\n return { config, file };\n}\n\n/** Returns the first existing config file in {@link CONFIG_FILENAMES}. */\nasync function findConfigFile(cwd: string): Promise<string | null> {\n for (const name of CONFIG_FILENAMES) {\n const candidate = resolveFrom(cwd, name);\n if (await isFile(candidate)) return candidate;\n }\n return null;\n}\n\n/**\n * Imports a config module and normalises its export to a {@link Config}.\n * Relies on the Node runtime's native TypeScript support for `.ts` files.\n */\nasync function importConfig(file: string): Promise<Config> {\n let mod: { default?: unknown };\n try {\n // Cache-bust so repeated loads (e.g. a future config-watch mode) re-read.\n const url = `${pathToFileURL(file).href}?t=${Date.now()}`;\n mod = (await import(url)) as { default?: unknown };\n } catch (cause) {\n throw new ConfigError(`Failed to load config file: ${file}`, { cause });\n }\n\n const exported = mod.default;\n if (exported === undefined) {\n throw new ConfigError(\n `Config file \"${file}\" has no default export. ` +\n `Export your config with \\`export default defineConfig({ ... })\\`.`,\n );\n }\n\n return normalise(exported as ConfigInput, file);\n}\n\n/** Resolves a {@link ConfigInput} (object or factory) into a {@link Config}. */\nasync function normalise(\n input: ConfigInput,\n file: string,\n): Promise<Config> {\n const value = typeof input === \"function\" ? await input() : input;\n\n if (value === null || typeof value !== \"object\") {\n throw new ConfigError(\n `Config file \"${file}\" must export an object (or a function returning one).`,\n );\n }\n\n return value;\n}\n","import type { Config } from \"../types/config.js\";\nimport type {\n ResolvedConfig,\n ResolvedDevConfig,\n} from \"../types/config-resolved.js\";\nimport type { ResolvedPaths } from \"../types/paths.js\";\nimport { DEFAULTS, DEV_DEFAULTS } from \"../shared/constants.js\";\nimport { resolveFrom } from \"../utils/paths.js\";\n\n/**\n * Applies defaults to a raw {@link Config} and resolves every directory to an\n * absolute path. This is the single source of truth for default values and\n * path resolution — no other module should re-derive these.\n *\n * @param raw User configuration (after loading; may be empty).\n * @param cwd Working directory the invocation started from.\n * @param configFile Absolute path of the loaded config file, or `null`.\n */\nexport function resolveConfig(\n raw: Config,\n cwd: string,\n configFile: string | null = null,\n): ResolvedConfig {\n const root = resolveFrom(cwd, raw.root ?? DEFAULTS.root);\n\n const paths: ResolvedPaths = {\n root,\n rootDir: resolveFrom(root, raw.rootDir ?? DEFAULTS.rootDir),\n publicDir: resolveFrom(root, raw.publicDir ?? DEFAULTS.publicDir),\n outDir: resolveFrom(root, raw.outDir ?? DEFAULTS.outDir),\n };\n\n const dev: ResolvedDevConfig = {\n port: raw.dev?.port ?? DEV_DEFAULTS.port,\n host: raw.dev?.host ?? DEV_DEFAULTS.host,\n };\n\n return { raw, paths, dev, configFile };\n}\n","import type { HtmlEntry, HtmlModuleScript } from \"../types/html.js\";\n\n/** Matches `<script ... type=\"module\" ... src=\"...\">` tags (any attr order). */\nconst SCRIPT_TAG = /<script\\b[^>]*>/gi;\nconst TYPE_MODULE = /\\btype\\s*=\\s*[\"']module[\"']/i;\nconst SRC_ATTR = /\\bsrc\\s*=\\s*[\"']([^\"']+)[\"']/i;\n\n/**\n * Parses raw HTML into an {@link HtmlEntry}, extracting `<script type=\"module\">`\n * `src` references.\n *\n * The analysis is intentionally regex-light rather than a full DOM parse: in\n * dev we only need to know the module entry points. This module is the single,\n * isolated home for HTML analysis, so it can grow toward a real parser (for\n * HMR boundaries, plugin transforms, virtual modules) without touching callers.\n */\nexport function parseHtml(file: string, html: string): HtmlEntry {\n const scripts: HtmlModuleScript[] = [];\n\n for (const [tag] of html.matchAll(SCRIPT_TAG)) {\n if (!TYPE_MODULE.test(tag)) continue;\n const src = SRC_ATTR.exec(tag)?.[1];\n if (src) scripts.push({ src });\n }\n\n return { file, html, scripts };\n}\n","import type { HtmlEntry } from \"../types/html.js\";\nimport { HTML_ENTRY_FILENAME } from \"../shared/constants.js\";\nimport { isFile, readTextFile } from \"../utils/fs.js\";\nimport { resolveFrom } from \"../utils/paths.js\";\nimport { parseHtml } from \"./parse.js\";\n\n/**\n * Locates the project's `index.html` entry at `root`.\n *\n * @returns The parsed {@link HtmlEntry}, or `null` if no entry exists.\n */\nexport async function detectHtmlEntry(root: string): Promise<HtmlEntry | null> {\n const file = resolveFrom(root, HTML_ENTRY_FILENAME);\n if (!(await isFile(file))) return null;\n\n const html = await readTextFile(file);\n return parseHtml(file, html);\n}\n","/**\n * The dev-only live-reload client, injected into the served HTML.\n *\n * v0.2.0 does a full page reload on any change. The WebSocket URL is derived\n * from `location.host` so it works regardless of how the host is addressed\n * (`localhost`, `127.0.0.1`, LAN IP). The message payload is ignored for now;\n * v1.x will branch on it to drive HMR instead of a full reload.\n */\nexport const DEV_CLIENT_SCRIPT = `<script type=\"module\">\n // Injected by Vantris dev server — live reload (full page).\n const connect = () => {\n const ws = new WebSocket(\"ws://\" + location.host);\n ws.addEventListener(\"message\", () => location.reload());\n // Reconnect if the dev server restarts.\n ws.addEventListener(\"close\", () => setTimeout(connect, 1000));\n };\n connect();\n</script>`;\n\n/**\n * Injects {@link DEV_CLIENT_SCRIPT} into an HTML document.\n *\n * The script is placed just before `</head>` when present, otherwise before\n * `</body>`, otherwise appended — so it loads before user modules without\n * requiring a well-formed document.\n */\nexport function injectDevClient(html: string): string {\n if (html.includes(\"</head>\")) {\n return html.replace(\"</head>\", `${DEV_CLIENT_SCRIPT}\\n</head>`);\n }\n if (html.includes(\"</body>\")) {\n return html.replace(\"</body>\", `${DEV_CLIENT_SCRIPT}\\n</body>`);\n }\n return `${html}\\n${DEV_CLIENT_SCRIPT}`;\n}\n","import type { Server as HttpServer } from \"node:http\";\nimport { WebSocket, WebSocketServer } from \"ws\";\nimport type { Logger } from \"../types/logger.js\";\nimport { RELOAD_MESSAGE } from \"../shared/constants.js\";\n\n/** Handle over the live-reload WebSocket channel. */\nexport interface ReloadSocket {\n /** Pushes a reload signal to every connected client. */\n broadcastReload(): void;\n /** Number of currently connected clients. */\n readonly clientCount: number;\n /** Closes the WebSocket server and all connections. */\n close(): Promise<void>;\n}\n\nexport interface ReloadSocketOptions {\n /** The HTTP server to share the port with (handles the WS upgrade). */\n server: HttpServer;\n logger: Logger;\n}\n\n/**\n * Attaches a live-reload WebSocket server to an existing HTTP server so the\n * client (injected into the HTML) and the server share a single port.\n *\n * The protocol is intentionally one-way and trivial in v0.2.0: the server\n * pushes {@link RELOAD_MESSAGE} and the client does a full page reload. v1.x\n * will replace this with a richer, bidirectional HMR channel — only this\n * module changes.\n */\nexport function createReloadSocket(options: ReloadSocketOptions): ReloadSocket {\n const { server, logger } = options;\n const wss = new WebSocketServer({ server });\n const clients = new Set<WebSocket>();\n\n wss.on(\"connection\", (socket) => {\n clients.add(socket);\n socket.on(\"close\", () => clients.delete(socket));\n socket.on(\"error\", () => clients.delete(socket));\n });\n\n wss.on(\"error\", (error) => {\n logger.error(`websocket error: ${error.message}`);\n });\n\n return {\n broadcastReload() {\n for (const socket of clients) {\n if (socket.readyState === WebSocket.OPEN) {\n socket.send(RELOAD_MESSAGE);\n }\n }\n },\n get clientCount() {\n return clients.size;\n },\n close() {\n return new Promise((resolveClose) => {\n for (const socket of clients) socket.terminate();\n clients.clear();\n wss.close(() => resolveClose());\n });\n },\n };\n}\n","import { extname } from \"node:path\";\n\n/**\n * Minimal extension → MIME type map for the dev server. Transpiled `.ts`/`.tsx`\n * files are served as JavaScript (see {@link contentTypeFor}). This stays small\n * on purpose; a full asset pipeline is out of scope for v0.2.0.\n */\nconst MIME_TYPES: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".mjs\": \"text/javascript; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".txt\": \"text/plain; charset=utf-8\",\n \".map\": \"application/json; charset=utf-8\",\n};\n\nconst JAVASCRIPT = \"text/javascript; charset=utf-8\";\n\n/**\n * Resolves the `Content-Type` for a file path.\n *\n * @param file Absolute or relative file path.\n * @param transpiled When `true`, the file is served as JavaScript regardless\n * of its source extension (e.g. a transpiled `.ts`).\n */\nexport function contentTypeFor(file: string, transpiled = false): string {\n if (transpiled) return JAVASCRIPT;\n return MIME_TYPES[extname(file).toLowerCase()] ?? \"application/octet-stream\";\n}\n","import { extname } from \"node:path\";\nimport { transform, type Loader } from \"esbuild\";\n\n/** Extensions handled by the on-the-fly TypeScript/JSX transpiler. */\nconst TRANSPILE_EXTENSIONS = new Set([\".ts\", \".tsx\", \".mts\", \".cts\", \".jsx\"]);\n\n/** Whether a file path should be transpiled before being served. */\nexport function shouldTranspile(file: string): boolean {\n return TRANSPILE_EXTENSIONS.has(extname(file).toLowerCase());\n}\n\n/** Maps a file extension to the matching esbuild loader. */\nfunction loaderFor(file: string): Loader {\n switch (extname(file).toLowerCase()) {\n case \".tsx\":\n return \"tsx\";\n case \".jsx\":\n return \"jsx\";\n default:\n return \"ts\";\n }\n}\n\n/**\n * Transpiles a single TypeScript/JSX module to browser-ready ESM using esbuild.\n *\n * This is a **transform only** — no bundling, no resolution, no production\n * optimisation (those belong to the build system in a later version). Import\n * specifiers are left untouched; the dev server resolves them per request.\n * An inline source map is emitted so the browser maps back to the original.\n */\nexport async function transpile(code: string, file: string): Promise<string> {\n const result = await transform(code, {\n loader: loaderFor(file),\n format: \"esm\",\n target: \"es2022\",\n sourcemap: \"inline\",\n sourcefile: file,\n });\n return result.code;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { extname, join, resolve, sep } from \"node:path\";\nimport { isFile } from \"../utils/fs.js\";\nimport { contentTypeFor } from \"./mime.js\";\nimport { shouldTranspile, transpile } from \"./transform.js\";\n\n/** Extensions tried when a request has no extension (bare module imports). */\nconst RESOLVE_EXTENSIONS = [\".ts\", \".tsx\", \".mts\", \".js\", \".mjs\", \".jsx\"];\n\n/** A resolved, ready-to-serve asset. */\nexport interface LoadedAsset {\n /** Response body — text for transpiled/HTML, bytes for binary assets. */\n body: string | Uint8Array;\n /** Resolved `Content-Type`. */\n contentType: string;\n /** `true` when the asset is an HTML document. */\n isHtml: boolean;\n}\n\nexport interface StaticLoaderOptions {\n /** Project root — base for resolving root-relative request paths. */\n root: string;\n /**\n * Source directory. Only files **inside** this directory are reachable via\n * root-relative paths (e.g. `/src/main.ts`). This is what keeps\n * `node_modules`, `package.json`, lockfiles, and config files unreachable.\n */\n rootDir: string;\n /** Public directory whose contents are served at `/` (Vite-style). */\n publicDir: string;\n}\n\n/**\n * Creates a per-request asset loader for the dev server.\n *\n * The serveable surface is an **allowlist** — only the source tree (`rootDir`)\n * and the public directory are exposed; nothing else under the project root is\n * reachable. Files are read fresh on every call so edits show up on reload, and\n * TypeScript/JSX is transpiled on the fly.\n *\n * @returns A function resolving a pathname to a {@link LoadedAsset}, or `null`\n * when nothing matches (or the path is outside the allowlist).\n */\nexport function createStaticLoader(options: StaticLoaderOptions) {\n const root = resolve(options.root);\n const rootDir = resolve(options.rootDir);\n const publicDir = resolve(options.publicDir);\n\n return async function loadAsset(\n pathname: string,\n ): Promise<LoadedAsset | null> {\n const relative = decodeURIComponent(pathname).replace(/^\\/+/, \"\");\n if (!relative) return null;\n\n // 1. Source files: resolved against the root but confined to `rootDir`,\n // so only the source subtree (e.g. `/src/*`) is ever served.\n const source = await resolveConfined(root, rootDir, relative);\n if (source) return readAsset(source);\n\n // 2. Public assets: served at `/` (e.g. `/favicon.svg`).\n const asset = await resolveConfined(publicDir, publicDir, relative);\n if (asset) return readAsset(asset);\n\n return null;\n };\n}\n\n/**\n * Resolves `relative` against `base`, trying extension candidates, and returns\n * the file only if it lands inside `confine` (the allowlist boundary). This\n * single check rejects both path traversal (`..`) and anything outside the\n * permitted directories.\n */\nasync function resolveConfined(\n base: string,\n confine: string,\n relative: string,\n): Promise<string | null> {\n const target = resolve(join(base, relative));\n if (target !== confine && !target.startsWith(confine + sep)) {\n return null;\n }\n\n if (await isFile(target)) return target;\n\n if (!extname(target)) {\n for (const ext of RESOLVE_EXTENSIONS) {\n const candidate = `${target}${ext}`;\n if (await isFile(candidate)) return candidate;\n }\n }\n return null;\n}\n\n/** Reads a file, transpiling it when needed, and resolves its content type. */\nasync function readAsset(file: string): Promise<LoadedAsset> {\n const ext = extname(file).toLowerCase();\n const isHtml = ext === \".html\";\n\n if (shouldTranspile(file)) {\n const source = await readFile(file, \"utf8\");\n return {\n body: await transpile(source, file),\n contentType: contentTypeFor(file, true),\n isHtml: false,\n };\n }\n\n if (isHtml) {\n return {\n body: await readFile(file, \"utf8\"),\n contentType: contentTypeFor(file),\n isHtml: true,\n };\n }\n\n return {\n body: await readFile(file),\n contentType: contentTypeFor(file),\n isHtml: false,\n };\n}\n","import { createServer, type Server as HttpServer } from \"node:http\";\nimport { readFile } from \"node:fs/promises\";\nimport { H3, getRequestURL, toNodeHandler } from \"h3\";\nimport type { H3Event } from \"h3\";\nimport type { Context } from \"../types/context.js\";\nimport type { HtmlEntry } from \"../types/html.js\";\nimport { injectDevClient } from \"../html/index.js\";\nimport { createReloadSocket, type ReloadSocket } from \"./websocket.js\";\nimport { createStaticLoader } from \"./static.js\";\n\n/** Options for {@link startDevServer}. */\nexport interface DevServerOptions {\n ctx: Context;\n /** The detected HTML entry, when present. */\n entry: HtmlEntry | null;\n}\n\n/** A running dev server. */\nexport interface DevServerHandle {\n /** Address the server is listening on, e.g. `http://localhost:3000/`. */\n readonly url: string;\n readonly host: string;\n readonly port: number;\n /** Pushes a full-page reload to every connected browser. */\n broadcastReload(): void;\n /** Stops the HTTP and WebSocket servers. */\n close(): Promise<void>;\n}\n\nconst HTML_HEADERS = {\n \"content-type\": \"text/html; charset=utf-8\",\n \"cache-control\": \"no-cache\",\n} as const;\n\n/**\n * Starts the H3-based development server.\n *\n * Responsibilities are split across the `server` module: this file owns the\n * HTTP routing (H3) and lifecycle, {@link createStaticLoader} owns file\n * resolution + transpilation, and {@link createReloadSocket} owns live reload.\n * The HTTP and WebSocket servers share a single port.\n */\nexport async function startDevServer(\n options: DevServerOptions,\n): Promise<DevServerHandle> {\n const { ctx, entry } = options;\n const { paths, dev } = ctx.config;\n\n const loadAsset = createStaticLoader({\n root: paths.root,\n rootDir: paths.rootDir,\n publicDir: paths.publicDir,\n });\n const entryFile = entry?.file ?? null;\n\n const app = new H3();\n const handler = async (event: H3Event) => {\n const { pathname } = getRequestURL(event);\n\n // 1. A real file on disk (transpiled if it's TypeScript/JSX).\n const asset = await loadAsset(pathname);\n if (asset) {\n if (asset.isHtml) {\n return new Response(injectDevClient(asset.body as string), {\n headers: HTML_HEADERS,\n });\n }\n return new Response(asset.body, {\n headers: { \"content-type\": asset.contentType, \"cache-control\": \"no-cache\" },\n });\n }\n\n // 2. Anything else falls back to the HTML entry. Root files\n // (package.json, configs, node_modules, …) are never read — they are\n // outside the served allowlist — so the client only ever gets index.html.\n if (entryFile) {\n const html = await readFile(entryFile, \"utf8\");\n return new Response(injectDevClient(html), { headers: HTML_HEADERS });\n }\n\n // 3. No HTML entry exists yet.\n return new Response(`404 Not Found: ${pathname}`, {\n status: 404,\n headers: { \"content-type\": \"text/plain; charset=utf-8\" },\n });\n };\n\n app.all(\"/\", handler);\n app.all(\"/**\", handler);\n\n const server: HttpServer = createServer(toNodeHandler(app));\n const reload: ReloadSocket = createReloadSocket({ server, logger: ctx.logger });\n\n await listen(server, dev.port, dev.host);\n\n const url = `http://${dev.host}:${dev.port}/`;\n\n return {\n url,\n host: dev.host,\n port: dev.port,\n broadcastReload: () => reload.broadcastReload(),\n async close() {\n await reload.close();\n await new Promise<void>((resolveClose, reject) => {\n server.close((err) => (err ? reject(err) : resolveClose()));\n });\n },\n };\n}\n\n/** Promisified `server.listen` with error propagation. */\nfunction listen(server: HttpServer, port: number, host: string): Promise<void> {\n return new Promise((resolveListen, reject) => {\n const onError = (err: NodeJS.ErrnoException) => {\n server.removeListener(\"error\", onError);\n reject(\n err.code === \"EADDRINUSE\"\n ? new Error(`Port ${port} is already in use.`)\n : err,\n );\n };\n server.once(\"error\", onError);\n server.listen(port, host, () => {\n server.removeListener(\"error\", onError);\n resolveListen();\n });\n });\n}\n","import type { Logger } from \"../types/logger.js\";\nimport { APP_NAME } from \"./constants.js\";\n\nexport interface LoggerOptions {\n /** When `false`, `debug` calls are dropped. @default false */\n verbose?: boolean;\n /** Sink for output. Defaults to the console; overridable for tests. */\n sink?: Pick<Console, \"log\" | \"warn\" | \"error\">;\n}\n\nconst prefix = `[${APP_NAME}]`;\n\n/**\n * Creates the default console-backed {@link Logger}.\n *\n * The sink is injectable so tests can capture output, and verbosity is a\n * construction-time concern rather than a global flag.\n */\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const { verbose = false, sink = console } = options;\n\n return {\n info(message) {\n sink.log(`${prefix} ${message}`);\n },\n warn(message) {\n sink.warn(`${prefix} ${message}`);\n },\n error(message) {\n sink.error(`${prefix} ${message}`);\n },\n debug(message) {\n if (verbose) sink.log(`${prefix} ${message}`);\n },\n };\n}\n","import type { Context } from \"../types/context.js\";\nimport type { Logger } from \"../types/logger.js\";\nimport { loadConfig } from \"../config/load.js\";\nimport { resolveConfig } from \"../config/resolve.js\";\n\nexport interface CreateContextOptions {\n /** Working directory the command was invoked from. */\n cwd: string;\n /** Injected logger. */\n logger: Logger;\n /** Optional explicit config file path. */\n configFile?: string;\n}\n\n/**\n * Builds the {@link Context} shared by every command: it loads the user config,\n * applies defaults, resolves paths, and bundles the injected services.\n *\n * Centralising construction here means commands never reach for global state —\n * everything they need arrives through the returned context.\n */\nexport async function createContext(\n options: CreateContextOptions,\n): Promise<Context> {\n const { cwd, logger } = options;\n\n const loaded = await loadConfig({\n cwd,\n logger,\n ...(options.configFile !== undefined\n ? { configFile: options.configFile }\n : {}),\n });\n\n const config = resolveConfig(loaded.config, cwd, loaded.file);\n\n return { cwd, config, logger };\n}\n","import { watch, type FSWatcher } from \"chokidar\";\nimport type { Logger } from \"../types/logger.js\";\n\n/** A change reported by the {@link Watcher}. */\nexport interface WatchEvent {\n /** What happened to the file. */\n kind: \"add\" | \"change\" | \"unlink\";\n /** Absolute path of the affected file. */\n file: string;\n}\n\nexport interface WatcherOptions {\n /** Directory tree to watch (typically `rootDir`). */\n dir: string;\n logger: Logger;\n /** Called on every relevant filesystem change. */\n onChange: (event: WatchEvent) => void;\n}\n\n/** A running filesystem watcher. */\nexport interface Watcher {\n /** Stops watching and releases OS resources. */\n close(): Promise<void>;\n}\n\n/**\n * Watches a directory tree and reports file changes.\n *\n * This is the single home for filesystem watching — the dev server depends on\n * the {@link Watcher} interface, not on chokidar, so the backing implementation\n * can change (or gain HMR-oriented metadata) without rippling outward.\n */\nexport function createWatcher(options: WatcherOptions): Watcher {\n const { dir, logger, onChange } = options;\n\n const watcher: FSWatcher = watch(dir, {\n ignoreInitial: true,\n persistent: true,\n ignored: (path) =>\n path.includes(\"node_modules\") || /(^|[/\\\\])\\.[^/\\\\]/.test(path),\n });\n\n const emit = (kind: WatchEvent[\"kind\"]) => (file: string) => {\n logger.debug(`watch ${kind}: ${file}`);\n onChange({ kind, file });\n };\n\n watcher\n .on(\"add\", emit(\"add\"))\n .on(\"change\", emit(\"change\"))\n .on(\"unlink\", emit(\"unlink\"))\n .on(\"error\", (error) =>\n logger.error(`watcher error: ${(error as Error).message}`),\n );\n\n return {\n close: () => watcher.close(),\n };\n}\n","import { relative } from \"node:path\";\nimport type { Context } from \"../types/context.js\";\nimport type { HtmlEntry } from \"../types/html.js\";\nimport { detectHtmlEntry } from \"../html/index.js\";\nimport { ensureDir } from \"../utils/fs.js\";\n\n/** Renders a path relative to the project root for tidy log output. */\nfunction rel(ctx: Context, target: string): string {\n return relative(ctx.config.paths.root, target) || \".\";\n}\n\n/**\n * Logs the resolved configuration and detects the HTML entry — the shared\n * preamble every command runs before delegating to its (future) engine.\n *\n * @returns The detected HTML entry, or `null` when none exists.\n */\nexport async function inspectProject(ctx: Context): Promise<HtmlEntry | null> {\n const { paths, configFile } = ctx.config;\n\n ctx.logger.info(\n `config: ${configFile ? rel(ctx, configFile) : \"defaults (no config file)\"}`,\n );\n ctx.logger.info(`rootDir: ${rel(ctx, paths.rootDir)}`);\n ctx.logger.info(`publicDir: ${rel(ctx, paths.publicDir)}`);\n ctx.logger.info(`outDir: ${rel(ctx, paths.outDir)}`);\n\n const entry = await detectHtmlEntry(paths.root);\n if (entry) {\n ctx.logger.info(`html entry: ${rel(ctx, entry.file)}`);\n } else {\n ctx.logger.warn(\n \"no index.html found at the project root; nothing to serve yet.\",\n );\n }\n\n return entry;\n}\n\n/** Ensures the given directories exist, creating them as needed. */\nexport async function prepareDirectories(\n ctx: Context,\n dirs: readonly string[],\n): Promise<void> {\n for (const dir of dirs) {\n await ensureDir(dir);\n ctx.logger.debug(`prepared directory: ${dir}`);\n }\n}\n","import { relative } from \"node:path\";\nimport type { Command } from \"../types/command.js\";\nimport { startDevServer } from \"../server/index.js\";\nimport { createWatcher } from \"../shared/watcher.js\";\nimport { inspectProject, prepareDirectories } from \"./support.js\";\n\n/** Coalesce a burst of filesystem events into a single reload. */\nconst RELOAD_DEBOUNCE_MS = 50;\n\n/**\n * `vantris dev` — start the development server.\n *\n * Runtime flow: load config (via context) → inspect project → init dev server\n * (HTTP + WebSocket) → start the file watcher → trigger live reload on change.\n * Runs until interrupted (Ctrl-C), then shuts everything down cleanly.\n */\nexport const dev: Command = {\n name: \"dev\",\n description: \"Start the development server\",\n async run(ctx) {\n const { root, rootDir, publicDir } = ctx.config.paths;\n await prepareDirectories(ctx, [rootDir, publicDir]);\n\n const entry = await inspectProject(ctx);\n\n const server = await startDevServer({ ctx, entry });\n ctx.logger.info(`ready — dev server running at ${server.url}`);\n\n let timer: NodeJS.Timeout | undefined;\n const watcher = createWatcher({\n dir: rootDir,\n logger: ctx.logger,\n onChange: ({ kind, file }) => {\n ctx.logger.info(`${kind}: ${relative(root, file)} — reloading`);\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => server.broadcastReload(), RELOAD_DEBOUNCE_MS);\n },\n });\n\n await waitForShutdown();\n\n ctx.logger.info(\"shutting down…\");\n if (timer) clearTimeout(timer);\n await watcher.close();\n await server.close();\n },\n};\n\n/** Resolves when the process receives an interrupt/terminate signal. */\nfunction waitForShutdown(): Promise<void> {\n return new Promise((resolve) => {\n const onSignal = () => {\n process.removeListener(\"SIGINT\", onSignal);\n process.removeListener(\"SIGTERM\", onSignal);\n resolve();\n };\n process.once(\"SIGINT\", onSignal);\n process.once(\"SIGTERM\", onSignal);\n });\n}\n","import type { Context } from \"../types/context.js\";\nimport type { HtmlEntry } from \"../types/html.js\";\n\n/** Options handed to the build pipeline. */\nexport interface BuildOptions {\n ctx: Context;\n /** The detected HTML entry, when present. */\n entry: HtmlEntry | null;\n}\n\n/**\n * Produces a production build into `outDir`.\n *\n * Reserved for a future version (planned: Rolldown for bundling, esbuild for\n * transforms). The seam exists now so `commands/build` can already delegate\n * here; only this file changes when the engine is implemented.\n */\nexport async function runBuild(options: BuildOptions): Promise<void> {\n const { ctx } = options;\n ctx.logger.info(\n \"build is not implemented in v0.1.0 (planned: Rolldown + esbuild).\",\n );\n}\n","import type { Command } from \"../types/command.js\";\nimport { runBuild } from \"../build/index.js\";\nimport { inspectProject, prepareDirectories } from \"./support.js\";\n\n/** `vantris build` — produce a production build. */\nexport const build: Command = {\n name: \"build\",\n description: \"Build the project for production\",\n async run(ctx) {\n const { rootDir, publicDir, outDir } = ctx.config.paths;\n await prepareDirectories(ctx, [rootDir, publicDir, outDir]);\n\n const entry = await inspectProject(ctx);\n await runBuild({ ctx, entry });\n },\n};\n","import type { Context } from \"../types/context.js\";\n\n/** Options handed to the preview server. */\nexport interface PreviewOptions {\n ctx: Context;\n}\n\n/**\n * Serves a previously produced production build from `outDir`.\n *\n * Reserved for a future version (planned: a static server over the build\n * output). The seam exists now so `commands/preview` can already delegate\n * here; only this file changes when the engine is implemented.\n */\nexport async function runPreview(options: PreviewOptions): Promise<void> {\n const { ctx } = options;\n ctx.logger.info(\n \"preview is not implemented in v0.1.0 (planned: static server over outDir).\",\n );\n}\n","import type { Command } from \"../types/command.js\";\nimport { runPreview } from \"../preview/index.js\";\nimport { inspectProject, prepareDirectories } from \"./support.js\";\n\n/** `vantris preview` — serve a production build locally. */\nexport const preview: Command = {\n name: \"preview\",\n description: \"Locally preview a production build\",\n async run(ctx) {\n await prepareDirectories(ctx, [ctx.config.paths.outDir]);\n\n await inspectProject(ctx);\n await runPreview({ ctx });\n },\n};\n","import type { Command } from \"../types/command.js\";\nimport { dev } from \"./dev.js\";\nimport { build } from \"./build.js\";\nimport { preview } from \"./preview.js\";\n\n/**\n * The command registry. The CLI routes purely against this map, so adding a\n * command is a one-line registration here plus its module — no CLI changes.\n */\nexport const commands: Readonly<Record<string, Command>> = {\n [dev.name]: dev,\n [build.name]: build,\n [preview.name]: preview,\n};\n\nexport type CommandName = keyof typeof commands;\n\nexport { dev, build, preview };\n","import { commands } from \"../commands/index.js\";\nimport { APP_NAME, VERSION } from \"../shared/constants.js\";\n\n/** Builds the help text listing every registered command. */\nexport function helpText(): string {\n const lines = [\n `${APP_NAME} v${VERSION} — a modern bundler for JavaScript/TypeScript`,\n \"\",\n \"Usage:\",\n ` ${APP_NAME} <command> [options]`,\n \"\",\n \"Commands:\",\n ];\n\n const width = Math.max(...Object.keys(commands).map((n) => n.length));\n for (const command of Object.values(commands)) {\n lines.push(` ${command.name.padEnd(width)} ${command.description}`);\n }\n\n lines.push(\n \"\",\n \"Options:\",\n \" -h, --help Show this help\",\n \" -v, --version Show the version number\",\n );\n\n return lines.join(\"\\n\");\n}\n\n/** Builds the version line. */\nexport function versionText(): string {\n return `${APP_NAME} v${VERSION}`;\n}\n","import type { Logger } from \"../types/logger.js\";\nimport { commands } from \"../commands/index.js\";\nimport { createContext } from \"../shared/context.js\";\nimport { createLogger } from \"../shared/logger.js\";\nimport { helpText, versionText } from \"./help.js\";\n\nexport interface RunOptions {\n /** Working directory; defaults to `process.cwd()`. */\n cwd?: string;\n /** Logger override, primarily for tests. */\n logger?: Logger;\n}\n\n/** Process exit codes used by the CLI. */\nexport const enum ExitCode {\n Ok = 0,\n Error = 1,\n}\n\n/**\n * Parses arguments and routes to a command. This is the entire CLI surface:\n * it owns argument handling and dispatch only — never command behaviour, which\n * lives behind the {@link commands} registry.\n *\n * @returns A process exit code.\n */\nexport async function run(\n argv: readonly string[],\n options: RunOptions = {},\n): Promise<ExitCode> {\n const verbose = argv.includes(\"--verbose\") || argv.includes(\"--debug\");\n const logger = options.logger ?? createLogger({ verbose });\n const cwd = options.cwd ?? process.cwd();\n\n const [first, ...rest] = argv.filter((arg) => !isGlobalFlag(arg));\n\n if (!first || first === \"--help\" || first === \"-h\" || first === \"help\") {\n logger.info(helpText());\n return ExitCode.Ok;\n }\n\n if (first === \"--version\" || first === \"-v\") {\n logger.info(versionText());\n return ExitCode.Ok;\n }\n\n const command = commands[first];\n if (!command) {\n logger.error(`Unknown command: \"${first}\"`);\n logger.info(helpText());\n return ExitCode.Error;\n }\n\n const ctx = await createContext({ cwd, logger });\n await command.run(ctx, rest);\n return ExitCode.Ok;\n}\n\n/** Flags handled by the runner itself rather than passed to commands. */\nfunction isGlobalFlag(arg: string): boolean {\n return arg === \"--verbose\" || arg === \"--debug\";\n}\n"]}
|