@idlesummer/pen 0.2.0 → 0.2.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/bin.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import{a as e,f as t,i as n,n as r,r as i,t as a}from"./element-tree-DoH7UgRL.mjs";import{join as o,resolve as s}from"path";import{pathToFileURL as c}from"url";import{existsSync as l}from"fs";import{Command as u}from"commander";import{duration as d,fileList as f,pipe as p}from"@idlesummer/tasker";import{mkdir as m,writeFile as h}from"fs/promises";import{build as g}from"rolldown";import _ from"rollup-plugin-node-externals";var v=Object.create,y=Object.defineProperty,b=Object.getOwnPropertyDescriptor,x=Object.getOwnPropertyNames,S=Object.getPrototypeOf,C=Object.prototype.hasOwnProperty,w=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),T=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=x(t),a=0,o=i.length,s;a<o;a++)s=i[a],!C.call(e,s)&&s!==n&&y(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=b(t,s))||r.enumerable});return e},E=(e,t,n)=>(n=e==null?{}:v(S(e)),T(t||!e||!e.__esModule?y(n,`default`,{value:e,enumerable:!0}):n,e));const D=`@idlesummer/pen`,O=`0.2.0`,k=`@idlesummer/pen`.split(`/`)?.[1]??`@idlesummer/pen`;var A=E(w(((e,t)=>{let n=process||{},r=n.argv||[],i=n.env||{},a=!(i.NO_COLOR||r.includes(`--no-color`))&&(!!i.FORCE_COLOR||r.includes(`--color`)||n.platform===`win32`||(n.stdout||{}).isTTY&&i.TERM!==`dumb`||!!i.CI),o=(e,t,n=e)=>r=>{let i=``+r,a=i.indexOf(t,e.length);return~a?e+s(i,t,n,a)+t:e+i+t},s=(e,t,n,r)=>{let i=``,a=0;do i+=e.substring(a,r)+n,a=r+t.length,r=e.indexOf(t,a);while(~r);return i+e.substring(a)},c=(e=a)=>{let t=e?o:()=>String;return{isColorSupported:e,reset:t(`\x1B[0m`,`\x1B[0m`),bold:t(`\x1B[1m`,`\x1B[22m`,`\x1B[22m\x1B[1m`),dim:t(`\x1B[2m`,`\x1B[22m`,`\x1B[22m\x1B[2m`),italic:t(`\x1B[3m`,`\x1B[23m`),underline:t(`\x1B[4m`,`\x1B[24m`),inverse:t(`\x1B[7m`,`\x1B[27m`),hidden:t(`\x1B[8m`,`\x1B[28m`),strikethrough:t(`\x1B[9m`,`\x1B[29m`),black:t(`\x1B[30m`,`\x1B[39m`),red:t(`\x1B[31m`,`\x1B[39m`),green:t(`\x1B[32m`,`\x1B[39m`),yellow:t(`\x1B[33m`,`\x1B[39m`),blue:t(`\x1B[34m`,`\x1B[39m`),magenta:t(`\x1B[35m`,`\x1B[39m`),cyan:t(`\x1B[36m`,`\x1B[39m`),white:t(`\x1B[37m`,`\x1B[39m`),gray:t(`\x1B[90m`,`\x1B[39m`),bgBlack:t(`\x1B[40m`,`\x1B[49m`),bgRed:t(`\x1B[41m`,`\x1B[49m`),bgGreen:t(`\x1B[42m`,`\x1B[49m`),bgYellow:t(`\x1B[43m`,`\x1B[49m`),bgBlue:t(`\x1B[44m`,`\x1B[49m`),bgMagenta:t(`\x1B[45m`,`\x1B[49m`),bgCyan:t(`\x1B[46m`,`\x1B[49m`),bgWhite:t(`\x1B[47m`,`\x1B[49m`),blackBright:t(`\x1B[90m`,`\x1B[39m`),redBright:t(`\x1B[91m`,`\x1B[39m`),greenBright:t(`\x1B[92m`,`\x1B[39m`),yellowBright:t(`\x1B[93m`,`\x1B[39m`),blueBright:t(`\x1B[94m`,`\x1B[39m`),magentaBright:t(`\x1B[95m`,`\x1B[39m`),cyanBright:t(`\x1B[96m`,`\x1B[39m`),whiteBright:t(`\x1B[97m`,`\x1B[39m`),bgBlackBright:t(`\x1B[100m`,`\x1B[49m`),bgRedBright:t(`\x1B[101m`,`\x1B[49m`),bgGreenBright:t(`\x1B[102m`,`\x1B[49m`),bgYellowBright:t(`\x1B[103m`,`\x1B[49m`),bgBlueBright:t(`\x1B[104m`,`\x1B[49m`),bgMagentaBright:t(`\x1B[105m`,`\x1B[49m`),bgCyanBright:t(`\x1B[106m`,`\x1B[49m`),bgWhiteBright:t(`\x1B[107m`,`\x1B[49m`)}};t.exports=c(),t.exports.createColors=c}))(),1);const j={name:`Building file tree`,onSuccess:(e,t)=>`Built file tree (${d(t)})`,run:async t=>({fileTree:e(t.appDir)})},M={name:`Building segment tree...`,onSuccess:(e,t)=>`Built segment tree (${d(t)})`,run:async e=>({segmentTree:n(e.fileTree)})},N={name:`Building route manifest`,onSuccess:(e,t)=>`Built route manifest (${d(t)})`,run:async e=>({manifest:i(e.segmentTree,e.outDir)})},P={name:`Building component map`,onSuccess:(e,t)=>`Built component map (${d(t)})`,run:async e=>({componentMap:r(e.manifest)})},F={name:`Building element trees`,onSuccess:(e,t)=>`Built element trees (${d(t)})`,run:async e=>({elementTrees:a(e.manifest,e.componentMap)})},I={name:`Writing manifest.ts`,onSuccess:(e,t)=>`Saved manifest.ts (${d(t)})`,run:async e=>{let t=o(e.outDir,`generated`),n=o(t,`manifest.ts`),r=[`// Auto-generated by ${D}`,`// Do not manually edit this file`,`// NOTE: This file is kept for documentation/debugging.`,`// Runtime uses pre-built routes from routes.ts instead.`,``,`import type { RouteManifest } from '${D}'`,``,`export const manifest: RouteManifest = ${JSON.stringify(e.manifest,null,2)} as const`,``].join(`
2
+ import{a as e,f as t,i as n,n as r,r as i,t as a}from"./element-tree-DoH7UgRL.mjs";import{join as o,resolve as s}from"path";import{pathToFileURL as c}from"url";import{existsSync as l}from"fs";import{Command as u}from"commander";import{duration as d,fileList as f,pipe as p}from"@idlesummer/tasker";import{mkdir as m,writeFile as h}from"fs/promises";import{build as g}from"rolldown";import _ from"rollup-plugin-node-externals";var v=Object.create,y=Object.defineProperty,b=Object.getOwnPropertyDescriptor,x=Object.getOwnPropertyNames,S=Object.getPrototypeOf,C=Object.prototype.hasOwnProperty,w=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),T=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=x(t),a=0,o=i.length,s;a<o;a++)s=i[a],!C.call(e,s)&&s!==n&&y(e,s,{get:(e=>t[e]).bind(null,s),enumerable:!(r=b(t,s))||r.enumerable});return e},E=(e,t,n)=>(n=e==null?{}:v(S(e)),T(t||!e||!e.__esModule?y(n,`default`,{value:e,enumerable:!0}):n,e));const D=`@idlesummer/pen`,O=`0.2.1`,k=`@idlesummer/pen`.split(`/`)?.[1]??`@idlesummer/pen`;var A=E(w(((e,t)=>{let n=process||{},r=n.argv||[],i=n.env||{},a=!(i.NO_COLOR||r.includes(`--no-color`))&&(!!i.FORCE_COLOR||r.includes(`--color`)||n.platform===`win32`||(n.stdout||{}).isTTY&&i.TERM!==`dumb`||!!i.CI),o=(e,t,n=e)=>r=>{let i=``+r,a=i.indexOf(t,e.length);return~a?e+s(i,t,n,a)+t:e+i+t},s=(e,t,n,r)=>{let i=``,a=0;do i+=e.substring(a,r)+n,a=r+t.length,r=e.indexOf(t,a);while(~r);return i+e.substring(a)},c=(e=a)=>{let t=e?o:()=>String;return{isColorSupported:e,reset:t(`\x1B[0m`,`\x1B[0m`),bold:t(`\x1B[1m`,`\x1B[22m`,`\x1B[22m\x1B[1m`),dim:t(`\x1B[2m`,`\x1B[22m`,`\x1B[22m\x1B[2m`),italic:t(`\x1B[3m`,`\x1B[23m`),underline:t(`\x1B[4m`,`\x1B[24m`),inverse:t(`\x1B[7m`,`\x1B[27m`),hidden:t(`\x1B[8m`,`\x1B[28m`),strikethrough:t(`\x1B[9m`,`\x1B[29m`),black:t(`\x1B[30m`,`\x1B[39m`),red:t(`\x1B[31m`,`\x1B[39m`),green:t(`\x1B[32m`,`\x1B[39m`),yellow:t(`\x1B[33m`,`\x1B[39m`),blue:t(`\x1B[34m`,`\x1B[39m`),magenta:t(`\x1B[35m`,`\x1B[39m`),cyan:t(`\x1B[36m`,`\x1B[39m`),white:t(`\x1B[37m`,`\x1B[39m`),gray:t(`\x1B[90m`,`\x1B[39m`),bgBlack:t(`\x1B[40m`,`\x1B[49m`),bgRed:t(`\x1B[41m`,`\x1B[49m`),bgGreen:t(`\x1B[42m`,`\x1B[49m`),bgYellow:t(`\x1B[43m`,`\x1B[49m`),bgBlue:t(`\x1B[44m`,`\x1B[49m`),bgMagenta:t(`\x1B[45m`,`\x1B[49m`),bgCyan:t(`\x1B[46m`,`\x1B[49m`),bgWhite:t(`\x1B[47m`,`\x1B[49m`),blackBright:t(`\x1B[90m`,`\x1B[39m`),redBright:t(`\x1B[91m`,`\x1B[39m`),greenBright:t(`\x1B[92m`,`\x1B[39m`),yellowBright:t(`\x1B[93m`,`\x1B[39m`),blueBright:t(`\x1B[94m`,`\x1B[39m`),magentaBright:t(`\x1B[95m`,`\x1B[39m`),cyanBright:t(`\x1B[96m`,`\x1B[39m`),whiteBright:t(`\x1B[97m`,`\x1B[39m`),bgBlackBright:t(`\x1B[100m`,`\x1B[49m`),bgRedBright:t(`\x1B[101m`,`\x1B[49m`),bgGreenBright:t(`\x1B[102m`,`\x1B[49m`),bgYellowBright:t(`\x1B[103m`,`\x1B[49m`),bgBlueBright:t(`\x1B[104m`,`\x1B[49m`),bgMagentaBright:t(`\x1B[105m`,`\x1B[49m`),bgCyanBright:t(`\x1B[106m`,`\x1B[49m`),bgWhiteBright:t(`\x1B[107m`,`\x1B[49m`)}};t.exports=c(),t.exports.createColors=c}))(),1);const j={name:`Building file tree`,onSuccess:(e,t)=>`Built file tree (${d(t)})`,run:async t=>({fileTree:e(t.appDir)})},M={name:`Building segment tree...`,onSuccess:(e,t)=>`Built segment tree (${d(t)})`,run:async e=>({segmentTree:n(e.fileTree)})},N={name:`Building route manifest`,onSuccess:(e,t)=>`Built route table (${d(t)})`,run:async e=>({manifest:i(e.segmentTree,e.outDir)})},P={name:`Building component map`,onSuccess:(e,t)=>`Built component map (${d(t)})`,run:async e=>({componentMap:r(e.manifest)})},F={name:`Building element trees`,onSuccess:(e,t)=>`Built element trees (${d(t)})`,run:async e=>({elementTrees:a(e.manifest,e.componentMap)})},I={name:`Writing route-table.ts`,onSuccess:(e,t)=>`Saved route-table.ts (${d(t)})`,run:async e=>{let t=o(e.outDir,`generated`),n=o(t,`route-table.ts`),r=[`// Auto-generated by ${D}`,`// Do not manually edit this file`,`// NOTE: This file is kept for documentation/debugging.`,`// Runtime uses pre-built routes from routes.ts instead.`,``,`import type { RouteTable } from '${D}'`,``,`export const manifest: RouteTable = ${JSON.stringify(e.manifest,null,2)} as const`,``].join(`
3
3
  `);await m(t,{recursive:!0}),await h(n,r,`utf-8`)}},L={name:`Writing element-tree.ts`,onSuccess:(e,t)=>`Saved element-tree.ts (${d(t)})`,run:async e=>{let t=o(e.outDir,`generated`),n=o(t,`element-tree.ts`),r=[`// Auto-generated by ${D}`,`// Do not manually edit this file`,`// NOTE: This file is kept for documentation/debugging.`,``,`import type { ElementTreeMap } from '${D}'`,``,`export const elementTrees: ElementTreeMap = ${JSON.stringify(e.elementTrees,null,2)} as const`,``].join(`
4
- `);await m(t,{recursive:!0}),await h(n,r,`utf-8`)}},R={name:`Writing components.ts`,onSuccess:(e,t)=>`Saved components.ts (${d(t)})`,run:async e=>{let t=o(e.outDir,`generated`),n=o(t,`components.ts`),r=e.componentMap,i=[`// Auto-generated by ${D}`,`// Do not manually edit this file`,``,`import type { ComponentMap } from '${D}'`,``,`export const componentMap: ComponentMap = ${JSON.stringify(r,null,2)} as const`,``].join(`
5
- `);await m(t,{recursive:!0}),await h(n,i,`utf-8`)}},z={name:`Writing routes.ts`,onSuccess:(e,t)=>`Saved routes.ts (${d(t)})`,run:async e=>{let t=o(e.outDir,`generated`),n=o(t,`routes.ts`),r=e.elementTrees,i=e.componentMap,a=Object.keys(i).map((e,t)=>`import Component${t} from '${e}'`).join(`
4
+ `);await m(t,{recursive:!0}),await h(n,r,`utf-8`)}},R={name:`Writing component-map.ts`,onSuccess:(e,t)=>`Saved component-map.ts (${d(t)})`,run:async e=>{let t=o(e.outDir,`generated`),n=o(t,`component-map.ts`),r=e.componentMap,i=[`// Auto-generated by ${D}`,`// Do not manually edit this file`,``,`import type { ComponentMap } from '${D}'`,``,`export const componentMap: ComponentMap = ${JSON.stringify(r,null,2)} as const`,``].join(`
5
+ `);await m(t,{recursive:!0}),await h(n,i,`utf-8`)}},z={name:`Writing compiled-routes.ts`,onSuccess:(e,t)=>`Saved compiled-routes.ts (${d(t)})`,run:async e=>{let t=o(e.outDir,`generated`),n=o(t,`compiled-routes.ts`),r=e.elementTrees,i=e.componentMap,a=Object.keys(i).map((e,t)=>`import Component${t} from '${e}'`).join(`
6
6
  `),s=[];for(let[e,t]of Object.entries(r)){let n=` ${B(t).replace(/\n/g,`
7
- `)}`;s.push(` '${e}':\n${n},`)}let c=[`// Auto-generated by ${D}`,`// Do not manually edit this file`,``,`import type { CompiledRoutes } from '${D}'`,`import { createElement } from 'react'`,``,a,``,`// Compiled route elements generated at build time`,`export const routes: CompiledRoutes = {`,s.join(`
7
+ `)}`;s.push(` '${e}':\n${n},`)}let c=[`// Auto-generated by ${D}`,`// Do not manually edit this file`,``,`import type { CompiledRoutes } from '${D}'`,`import { createElement } from 'react'`,``,a,``,`// Compiled route elements generated at build time`,`export const compiledRoutes: CompiledRoutes = {`,s.join(`
8
8
  `),`} as const`,``].join(`
9
- `);await m(t,{recursive:!0}),await h(n,c,`utf-8`)}};function B(e,t=0){let n=` `.repeat(t),r=Object.entries(e.props).map(([e,t])=>`${e}: ${t}`).join(`, `);if(!e.children)return`createElement(${e.component}, { ${r} })`;let i=B(e.children,t+1);return`createElement(${e.component}, { ${r} },\n${n} ${i}\n${n})`}const V={name:`Writing entry.ts`,onSuccess:(e,t)=>`Saved entry.ts (${d(t)})`,run:async e=>{let t=o(e.outDir,`generated`),n=o(t,`entry.ts`),r=[`// Auto-generated by ${D}`,`// Do not manually edit this file`,``,`import { createElement } from 'react'`,`import { render } from 'ink'`,`import { App } from '${D}'`,`import { routes } from './routes'`,``,`export async function run(initialUrl: string) {`,` const element = createElement(App, { initialUrl, routes })`,` const { waitUntilExit } = render(element)`,` await waitUntilExit()`,`}`,``].join(`
9
+ `);await m(t,{recursive:!0}),await h(n,c,`utf-8`)}};function B(e,t=0){let n=` `.repeat(t),r=Object.entries(e.props).map(([e,t])=>`${e}: ${t}`).join(`, `);if(!e.children)return`createElement(${e.component}, { ${r} })`;let i=B(e.children,t+1);return`createElement(${e.component}, { ${r} },\n${n} ${i}\n${n})`}const V={name:`Writing entry.ts`,onSuccess:(e,t)=>`Saved entry.ts (${d(t)})`,run:async e=>{let t=o(e.outDir,`generated`),n=o(t,`entry.ts`),r=[`// Auto-generated by ${D}`,`// Do not manually edit this file`,``,`import { createElement } from 'react'`,`import { render } from 'ink'`,`import { App } from '${D}'`,`import { compiledRoutes as routes } from './compiled-routes'`,``,`export async function run(initialUrl: string) {`,` const element = createElement(App, { initialUrl, routes })`,` const { waitUntilExit } = render(element)`,` await waitUntilExit()`,`}`,``].join(`
10
10
  `);await m(t,{recursive:!0}),await h(n,r,`utf-8`)}},H={name:`Compiling application`,onSuccess:(e,t)=>`Compiled application (${d(t)})`,onError:e=>`Compilation failed: ${e.message}`,run:async e=>{await g({input:s(o(e.outDir,`generated`,`entry.ts`)),platform:`node`,resolve:{extensions:[`.ts`,`.tsx`,`.js`,`.jsx`]},plugins:[_()],output:{dir:s(o(e.outDir,`dist`)),format:`esm`,sourcemap:!0,minify:!0}})}},U={name:`build`,desc:`Build the route manifest and compile application`,action:async()=>{try{let{appDir:e,outDir:n,emitMetadata:r}=await t();console.log(A.default.cyan(` Starting production build...
11
11
  `)),console.log(A.default.bold(` ✎ ${k} v${O}\n`)),console.log(A.default.dim(` entry: ${e}`)),console.log(A.default.dim(` target: node24`)),console.log(A.default.dim(` output: ${n}`)),console.log();let{duration:i}=await p([j,M,N,P,F,r&&I,r&&L,r&&R,z,V,H]).run({appDir:e,outDir:n});console.log(),console.log(f(n,`**/*`)),console.log(),console.log(`${A.default.green(`✓`)} Built in ${A.default.bold(d(i))}`),console.log()}catch(e){console.error(`${A.default.red(`✗`)} Build failed`),console.log();let t=e instanceof Error?e.message:String(e);console.error(A.default.red(t)),console.log(),process.exit(1)}}},W={name:`init`,desc:`Initialize a new Pen project`,action:async()=>{if(console.log(A.default.cyan(`\n Initializing ${k} project...\n`)),l(`pen.config.ts`)){console.error(A.default.yellow(`⚠`)+` Project already initialized`),console.error(A.default.dim(` pen.config.ts already exists`));return}await h(`pen.config.ts`,[`import { defineConfig } from '${D}'`,``,`export default defineConfig({`,` appDir: './src/app',`,` outDir: './.pen',`,`})`,``].join(`
12
12
  `),`utf-8`),console.log(A.default.green(`✓`)+` Created pen.config.ts`);let e=`./src/app`;await m(e,{recursive:!0});let t=[`import { Box, Text } from 'ink'`,`import type { ReactNode } from 'react'`,``,`export default function Layout({ children }: { children?: ReactNode }) {`,` return (`,` <Box flexDirection="column" padding={1}>`,` <Box marginBottom={1} borderStyle="round" borderColor="cyan" paddingX={2}>`,` <Text bold color="cyan">Welcome to Pen</Text>`,` </Box>`,` {children}`,` </Box>`,` )`,`}`,``].join(`
package/dist/bin.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.mjs","names":["rolldownBuild","build","pc","pc","pc","run","build"],"sources":["../src/pen/constants.ts","../node_modules/picocolors/picocolors.js","../src/cli/commands/build/tasks/build-file-tree.ts","../src/cli/commands/build/tasks/build-segment-tree.ts","../src/cli/commands/build/tasks/build-route-manifest.ts","../src/cli/commands/build/tasks/build-component-map.ts","../src/cli/commands/build/tasks/build-element-tree.ts","../src/cli/commands/build/tasks/write-manifest-file.ts","../src/cli/commands/build/tasks/write-element-tree-file.ts","../src/cli/commands/build/tasks/write-component-map-file.ts","../src/cli/commands/build/tasks/write-routes-file.ts","../src/cli/commands/build/tasks/write-entry-file.ts","../src/cli/commands/build/tasks/compile-application.ts","../src/cli/commands/build/index.ts","../src/cli/commands/init/index.ts","../src/cli/commands/start/index.ts","../src/cli/index.ts","../src/bin.ts"],"sourcesContent":["// Build-time globals injected by tsdown via `define`.\r\n// tsdown replaces these placeholders with actual values\r\n// from package.json at compile time.\r\n\r\ndeclare const __DESCRIPTION__: string\r\ndeclare const __PACKAGE_NAME__: string\r\ndeclare const __VERSION__: string\r\n\r\n// Package metadata\r\nexport const DESCRIPTION = __DESCRIPTION__\r\nexport const PACKAGE_NAME = __PACKAGE_NAME__\r\nexport const VERSION = __VERSION__\r\n\r\n// Framework metadata\r\nexport const CLI_NAME = __PACKAGE_NAME__.split('/')?.[1] ?? __PACKAGE_NAME__\r\n","let p = process || {}, argv = p.argv || [], env = p.env || {}\nlet isColorSupported =\n\t!(!!env.NO_COLOR || argv.includes(\"--no-color\")) &&\n\t(!!env.FORCE_COLOR || argv.includes(\"--color\") || p.platform === \"win32\" || ((p.stdout || {}).isTTY && env.TERM !== \"dumb\") || !!env.CI)\n\nlet formatter = (open, close, replace = open) =>\n\tinput => {\n\t\tlet string = \"\" + input, index = string.indexOf(close, open.length)\n\t\treturn ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close\n\t}\n\nlet replaceClose = (string, close, replace, index) => {\n\tlet result = \"\", cursor = 0\n\tdo {\n\t\tresult += string.substring(cursor, index) + replace\n\t\tcursor = index + close.length\n\t\tindex = string.indexOf(close, cursor)\n\t} while (~index)\n\treturn result + string.substring(cursor)\n}\n\nlet createColors = (enabled = isColorSupported) => {\n\tlet f = enabled ? formatter : () => String\n\treturn {\n\t\tisColorSupported: enabled,\n\t\treset: f(\"\\x1b[0m\", \"\\x1b[0m\"),\n\t\tbold: f(\"\\x1b[1m\", \"\\x1b[22m\", \"\\x1b[22m\\x1b[1m\"),\n\t\tdim: f(\"\\x1b[2m\", \"\\x1b[22m\", \"\\x1b[22m\\x1b[2m\"),\n\t\titalic: f(\"\\x1b[3m\", \"\\x1b[23m\"),\n\t\tunderline: f(\"\\x1b[4m\", \"\\x1b[24m\"),\n\t\tinverse: f(\"\\x1b[7m\", \"\\x1b[27m\"),\n\t\thidden: f(\"\\x1b[8m\", \"\\x1b[28m\"),\n\t\tstrikethrough: f(\"\\x1b[9m\", \"\\x1b[29m\"),\n\n\t\tblack: f(\"\\x1b[30m\", \"\\x1b[39m\"),\n\t\tred: f(\"\\x1b[31m\", \"\\x1b[39m\"),\n\t\tgreen: f(\"\\x1b[32m\", \"\\x1b[39m\"),\n\t\tyellow: f(\"\\x1b[33m\", \"\\x1b[39m\"),\n\t\tblue: f(\"\\x1b[34m\", \"\\x1b[39m\"),\n\t\tmagenta: f(\"\\x1b[35m\", \"\\x1b[39m\"),\n\t\tcyan: f(\"\\x1b[36m\", \"\\x1b[39m\"),\n\t\twhite: f(\"\\x1b[37m\", \"\\x1b[39m\"),\n\t\tgray: f(\"\\x1b[90m\", \"\\x1b[39m\"),\n\n\t\tbgBlack: f(\"\\x1b[40m\", \"\\x1b[49m\"),\n\t\tbgRed: f(\"\\x1b[41m\", \"\\x1b[49m\"),\n\t\tbgGreen: f(\"\\x1b[42m\", \"\\x1b[49m\"),\n\t\tbgYellow: f(\"\\x1b[43m\", \"\\x1b[49m\"),\n\t\tbgBlue: f(\"\\x1b[44m\", \"\\x1b[49m\"),\n\t\tbgMagenta: f(\"\\x1b[45m\", \"\\x1b[49m\"),\n\t\tbgCyan: f(\"\\x1b[46m\", \"\\x1b[49m\"),\n\t\tbgWhite: f(\"\\x1b[47m\", \"\\x1b[49m\"),\n\n\t\tblackBright: f(\"\\x1b[90m\", \"\\x1b[39m\"),\n\t\tredBright: f(\"\\x1b[91m\", \"\\x1b[39m\"),\n\t\tgreenBright: f(\"\\x1b[92m\", \"\\x1b[39m\"),\n\t\tyellowBright: f(\"\\x1b[93m\", \"\\x1b[39m\"),\n\t\tblueBright: f(\"\\x1b[94m\", \"\\x1b[39m\"),\n\t\tmagentaBright: f(\"\\x1b[95m\", \"\\x1b[39m\"),\n\t\tcyanBright: f(\"\\x1b[96m\", \"\\x1b[39m\"),\n\t\twhiteBright: f(\"\\x1b[97m\", \"\\x1b[39m\"),\n\n\t\tbgBlackBright: f(\"\\x1b[100m\", \"\\x1b[49m\"),\n\t\tbgRedBright: f(\"\\x1b[101m\", \"\\x1b[49m\"),\n\t\tbgGreenBright: f(\"\\x1b[102m\", \"\\x1b[49m\"),\n\t\tbgYellowBright: f(\"\\x1b[103m\", \"\\x1b[49m\"),\n\t\tbgBlueBright: f(\"\\x1b[104m\", \"\\x1b[49m\"),\n\t\tbgMagentaBright: f(\"\\x1b[105m\", \"\\x1b[49m\"),\n\t\tbgCyanBright: f(\"\\x1b[106m\", \"\\x1b[49m\"),\n\t\tbgWhiteBright: f(\"\\x1b[107m\", \"\\x1b[49m\"),\n\t}\n}\n\nmodule.exports = createColors()\nmodule.exports.createColors = createColors\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { createFileTree } from '@/pen/compiler'\r\n\r\n// ===== Main Task =====\r\n\r\nexport const buildFileTree: Task<BuildContext> = {\r\n name: 'Building file tree',\r\n onSuccess: (_, dur) => `Built file tree (${duration(dur)})`,\r\n run: async (ctx) => ({\r\n fileTree: createFileTree(ctx.appDir),\r\n }),\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { createSegmentTree } from '@/pen/compiler'\r\n\r\n// ===== Main Task =====\r\n\r\nexport const buildSegmentTree: Task<BuildContext> = {\r\n name: 'Building segment tree...',\r\n onSuccess: (_, dur) => `Built segment tree (${duration(dur)})`,\r\n run: async (ctx) => ({\r\n segmentTree: createSegmentTree(ctx.fileTree!),\r\n }),\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { createRouteManifest } from '@/pen/compiler'\r\n\r\n// ===== Main Task =====\r\n\r\nexport const buildRouteManifest: Task<BuildContext> = {\r\n name: 'Building route manifest',\r\n onSuccess: (_, dur) => `Built route manifest (${duration(dur)})`,\r\n run: async (ctx) => ({\r\n manifest: createRouteManifest(ctx.segmentTree!, ctx.outDir),\r\n }),\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { createComponentMap } from '@/pen/compiler'\r\n\r\nexport const buildComponentMap: Task<BuildContext> = {\r\n name: 'Building component map',\r\n onSuccess: (_, dur) => `Built component map (${duration(dur)})`,\r\n run: async (ctx) => ({\r\n componentMap: createComponentMap(ctx.manifest!),\r\n }),\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { createElementTrees } from '@/pen/compiler'\r\n\r\nexport const buildElementTree: Task<BuildContext> = {\r\n name: 'Building element trees',\r\n onSuccess: (_, dur) => `Built element trees (${duration(dur)})`,\r\n run: async (ctx) => ({\r\n elementTrees: createElementTrees(ctx.manifest!, ctx.componentMap!),\r\n }),\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { mkdir, writeFile } from 'fs/promises'\r\nimport { join } from 'path'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { PACKAGE_NAME } from '@/pen/constants'\r\n\r\n// ===== Main Task =====\r\n\r\nexport const writeManifestFile: Task<BuildContext> = {\r\n name: 'Writing manifest.ts',\r\n onSuccess: (_, dur) => `Saved manifest.ts (${duration(dur)})`,\r\n run: async (ctx) => {\r\n const genDir = join(ctx.outDir, 'generated')\r\n const manifestPath = join(genDir, 'manifest.ts')\r\n const code = [\r\n `// Auto-generated by ${PACKAGE_NAME}`,\r\n '// Do not manually edit this file',\r\n '// NOTE: This file is kept for documentation/debugging.',\r\n '// Runtime uses pre-built routes from routes.ts instead.',\r\n '',\r\n `import type { RouteManifest } from '${PACKAGE_NAME}'`,\r\n '',\r\n `export const manifest: RouteManifest = ${JSON.stringify(ctx.manifest!, null, 2)} as const`,\r\n '',\r\n ].join('\\n')\r\n\r\n await mkdir(genDir, { recursive: true })\r\n await writeFile(manifestPath, code, 'utf-8')\r\n },\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { mkdir, writeFile } from 'fs/promises'\r\nimport { join } from 'path'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { PACKAGE_NAME } from '@/pen/constants'\r\n\r\n// ===== Main Task =====\r\n\r\nexport const writeElementTreeFile: Task<BuildContext> = {\r\n name: 'Writing element-tree.ts',\r\n onSuccess: (_, dur) => `Saved element-tree.ts (${duration(dur)})`,\r\n run: async (ctx) => {\r\n const genDir = join(ctx.outDir, 'generated')\r\n const elementTreePath = join(genDir, 'element-tree.ts')\r\n\r\n const code = [\r\n `// Auto-generated by ${PACKAGE_NAME}`,\r\n '// Do not manually edit this file',\r\n '// NOTE: This file is kept for documentation/debugging.',\r\n '',\r\n `import type { ElementTreeMap } from '${PACKAGE_NAME}'`,\r\n '',\r\n `export const elementTrees: ElementTreeMap = ${JSON.stringify(ctx.elementTrees!, null, 2)} as const`,\r\n '',\r\n ].join('\\n')\r\n\r\n await mkdir(genDir, { recursive: true })\r\n await writeFile(elementTreePath, code, 'utf-8')\r\n },\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { mkdir, writeFile } from 'fs/promises'\r\nimport { join } from 'path'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { PACKAGE_NAME } from '@/pen/constants'\r\n\r\nexport const writeComponentMapFile: Task<BuildContext> = {\r\n name: 'Writing components.ts',\r\n onSuccess: (_, dur) => `Saved components.ts (${duration(dur)})`,\r\n run: async (ctx) => {\r\n const genDir = join(ctx.outDir, 'generated')\r\n const componentsPath = join(genDir, 'components.ts')\r\n\r\n const componentMap = ctx.componentMap!\r\n const code = [\r\n `// Auto-generated by ${PACKAGE_NAME}`,\r\n '// Do not manually edit this file',\r\n '',\r\n `import type { ComponentMap } from '${PACKAGE_NAME}'`,\r\n '',\r\n `export const componentMap: ComponentMap = ${JSON.stringify(componentMap, null, 2)} as const`,\r\n '',\r\n ].join('\\n')\r\n\r\n await mkdir(genDir, { recursive: true })\r\n await writeFile(componentsPath, code, 'utf-8')\r\n },\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { ElementTree } from '@/pen/compiler'\r\nimport type { BuildContext } from '../types'\r\nimport { mkdir, writeFile } from 'fs/promises'\r\nimport { join } from 'path'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { PACKAGE_NAME } from '@/pen/constants'\r\n\r\nexport const writeRoutesFile: Task<BuildContext> = {\r\n name: 'Writing routes.ts',\r\n onSuccess: (_, dur) => `Saved routes.ts (${duration(dur)})`,\r\n run: async (ctx) => {\r\n const genDir = join(ctx.outDir, 'generated')\r\n const routesPath = join(genDir, 'routes.ts')\r\n const elementTrees = ctx.elementTrees!\r\n const componentMap = ctx.componentMap!\r\n\r\n // Get sorted imports from component map\r\n const sortedImports = Object.keys(componentMap)\r\n\r\n // Generate component imports\r\n const importStatements = sortedImports\r\n .map((importPath, i) => `import Component${i} from '${importPath}'`)\r\n .join('\\n')\r\n\r\n // Generate pre-built route elements from element trees\r\n const routeElements: string[] = []\r\n for (const [url, tree] of Object.entries(elementTrees)) {\r\n const elementCode = ` ${serialize(tree).replace(/\\n/g, '\\n ')}`\r\n routeElements.push(` '${url}':\\n${elementCode},`)\r\n }\r\n\r\n const code = [\r\n `// Auto-generated by ${PACKAGE_NAME}`,\r\n '// Do not manually edit this file',\r\n '',\r\n `import type { CompiledRoutes } from '${PACKAGE_NAME}'`,\r\n 'import { createElement } from \\'react\\'',\r\n '',\r\n importStatements,\r\n '',\r\n '// Compiled route elements generated at build time',\r\n 'export const routes: CompiledRoutes = {',\r\n routeElements.join('\\n'),\r\n '} as const',\r\n '',\r\n ].join('\\n')\r\n\r\n await mkdir(genDir, { recursive: true })\r\n await writeFile(routesPath, code, 'utf-8')\r\n },\r\n}\r\n\r\n/** Serializes an ElementTree to React.createElement() code string. */\r\nexport function serialize(tree: ElementTree, indent = 0): string {\r\n const spaces = ' '.repeat(indent)\r\n\r\n // Props are already pre-serialized (strings have quotes, identifiers don't)\r\n const props = Object.entries(tree.props)\r\n .map(([key, value]) => `${key}: ${value}`)\r\n .join(', ')\r\n\r\n if (!tree.children)\r\n return `createElement(${tree.component}, { ${props} })`\r\n\r\n const childCode = serialize(tree.children, indent + 1)\r\n return `createElement(${tree.component}, { ${props} },\\n${spaces} ${childCode}\\n${spaces})`\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { mkdir, writeFile } from 'fs/promises'\r\nimport { join } from 'path'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { PACKAGE_NAME } from '@/pen/constants'\r\n\r\n// ===== Main Task =====\r\n\r\nexport const writeEntryFile: Task<BuildContext> = {\r\n name: 'Writing entry.ts',\r\n onSuccess: (_, dur) => `Saved entry.ts (${duration(dur)})`,\r\n run: async (ctx) => {\r\n const genDir = join(ctx.outDir, 'generated')\r\n const entryPath = join(genDir, 'entry.ts')\r\n const code = [\r\n `// Auto-generated by ${PACKAGE_NAME}`,\r\n '// Do not manually edit this file',\r\n '',\r\n 'import { createElement } from \\'react\\'',\r\n 'import { render } from \\'ink\\'',\r\n `import { App } from '${PACKAGE_NAME}'`,\r\n 'import { routes } from \\'./routes\\'',\r\n '',\r\n 'export async function run(initialUrl: string) {',\r\n ' const element = createElement(App, { initialUrl, routes })',\r\n ' const { waitUntilExit } = render(element)',\r\n ' await waitUntilExit()',\r\n '}',\r\n '',\r\n ].join('\\n')\r\n\r\n await mkdir(genDir, { recursive: true })\r\n await writeFile(entryPath, code, 'utf-8')\r\n },\r\n}\r\n","import { join, resolve } from 'path'\r\nimport { build as rolldownBuild } from 'rolldown'\r\nimport nodeExternals from 'rollup-plugin-node-externals'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\n\r\nexport const compileApplication: Task<BuildContext> = {\r\n name: 'Compiling application',\r\n onSuccess: (_, dur) => `Compiled application (${duration(dur)})`,\r\n onError: (err) => `Compilation failed: ${err.message}`,\r\n run: async (ctx) => {\r\n await rolldownBuild({\r\n input: resolve(join(ctx.outDir, 'generated', 'entry.ts')), // entry point\r\n platform: 'node',\r\n resolve: {\r\n extensions: ['.ts', '.tsx', '.js', '.jsx'],\r\n },\r\n plugins: [nodeExternals()],\r\n output: {\r\n dir: resolve(join(ctx.outDir, 'dist')),\r\n format: 'esm',\r\n sourcemap: true,\r\n minify: true,\r\n },\r\n })\r\n },\r\n}\r\n","import type { CLICommand } from '../../types'\r\nimport pc from 'picocolors'\r\nimport { pipe, duration, fileList } from '@idlesummer/tasker'\r\nimport { loadConfig } from '@/pen/config'\r\nimport { CLI_NAME, VERSION } from '@/pen/constants'\r\n\r\n// Import individual tasks\r\nimport { buildFileTree } from './tasks/build-file-tree'\r\nimport { buildSegmentTree } from './tasks/build-segment-tree'\r\nimport { buildRouteManifest } from './tasks/build-route-manifest'\r\nimport { buildComponentMap } from './tasks/build-component-map'\r\nimport { buildElementTree } from './tasks/build-element-tree'\r\nimport { writeManifestFile } from './tasks/write-manifest-file'\r\nimport { writeElementTreeFile } from './tasks/write-element-tree-file'\r\nimport { writeComponentMapFile } from './tasks/write-component-map-file'\r\nimport { writeRoutesFile } from './tasks/write-routes-file'\r\nimport { writeEntryFile } from './tasks/write-entry-file'\r\nimport { compileApplication } from './tasks/compile-application'\r\n\r\nexport const build: CLICommand = {\r\n name: 'build',\r\n desc: 'Build the route manifest and compile application',\r\n action: async () => {\r\n try {\r\n const { appDir, outDir, emitMetadata } = await loadConfig()\r\n console.log(pc.cyan(' Starting production build...\\n'))\r\n console.log(pc.bold(` ✎ ${CLI_NAME} v${VERSION}\\n`))\r\n console.log(pc.dim( ` entry: ${appDir}`))\r\n console.log(pc.dim( ' target: node24'))\r\n console.log(pc.dim( ` output: ${outDir}`))\r\n console.log()\r\n\r\n const pipeline = pipe([\r\n buildFileTree,\r\n buildSegmentTree,\r\n buildRouteManifest,\r\n buildComponentMap,\r\n buildElementTree,\r\n\r\n // Conditionally add metadata file generation tasks\r\n emitMetadata && writeManifestFile,\r\n emitMetadata && writeElementTreeFile,\r\n emitMetadata && writeComponentMapFile,\r\n\r\n writeRoutesFile,\r\n writeEntryFile,\r\n compileApplication,\r\n ])\r\n\r\n const { duration: dur } = await pipeline.run({ appDir, outDir })\r\n console.log()\r\n console.log(fileList(outDir, '**/*'))\r\n console.log()\r\n console.log(`${pc.green('✓')} Built in ${pc.bold(duration(dur))}`)\r\n console.log()\r\n }\r\n\r\n catch (err) {\r\n console.error(`${pc.red('✗')} Build failed`)\r\n console.log()\r\n\r\n const message = err instanceof Error ? err.message : String(err)\r\n console.error(pc.red(message))\r\n console.log()\r\n process.exit(1)\r\n }\r\n },\r\n}\r\n","import { existsSync } from 'fs'\r\nimport { mkdir, writeFile } from 'fs/promises'\r\nimport { join } from 'path'\r\nimport pc from 'picocolors'\r\n\r\nimport { CLI_NAME, PACKAGE_NAME } from '@/pen/constants'\r\nimport type { CLICommand } from '../../types'\r\n\r\nexport const init: CLICommand = {\r\n name: 'init',\r\n desc: 'Initialize a new Pen project',\r\n action: async () => {\r\n console.log(pc.cyan(`\\n Initializing ${CLI_NAME} project...\\n`))\r\n\r\n // Check if already initialized\r\n if (existsSync('pen.config.ts')) {\r\n console.error(pc.yellow('⚠') + ' Project already initialized')\r\n console.error(pc.dim(' pen.config.ts already exists'))\r\n return\r\n }\r\n\r\n // Create pen.config.ts\r\n const configContent = [\r\n `import { defineConfig } from '${PACKAGE_NAME}'`,\r\n '',\r\n 'export default defineConfig({',\r\n ' appDir: \\'./src/app\\',',\r\n ' outDir: \\'./.pen\\',',\r\n '})',\r\n '',\r\n ].join('\\n')\r\n\r\n await writeFile('pen.config.ts', configContent, 'utf-8')\r\n console.log(pc.green('✓') + ' Created pen.config.ts')\r\n\r\n // Create src/app directory\r\n const appDir = './src/app'\r\n await mkdir(appDir, { recursive: true })\r\n\r\n // Create layout.tsx\r\n const layoutContent = [\r\n 'import { Box, Text } from \\'ink\\'',\r\n 'import type { ReactNode } from \\'react\\'',\r\n '',\r\n 'export default function Layout({ children }: { children?: ReactNode }) {',\r\n ' return (',\r\n ' <Box flexDirection=\"column\" padding={1}>',\r\n ' <Box marginBottom={1} borderStyle=\"round\" borderColor=\"cyan\" paddingX={2}>',\r\n ' <Text bold color=\"cyan\">Welcome to Pen</Text>',\r\n ' </Box>',\r\n ' {children}',\r\n ' </Box>',\r\n ' )',\r\n '}',\r\n '',\r\n ].join('\\n')\r\n\r\n await writeFile(join(appDir, 'layout.tsx'), layoutContent, 'utf-8')\r\n console.log(pc.green('✓') + ' Created src/app/layout.tsx')\r\n\r\n // Create screen.tsx\r\n const screenContent = [\r\n 'import { useState } from \\'react\\'',\r\n 'import { Box, Text, useInput } from \\'ink\\'',\r\n '',\r\n 'export default function Screen() {',\r\n ' const [count, setCount] = useState(0)',\r\n '',\r\n ' useInput((input) => {',\r\n ' if (input === \\' \\') setCount(c => c + 1)',\r\n ' })',\r\n '',\r\n ' return (',\r\n ' <Box flexDirection=\"column\" gap={1}>',\r\n ' <Box>',\r\n ' <Text>Count: <Text bold color=\"green\">{count}</Text></Text>',\r\n ' </Box>',\r\n ' <Box>',\r\n ' <Text dimColor>Press <Text bold>SPACE</Text> to increment</Text>',\r\n ' </Box>',\r\n ' </Box>',\r\n ' )',\r\n '}',\r\n '',\r\n ].join('\\n')\r\n\r\n await writeFile(join(appDir, 'screen.tsx'), screenContent, 'utf-8')\r\n console.log(pc.green('✓') + ' Created src/app/screen.tsx')\r\n\r\n // Success message with instructions\r\n console.log()\r\n console.log(pc.green('✓') + ' Project initialized!')\r\n console.log()\r\n console.log(pc.bold(' Next steps:'))\r\n console.log()\r\n console.log(pc.dim(' 1. Add scripts to package.json:'))\r\n console.log()\r\n console.log(' {')\r\n console.log(' \"scripts\": {')\r\n console.log(` \"build\": \"${CLI_NAME} build\",`)\r\n console.log(` \"start\": \"${CLI_NAME} start\"`)\r\n console.log(' }')\r\n console.log(' }')\r\n console.log()\r\n console.log(pc.dim(' 2. Run \"npm run build\" to build your app'))\r\n console.log(pc.dim(' 3. Run \"npm run start\" to start your app'))\r\n console.log()\r\n },\r\n}\r\n","import { existsSync } from 'fs'\r\nimport { resolve } from 'path'\r\nimport { pathToFileURL } from 'url'\r\nimport pc from 'picocolors'\r\n\r\nimport { loadConfig } from '@/pen/config'\r\nimport { CLI_NAME } from '@/pen/constants'\r\nimport type { CLICommand } from '../../types'\r\n\r\nexport const start: CLICommand = {\r\n name: 'start',\r\n desc: 'Start the application',\r\n action: async () => {\r\n const { outDir } = await loadConfig()\r\n const initialUrl = '/'\r\n const entryPath = resolve(outDir, 'dist', 'entry.js')\r\n\r\n // Check if build exists\r\n if (!existsSync(entryPath)) {\r\n console.error(pc.red('✗') + ' Build not found')\r\n console.error(pc.dim(` Run \"${CLI_NAME} build\" first`))\r\n throw new Error('Build not found') // Let Commander handle exit\r\n }\r\n\r\n // Import and run the bundled entry\r\n const entryUrl = pathToFileURL(entryPath).href\r\n const { run } = await import(entryUrl)\r\n\r\n // Run with initial URL\r\n await run(initialUrl)\r\n },\r\n}\r\n","import { Command } from 'commander'\r\nimport { CLI_NAME, DESCRIPTION, VERSION } from '@/pen/constants'\r\nimport { build } from './commands/build'\r\nimport { init } from './commands/init'\r\nimport { start } from './commands/start'\r\n\r\nfunction configureProgram(program: Command) {\r\n program\r\n .name(CLI_NAME)\r\n .description(DESCRIPTION)\r\n .version(VERSION)\r\n\r\n const commands = [build, init, start] as const\r\n for (const { name, desc, action } of commands) {\r\n program\r\n .command(name)\r\n .description(desc)\r\n .action(action)\r\n }\r\n return program\r\n}\r\n\r\nexport async function run(argv: string[]) {\r\n const command = new Command()\r\n const program = configureProgram(command)\r\n\r\n try {\r\n await program.parseAsync(argv)\r\n return 0\r\n }\r\n catch (err) {\r\n const message = err instanceof Error ? err.message : 'Unknown error'\r\n console.error(message)\r\n return 1\r\n }\r\n}\r\n","#!/usr/bin/env node\r\n\r\nimport { run } from './cli'\r\n\r\nprocess.exit(await run(process.argv))\r\n"],"x_google_ignoreList":[1],"mappings":"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"}
1
+ {"version":3,"file":"bin.mjs","names":["rolldownBuild","build","pc","pc","pc","run","build"],"sources":["../src/pen/constants.ts","../node_modules/picocolors/picocolors.js","../src/cli/commands/build/tasks/build-file-tree.ts","../src/cli/commands/build/tasks/build-segment-tree.ts","../src/cli/commands/build/tasks/build-route-table.ts","../src/cli/commands/build/tasks/build-component-map.ts","../src/cli/commands/build/tasks/build-element-tree.ts","../src/cli/commands/build/tasks/write-route-table-file.ts","../src/cli/commands/build/tasks/write-element-tree-file.ts","../src/cli/commands/build/tasks/write-component-map-file.ts","../src/cli/commands/build/tasks/write-compiled-routes-file.ts","../src/cli/commands/build/tasks/write-entry-file.ts","../src/cli/commands/build/tasks/compile-application.ts","../src/cli/commands/build/index.ts","../src/cli/commands/init/index.ts","../src/cli/commands/start/index.ts","../src/cli/index.ts","../src/bin.ts"],"sourcesContent":["// Build-time globals injected by tsdown via `define`.\r\n// tsdown replaces these placeholders with actual values\r\n// from package.json at compile time.\r\n\r\ndeclare const __DESCRIPTION__: string\r\ndeclare const __PACKAGE_NAME__: string\r\ndeclare const __VERSION__: string\r\n\r\n// Package metadata\r\nexport const DESCRIPTION = __DESCRIPTION__\r\nexport const PACKAGE_NAME = __PACKAGE_NAME__\r\nexport const VERSION = __VERSION__\r\n\r\n// Framework metadata\r\nexport const CLI_NAME = __PACKAGE_NAME__.split('/')?.[1] ?? __PACKAGE_NAME__\r\n","let p = process || {}, argv = p.argv || [], env = p.env || {}\nlet isColorSupported =\n\t!(!!env.NO_COLOR || argv.includes(\"--no-color\")) &&\n\t(!!env.FORCE_COLOR || argv.includes(\"--color\") || p.platform === \"win32\" || ((p.stdout || {}).isTTY && env.TERM !== \"dumb\") || !!env.CI)\n\nlet formatter = (open, close, replace = open) =>\n\tinput => {\n\t\tlet string = \"\" + input, index = string.indexOf(close, open.length)\n\t\treturn ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close\n\t}\n\nlet replaceClose = (string, close, replace, index) => {\n\tlet result = \"\", cursor = 0\n\tdo {\n\t\tresult += string.substring(cursor, index) + replace\n\t\tcursor = index + close.length\n\t\tindex = string.indexOf(close, cursor)\n\t} while (~index)\n\treturn result + string.substring(cursor)\n}\n\nlet createColors = (enabled = isColorSupported) => {\n\tlet f = enabled ? formatter : () => String\n\treturn {\n\t\tisColorSupported: enabled,\n\t\treset: f(\"\\x1b[0m\", \"\\x1b[0m\"),\n\t\tbold: f(\"\\x1b[1m\", \"\\x1b[22m\", \"\\x1b[22m\\x1b[1m\"),\n\t\tdim: f(\"\\x1b[2m\", \"\\x1b[22m\", \"\\x1b[22m\\x1b[2m\"),\n\t\titalic: f(\"\\x1b[3m\", \"\\x1b[23m\"),\n\t\tunderline: f(\"\\x1b[4m\", \"\\x1b[24m\"),\n\t\tinverse: f(\"\\x1b[7m\", \"\\x1b[27m\"),\n\t\thidden: f(\"\\x1b[8m\", \"\\x1b[28m\"),\n\t\tstrikethrough: f(\"\\x1b[9m\", \"\\x1b[29m\"),\n\n\t\tblack: f(\"\\x1b[30m\", \"\\x1b[39m\"),\n\t\tred: f(\"\\x1b[31m\", \"\\x1b[39m\"),\n\t\tgreen: f(\"\\x1b[32m\", \"\\x1b[39m\"),\n\t\tyellow: f(\"\\x1b[33m\", \"\\x1b[39m\"),\n\t\tblue: f(\"\\x1b[34m\", \"\\x1b[39m\"),\n\t\tmagenta: f(\"\\x1b[35m\", \"\\x1b[39m\"),\n\t\tcyan: f(\"\\x1b[36m\", \"\\x1b[39m\"),\n\t\twhite: f(\"\\x1b[37m\", \"\\x1b[39m\"),\n\t\tgray: f(\"\\x1b[90m\", \"\\x1b[39m\"),\n\n\t\tbgBlack: f(\"\\x1b[40m\", \"\\x1b[49m\"),\n\t\tbgRed: f(\"\\x1b[41m\", \"\\x1b[49m\"),\n\t\tbgGreen: f(\"\\x1b[42m\", \"\\x1b[49m\"),\n\t\tbgYellow: f(\"\\x1b[43m\", \"\\x1b[49m\"),\n\t\tbgBlue: f(\"\\x1b[44m\", \"\\x1b[49m\"),\n\t\tbgMagenta: f(\"\\x1b[45m\", \"\\x1b[49m\"),\n\t\tbgCyan: f(\"\\x1b[46m\", \"\\x1b[49m\"),\n\t\tbgWhite: f(\"\\x1b[47m\", \"\\x1b[49m\"),\n\n\t\tblackBright: f(\"\\x1b[90m\", \"\\x1b[39m\"),\n\t\tredBright: f(\"\\x1b[91m\", \"\\x1b[39m\"),\n\t\tgreenBright: f(\"\\x1b[92m\", \"\\x1b[39m\"),\n\t\tyellowBright: f(\"\\x1b[93m\", \"\\x1b[39m\"),\n\t\tblueBright: f(\"\\x1b[94m\", \"\\x1b[39m\"),\n\t\tmagentaBright: f(\"\\x1b[95m\", \"\\x1b[39m\"),\n\t\tcyanBright: f(\"\\x1b[96m\", \"\\x1b[39m\"),\n\t\twhiteBright: f(\"\\x1b[97m\", \"\\x1b[39m\"),\n\n\t\tbgBlackBright: f(\"\\x1b[100m\", \"\\x1b[49m\"),\n\t\tbgRedBright: f(\"\\x1b[101m\", \"\\x1b[49m\"),\n\t\tbgGreenBright: f(\"\\x1b[102m\", \"\\x1b[49m\"),\n\t\tbgYellowBright: f(\"\\x1b[103m\", \"\\x1b[49m\"),\n\t\tbgBlueBright: f(\"\\x1b[104m\", \"\\x1b[49m\"),\n\t\tbgMagentaBright: f(\"\\x1b[105m\", \"\\x1b[49m\"),\n\t\tbgCyanBright: f(\"\\x1b[106m\", \"\\x1b[49m\"),\n\t\tbgWhiteBright: f(\"\\x1b[107m\", \"\\x1b[49m\"),\n\t}\n}\n\nmodule.exports = createColors()\nmodule.exports.createColors = createColors\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { createFileTree } from '@/pen/compiler'\r\n\r\n// ===== Main Task =====\r\n\r\nexport const buildFileTree: Task<BuildContext> = {\r\n name: 'Building file tree',\r\n onSuccess: (_, dur) => `Built file tree (${duration(dur)})`,\r\n run: async (ctx) => ({\r\n fileTree: createFileTree(ctx.appDir),\r\n }),\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { createSegmentTree } from '@/pen/compiler'\r\n\r\n// ===== Main Task =====\r\n\r\nexport const buildSegmentTree: Task<BuildContext> = {\r\n name: 'Building segment tree...',\r\n onSuccess: (_, dur) => `Built segment tree (${duration(dur)})`,\r\n run: async (ctx) => ({\r\n segmentTree: createSegmentTree(ctx.fileTree!),\r\n }),\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { createRouteTable } from '@/pen/compiler'\r\n\r\n// ===== Main Task =====\r\n\r\nexport const buildRouteTable: Task<BuildContext> = {\r\n name: 'Building route manifest',\r\n onSuccess: (_, dur) => `Built route table (${duration(dur)})`,\r\n run: async (ctx) => ({\r\n manifest: createRouteTable(ctx.segmentTree!, ctx.outDir),\r\n }),\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { createComponentMap } from '@/pen/compiler'\r\n\r\nexport const buildComponentMap: Task<BuildContext> = {\r\n name: 'Building component map',\r\n onSuccess: (_, dur) => `Built component map (${duration(dur)})`,\r\n run: async (ctx) => ({\r\n componentMap: createComponentMap(ctx.manifest!),\r\n }),\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { createElementTrees } from '@/pen/compiler'\r\n\r\nexport const buildElementTree: Task<BuildContext> = {\r\n name: 'Building element trees',\r\n onSuccess: (_, dur) => `Built element trees (${duration(dur)})`,\r\n run: async (ctx) => ({\r\n elementTrees: createElementTrees(ctx.manifest!, ctx.componentMap!),\r\n }),\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { mkdir, writeFile } from 'fs/promises'\r\nimport { join } from 'path'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { PACKAGE_NAME } from '@/pen/constants'\r\n\r\nexport const writeRouteTableFile: Task<BuildContext> = {\r\n name: 'Writing route-table.ts',\r\n onSuccess: (_, dur) => `Saved route-table.ts (${duration(dur)})`,\r\n run: async (ctx) => {\r\n const genDir = join(ctx.outDir, 'generated')\r\n const outDir = join(genDir, 'route-table.ts')\r\n const code = [\r\n `// Auto-generated by ${PACKAGE_NAME}`,\r\n '// Do not manually edit this file',\r\n '// NOTE: This file is kept for documentation/debugging.',\r\n '// Runtime uses pre-built routes from routes.ts instead.',\r\n '',\r\n `import type { RouteTable } from '${PACKAGE_NAME}'`,\r\n '',\r\n `export const manifest: RouteTable = ${JSON.stringify(ctx.manifest!, null, 2)} as const`,\r\n '',\r\n ].join('\\n')\r\n\r\n await mkdir(genDir, { recursive: true })\r\n await writeFile(outDir, code, 'utf-8')\r\n },\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { mkdir, writeFile } from 'fs/promises'\r\nimport { join } from 'path'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { PACKAGE_NAME } from '@/pen/constants'\r\n\r\n// ===== Main Task =====\r\n\r\nexport const writeElementTreeFile: Task<BuildContext> = {\r\n name: 'Writing element-tree.ts',\r\n onSuccess: (_, dur) => `Saved element-tree.ts (${duration(dur)})`,\r\n run: async (ctx) => {\r\n const genDir = join(ctx.outDir, 'generated')\r\n const outDir = join(genDir, 'element-tree.ts')\r\n\r\n const code = [\r\n `// Auto-generated by ${PACKAGE_NAME}`,\r\n '// Do not manually edit this file',\r\n '// NOTE: This file is kept for documentation/debugging.',\r\n '',\r\n `import type { ElementTreeMap } from '${PACKAGE_NAME}'`,\r\n '',\r\n `export const elementTrees: ElementTreeMap = ${JSON.stringify(ctx.elementTrees!, null, 2)} as const`,\r\n '',\r\n ].join('\\n')\r\n\r\n await mkdir(genDir, { recursive: true })\r\n await writeFile(outDir, code, 'utf-8')\r\n },\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { mkdir, writeFile } from 'fs/promises'\r\nimport { join } from 'path'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { PACKAGE_NAME } from '@/pen/constants'\r\n\r\nexport const writeComponentMapFile: Task<BuildContext> = {\r\n name: 'Writing component-map.ts',\r\n onSuccess: (_, dur) => `Saved component-map.ts (${duration(dur)})`,\r\n run: async (ctx) => {\r\n const genDir = join(ctx.outDir, 'generated')\r\n const outDir = join(genDir, 'component-map.ts')\r\n\r\n const componentMap = ctx.componentMap!\r\n const code = [\r\n `// Auto-generated by ${PACKAGE_NAME}`,\r\n '// Do not manually edit this file',\r\n '',\r\n `import type { ComponentMap } from '${PACKAGE_NAME}'`,\r\n '',\r\n `export const componentMap: ComponentMap = ${JSON.stringify(componentMap, null, 2)} as const`,\r\n '',\r\n ].join('\\n')\r\n\r\n await mkdir(genDir, { recursive: true })\r\n await writeFile(outDir, code, 'utf-8')\r\n },\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { ElementTree } from '@/pen/compiler'\r\nimport type { BuildContext } from '../types'\r\nimport { mkdir, writeFile } from 'fs/promises'\r\nimport { join } from 'path'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { PACKAGE_NAME } from '@/pen/constants'\r\n\r\nexport const writeCompiledRoutesFile: Task<BuildContext> = {\r\n name: 'Writing compiled-routes.ts',\r\n onSuccess: (_, dur) => `Saved compiled-routes.ts (${duration(dur)})`,\r\n run: async (ctx) => {\r\n const genDir = join(ctx.outDir, 'generated')\r\n const outDir = join(genDir, 'compiled-routes.ts')\r\n const elementTrees = ctx.elementTrees!\r\n const componentMap = ctx.componentMap!\r\n\r\n // Get sorted imports from component map\r\n const sortedImports = Object.keys(componentMap)\r\n\r\n // Generate component imports\r\n const importStatements = sortedImports\r\n .map((importPath, i) => `import Component${i} from '${importPath}'`)\r\n .join('\\n')\r\n\r\n // Generate pre-built route elements from element trees\r\n const routeElements: string[] = []\r\n for (const [url, tree] of Object.entries(elementTrees)) {\r\n const elementCode = ` ${serialize(tree).replace(/\\n/g, '\\n ')}`\r\n routeElements.push(` '${url}':\\n${elementCode},`)\r\n }\r\n\r\n const code = [\r\n `// Auto-generated by ${PACKAGE_NAME}`,\r\n '// Do not manually edit this file',\r\n '',\r\n `import type { CompiledRoutes } from '${PACKAGE_NAME}'`,\r\n 'import { createElement } from \\'react\\'',\r\n '',\r\n importStatements,\r\n '',\r\n '// Compiled route elements generated at build time',\r\n 'export const compiledRoutes: CompiledRoutes = {',\r\n routeElements.join('\\n'),\r\n '} as const',\r\n '',\r\n ].join('\\n')\r\n\r\n await mkdir(genDir, { recursive: true })\r\n await writeFile(outDir, code, 'utf-8')\r\n },\r\n}\r\n\r\n/** Serializes an ElementTree to React.createElement() code string. */\r\nexport function serialize(tree: ElementTree, indent = 0): string {\r\n const spaces = ' '.repeat(indent)\r\n\r\n // Props are already pre-serialized (strings have quotes, identifiers don't)\r\n const props = Object.entries(tree.props)\r\n .map(([key, value]) => `${key}: ${value}`)\r\n .join(', ')\r\n\r\n if (!tree.children)\r\n return `createElement(${tree.component}, { ${props} })`\r\n\r\n const childCode = serialize(tree.children, indent + 1)\r\n return `createElement(${tree.component}, { ${props} },\\n${spaces} ${childCode}\\n${spaces})`\r\n}\r\n","import type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\nimport { mkdir, writeFile } from 'fs/promises'\r\nimport { join } from 'path'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport { PACKAGE_NAME } from '@/pen/constants'\r\n\r\n// ===== Main Task =====\r\n\r\nexport const writeEntryFile: Task<BuildContext> = {\r\n name: 'Writing entry.ts',\r\n onSuccess: (_, dur) => `Saved entry.ts (${duration(dur)})`,\r\n run: async (ctx) => {\r\n const genDir = join(ctx.outDir, 'generated')\r\n const outDir = join(genDir, 'entry.ts')\r\n const code = [\r\n `// Auto-generated by ${PACKAGE_NAME}`,\r\n '// Do not manually edit this file',\r\n '',\r\n 'import { createElement } from \\'react\\'',\r\n 'import { render } from \\'ink\\'',\r\n `import { App } from '${PACKAGE_NAME}'`,\r\n 'import { compiledRoutes as routes } from \\'./compiled-routes\\'',\r\n '',\r\n 'export async function run(initialUrl: string) {',\r\n ' const element = createElement(App, { initialUrl, routes })',\r\n ' const { waitUntilExit } = render(element)',\r\n ' await waitUntilExit()',\r\n '}',\r\n '',\r\n ].join('\\n')\r\n\r\n await mkdir(genDir, { recursive: true })\r\n await writeFile(outDir, code, 'utf-8')\r\n },\r\n}\r\n","import { join, resolve } from 'path'\r\nimport { build as rolldownBuild } from 'rolldown'\r\nimport nodeExternals from 'rollup-plugin-node-externals'\r\nimport { duration } from '@idlesummer/tasker'\r\nimport type { Task } from '@idlesummer/tasker'\r\nimport type { BuildContext } from '../types'\r\n\r\nexport const compileApplication: Task<BuildContext> = {\r\n name: 'Compiling application',\r\n onSuccess: (_, dur) => `Compiled application (${duration(dur)})`,\r\n onError: (err) => `Compilation failed: ${err.message}`,\r\n run: async (ctx) => {\r\n await rolldownBuild({\r\n input: resolve(join(ctx.outDir, 'generated', 'entry.ts')), // entry point\r\n platform: 'node',\r\n resolve: {\r\n extensions: ['.ts', '.tsx', '.js', '.jsx'],\r\n },\r\n plugins: [nodeExternals()],\r\n output: {\r\n dir: resolve(join(ctx.outDir, 'dist')),\r\n format: 'esm',\r\n sourcemap: true,\r\n minify: true,\r\n },\r\n })\r\n },\r\n}\r\n","import type { CLICommand } from '../../types'\r\nimport pc from 'picocolors'\r\nimport { pipe, duration, fileList } from '@idlesummer/tasker'\r\nimport { loadConfig } from '@/pen/config'\r\nimport { CLI_NAME, VERSION } from '@/pen/constants'\r\n\r\n// Import individual tasks\r\nimport { buildFileTree } from './tasks/build-file-tree'\r\nimport { buildSegmentTree } from './tasks/build-segment-tree'\r\nimport { buildRouteTable } from './tasks/build-route-table'\r\nimport { buildComponentMap } from './tasks/build-component-map'\r\nimport { buildElementTree } from './tasks/build-element-tree'\r\nimport { writeRouteTableFile } from './tasks/write-route-table-file'\r\nimport { writeElementTreeFile } from './tasks/write-element-tree-file'\r\nimport { writeComponentMapFile } from './tasks/write-component-map-file'\r\nimport { writeCompiledRoutesFile } from './tasks/write-compiled-routes-file'\r\nimport { writeEntryFile } from './tasks/write-entry-file'\r\nimport { compileApplication } from './tasks/compile-application'\r\n\r\nexport const build: CLICommand = {\r\n name: 'build',\r\n desc: 'Build the route manifest and compile application',\r\n action: async () => {\r\n try {\r\n const { appDir, outDir, emitMetadata } = await loadConfig()\r\n console.log(pc.cyan(' Starting production build...\\n'))\r\n console.log(pc.bold(` ✎ ${CLI_NAME} v${VERSION}\\n`))\r\n console.log(pc.dim( ` entry: ${appDir}`))\r\n console.log(pc.dim( ' target: node24'))\r\n console.log(pc.dim( ` output: ${outDir}`))\r\n console.log()\r\n\r\n const pipeline = pipe([\r\n buildFileTree,\r\n buildSegmentTree,\r\n buildRouteTable,\r\n buildComponentMap,\r\n buildElementTree,\r\n\r\n // Conditionally add metadata file generation tasks\r\n emitMetadata && writeRouteTableFile,\r\n emitMetadata && writeElementTreeFile,\r\n emitMetadata && writeComponentMapFile,\r\n\r\n writeCompiledRoutesFile,\r\n writeEntryFile,\r\n compileApplication,\r\n ])\r\n\r\n const { duration: dur } = await pipeline.run({ appDir, outDir })\r\n console.log()\r\n console.log(fileList(outDir, '**/*'))\r\n console.log()\r\n console.log(`${pc.green('✓')} Built in ${pc.bold(duration(dur))}`)\r\n console.log()\r\n }\r\n\r\n catch (err) {\r\n console.error(`${pc.red('✗')} Build failed`)\r\n console.log()\r\n\r\n const message = err instanceof Error ? err.message : String(err)\r\n console.error(pc.red(message))\r\n console.log()\r\n process.exit(1)\r\n }\r\n },\r\n}\r\n","import { existsSync } from 'fs'\r\nimport { mkdir, writeFile } from 'fs/promises'\r\nimport { join } from 'path'\r\nimport pc from 'picocolors'\r\n\r\nimport { CLI_NAME, PACKAGE_NAME } from '@/pen/constants'\r\nimport type { CLICommand } from '../../types'\r\n\r\nexport const init: CLICommand = {\r\n name: 'init',\r\n desc: 'Initialize a new Pen project',\r\n action: async () => {\r\n console.log(pc.cyan(`\\n Initializing ${CLI_NAME} project...\\n`))\r\n\r\n // Check if already initialized\r\n if (existsSync('pen.config.ts')) {\r\n console.error(pc.yellow('⚠') + ' Project already initialized')\r\n console.error(pc.dim(' pen.config.ts already exists'))\r\n return\r\n }\r\n\r\n // Create pen.config.ts\r\n const configContent = [\r\n `import { defineConfig } from '${PACKAGE_NAME}'`,\r\n '',\r\n 'export default defineConfig({',\r\n ' appDir: \\'./src/app\\',',\r\n ' outDir: \\'./.pen\\',',\r\n '})',\r\n '',\r\n ].join('\\n')\r\n\r\n await writeFile('pen.config.ts', configContent, 'utf-8')\r\n console.log(pc.green('✓') + ' Created pen.config.ts')\r\n\r\n // Create src/app directory\r\n const appDir = './src/app'\r\n await mkdir(appDir, { recursive: true })\r\n\r\n // Create layout.tsx\r\n const layoutContent = [\r\n 'import { Box, Text } from \\'ink\\'',\r\n 'import type { ReactNode } from \\'react\\'',\r\n '',\r\n 'export default function Layout({ children }: { children?: ReactNode }) {',\r\n ' return (',\r\n ' <Box flexDirection=\"column\" padding={1}>',\r\n ' <Box marginBottom={1} borderStyle=\"round\" borderColor=\"cyan\" paddingX={2}>',\r\n ' <Text bold color=\"cyan\">Welcome to Pen</Text>',\r\n ' </Box>',\r\n ' {children}',\r\n ' </Box>',\r\n ' )',\r\n '}',\r\n '',\r\n ].join('\\n')\r\n\r\n await writeFile(join(appDir, 'layout.tsx'), layoutContent, 'utf-8')\r\n console.log(pc.green('✓') + ' Created src/app/layout.tsx')\r\n\r\n // Create screen.tsx\r\n const screenContent = [\r\n 'import { useState } from \\'react\\'',\r\n 'import { Box, Text, useInput } from \\'ink\\'',\r\n '',\r\n 'export default function Screen() {',\r\n ' const [count, setCount] = useState(0)',\r\n '',\r\n ' useInput((input) => {',\r\n ' if (input === \\' \\') setCount(c => c + 1)',\r\n ' })',\r\n '',\r\n ' return (',\r\n ' <Box flexDirection=\"column\" gap={1}>',\r\n ' <Box>',\r\n ' <Text>Count: <Text bold color=\"green\">{count}</Text></Text>',\r\n ' </Box>',\r\n ' <Box>',\r\n ' <Text dimColor>Press <Text bold>SPACE</Text> to increment</Text>',\r\n ' </Box>',\r\n ' </Box>',\r\n ' )',\r\n '}',\r\n '',\r\n ].join('\\n')\r\n\r\n await writeFile(join(appDir, 'screen.tsx'), screenContent, 'utf-8')\r\n console.log(pc.green('✓') + ' Created src/app/screen.tsx')\r\n\r\n // Success message with instructions\r\n console.log()\r\n console.log(pc.green('✓') + ' Project initialized!')\r\n console.log()\r\n console.log(pc.bold(' Next steps:'))\r\n console.log()\r\n console.log(pc.dim(' 1. Add scripts to package.json:'))\r\n console.log()\r\n console.log(' {')\r\n console.log(' \"scripts\": {')\r\n console.log(` \"build\": \"${CLI_NAME} build\",`)\r\n console.log(` \"start\": \"${CLI_NAME} start\"`)\r\n console.log(' }')\r\n console.log(' }')\r\n console.log()\r\n console.log(pc.dim(' 2. Run \"npm run build\" to build your app'))\r\n console.log(pc.dim(' 3. Run \"npm run start\" to start your app'))\r\n console.log()\r\n },\r\n}\r\n","import { existsSync } from 'fs'\r\nimport { resolve } from 'path'\r\nimport { pathToFileURL } from 'url'\r\nimport pc from 'picocolors'\r\n\r\nimport { loadConfig } from '@/pen/config'\r\nimport { CLI_NAME } from '@/pen/constants'\r\nimport type { CLICommand } from '../../types'\r\n\r\nexport const start: CLICommand = {\r\n name: 'start',\r\n desc: 'Start the application',\r\n action: async () => {\r\n const { outDir } = await loadConfig()\r\n const initialUrl = '/'\r\n const entryPath = resolve(outDir, 'dist', 'entry.js')\r\n\r\n // Check if build exists\r\n if (!existsSync(entryPath)) {\r\n console.error(pc.red('✗') + ' Build not found')\r\n console.error(pc.dim(` Run \"${CLI_NAME} build\" first`))\r\n throw new Error('Build not found') // Let Commander handle exit\r\n }\r\n\r\n // Import and run the bundled entry\r\n const entryUrl = pathToFileURL(entryPath).href\r\n const { run } = await import(entryUrl)\r\n\r\n // Run with initial URL\r\n await run(initialUrl)\r\n },\r\n}\r\n","import { Command } from 'commander'\r\nimport { CLI_NAME, DESCRIPTION, VERSION } from '@/pen/constants'\r\nimport { build } from './commands/build'\r\nimport { init } from './commands/init'\r\nimport { start } from './commands/start'\r\n\r\nfunction configureProgram(program: Command) {\r\n program\r\n .name(CLI_NAME)\r\n .description(DESCRIPTION)\r\n .version(VERSION)\r\n\r\n const commands = [build, init, start] as const\r\n for (const { name, desc, action } of commands) {\r\n program\r\n .command(name)\r\n .description(desc)\r\n .action(action)\r\n }\r\n return program\r\n}\r\n\r\nexport async function run(argv: string[]) {\r\n const command = new Command()\r\n const program = configureProgram(command)\r\n\r\n try {\r\n await program.parseAsync(argv)\r\n return 0\r\n }\r\n catch (err) {\r\n const message = err instanceof Error ? err.message : 'Unknown error'\r\n console.error(message)\r\n return 1\r\n }\r\n}\r\n","#!/usr/bin/env node\r\n\r\nimport { run } from './cli'\r\n\r\nprocess.exit(await run(process.argv))\r\n"],"x_google_ignoreList":[1],"mappings":";k8BASA,MACa,EAAA,kBACA,EAAA,QAGA,EAAA,kBAA4B,MAAM,IAAI,GAAG,IAAA,qCCdtD,IAAI,EAAI,SAAW,EAAE,CAAE,EAAO,EAAE,MAAQ,EAAE,CAAE,EAAM,EAAE,KAAO,EAAE,CACzD,EACH,EAAI,EAAI,UAAY,EAAK,SAAS,aAAa,IAC9C,CAAC,CAAC,EAAI,aAAe,EAAK,SAAS,UAAU,EAAI,EAAE,WAAa,UAAa,EAAE,QAAU,EAAE,EAAE,OAAS,EAAI,OAAS,QAAW,CAAC,CAAC,EAAI,IAElI,GAAa,EAAM,EAAO,EAAU,IACvC,GAAS,CACR,IAAI,EAAS,GAAK,EAAO,EAAQ,EAAO,QAAQ,EAAO,EAAK,OAAO,CACnE,MAAO,CAAC,EAAQ,EAAO,EAAa,EAAQ,EAAO,EAAS,EAAM,CAAG,EAAQ,EAAO,EAAS,GAG3F,GAAgB,EAAQ,EAAO,EAAS,IAAU,CACrD,IAAI,EAAS,GAAI,EAAS,EAC1B,EACC,IAAU,EAAO,UAAU,EAAQ,EAAM,CAAG,EAC5C,EAAS,EAAQ,EAAM,OACvB,EAAQ,EAAO,QAAQ,EAAO,EAAO,OAC7B,CAAC,GACV,OAAO,EAAS,EAAO,UAAU,EAAO,EAGrC,GAAgB,EAAU,IAAqB,CAClD,IAAI,EAAI,EAAU,MAAkB,OACpC,MAAO,CACN,iBAAkB,EAClB,MAAO,EAAE,UAAW,UAAU,CAC9B,KAAM,EAAE,UAAW,WAAY,kBAAkB,CACjD,IAAK,EAAE,UAAW,WAAY,kBAAkB,CAChD,OAAQ,EAAE,UAAW,WAAW,CAChC,UAAW,EAAE,UAAW,WAAW,CACnC,QAAS,EAAE,UAAW,WAAW,CACjC,OAAQ,EAAE,UAAW,WAAW,CAChC,cAAe,EAAE,UAAW,WAAW,CAEvC,MAAO,EAAE,WAAY,WAAW,CAChC,IAAK,EAAE,WAAY,WAAW,CAC9B,MAAO,EAAE,WAAY,WAAW,CAChC,OAAQ,EAAE,WAAY,WAAW,CACjC,KAAM,EAAE,WAAY,WAAW,CAC/B,QAAS,EAAE,WAAY,WAAW,CAClC,KAAM,EAAE,WAAY,WAAW,CAC/B,MAAO,EAAE,WAAY,WAAW,CAChC,KAAM,EAAE,WAAY,WAAW,CAE/B,QAAS,EAAE,WAAY,WAAW,CAClC,MAAO,EAAE,WAAY,WAAW,CAChC,QAAS,EAAE,WAAY,WAAW,CAClC,SAAU,EAAE,WAAY,WAAW,CACnC,OAAQ,EAAE,WAAY,WAAW,CACjC,UAAW,EAAE,WAAY,WAAW,CACpC,OAAQ,EAAE,WAAY,WAAW,CACjC,QAAS,EAAE,WAAY,WAAW,CAElC,YAAa,EAAE,WAAY,WAAW,CACtC,UAAW,EAAE,WAAY,WAAW,CACpC,YAAa,EAAE,WAAY,WAAW,CACtC,aAAc,EAAE,WAAY,WAAW,CACvC,WAAY,EAAE,WAAY,WAAW,CACrC,cAAe,EAAE,WAAY,WAAW,CACxC,WAAY,EAAE,WAAY,WAAW,CACrC,YAAa,EAAE,WAAY,WAAW,CAEtC,cAAe,EAAE,YAAa,WAAW,CACzC,YAAa,EAAE,YAAa,WAAW,CACvC,cAAe,EAAE,YAAa,WAAW,CACzC,eAAgB,EAAE,YAAa,WAAW,CAC1C,aAAc,EAAE,YAAa,WAAW,CACxC,gBAAiB,EAAE,YAAa,WAAW,CAC3C,aAAc,EAAE,YAAa,WAAW,CACxC,cAAe,EAAE,YAAa,WAAW,CACzC,EAGF,EAAO,QAAU,GAAc,CAC/B,EAAO,QAAQ,aAAe,UCnE9B,MAAA,EAAA,+GCAa,EAAuC,CAClD,KAAM,2BACN,WAAY,EAAG,IAAQ,uBAAuB,EAAS,EAAI,CAAC,GAC5D,IAAK,KAAO,KAAS,CACnB,YAAa,EAAkB,EAAI,SAAU,CAC9C,EACF,CCNY,EAAsC,CACjD,KAAM,0BACN,WAAY,EAAG,IAAQ,sBAAsB,EAAS,EAAI,CAAC,GAC3D,IAAK,KAAO,KAAS,CACnB,SAAU,EAAiB,EAAI,YAAc,EAAI,OAAO,CACzD,EACF,CCRY,EAAwC,CACnD,KAAM,yBACN,WAAY,EAAG,IAAQ,wBAAwB,EAAS,EAAI,CAAC,GAC7D,IAAK,KAAO,KAAS,CACnB,aAAc,EAAmB,EAAI,SAAU,CAChD,EACF,CCNY,EAAuC,CAClD,KAAM,yBACN,WAAY,EAAG,IAAQ,wBAAwB,EAAS,EAAI,CAAC,GAC7D,IAAK,KAAO,KAAS,CACnB,aAAc,EAAmB,EAAI,SAAW,EAAI,aAAc,CACnE,EACF,CCJY,EAA0C,CACrD,KAAM,yBACN,WAAY,EAAG,IAAQ,yBAAyB,EAAS,EAAI,CAAC,GAC9D,IAAK,KAAO,IAAQ,CAClB,IAAM,EAAS,EAAK,EAAI,OAAQ,YAAY,CACtC,EAAS,EAAK,EAAQ,iBAAiB,CACvC,EAAO,CACX,wBAAwB,IACxB,oCACA,0DACA,2DACA,GACA,oCAAoC,EAAa,GACjD,GACA,uCAAuC,KAAK,UAAU,EAAI,SAAW,KAAM,EAAE,CAAC,WAC9E,GACD,CAAC,KAAK;EAAK,CAEZ,MAAM,EAAM,EAAQ,CAAE,UAAW,GAAM,CAAC,CACxC,MAAM,EAAU,EAAQ,EAAM,QAAQ,EAEzC,CCnBY,EAA2C,CACtD,KAAM,0BACN,WAAY,EAAG,IAAQ,0BAA0B,EAAS,EAAI,CAAC,GAC/D,IAAK,KAAO,IAAQ,CAClB,IAAM,EAAS,EAAK,EAAI,OAAQ,YAAY,CACtC,EAAS,EAAK,EAAQ,kBAAkB,CAExC,EAAO,CACX,wBAAwB,IACxB,oCACA,0DACA,GACA,wCAAwC,EAAa,GACrD,GACA,+CAA+C,KAAK,UAAU,EAAI,aAAe,KAAM,EAAE,CAAC,WAC1F,GACD,CAAC,KAAK;EAAK,CAEZ,MAAM,EAAM,EAAQ,CAAE,UAAW,GAAM,CAAC,CACxC,MAAM,EAAU,EAAQ,EAAM,QAAQ,EAEzC,CCvBY,EAA4C,CACvD,KAAM,2BACN,WAAY,EAAG,IAAQ,2BAA2B,EAAS,EAAI,CAAC,GAChE,IAAK,KAAO,IAAQ,CAClB,IAAM,EAAS,EAAK,EAAI,OAAQ,YAAY,CACtC,EAAS,EAAK,EAAQ,mBAAmB,CAEzC,EAAe,EAAI,aACnB,EAAO,CACX,wBAAwB,IACxB,oCACA,GACA,sCAAsC,EAAa,GACnD,GACA,6CAA6C,KAAK,UAAU,EAAc,KAAM,EAAE,CAAC,WACnF,GACD,CAAC,KAAK;EAAK,CAEZ,MAAM,EAAM,EAAQ,CAAE,UAAW,GAAM,CAAC,CACxC,MAAM,EAAU,EAAQ,EAAM,QAAQ,EAEzC,CCpBY,EAA8C,CACzD,KAAM,6BACN,WAAY,EAAG,IAAQ,6BAA6B,EAAS,EAAI,CAAC,GAClE,IAAK,KAAO,IAAQ,CAClB,IAAM,EAAS,EAAK,EAAI,OAAQ,YAAY,CACtC,EAAS,EAAK,EAAQ,qBAAqB,CAC3C,EAAe,EAAI,aACnB,EAAe,EAAI,aAMnB,EAHgB,OAAO,KAAK,EAAa,CAI5C,KAAK,EAAY,IAAM,mBAAmB,EAAE,SAAS,EAAW,GAAG,CACnE,KAAK;EAAK,CAGP,EAA0B,EAAE,CAClC,IAAK,GAAM,CAAC,EAAK,KAAS,OAAO,QAAQ,EAAa,CAAE,CACtD,IAAM,EAAc,OAAO,EAAU,EAAK,CAAC,QAAQ,MAAO;MAAS,GACnE,EAAc,KAAK,MAAM,EAAI,MAAM,EAAY,GAAG,CAGpD,IAAM,EAAO,CACX,wBAAwB,IACxB,oCACA,GACA,wCAAwC,EAAa,GACrD,wCACA,GACA,EACA,GACA,qDACA,kDACA,EAAc,KAAK;EAAK,CACxB,aACA,GACD,CAAC,KAAK;EAAK,CAEZ,MAAM,EAAM,EAAQ,CAAE,UAAW,GAAM,CAAC,CACxC,MAAM,EAAU,EAAQ,EAAM,QAAQ,EAEzC,CAGD,SAAgB,EAAU,EAAmB,EAAS,EAAW,CAC/D,IAAM,EAAS,KAAK,OAAO,EAAO,CAG5B,EAAQ,OAAO,QAAQ,EAAK,MAAM,CACrC,KAAK,CAAC,EAAK,KAAW,GAAG,EAAI,IAAI,IAAQ,CACzC,KAAK,KAAK,CAEb,GAAI,CAAC,EAAK,SACR,MAAO,iBAAiB,EAAK,UAAU,MAAM,EAAM,KAErD,IAAM,EAAY,EAAU,EAAK,SAAU,EAAS,EAAE,CACtD,MAAO,iBAAiB,EAAK,UAAU,MAAM,EAAM,OAAO,EAAO,IAAI,EAAU,IAAI,EAAO,GCzD5F,MAAa,EAAqC,CAChD,KAAM,mBACN,WAAY,EAAG,IAAQ,mBAAmB,EAAS,EAAI,CAAC,GACxD,IAAK,KAAO,IAAQ,CAClB,IAAM,EAAS,EAAK,EAAI,OAAQ,YAAY,CACtC,EAAS,EAAK,EAAQ,WAAW,CACjC,EAAO,CACX,wBAAwB,IACxB,oCACA,GACA,wCACA,+BACA,wBAAwB,EAAa,GACrC,+DACA,GACA,kDACA,+DACA,8CACA,0BACA,IACA,GACD,CAAC,KAAK;EAAK,CAEZ,MAAM,EAAM,EAAQ,CAAE,UAAW,GAAM,CAAC,CACxC,MAAM,EAAU,EAAQ,EAAM,QAAQ,EAEzC,CC5BY,EAAyC,CACpD,KAAM,wBACN,WAAY,EAAG,IAAQ,yBAAyB,EAAS,EAAI,CAAC,GAC9D,QAAU,GAAQ,uBAAuB,EAAI,UAC7C,IAAK,KAAO,IAAQ,CAClB,MAAMA,EAAc,CAClB,MAAO,EAAQ,EAAK,EAAI,OAAQ,YAAa,WAAW,CAAC,CACzD,SAAU,OACV,QAAS,CACP,WAAY,CAAC,MAAO,OAAQ,MAAO,OAAO,CAC3C,CACD,QAAS,CAAC,GAAe,CAAC,CAC1B,OAAQ,CACN,IAAK,EAAQ,EAAK,EAAI,OAAQ,OAAO,CAAC,CACtC,OAAQ,MACR,UAAW,GACX,OAAQ,GACT,CACF,CAAC,EAEL,CCRYC,EAAoB,CAC/B,KAAM,QACN,KAAM,mDACN,OAAQ,SAAY,CAClB,GAAI,CACF,GAAM,CAAE,SAAQ,SAAQ,gBAAiB,MAAM,GAAY,CAC3D,QAAQ,IAAIC,EAAAA,QAAG,KAAK;EAAmC,CAAC,CACxD,QAAQ,IAAIA,EAAAA,QAAG,KAAK,QAAQ,EAAS,IAAI,EAAQ,IAAI,CAAC,CACtD,QAAQ,IAAIA,EAAAA,QAAG,IAAK,aAAa,IAAS,CAAC,CAC3C,QAAQ,IAAIA,EAAAA,QAAG,IAAK,mBAAmB,CAAC,CACxC,QAAQ,IAAIA,EAAAA,QAAG,IAAK,aAAa,IAAS,CAAC,CAC3C,QAAQ,KAAK,CAmBb,GAAM,CAAE,SAAU,GAAQ,MAjBT,EAAK,CACpB,EACA,EACA,EACA,EACA,EAGA,GAAgB,EAChB,GAAgB,EAChB,GAAgB,EAEhB,EACA,EACA,EACD,CAAC,CAEuC,IAAI,CAAE,SAAQ,SAAQ,CAAC,CAChE,QAAQ,KAAK,CACb,QAAQ,IAAI,EAAS,EAAQ,OAAO,CAAC,CACrC,QAAQ,KAAK,CACb,QAAQ,IAAI,GAAGA,EAAAA,QAAG,MAAM,IAAI,CAAC,YAAYA,EAAAA,QAAG,KAAK,EAAS,EAAI,CAAC,GAAG,CAClE,QAAQ,KAAK,OAGR,EAAK,CACV,QAAQ,MAAM,GAAGA,EAAAA,QAAG,IAAI,IAAI,CAAC,eAAe,CAC5C,QAAQ,KAAK,CAEb,IAAM,EAAU,aAAe,MAAQ,EAAI,QAAU,OAAO,EAAI,CAChE,QAAQ,MAAMA,EAAAA,QAAG,IAAI,EAAQ,CAAC,CAC9B,QAAQ,KAAK,CACb,QAAQ,KAAK,EAAE,GAGpB,CC3DY,EAAmB,CAC9B,KAAM,OACN,KAAM,+BACN,OAAQ,SAAY,CAIlB,GAHA,QAAQ,IAAIC,EAAAA,QAAG,KAAK,oBAAoB,EAAS,eAAe,CAAC,CAG7D,EAAW,gBAAgB,CAAE,CAC/B,QAAQ,MAAMA,EAAAA,QAAG,OAAO,IAAI,CAAG,+BAA+B,CAC9D,QAAQ,MAAMA,EAAAA,QAAG,IAAI,iCAAiC,CAAC,CACvD,OAcF,MAAM,EAAU,gBAVM,CACpB,iCAAiC,EAAa,GAC9C,GACA,gCACA,yBACA,sBACA,KACA,GACD,CAAC,KAAK;EAAK,CAEoC,QAAQ,CACxD,QAAQ,IAAIA,EAAAA,QAAG,MAAM,IAAI,CAAG,yBAAyB,CAGrD,IAAM,EAAS,YACf,MAAM,EAAM,EAAQ,CAAE,UAAW,GAAM,CAAC,CAGxC,IAAM,EAAgB,CACpB,kCACA,yCACA,GACA,2EACA,aACA,+CACA,mFACA,wDACA,eACA,mBACA,aACA,MACA,IACA,GACD,CAAC,KAAK;EAAK,CAEZ,MAAM,EAAU,EAAK,EAAQ,aAAa,CAAE,EAAe,QAAQ,CACnE,QAAQ,IAAIA,EAAAA,QAAG,MAAM,IAAI,CAAG,8BAA8B,CAG1D,IAAM,EAAgB,CACpB,mCACA,4CACA,GACA,qCACA,0CACA,GACA,0BACA,8CACA,OACA,GACA,aACA,2CACA,cACA,sEACA,eACA,cACA,2EACA,eACA,aACA,MACA,IACA,GACD,CAAC,KAAK;EAAK,CAEZ,MAAM,EAAU,EAAK,EAAQ,aAAa,CAAE,EAAe,QAAQ,CACnE,QAAQ,IAAIA,EAAAA,QAAG,MAAM,IAAI,CAAG,8BAA8B,CAG1D,QAAQ,KAAK,CACb,QAAQ,IAAIA,EAAAA,QAAG,MAAM,IAAI,CAAG,wBAAwB,CACpD,QAAQ,KAAK,CACb,QAAQ,IAAIA,EAAAA,QAAG,KAAK,gBAAgB,CAAC,CACrC,QAAQ,KAAK,CACb,QAAQ,IAAIA,EAAAA,QAAG,IAAI,oCAAoC,CAAC,CACxD,QAAQ,KAAK,CACb,QAAQ,IAAI,SAAS,CACrB,QAAQ,IAAI,sBAAsB,CAClC,QAAQ,IAAI,sBAAsB,EAAS,UAAU,CACrD,QAAQ,IAAI,sBAAsB,EAAS,SAAS,CACpD,QAAQ,IAAI,WAAW,CACvB,QAAQ,IAAI,SAAS,CACrB,QAAQ,KAAK,CACb,QAAQ,IAAIA,EAAAA,QAAG,IAAI,6CAA6C,CAAC,CACjE,QAAQ,IAAIA,EAAAA,QAAG,IAAI,6CAA6C,CAAC,CACjE,QAAQ,KAAK,EAEhB,CCnGY,EAAoB,CAC/B,KAAM,QACN,KAAM,wBACN,OAAQ,SAAY,CAClB,GAAM,CAAE,UAAW,MAAM,GAAY,CAE/B,EAAY,EAAQ,EAAQ,OAAQ,WAAW,CAGrD,GAAI,CAAC,EAAW,EAAU,CAGxB,MAFA,QAAQ,MAAMC,EAAAA,QAAG,IAAI,IAAI,CAAG,mBAAmB,CAC/C,QAAQ,MAAMA,EAAAA,QAAG,IAAI,UAAU,EAAS,eAAe,CAAC,CAC9C,MAAM,kBAAkB,CAKpC,GAAM,CAAE,IAAA,GAAQ,MAAM,OADL,EAAc,EAAU,CAAC,MAI1C,MAAMC,EAAI,IAAW,EAExB,CCzBD,SAAS,EAAiB,EAAkB,CAC1C,EACG,KAAK,EAAS,CACd,YAAY,uDAAY,CACxB,QAAQ,EAAQ,CAEnB,IAAM,EAAW,CAACC,EAAO,EAAM,EAAM,CACrC,IAAK,GAAM,CAAE,OAAM,OAAM,YAAY,EACnC,EACG,QAAQ,EAAK,CACb,YAAY,EAAK,CACjB,OAAO,EAAO,CAEnB,OAAO,EAGT,eAAsB,EAAI,EAAgB,CAExC,IAAM,EAAU,EADA,IAAI,EACqB,CAEzC,GAAI,CAEF,OADA,MAAM,EAAQ,WAAW,EAAK,CACvB,QAEF,EAAK,CACV,IAAM,EAAU,aAAe,MAAQ,EAAI,QAAU,gBAErD,OADA,QAAQ,MAAM,EAAQ,CACf,GC7BX,QAAQ,KAAK,MAAM,EAAI,QAAQ,KAAK,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"element-tree-DoH7UgRL.mjs","names":[],"sources":["../src/pen/config.ts","../src/lib/tree.ts","../src/pen/compiler/errors.ts","../src/pen/compiler/builders/file-tree.ts","../src/pen/compiler/builders/segment-tree.ts","../src/lib/path-utils.ts","../src/pen/compiler/builders/route-manifest.ts","../src/pen/compiler/builders/component-map.ts","../src/pen/compiler/builders/element-tree.ts"],"sourcesContent":["import { resolve } from 'path'\r\nimport { pathToFileURL } from 'url'\r\n\r\n/**\r\n * Resolved configuration with all fields guaranteed to be present.\r\n * This is what loadConfig() returns after merging user config with defaults.\r\n */\r\nexport type ResolvedPenConfig = {\r\n /**\r\n * Directory containing your app routes.\r\n * @default './src/app'\r\n */\r\n appDir: string\r\n\r\n /**\r\n * Output directory for generated files and build artifacts.\r\n * @default './.pen'\r\n */\r\n outDir: string\r\n\r\n /**\r\n * Emit metadata files (manifest, components, element-tree) to aid debugging and tooling.\r\n * These files provide introspection into your app's structure.\r\n * @default true\r\n */\r\n emitMetadata: boolean\r\n}\r\n\r\n/**\r\n * User-facing configuration (what users write in pen.config.ts).\r\n * All fields are optional and will be merged with defaults.\r\n */\r\nexport type PenConfig = Partial<ResolvedPenConfig>\r\n\r\nexport function defineConfig(config: PenConfig): PenConfig {\r\n return config\r\n}\r\n\r\nconst defaultConfig: ResolvedPenConfig = {\r\n appDir: './src/app',\r\n outDir: './.pen',\r\n emitMetadata: false,\r\n}\r\n\r\n/**\r\n * Loads pen.config.ts from the current directory.\r\n * Falls back to defaults if config file doesn't exist.\r\n * Returns a fully resolved config with all fields guaranteed to be present.\r\n */\r\nexport async function loadConfig(): Promise<ResolvedPenConfig> {\r\n try {\r\n const configPath = resolve(process.cwd(), 'pen.config.ts')\r\n const configUrl = pathToFileURL(configPath).href\r\n\r\n const module = await import(configUrl) as { default?: PenConfig }\r\n const userConfig = module.default || {}\r\n\r\n // Merge with defaults\r\n return { ...defaultConfig, ...userConfig }\r\n }\r\n catch {\r\n // Config file doesn't exist or failed to load - use defaults\r\n return defaultConfig\r\n }\r\n}\r\n","/** Callbacks for tree traversal. */\r\nexport type TraverseCallbacks<TNode> = {\r\n /** Called when visiting each node (pre-order) */\r\n visit?: (node: TNode) => void\r\n /** Returns children for a node (or creates them) */\r\n expand?: (node: TNode) => TNode[]\r\n /** Attaches a child to its parent */\r\n attach?: (child: TNode, parent: TNode) => void\r\n}\r\n\r\n/**\r\n * Depth-first tree traversal with pluggable callbacks.\r\n *\r\n * @template TNode - The type of tree nodes\r\n * @param root - The root node to start traversal from\r\n * @param callbacks - Callbacks for visit, expand, and attach operations\r\n *\r\n * @example\r\n * // Visit existing tree\r\n * traverse(tree, {\r\n * visit: (node) => console.log(node.name),\r\n * expand: (node) => node.children ?? []\r\n * })\r\n *\r\n * @example\r\n * // Build new tree\r\n * traverse(root, {\r\n * expand: (node) => createChildren(node),\r\n * attach: (child, parent) => parent.children.push(child)\r\n * })\r\n */\r\nexport function traverse<TNode>(root: TNode, callbacks: TraverseCallbacks<TNode>) {\r\n const { visit, expand, attach } = callbacks\r\n const stack = [root]\r\n\r\n while (stack.length) {\r\n const node = stack.pop()!\r\n visit?.(node)\r\n\r\n // Process children in reverse so\r\n // they're popped in correct order\r\n const children = expand?.(node) ?? []\r\n\r\n for (let i = children.length-1; i >= 0; i--) {\r\n const child = children[i]!\r\n attach?.(child, node)\r\n stack.push(child)\r\n }\r\n }\r\n}\r\n\r\n/** Callbacks for ancestor traversal. */\r\nexport type AncestorCallbacks<TNode> = {\r\n /** Called when visiting each ancestor node (from leaf to root) */\r\n visit: (node: TNode) => void\r\n /** Returns the parent node for a given node */\r\n parent: (node: TNode) => TNode | undefined\r\n}\r\n\r\n/**\r\n * Traverses the ancestor chain of a given node from leaf to root.\r\n *\r\n * @template TNode - The type of tree nodes\r\n * @param node - The node to start the ancestor traversal from\r\n * @param callbacks - Callbacks for visit and parent operations\r\n *\r\n * @example\r\n * // Visit ancestors in a tree structure\r\n * ancestors(node, {\r\n * visit: (node) => console.log(`Visiting: ${node.name}`),\r\n * parent: (node) => node.parent // Return the parent of the node\r\n * })\r\n *\r\n * @example\r\n * // Collect all ancestors' roles in a tree structure\r\n * const roles = []\r\n * ancestors(node, {\r\n * visit: (node) => roles.push(node.role),\r\n * parent: (node) => node.parent\r\n * })\r\n * console.log(roles) // Logs all ancestor roles from leaf to root\r\n */\r\nexport function ancestors<TNode>(node: TNode, callbacks: AncestorCallbacks<TNode>) {\r\n const { visit, parent } = callbacks\r\n let currentNode: TNode | undefined = node\r\n\r\n while (currentNode) {\r\n visit(currentNode)\r\n currentNode = parent(currentNode)\r\n }\r\n}\r\n","/**\r\n * Base error for all route-builder build errors\r\n */\r\nexport class FileRouterError extends Error {\r\n constructor(message: string) {\r\n super(message)\r\n this.name = 'FileRouterError'\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// File Tree Errors\r\n// ============================================================================\r\n\r\nexport class DirectoryNotFoundError extends FileRouterError {\r\n constructor(public path: string) {\r\n super(`Directory not found: \"${path}\"`)\r\n this.name = 'DirectoryNotFoundError'\r\n }\r\n}\r\n\r\nexport class NotADirectoryError extends FileRouterError {\r\n constructor(public path: string) {\r\n super(`Path is not a directory: \"${path}\"`)\r\n this.name = 'NotADirectoryError'\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Route Tree Errors\r\n// ============================================================================\r\n\r\nexport class RootIsFileError extends FileRouterError {\r\n constructor(public path: string) {\r\n super(\r\n `Root path is a file, not a directory: \"${path}\"\\n\\n` +\r\n 'The app directory must be a directory, not a file.',\r\n )\r\n this.name = 'RootIsFileError'\r\n }\r\n}\r\n\r\nexport class DuplicateScreenError extends FileRouterError {\r\n constructor(\r\n public url: string,\r\n public files: string[],\r\n ) {\r\n super(\r\n `Conflicting screen routes found at \"${url}\":\\n` +\r\n files.map(f => ` - ${f}`).join('\\n') + '\\n\\n' +\r\n 'Each URL can only have one screen file.\\n' +\r\n 'Move one screen to a different directory or rename the route segment.',\r\n )\r\n this.name = 'DuplicateScreenError'\r\n }\r\n}\r\n","import { readdirSync, statSync, type Dirent } from 'fs'\r\nimport { resolve, join, posix } from 'path'\r\nimport { traverse } from '@/lib/tree'\r\nimport { DirectoryNotFoundError, NotADirectoryError } from '../errors'\r\n\r\nexport type FileNode = {\r\n name: string // dirent name\r\n relPath: string\r\n absPath: string\r\n children?: FileNode[] // present only for directories\r\n}\r\n\r\n/**\r\n * Builds a file tree from a directory path.\r\n *\r\n * @param appPath - Path to the app directory\r\n * @returns File tree structure\r\n * @throws {DirectoryNotFoundError} If the directory doesn't exist\r\n * @throws {NotADirectoryError} If the path is not a directory\r\n */\r\nexport function createFileTree(appPath: string): FileNode {\r\n const absPath = resolve(appPath)\r\n validateDirectory(absPath)\r\n\r\n // Root node\r\n const name = 'app'\r\n const relPath = '/app'\r\n const root: FileNode = { name, relPath, absPath, children: [] }\r\n\r\n traverse(root, {\r\n attach: (child, parent) => parent.children!.push(child),\r\n expand: (file) => {\r\n if (!file.children) return []\r\n\r\n return readdirSync(file.absPath, { withFileTypes: true })\r\n .filter(d => d.isFile() || d.isDirectory())\r\n .map(d => createFileNode(d, file))\r\n .sort((a, b) => a.name.localeCompare(b.name))\r\n },\r\n })\r\n return root\r\n}\r\n\r\n/** Validates that the path exists and is a directory. */\r\nfunction validateDirectory(path: string) {\r\n const stat = statSync(path, { throwIfNoEntry: false })\r\n if (!stat) throw new DirectoryNotFoundError(path)\r\n if (!stat.isDirectory()) throw new NotADirectoryError(path)\r\n}\r\n\r\nfunction createFileNode(dirent: Dirent, parent: FileNode) {\r\n const relPath = posix.join(parent.relPath, dirent.name)\r\n const absPath = join(parent.absPath, dirent.name)\r\n\r\n return dirent.isDirectory()\r\n ? { name: dirent.name, relPath, absPath, children: [] }\r\n : { name: dirent.name, relPath, absPath }\r\n}\r\n","import type { FileNode } from './file-tree'\r\nimport { parse, posix } from 'path'\r\nimport { traverse } from '@/lib/tree'\r\nimport { RootIsFileError, DuplicateScreenError } from '../errors'\r\n\r\nexport const SEGMENT_ROLES = ['layout', 'screen', 'error', 'not-found'] as const\r\nexport type SegmentRole = typeof SEGMENT_ROLES[number]\r\n\r\nexport type SegmentRoles = Partial<Record<SegmentRole, string>>\r\nexport type SegmentNode = {\r\n segment: string\r\n url: `${string}/`\r\n type: 'page' | 'group'\r\n roles: SegmentRoles\r\n parent?: SegmentNode\r\n children?: SegmentNode[]\r\n file: FileNode\r\n}\r\n\r\n/**\r\n * Creates a segment tree from a file system tree.\r\n *\r\n * @param fileTree - File system tree\r\n * @returns Segment tree with assigned roles and validated structure\r\n * @throws {RootIsFileError} If the root is a file instead of a directory\r\n * @throws {DuplicateScreenError} If multiple screens map to the same URL\r\n */\r\nexport function createSegmentTree(fileTree: FileNode): SegmentNode {\r\n const tree = buildSegmentTree(fileTree) // Builds segment tree structure from file tree\r\n bindSegmentTree(tree) // Binds roles to segments and validates tree structure\r\n return tree\r\n}\r\n\r\nfunction buildSegmentTree(fileTree: FileNode) {\r\n if (fileTree.children === undefined)\r\n throw new RootIsFileError(fileTree.absPath)\r\n\r\n const root: SegmentNode = {\r\n segment: '',\r\n url: '/',\r\n type: 'page',\r\n roles: {},\r\n children: [],\r\n file: fileTree,\r\n }\r\n\r\n traverse(root, {\r\n attach: (child, parent) => parent.children!.push(child),\r\n expand: segment =>\r\n (segment.file.children ?? [])\r\n .filter(file => file.children && !file.name.startsWith('_'))\r\n .map(file => createSegmentNode(file, segment))\r\n .sort((a, b) => a.segment.localeCompare(b.segment)),\r\n })\r\n return root\r\n}\r\n\r\nfunction bindSegmentTree(segmentTree: SegmentNode) {\r\n const screens: Record<SegmentNode['url'], string> = {}\r\n\r\n traverse(segmentTree, {\r\n expand: segment => segment.children ?? [],\r\n visit: segment => {\r\n assignRoles(segment)\r\n validateScreenUniqueness(segment, screens)\r\n },\r\n })\r\n}\r\n\r\nfunction createSegmentNode(file: FileNode, parent: SegmentNode) {\r\n const isGroup = file.name.startsWith('(') && file.name.endsWith(')')\r\n const segmentNode: SegmentNode = {\r\n segment: file.name,\r\n url: isGroup ? parent.url : `${posix.join(parent.url, file.name)}/`,\r\n type: isGroup ? 'group' : 'page',\r\n roles: {},\r\n parent,\r\n children: [],\r\n file,\r\n }\r\n return segmentNode\r\n}\r\n\r\nfunction assignRoles(segment: SegmentNode) {\r\n for (const child of segment.file.children ?? []) {\r\n const { name, ext } = parse(child.name)\r\n if (ext === '.tsx' && SEGMENT_ROLES.includes(name as SegmentRole))\r\n segment.roles[name as SegmentRole] = child.absPath\r\n }\r\n}\r\n\r\nfunction validateScreenUniqueness(segment: SegmentNode, screens: Record<SegmentNode['url'], string>) {\r\n if (!segment.roles.screen) return\r\n\r\n const existing = screens[segment.url]\r\n if (existing)\r\n throw new DuplicateScreenError(segment.url, [existing, segment.file.absPath])\r\n screens[segment.url] = segment.file.absPath\r\n}\r\n","import { parse, join } from 'path'\r\n\r\nexport function removeExtension(filePath: string) {\r\n const parsed = parse(filePath)\r\n return join(parsed.dir, parsed.name) // Use posix for forward slashes\r\n}\r\n","import type { SegmentNode, SegmentRoles } from './segment-tree'\r\nimport { ancestors, traverse } from '@/lib/tree'\r\nimport { relative } from 'path'\r\nimport { removeExtension } from '@/lib/path-utils'\r\n\r\nexport type RouteManifest = Record<string, Route>\r\nexport type Route = {\r\n url: string\r\n chain: SegmentRoles[]\r\n}\r\n\r\n/**\r\n * Builds a route manifest from a segment tree.\r\n *\r\n * Flattens the tree into a dictionary mapping URLs to route metadata.\r\n * Only includes routes that have screens.\r\n * Paths are stored as relative import paths from the generated directory.\r\n *\r\n * @param segmentTree - Segment tree with parent pointers\r\n * @param outDir - Output directory (to calculate relative import paths)\r\n * @returns Flat manifest ready for runtime composition\r\n */\r\nexport function createRouteManifest(segmentTree: SegmentNode, outDir: string): RouteManifest {\r\n const manifest: RouteManifest = {}\r\n const genDir = `${outDir}/generated`\r\n\r\n traverse(segmentTree, {\r\n expand: parentSegment => parentSegment.children ?? [],\r\n visit: segment => {\r\n if (!segment.roles.screen) return\r\n const url = segment.url\r\n const chain = createSegmentChain(segment, genDir)\r\n manifest[url] = { url, chain }\r\n },\r\n })\r\n return manifest\r\n}\r\n\r\n/** Builds ancestor chain from leaf → root order. */\r\nfunction createSegmentChain(segment: SegmentNode, genDir: string) {\r\n const chain: SegmentRoles[] = []\r\n\r\n ancestors(segment, {\r\n parent: ancestorSegment => ancestorSegment.parent,\r\n visit: ancestorSegment => {\r\n const roles: SegmentRoles = {}\r\n const entries = Object.entries(ancestorSegment.roles) as [keyof SegmentRoles, string][]\r\n\r\n for (const [name, path] of entries) {\r\n if (name !== 'screen' || ancestorSegment === segment) { // Skip ancestor screens\r\n const importPath = removeExtension(path) // Remove extension\r\n const relPath = relative(genDir, importPath).replace(/\\\\/g, '/') // Convert to relative path\r\n roles[name] = `${relPath}.js` // Add .js for ES modules\r\n }\r\n }\r\n chain.push(roles)\r\n },\r\n })\r\n return chain\r\n}\r\n","import type { RouteManifest } from './route-manifest'\r\nimport { SEGMENT_ROLES } from './segment-tree'\r\n\r\n/** Map from import path to component index (keys are in sorted order) */\r\nexport type ComponentMap = Record<string, number>\r\n\r\n/**\r\n * Builds a mapping of import paths to component IDs from the manifest.\r\n * Collects all unique import paths and assigns them indices.\r\n * Keys are stored in sorted order for deterministic output.\r\n */\r\nexport function createComponentMap(manifest: RouteManifest): ComponentMap {\r\n const importPaths = new Set<string>()\r\n\r\n // Collect all unique import paths from manifest\r\n for (const route of Object.values(manifest)) {\r\n for (const segment of route.chain) {\r\n for (const role of SEGMENT_ROLES)\r\n if (segment[role]) importPaths.add(segment[role])\r\n }\r\n }\r\n\r\n // Sort for deterministic output\r\n const imports = Array.from(importPaths).sort()\r\n const mapping: ComponentMap = {}\r\n for (let i = 0; i < imports.length; i++)\r\n mapping[imports[i]!] = i\r\n\r\n return mapping\r\n}\r\n","import type { Route, RouteManifest } from './route-manifest'\r\nimport type { ComponentMap } from './component-map'\r\n\r\nexport interface ElementTree {\r\n component: string\r\n props: Record<string, unknown>\r\n children?: ElementTree\r\n}\r\n\r\nexport type ElementTreeMap = Record<string, ElementTree>\r\n\r\n/**\r\n * Creates element trees for all routes in the manifest.\r\n * Each tree represents the nested React component structure for a route.\r\n */\r\nexport function createElementTrees(manifest: RouteManifest, componentMap: ComponentMap): ElementTreeMap {\r\n const elementTrees: ElementTreeMap = {}\r\n for (const [url, route] of Object.entries(manifest))\r\n elementTrees[url] = createElementTree(route, componentMap)\r\n return elementTrees\r\n}\r\n\r\n/**\r\n * Builds a structured element tree representing nested React components.\r\n *\r\n * This function mirrors the runtime composition logic but creates a structured data tree\r\n * that will be serialized into createElement calls for the generated routes.ts file.\r\n *\r\n * Composition order per segment (inside to outside):\r\n * 1. Screen component (only in leaf segment)\r\n * 2. Not-found boundary (wraps screen if present)\r\n * 3. Layout (wraps content)\r\n * 4. Error boundary (wraps layout + all descendants)\r\n */\r\nfunction createElementTree(route: Route, mapping: ComponentMap): ElementTree {\r\n const imports = Object.keys(mapping)\r\n\r\n // Start with the screen from the first segment\r\n const screenSegment = route.chain[0]!\r\n const screenPath = screenSegment['screen']!\r\n const screenIndex = mapping[screenPath]!\r\n const screenKey = JSON.stringify(imports[screenIndex]!)\r\n\r\n let tree: ElementTree = {\r\n component: `Component${screenIndex}`,\r\n props: { key: screenKey },\r\n }\r\n\r\n // Process segments from leaf → root (same order as runtime composition)\r\n for (const segment of route.chain) {\r\n // Not-found boundary\r\n if (segment['not-found']) {\r\n const path = segment['not-found']\r\n const index = mapping[path]!\r\n const key = JSON.stringify(imports[index]!)\r\n const fallback = `Component${index}`\r\n tree = {\r\n component: 'NotFoundBoundary',\r\n props: { key, fallback },\r\n children: tree,\r\n }\r\n }\r\n // Error boundary\r\n if (segment['error']) {\r\n const path = segment['error']\r\n const index = mapping[path]!\r\n const key = JSON.stringify(imports[index]!)\r\n const fallback = `Component${index}`\r\n tree = {\r\n component: 'ErrorBoundary',\r\n props: { key, fallback },\r\n children: tree,\r\n }\r\n }\r\n // Layout\r\n if (segment['layout']) {\r\n const path = segment['layout']\r\n const index = mapping[path]!\r\n const key = JSON.stringify(imports[index]!)\r\n tree = {\r\n component: `Component${index}`,\r\n props: { key },\r\n children: tree,\r\n }\r\n }\r\n }\r\n return tree\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"element-tree-DoH7UgRL.mjs","names":[],"sources":["../src/pen/config.ts","../src/lib/tree.ts","../src/pen/compiler/errors.ts","../src/pen/compiler/builders/file-tree.ts","../src/pen/compiler/builders/segment-tree.ts","../src/lib/path-utils.ts","../src/pen/compiler/builders/route-manifest.ts","../src/pen/compiler/builders/component-map.ts","../src/pen/compiler/builders/element-tree.ts"],"sourcesContent":["import { resolve } from 'path'\r\nimport { pathToFileURL } from 'url'\r\n\r\n/**\r\n * Resolved configuration with all fields guaranteed to be present.\r\n * This is what loadConfig() returns after merging user config with defaults.\r\n */\r\nexport type ResolvedPenConfig = {\r\n /**\r\n * Directory containing your app routes.\r\n * @default './src/app'\r\n */\r\n appDir: string\r\n\r\n /**\r\n * Output directory for generated files and build artifacts.\r\n * @default './.pen'\r\n */\r\n outDir: string\r\n\r\n /**\r\n * Emit metadata files (manifest, components, element-tree) to aid debugging and tooling.\r\n * These files provide introspection into your app's structure.\r\n * @default true\r\n */\r\n emitMetadata: boolean\r\n}\r\n\r\n/**\r\n * User-facing configuration (what users write in pen.config.ts).\r\n * All fields are optional and will be merged with defaults.\r\n */\r\nexport type PenConfig = Partial<ResolvedPenConfig>\r\n\r\nexport function defineConfig(config: PenConfig): PenConfig {\r\n return config\r\n}\r\n\r\nconst defaultConfig: ResolvedPenConfig = {\r\n appDir: './src/app',\r\n outDir: './.pen',\r\n emitMetadata: false,\r\n}\r\n\r\n/**\r\n * Loads pen.config.ts from the current directory.\r\n * Falls back to defaults if config file doesn't exist.\r\n * Returns a fully resolved config with all fields guaranteed to be present.\r\n */\r\nexport async function loadConfig(): Promise<ResolvedPenConfig> {\r\n try {\r\n const configPath = resolve(process.cwd(), 'pen.config.ts')\r\n const configUrl = pathToFileURL(configPath).href\r\n\r\n const module = await import(configUrl) as { default?: PenConfig }\r\n const userConfig = module.default || {}\r\n\r\n // Merge with defaults\r\n return { ...defaultConfig, ...userConfig }\r\n }\r\n catch {\r\n // Config file doesn't exist or failed to load - use defaults\r\n return defaultConfig\r\n }\r\n}\r\n","/** Callbacks for tree traversal. */\r\nexport type TraverseCallbacks<TNode> = {\r\n /** Called when visiting each node (pre-order) */\r\n visit?: (node: TNode) => void\r\n /** Returns children for a node (or creates them) */\r\n expand?: (node: TNode) => TNode[]\r\n /** Attaches a child to its parent */\r\n attach?: (child: TNode, parent: TNode) => void\r\n}\r\n\r\n/**\r\n * Depth-first tree traversal with pluggable callbacks.\r\n *\r\n * @template TNode - The type of tree nodes\r\n * @param root - The root node to start traversal from\r\n * @param callbacks - Callbacks for visit, expand, and attach operations\r\n *\r\n * @example\r\n * // Visit existing tree\r\n * traverse(tree, {\r\n * visit: (node) => console.log(node.name),\r\n * expand: (node) => node.children ?? []\r\n * })\r\n *\r\n * @example\r\n * // Build new tree\r\n * traverse(root, {\r\n * expand: (node) => createChildren(node),\r\n * attach: (child, parent) => parent.children.push(child)\r\n * })\r\n */\r\nexport function traverse<TNode>(root: TNode, callbacks: TraverseCallbacks<TNode>) {\r\n const { visit, expand, attach } = callbacks\r\n const stack = [root]\r\n\r\n while (stack.length) {\r\n const node = stack.pop()!\r\n visit?.(node)\r\n\r\n // Process children in reverse so\r\n // they're popped in correct order\r\n const children = expand?.(node) ?? []\r\n\r\n for (let i = children.length-1; i >= 0; i--) {\r\n const child = children[i]!\r\n attach?.(child, node)\r\n stack.push(child)\r\n }\r\n }\r\n}\r\n\r\n/** Callbacks for ancestor traversal. */\r\nexport type AncestorCallbacks<TNode> = {\r\n /** Called when visiting each ancestor node (from leaf to root) */\r\n visit: (node: TNode) => void\r\n /** Returns the parent node for a given node */\r\n parent: (node: TNode) => TNode | undefined\r\n}\r\n\r\n/**\r\n * Traverses the ancestor chain of a given node from leaf to root.\r\n *\r\n * @template TNode - The type of tree nodes\r\n * @param node - The node to start the ancestor traversal from\r\n * @param callbacks - Callbacks for visit and parent operations\r\n *\r\n * @example\r\n * // Visit ancestors in a tree structure\r\n * ancestors(node, {\r\n * visit: (node) => console.log(`Visiting: ${node.name}`),\r\n * parent: (node) => node.parent // Return the parent of the node\r\n * })\r\n *\r\n * @example\r\n * // Collect all ancestors' roles in a tree structure\r\n * const roles = []\r\n * ancestors(node, {\r\n * visit: (node) => roles.push(node.role),\r\n * parent: (node) => node.parent\r\n * })\r\n * console.log(roles) // Logs all ancestor roles from leaf to root\r\n */\r\nexport function ancestors<TNode>(node: TNode, callbacks: AncestorCallbacks<TNode>) {\r\n const { visit, parent } = callbacks\r\n let currentNode: TNode | undefined = node\r\n\r\n while (currentNode) {\r\n visit(currentNode)\r\n currentNode = parent(currentNode)\r\n }\r\n}\r\n","/**\r\n * Base error for all route-builder build errors\r\n */\r\nexport class FileRouterError extends Error {\r\n constructor(message: string) {\r\n super(message)\r\n this.name = 'FileRouterError'\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// File Tree Errors\r\n// ============================================================================\r\n\r\nexport class DirectoryNotFoundError extends FileRouterError {\r\n constructor(public path: string) {\r\n super(`Directory not found: \"${path}\"`)\r\n this.name = 'DirectoryNotFoundError'\r\n }\r\n}\r\n\r\nexport class NotADirectoryError extends FileRouterError {\r\n constructor(public path: string) {\r\n super(`Path is not a directory: \"${path}\"`)\r\n this.name = 'NotADirectoryError'\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Route Tree Errors\r\n// ============================================================================\r\n\r\nexport class RootIsFileError extends FileRouterError {\r\n constructor(public path: string) {\r\n super(\r\n `Root path is a file, not a directory: \"${path}\"\\n\\n` +\r\n 'The app directory must be a directory, not a file.',\r\n )\r\n this.name = 'RootIsFileError'\r\n }\r\n}\r\n\r\nexport class DuplicateScreenError extends FileRouterError {\r\n constructor(\r\n public url: string,\r\n public files: string[],\r\n ) {\r\n super(\r\n `Conflicting screen routes found at \"${url}\":\\n` +\r\n files.map(f => ` - ${f}`).join('\\n') + '\\n\\n' +\r\n 'Each URL can only have one screen file.\\n' +\r\n 'Move one screen to a different directory or rename the route segment.',\r\n )\r\n this.name = 'DuplicateScreenError'\r\n }\r\n}\r\n","import { readdirSync, statSync, type Dirent } from 'fs'\r\nimport { resolve, join, posix } from 'path'\r\nimport { traverse } from '@/lib/tree'\r\nimport { DirectoryNotFoundError, NotADirectoryError } from '../errors'\r\n\r\nexport type FileNode = {\r\n name: string // dirent name\r\n relPath: string\r\n absPath: string\r\n children?: FileNode[] // present only for directories\r\n}\r\n\r\n/**\r\n * Builds a file tree from a directory path.\r\n *\r\n * @param appPath - Path to the app directory\r\n * @returns File tree structure\r\n * @throws {DirectoryNotFoundError} If the directory doesn't exist\r\n * @throws {NotADirectoryError} If the path is not a directory\r\n */\r\nexport function createFileTree(appPath: string): FileNode {\r\n const absPath = resolve(appPath)\r\n validateDirectory(absPath)\r\n\r\n // Root node\r\n const name = 'app'\r\n const relPath = '/app'\r\n const root: FileNode = { name, relPath, absPath, children: [] }\r\n\r\n traverse(root, {\r\n attach: (child, parent) => parent.children!.push(child),\r\n expand: (file) => {\r\n if (!file.children) return []\r\n\r\n return readdirSync(file.absPath, { withFileTypes: true })\r\n .filter(d => d.isFile() || d.isDirectory())\r\n .map(d => createFileNode(d, file))\r\n .sort((a, b) => a.name.localeCompare(b.name))\r\n },\r\n })\r\n return root\r\n}\r\n\r\n/** Validates that the path exists and is a directory. */\r\nfunction validateDirectory(path: string) {\r\n const stat = statSync(path, { throwIfNoEntry: false })\r\n if (!stat) throw new DirectoryNotFoundError(path)\r\n if (!stat.isDirectory()) throw new NotADirectoryError(path)\r\n}\r\n\r\nfunction createFileNode(dirent: Dirent, parent: FileNode) {\r\n const relPath = posix.join(parent.relPath, dirent.name)\r\n const absPath = join(parent.absPath, dirent.name)\r\n\r\n return dirent.isDirectory()\r\n ? { name: dirent.name, relPath, absPath, children: [] }\r\n : { name: dirent.name, relPath, absPath }\r\n}\r\n","import type { FileNode } from './file-tree'\r\nimport { parse, posix } from 'path'\r\nimport { traverse } from '@/lib/tree'\r\nimport { RootIsFileError, DuplicateScreenError } from '../errors'\r\n\r\nexport const SEGMENT_ROLES = ['layout', 'screen', 'error', 'not-found'] as const\r\nexport type SegmentRole = typeof SEGMENT_ROLES[number]\r\n\r\nexport type SegmentRoles = Partial<Record<SegmentRole, string>>\r\nexport type SegmentNode = {\r\n segment: string\r\n url: `${string}/`\r\n type: 'page' | 'group'\r\n roles: SegmentRoles\r\n parent?: SegmentNode\r\n children?: SegmentNode[]\r\n file: FileNode\r\n}\r\n\r\n/**\r\n * Creates a segment tree from a file system tree.\r\n *\r\n * @param fileTree - File system tree\r\n * @returns Segment tree with assigned roles and validated structure\r\n * @throws {RootIsFileError} If the root is a file instead of a directory\r\n * @throws {DuplicateScreenError} If multiple screens map to the same URL\r\n */\r\nexport function createSegmentTree(fileTree: FileNode): SegmentNode {\r\n const tree = buildSegmentTree(fileTree) // Builds segment tree structure from file tree\r\n bindSegmentTree(tree) // Binds roles to segments and validates tree structure\r\n return tree\r\n}\r\n\r\nfunction buildSegmentTree(fileTree: FileNode) {\r\n if (fileTree.children === undefined)\r\n throw new RootIsFileError(fileTree.absPath)\r\n\r\n const root: SegmentNode = {\r\n segment: '',\r\n url: '/',\r\n type: 'page',\r\n roles: {},\r\n children: [],\r\n file: fileTree,\r\n }\r\n\r\n traverse(root, {\r\n attach: (child, parent) => parent.children!.push(child),\r\n expand: segment =>\r\n (segment.file.children ?? [])\r\n .filter(file => file.children && !file.name.startsWith('_'))\r\n .map(file => createSegmentNode(file, segment))\r\n .sort((a, b) => a.segment.localeCompare(b.segment)),\r\n })\r\n return root\r\n}\r\n\r\nfunction bindSegmentTree(segmentTree: SegmentNode) {\r\n const screens: Record<SegmentNode['url'], string> = {}\r\n\r\n traverse(segmentTree, {\r\n expand: segment => segment.children ?? [],\r\n visit: segment => {\r\n assignRoles(segment)\r\n validateScreenUniqueness(segment, screens)\r\n },\r\n })\r\n}\r\n\r\nfunction createSegmentNode(file: FileNode, parent: SegmentNode) {\r\n const isGroup = file.name.startsWith('(') && file.name.endsWith(')')\r\n const segmentNode: SegmentNode = {\r\n segment: file.name,\r\n url: isGroup ? parent.url : `${posix.join(parent.url, file.name)}/`,\r\n type: isGroup ? 'group' : 'page',\r\n roles: {},\r\n parent,\r\n children: [],\r\n file,\r\n }\r\n return segmentNode\r\n}\r\n\r\nfunction assignRoles(segment: SegmentNode) {\r\n for (const child of segment.file.children ?? []) {\r\n const { name, ext } = parse(child.name)\r\n if (ext === '.tsx' && SEGMENT_ROLES.includes(name as SegmentRole))\r\n segment.roles[name as SegmentRole] = child.absPath\r\n }\r\n}\r\n\r\nfunction validateScreenUniqueness(segment: SegmentNode, screens: Record<SegmentNode['url'], string>) {\r\n if (!segment.roles.screen) return\r\n\r\n const existing = screens[segment.url]\r\n if (existing)\r\n throw new DuplicateScreenError(segment.url, [existing, segment.file.absPath])\r\n screens[segment.url] = segment.file.absPath\r\n}\r\n","import { parse, join } from 'path'\r\n\r\nexport function removeExtension(filePath: string) {\r\n const parsed = parse(filePath)\r\n return join(parsed.dir, parsed.name) // Use posix for forward slashes\r\n}\r\n","import type { SegmentNode, SegmentRoles } from './segment-tree'\r\nimport { ancestors, traverse } from '@/lib/tree'\r\nimport { relative } from 'path'\r\nimport { removeExtension } from '@/lib/path-utils'\r\n\r\nexport type RouteTable = Record<string, Route>\r\nexport type Route = {\r\n url: string\r\n chain: SegmentRoles[]\r\n}\r\n\r\n/**\r\n * Builds a route manifest from a segment tree.\r\n *\r\n * Flattens the tree into a dictionary mapping URLs to route metadata.\r\n * Only includes routes that have screens.\r\n * Paths are stored as relative import paths from the generated directory.\r\n *\r\n * @param segmentTree - Segment tree with parent pointers\r\n * @param outDir - Output directory (to calculate relative import paths)\r\n * @returns Flat manifest ready for runtime composition\r\n */\r\nexport function createRouteTable(segmentTree: SegmentNode, outDir: string): RouteTable {\r\n const manifest: RouteTable = {}\r\n const genDir = `${outDir}/generated`\r\n\r\n traverse(segmentTree, {\r\n expand: parentSegment => parentSegment.children ?? [],\r\n visit: segment => {\r\n if (!segment.roles.screen) return\r\n const url = segment.url\r\n const chain = createSegmentChain(segment, genDir)\r\n manifest[url] = { url, chain }\r\n },\r\n })\r\n return manifest\r\n}\r\n\r\n/** Builds ancestor chain from leaf → root order. */\r\nfunction createSegmentChain(segment: SegmentNode, genDir: string) {\r\n const chain: SegmentRoles[] = []\r\n\r\n ancestors(segment, {\r\n parent: ancestorSegment => ancestorSegment.parent,\r\n visit: ancestorSegment => {\r\n const roles: SegmentRoles = {}\r\n const entries = Object.entries(ancestorSegment.roles) as [keyof SegmentRoles, string][]\r\n\r\n for (const [name, path] of entries) {\r\n if (name !== 'screen' || ancestorSegment === segment) { // Skip ancestor screens\r\n const importPath = removeExtension(path) // Remove extension\r\n const relPath = relative(genDir, importPath).replace(/\\\\/g, '/') // Convert to relative path\r\n roles[name] = `${relPath}.js` // Add .js for ES modules\r\n }\r\n }\r\n chain.push(roles)\r\n },\r\n })\r\n return chain\r\n}\r\n","import type { RouteTable } from './route-manifest'\r\nimport { SEGMENT_ROLES } from './segment-tree'\r\n\r\n/** Map from import path to component index (keys are in sorted order) */\r\nexport type ComponentMap = Record<string, number>\r\n\r\n/**\r\n * Builds a mapping of import paths to component IDs from the manifest.\r\n * Collects all unique import paths and assigns them indices.\r\n * Keys are stored in sorted order for deterministic output.\r\n */\r\nexport function createComponentMap(manifest: RouteTable): ComponentMap {\r\n const importPaths = new Set<string>()\r\n\r\n // Collect all unique import paths from manifest\r\n for (const route of Object.values(manifest)) {\r\n for (const segment of route.chain) {\r\n for (const role of SEGMENT_ROLES)\r\n if (segment[role]) importPaths.add(segment[role])\r\n }\r\n }\r\n\r\n // Sort for deterministic output\r\n const imports = Array.from(importPaths).sort()\r\n const mapping: ComponentMap = {}\r\n for (let i = 0; i < imports.length; i++)\r\n mapping[imports[i]!] = i\r\n\r\n return mapping\r\n}\r\n","import type { Route, RouteTable } from './route-manifest'\r\nimport type { ComponentMap } from './component-map'\r\n\r\nexport interface ElementTree {\r\n component: string\r\n props: Record<string, unknown>\r\n children?: ElementTree\r\n}\r\n\r\nexport type ElementTreeMap = Record<string, ElementTree>\r\n\r\n/**\r\n * Creates element trees for all routes in the manifest.\r\n * Each tree represents the nested React component structure for a route.\r\n */\r\nexport function createElementTrees(manifest: RouteTable, componentMap: ComponentMap): ElementTreeMap {\r\n const elementTrees: ElementTreeMap = {}\r\n for (const [url, route] of Object.entries(manifest))\r\n elementTrees[url] = createElementTree(route, componentMap)\r\n return elementTrees\r\n}\r\n\r\n/**\r\n * Builds a structured element tree representing nested React components.\r\n *\r\n * This function mirrors the runtime composition logic but creates a structured data tree\r\n * that will be serialized into createElement calls for the generated routes.ts file.\r\n *\r\n * Composition order per segment (inside to outside):\r\n * 1. Screen component (only in leaf segment)\r\n * 2. Not-found boundary (wraps screen if present)\r\n * 3. Layout (wraps content)\r\n * 4. Error boundary (wraps layout + all descendants)\r\n */\r\nfunction createElementTree(route: Route, mapping: ComponentMap): ElementTree {\r\n const imports = Object.keys(mapping)\r\n\r\n // Start with the screen from the first segment\r\n const screenSegment = route.chain[0]!\r\n const screenPath = screenSegment['screen']!\r\n const screenIndex = mapping[screenPath]!\r\n const screenKey = JSON.stringify(imports[screenIndex]!)\r\n\r\n let tree: ElementTree = {\r\n component: `Component${screenIndex}`,\r\n props: { key: screenKey },\r\n }\r\n\r\n // Process segments from leaf → root (same order as runtime composition)\r\n for (const segment of route.chain) {\r\n // Not-found boundary\r\n if (segment['not-found']) {\r\n const path = segment['not-found']\r\n const index = mapping[path]!\r\n const key = JSON.stringify(imports[index]!)\r\n const fallback = `Component${index}`\r\n tree = {\r\n component: 'NotFoundBoundary',\r\n props: { key, fallback },\r\n children: tree,\r\n }\r\n }\r\n // Error boundary\r\n if (segment['error']) {\r\n const path = segment['error']\r\n const index = mapping[path]!\r\n const key = JSON.stringify(imports[index]!)\r\n const fallback = `Component${index}`\r\n tree = {\r\n component: 'ErrorBoundary',\r\n props: { key, fallback },\r\n children: tree,\r\n }\r\n }\r\n // Layout\r\n if (segment['layout']) {\r\n const path = segment['layout']\r\n const index = mapping[path]!\r\n const key = JSON.stringify(imports[index]!)\r\n tree = {\r\n component: `Component${index}`,\r\n props: { key },\r\n children: tree,\r\n }\r\n }\r\n }\r\n return tree\r\n}\r\n"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -87,7 +87,7 @@ type SegmentNode = {
87
87
  declare function createSegmentTree(fileTree: FileNode): SegmentNode;
88
88
  //#endregion
89
89
  //#region src/pen/compiler/builders/route-manifest.d.ts
90
- type RouteManifest = Record<string, Route>;
90
+ type RouteTable = Record<string, Route>;
91
91
  type Route = {
92
92
  url: string;
93
93
  chain: SegmentRoles[];
@@ -103,7 +103,7 @@ type Route = {
103
103
  * @param outDir - Output directory (to calculate relative import paths)
104
104
  * @returns Flat manifest ready for runtime composition
105
105
  */
106
- declare function createRouteManifest(segmentTree: SegmentNode, outDir: string): RouteManifest;
106
+ declare function createRouteTable(segmentTree: SegmentNode, outDir: string): RouteTable;
107
107
  //#endregion
108
108
  //#region src/pen/compiler/builders/component-map.d.ts
109
109
  /** Map from import path to component index (keys are in sorted order) */
@@ -113,7 +113,7 @@ type ComponentMap = Record<string, number>;
113
113
  * Collects all unique import paths and assigns them indices.
114
114
  * Keys are stored in sorted order for deterministic output.
115
115
  */
116
- declare function createComponentMap(manifest: RouteManifest): ComponentMap;
116
+ declare function createComponentMap(manifest: RouteTable): ComponentMap;
117
117
  //#endregion
118
118
  //#region src/pen/compiler/builders/element-tree.d.ts
119
119
  interface ElementTree {
@@ -126,7 +126,7 @@ type ElementTreeMap = Record<string, ElementTree>;
126
126
  * Creates element trees for all routes in the manifest.
127
127
  * Each tree represents the nested React component structure for a route.
128
128
  */
129
- declare function createElementTrees(manifest: RouteManifest, componentMap: ComponentMap): ElementTreeMap;
129
+ declare function createElementTrees(manifest: RouteTable, componentMap: ComponentMap): ElementTreeMap;
130
130
  //#endregion
131
131
  //#region src/pen/compiler/errors.d.ts
132
132
  /**
@@ -371,5 +371,5 @@ interface MemoryUsage {
371
371
  */
372
372
  declare function useMemoryMonitor(intervalMs?: number): MemoryUsage;
373
373
  //#endregion
374
- export { App, type AppProps, type CompiledRoutes, type ComponentMap, ComponentNotFoundError, DirectoryNotFoundError, DuplicateScreenError, type ElementTree, type ElementTreeMap, EmptyChainError, ErrorBoundary, type ErrorComponentProps, ErrorScreen, type FileNode, FileRouter, FileRouterError, type FileRouterProps, MemoryUsage, NotADirectoryError, NotFoundBoundary, type NotFoundComponentProps, NotFoundError, NotFoundScreen, PenConfig, ResolvedPenConfig, RootIsFileError, type Route, type RouteManifest, RouterContext, type RouterContextValue, RouterProvider, type RouterProviderProps, type SegmentNode, type SegmentRoles, createComponentMap, createElementTrees, createFileTree, createRouteManifest, createSegmentTree, defineConfig, loadConfig, useHistory, useMemoryMonitor, useNavigate, useRouteData, useRouter, useUrl };
374
+ export { App, type AppProps, type CompiledRoutes, type ComponentMap, ComponentNotFoundError, DirectoryNotFoundError, DuplicateScreenError, type ElementTree, type ElementTreeMap, EmptyChainError, ErrorBoundary, type ErrorComponentProps, ErrorScreen, type FileNode, FileRouter, FileRouterError, type FileRouterProps, MemoryUsage, NotADirectoryError, NotFoundBoundary, type NotFoundComponentProps, NotFoundError, NotFoundScreen, PenConfig, ResolvedPenConfig, RootIsFileError, type Route, type RouteTable, RouterContext, type RouterContextValue, RouterProvider, type RouterProviderProps, type SegmentNode, type SegmentRoles, createComponentMap, createElementTrees, createFileTree, createRouteTable, createSegmentTree, defineConfig, loadConfig, useHistory, useMemoryMonitor, useNavigate, useRouteData, useRouter, useUrl };
375
375
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/pen/config.ts","../src/pen/compiler/types.ts","../src/pen/compiler/builders/file-tree.ts","../src/pen/compiler/builders/segment-tree.ts","../src/pen/compiler/builders/route-manifest.ts","../src/pen/compiler/builders/component-map.ts","../src/pen/compiler/builders/element-tree.ts","../src/pen/compiler/errors.ts","../src/pen/router/RouterProvider.tsx","../src/pen/router/hooks/use-history.ts","../src/pen/router/hooks/use-navigate.ts","../src/pen/router/hooks/use-route-data.ts","../src/pen/router/hooks/use-router.ts","../src/pen/router/hooks/use-url.ts","../src/pen/runtime/App.tsx","../src/pen/runtime/ui/ErrorBoundary.tsx","../src/pen/runtime/ui/NotFoundBoundary.tsx","../src/pen/runtime/ui/ErrorScreen.tsx","../src/pen/runtime/ui/NotFoundScreen.tsx","../src/pen/runtime/FileRouter.tsx","../src/pen/runtime/errors.ts","../src/pen/utils/use-memory-monitor.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/pen/config.ts","../src/pen/compiler/types.ts","../src/pen/compiler/builders/file-tree.ts","../src/pen/compiler/builders/segment-tree.ts","../src/pen/compiler/builders/route-manifest.ts","../src/pen/compiler/builders/component-map.ts","../src/pen/compiler/builders/element-tree.ts","../src/pen/compiler/errors.ts","../src/pen/router/RouterProvider.tsx","../src/pen/router/hooks/use-history.ts","../src/pen/router/hooks/use-navigate.ts","../src/pen/router/hooks/use-route-data.ts","../src/pen/router/hooks/use-router.ts","../src/pen/router/hooks/use-url.ts","../src/pen/runtime/App.tsx","../src/pen/runtime/ui/ErrorBoundary.tsx","../src/pen/runtime/ui/NotFoundBoundary.tsx","../src/pen/runtime/ui/ErrorScreen.tsx","../src/pen/runtime/ui/NotFoundScreen.tsx","../src/pen/runtime/FileRouter.tsx","../src/pen/runtime/errors.ts","../src/pen/utils/use-memory-monitor.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,r as c,s as l,t as u,u as d}from"./element-tree-DoH7UgRL.mjs";import{Component as f,createContext as p,useCallback as m,useContext as h,useEffect as g,useState as _}from"react";import{jsx as v,jsxs as y}from"react/jsx-runtime";import{Box as b,Text as x,useInput as S}from"ink";function C(e){return e.endsWith(`/`)?e:`${e}/`}function w(e,t,n){return{stack:[...e.stack.slice(0,e.position+1),{url:C(t),data:n}],position:e.position+1}}function T(e,t){let n=[...e.stack];return n[e.position]={url:C(t)},{...e,stack:n}}function E(e){return e.position>0?{...e,position:e.position-1}:e}function D(e){return e.position<e.stack.length-1?{...e,position:e.position+1}:e}const O=p(null);function k({initialUrl:e,children:t}){let n=C(e),[r,i]=_({stack:[{url:n}],position:0}),{url:a,data:o}=r.stack[r.position]??{url:n},s=m((e,t)=>{i(n=>w(n,e,t))},[]),c=m(e=>{i(t=>T(t,e))},[]),l=m(()=>{i(e=>E(e))},[]),u=m(()=>{i(e=>D(e))},[]);return v(O.Provider,{value:{url:a,data:o,history:r.stack.map(e=>e.url),position:r.position,push:s,replace:c,back:l,forward:u},children:t})}function A(){let e=h(O);if(!e)throw Error(`useRouter must be used within a RouterProvider`);return e}function j(){let{history:e}=A();return e}function M(){let{push:e,replace:t,back:n,forward:r}=A();return{push:e,replace:t,back:n,forward:r}}function N(){let{data:e}=A();return e}function P(){let{url:e}=A();return e}var F=class extends f{state;constructor(e){super(e),this.state={error:null},this.reset=this.reset.bind(this)}static getDerivedStateFromError(e){return{error:e}}componentDidCatch(){}reset(){this.setState({error:null})}render(){if(this.state.error){let e=this.props.fallback;return v(e,{error:this.state.error,reset:this.reset})}return this.props.children}},I=class extends Error{url;constructor(e,t=`Not Found`){super(t),this.name=`NotFoundError`,this.url=e}},L=class extends Error{constructor(e){super(`Route ${e} has an empty chain. This indicates a bug in manifest generation - routes must have at least one segment.`),this.url=e,this.name=`EmptyChainError`}},R=class extends Error{constructor(e){super(`Component not found: ${e}. This indicates the component map is out of sync with the manifest. Try running 'pen build' again.`),this.componentPath=e,this.name=`ComponentNotFoundError`}},z=class extends f{state;constructor(e){super(e),this.state={url:null}}static getDerivedStateFromError(e){return e instanceof I?{url:e.url}:null}componentDidCatch(e){if(!(e instanceof I))throw e}componentDidUpdate(e){e.url!==this.props.url&&this.state.url&&this.setState({url:null})}render(){if(this.state.url){let e=this.props.fallback;return v(e,{url:this.state.url})}return this.props.children}};function B({fallback:e,children:t}){let{url:n}=A();return v(z,{fallback:e,url:n,children:t})}function V({error:e,reset:t}){let[n,r]=_(!1);return S(e=>{e===`r`&&t(),e===`s`&&r(e=>!e),e===`q`&&process.exit(1)}),y(b,{flexDirection:`column`,padding:2,borderStyle:`double`,borderColor:`red`,children:[v(b,{marginBottom:1,children:v(x,{bold:!0,color:`red`,children:`💥 Critical Application Error`})}),v(b,{marginBottom:1,children:v(x,{color:`red`,children:`The application encountered a fatal error and cannot continue.`})}),y(b,{flexDirection:`column`,padding:1,borderStyle:`round`,borderColor:`yellow`,marginBottom:1,children:[v(x,{bold:!0,color:`yellow`,children:`Error Details:`}),v(x,{children:e.message})]}),n&&e.stack&&y(b,{flexDirection:`column`,padding:1,borderStyle:`single`,borderColor:`gray`,marginBottom:1,children:[v(x,{bold:!0,dimColor:!0,children:`Stack Trace:`}),v(x,{dimColor:!0,children:e.stack})]}),y(b,{flexDirection:`column`,marginTop:1,children:[v(x,{bold:!0,children:`Options:`}),v(x,{dimColor:!0,children:` [r] Retry [s] Toggle Stack Trace [q] Quit`})]}),v(b,{marginTop:1,children:v(x,{dimColor:!0,children:`If this error persists, please report it.`})})]})}function H({url:e}){let t=A();return S(e=>{e===`b`&&t.back(),e===`q`&&process.exit(0)}),y(b,{flexDirection:`column`,padding:2,borderStyle:`round`,borderColor:`red`,children:[y(b,{flexDirection:`column`,marginBottom:1,children:[v(x,{bold:!0,color:`red`,children:`Route Not Found`}),v(x,{dimColor:!0,children:`The router couldn't match the requested URL.`})]}),v(b,{flexDirection:`column`,paddingLeft:1,marginBottom:1,children:y(x,{children:[`Requested:`,` `,v(x,{color:`yellow`,bold:!0,children:e})]})}),y(b,{flexDirection:`column`,padding:1,borderStyle:`single`,borderColor:`gray`,marginBottom:1,children:[v(x,{bold:!0,children:`Actions`}),v(x,{dimColor:!0,children:` [b] Go back`}),v(x,{dimColor:!0,children:` [q] Quit`})]}),v(x,{dimColor:!0,children:`Tip: Check the route segment name or add a screen.tsx for this path.`})]})}function U({routes:e}){let{url:t}=A(),n=e[t];if(!n)throw new I(t);return n}function W({initialUrl:e,routes:t}){return v(F,{fallback:V,children:v(k,{initialUrl:e,children:v(B,{fallback:H,children:v(U,{routes:t})})})})}function G(e=1e3){let[t,n]=_({heapUsed:0,heapTotal:0,rss:0,external:0});return g(()=>{let t=()=>{let e=process.memoryUsage();n({heapUsed:Math.round(e.heapUsed/1024/1024),heapTotal:Math.round(e.heapTotal/1024/1024),rss:Math.round(e.rss/1024/1024),external:Math.round(e.external/1024/1024)})};t();let r=setInterval(t,e);return()=>clearInterval(r)},[e]),t}export{W as App,R as ComponentNotFoundError,s as DirectoryNotFoundError,l as DuplicateScreenError,L as EmptyChainError,F as ErrorBoundary,V as ErrorScreen,U as FileRouter,t as FileRouterError,a as NotADirectoryError,B as NotFoundBoundary,I as NotFoundError,H as NotFoundScreen,d as RootIsFileError,O as RouterContext,k as RouterProvider,o as createComponentMap,u as createElementTrees,e as createFileTree,c as createRouteManifest,i as createSegmentTree,n as defineConfig,r as loadConfig,j as useHistory,G as useMemoryMonitor,M as useNavigate,N as useRouteData,A as useRouter,P as useUrl};
1
+ import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,r as c,s as l,t as u,u as d}from"./element-tree-DoH7UgRL.mjs";import{Component as f,createContext as p,useCallback as m,useContext as h,useEffect as g,useState as _}from"react";import{jsx as v,jsxs as y}from"react/jsx-runtime";import{Box as b,Text as x,useInput as S}from"ink";function C(e){return e.endsWith(`/`)?e:`${e}/`}function w(e,t,n){return{stack:[...e.stack.slice(0,e.position+1),{url:C(t),data:n}],position:e.position+1}}function T(e,t){let n=[...e.stack];return n[e.position]={url:C(t)},{...e,stack:n}}function E(e){return e.position>0?{...e,position:e.position-1}:e}function D(e){return e.position<e.stack.length-1?{...e,position:e.position+1}:e}const O=p(null);function k({initialUrl:e,children:t}){let n=C(e),[r,i]=_({stack:[{url:n}],position:0}),{url:a,data:o}=r.stack[r.position]??{url:n},s=m((e,t)=>{i(n=>w(n,e,t))},[]),c=m(e=>{i(t=>T(t,e))},[]),l=m(()=>{i(e=>E(e))},[]),u=m(()=>{i(e=>D(e))},[]);return v(O.Provider,{value:{url:a,data:o,history:r.stack.map(e=>e.url),position:r.position,push:s,replace:c,back:l,forward:u},children:t})}function A(){let e=h(O);if(!e)throw Error(`useRouter must be used within a RouterProvider`);return e}function j(){let{history:e}=A();return e}function M(){let{push:e,replace:t,back:n,forward:r}=A();return{push:e,replace:t,back:n,forward:r}}function N(){let{data:e}=A();return e}function P(){let{url:e}=A();return e}var F=class extends f{state;constructor(e){super(e),this.state={error:null},this.reset=this.reset.bind(this)}static getDerivedStateFromError(e){return{error:e}}componentDidCatch(){}reset(){this.setState({error:null})}render(){if(this.state.error){let e=this.props.fallback;return v(e,{error:this.state.error,reset:this.reset})}return this.props.children}},I=class extends Error{url;constructor(e,t=`Not Found`){super(t),this.name=`NotFoundError`,this.url=e}},L=class extends Error{constructor(e){super(`Route ${e} has an empty chain. This indicates a bug in manifest generation - routes must have at least one segment.`),this.url=e,this.name=`EmptyChainError`}},R=class extends Error{constructor(e){super(`Component not found: ${e}. This indicates the component map is out of sync with the manifest. Try running 'pen build' again.`),this.componentPath=e,this.name=`ComponentNotFoundError`}},z=class extends f{state;constructor(e){super(e),this.state={url:null}}static getDerivedStateFromError(e){return e instanceof I?{url:e.url}:null}componentDidCatch(e){if(!(e instanceof I))throw e}componentDidUpdate(e){e.url!==this.props.url&&this.state.url&&this.setState({url:null})}render(){if(this.state.url){let e=this.props.fallback;return v(e,{url:this.state.url})}return this.props.children}};function B({fallback:e,children:t}){let{url:n}=A();return v(z,{fallback:e,url:n,children:t})}function V({error:e,reset:t}){let[n,r]=_(!1);return S(e=>{e===`r`&&t(),e===`s`&&r(e=>!e),e===`q`&&process.exit(1)}),y(b,{flexDirection:`column`,padding:2,borderStyle:`double`,borderColor:`red`,children:[v(b,{marginBottom:1,children:v(x,{bold:!0,color:`red`,children:`💥 Critical Application Error`})}),v(b,{marginBottom:1,children:v(x,{color:`red`,children:`The application encountered a fatal error and cannot continue.`})}),y(b,{flexDirection:`column`,padding:1,borderStyle:`round`,borderColor:`yellow`,marginBottom:1,children:[v(x,{bold:!0,color:`yellow`,children:`Error Details:`}),v(x,{children:e.message})]}),n&&e.stack&&y(b,{flexDirection:`column`,padding:1,borderStyle:`single`,borderColor:`gray`,marginBottom:1,children:[v(x,{bold:!0,dimColor:!0,children:`Stack Trace:`}),v(x,{dimColor:!0,children:e.stack})]}),y(b,{flexDirection:`column`,marginTop:1,children:[v(x,{bold:!0,children:`Options:`}),v(x,{dimColor:!0,children:` [r] Retry [s] Toggle Stack Trace [q] Quit`})]}),v(b,{marginTop:1,children:v(x,{dimColor:!0,children:`If this error persists, please report it.`})})]})}function H({url:e}){let t=A();return S(e=>{e===`b`&&t.back(),e===`q`&&process.exit(0)}),y(b,{flexDirection:`column`,padding:2,borderStyle:`round`,borderColor:`red`,children:[y(b,{flexDirection:`column`,marginBottom:1,children:[v(x,{bold:!0,color:`red`,children:`Route Not Found`}),v(x,{dimColor:!0,children:`The router couldn't match the requested URL.`})]}),v(b,{flexDirection:`column`,paddingLeft:1,marginBottom:1,children:y(x,{children:[`Requested:`,` `,v(x,{color:`yellow`,bold:!0,children:e})]})}),y(b,{flexDirection:`column`,padding:1,borderStyle:`single`,borderColor:`gray`,marginBottom:1,children:[v(x,{bold:!0,children:`Actions`}),v(x,{dimColor:!0,children:` [b] Go back`}),v(x,{dimColor:!0,children:` [q] Quit`})]}),v(x,{dimColor:!0,children:`Tip: Check the route segment name or add a screen.tsx for this path.`})]})}function U({routes:e}){let{url:t}=A(),n=e[t];if(!n)throw new I(t);return n}function W({initialUrl:e,routes:t}){return v(F,{fallback:V,children:v(k,{initialUrl:e,children:v(B,{fallback:H,children:v(U,{routes:t})})})})}function G(e=1e3){let[t,n]=_({heapUsed:0,heapTotal:0,rss:0,external:0});return g(()=>{let t=()=>{let e=process.memoryUsage();n({heapUsed:Math.round(e.heapUsed/1024/1024),heapTotal:Math.round(e.heapTotal/1024/1024),rss:Math.round(e.rss/1024/1024),external:Math.round(e.external/1024/1024)})};t();let r=setInterval(t,e);return()=>clearInterval(r)},[e]),t}export{W as App,R as ComponentNotFoundError,s as DirectoryNotFoundError,l as DuplicateScreenError,L as EmptyChainError,F as ErrorBoundary,V as ErrorScreen,U as FileRouter,t as FileRouterError,a as NotADirectoryError,B as NotFoundBoundary,I as NotFoundError,H as NotFoundScreen,d as RootIsFileError,O as RouterContext,k as RouterProvider,o as createComponentMap,u as createElementTrees,e as createFileTree,c as createRouteTable,i as createSegmentTree,n as defineConfig,r as loadConfig,j as useHistory,G as useMemoryMonitor,M as useNavigate,N as useRouteData,A as useRouter,P as useUrl};
2
2
  //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idlesummer/pen",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "File-based routing for React Ink apps (experimental)",
5
5
  "keywords": [
6
6
  "cli",
@@ -35,7 +35,7 @@
35
35
  "examples/*"
36
36
  ],
37
37
  "scripts": {
38
- "build": "tsdown",
38
+ "build": "tsc --noEmit && tsdown",
39
39
  "lint": "eslint",
40
40
  "prepare": "npm run build",
41
41
  "test": "vitest",