@wolfstar/cli 2.2.0 → 2.3.0-next-20261004142621
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -201
- package/README.md +465 -304
- package/dist/{_shared-DJrpalNQ.js → _shared-BIQK0Bhm.js} +2 -2
- package/dist/_shared-BIQK0Bhm.js.map +1 -0
- package/dist/bridge-BvkmlAOZ.js +410 -0
- package/dist/bridge-BvkmlAOZ.js.map +1 -0
- package/dist/{build-CluOR8dJ.js → build-DJcc95Yq.js} +5 -5
- package/dist/build-DJcc95Yq.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/{codegen-D6V1i_fa.js → codegen-aJSyPz-J.js} +4 -4
- package/dist/codegen-aJSyPz-J.js.map +1 -0
- package/dist/command-diff-BK912Hjc.js +78 -0
- package/dist/command-diff-BK912Hjc.js.map +1 -0
- package/dist/commands-CIPWQtF0.js +3 -0
- package/dist/commands-Clpbqq3K.js +15 -0
- package/dist/commands-Clpbqq3K.js.map +1 -0
- package/dist/{commands-BJ589_AC.js → commands-DVC7ky6f.js} +259 -9
- package/dist/commands-DVC7ky6f.js.map +1 -0
- package/dist/completions-D2KYtrrv.js +161 -0
- package/dist/completions-D2KYtrrv.js.map +1 -0
- package/dist/{dev-DJJZN4NJ.js → dev-oPPVR7d_.js} +434 -28
- package/dist/dev-oPPVR7d_.js.map +1 -0
- package/dist/{diagnostics-3JRAy8Xj.js → diagnostics-BysbNnPD.js} +22 -1
- package/dist/diagnostics-BysbNnPD.js.map +1 -0
- package/dist/doctor-DkVUwgDd.js +334 -0
- package/dist/doctor-DkVUwgDd.js.map +1 -0
- package/dist/errors-COFWKKKw.js.map +1 -1
- package/dist/external-CxFKxwi3.js.map +1 -1
- package/dist/framework-auto-imports-Gu_PXSyr.js.map +1 -1
- package/dist/{hooks-BfDFM38k.js → hooks-Cy6F2bhH.js} +20 -4
- package/dist/hooks-Cy6F2bhH.js.map +1 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/{info-C1Kx_4Og.js → info-CKJVMWIT.js} +15 -4
- package/dist/info-CKJVMWIT.js.map +1 -0
- package/dist/{locales-BzOLRBVg.js → locales-BJAP4HYf.js} +5 -5
- package/dist/locales-BJAP4HYf.js.map +1 -0
- package/dist/log-view-B7uJEnMR.js +342 -0
- package/dist/log-view-B7uJEnMR.js.map +1 -0
- package/dist/{nitro-yjqZBh5L.js → nitro-B8u1iVgf.js} +2 -2
- package/dist/nitro-B8u1iVgf.js.map +1 -0
- package/dist/none-uC_wi_l4.js.map +1 -1
- package/dist/output-mode-Bp7Da8vJ.js.map +1 -1
- package/dist/{plain-B6z85uQP.js → plain-DG7cy0Kk.js} +7 -2
- package/dist/plain-DG7cy0Kk.js.map +1 -0
- package/dist/{prepare-Cb45Z4re.js → prepare-BM93i3Rm.js} +4 -4
- package/dist/prepare-BM93i3Rm.js.map +1 -0
- package/dist/{project-D-8VIcyF.js → project-zlQStwsf.js} +2 -2
- package/dist/project-zlQStwsf.js.map +1 -0
- package/dist/{run-BiLZqib3.js → run-DMM2YlP3.js} +2 -12
- package/dist/run-DMM2YlP3.js.map +1 -0
- package/dist/{theme-3Fc_LI-2.js → theme-yS2h5dd_.js} +25 -1
- package/dist/theme-yS2h5dd_.js.map +1 -0
- package/dist/tsc-C5l5TQGC.js +3 -0
- package/dist/{tsc-DEBcwIO0.js → tsc-puVAcwmo.js} +24 -5
- package/dist/tsc-puVAcwmo.js.map +1 -0
- package/dist/{tsdown-DrWXld54.js → tsdown-Dwt3JhPw.js} +2 -2
- package/dist/tsdown-Dwt3JhPw.js.map +1 -0
- package/dist/{tui-BRddrLQP.js → tui-nldGSD4c.js} +913 -141
- package/dist/tui-nldGSD4c.js.map +1 -0
- package/dist/version-BzclCE19.js.map +1 -1
- package/dist/{vite-Bf7nrJx7.js → vite-YZUtv2Hk.js} +2 -2
- package/dist/vite-YZUtv2Hk.js.map +1 -0
- package/package.json +5 -5
- package/dist/_shared-DJrpalNQ.js.map +0 -1
- package/dist/build-CluOR8dJ.js.map +0 -1
- package/dist/codegen-D6V1i_fa.js.map +0 -1
- package/dist/commands-BJ589_AC.js.map +0 -1
- package/dist/dev-DJJZN4NJ.js.map +0 -1
- package/dist/diagnostics-3JRAy8Xj.js.map +0 -1
- package/dist/hooks-BfDFM38k.js.map +0 -1
- package/dist/info-C1Kx_4Og.js.map +0 -1
- package/dist/locales-BzOLRBVg.js.map +0 -1
- package/dist/log-buffer-CY82aqnb.js +0 -72
- package/dist/log-buffer-CY82aqnb.js.map +0 -1
- package/dist/nitro-yjqZBh5L.js.map +0 -1
- package/dist/plain-B6z85uQP.js.map +0 -1
- package/dist/prepare-Cb45Z4re.js.map +0 -1
- package/dist/project-D-8VIcyF.js.map +0 -1
- package/dist/run-BiLZqib3.js.map +0 -1
- package/dist/theme-3Fc_LI-2.js.map +0 -1
- package/dist/tsc-B931Ezh7.js +0 -3
- package/dist/tsc-DEBcwIO0.js.map +0 -1
- package/dist/tsdown-DrWXld54.js.map +0 -1
- package/dist/tui-BRddrLQP.js.map +0 -1
- package/dist/tunnel-DHSxOZKr.js +0 -175
- package/dist/tunnel-DHSxOZKr.js.map +0 -1
- package/dist/vite-Bf7nrJx7.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hooks-BfDFM38k.js","names":["resolveModule"],"sources":["../src/utils/args.ts","../src/utils/env-import.ts","../src/utils/modules.ts","../src/utils/project-env.ts","../src/utils/hooks.ts"],"sourcesContent":["import type { ArgsDef } from 'citty';\r\nimport { resolve } from 'node:path';\r\n\r\n/**\r\n * Arguments shared by every command that reads the project configuration.\r\n */\r\nexport const projectArgs = {\r\n\tconfig: {\r\n\t\ttype: 'string',\r\n\t\talias: 'c',\r\n\t\tdescription: 'Path to the configuration file (defaults to stars.config.* in the working directory)'\r\n\t},\r\n\tcwd: {\r\n\t\ttype: 'string',\r\n\t\tdescription: 'Working directory to run from (defaults to the current directory)'\r\n\t}\r\n} as const satisfies ArgsDef;\r\n\r\nexport interface ProjectArgs {\r\n\tconfig?: string;\r\n\tcwd?: string;\r\n}\r\n\r\nexport function resolveCwd(args: ProjectArgs): string {\r\n\treturn args.cwd ? resolve(process.cwd(), args.cwd) : process.cwd();\r\n}\r\n","import type { ResolvedStarsConfig } from '@wolfstar/schema';\r\nimport { envModuleSource, modulesModuleSource } from '@wolfstar/vite-server/internal';\r\nimport { resolveSync } from 'mlly';\r\nimport { isAbsolute } from 'node:path';\r\nimport { pathToFileURL } from 'node:url';\r\nimport { cliDiagnostics } from './diagnostics.js';\r\nimport { resolveFromProject } from './project.js';\r\n\r\n/** Build tools whose output never passes through the entry transform that registers `env`. */\r\nexport const UNTRANSFORMED_TOOLS = new Set<string>(['none', 'tsc']);\r\n\r\n/**\r\n * `node` arguments that register `env` before the entry runs, for the build tools the entry transform cannot reach.\r\n * The preload is a `data:` URL, so `.stars/` gets no generated runtime file; a `data:` URL cannot resolve bare\r\n * specifiers, so `@wolfstar/env-utilities` is resolved from the project first. When it cannot be resolved nothing is\r\n * preloaded, and the bot's own import of it reports the missing install.\r\n */\r\nexport function envImportArgs(config: ResolvedStarsConfig): string[] {\r\n\tif (!config.env.enabled || !UNTRANSFORMED_TOOLS.has(config.build.tool)) return [];\r\n\r\n\tconst resolved = resolveFromProject(config.root, '@wolfstar/env-utilities');\r\n\tif (resolved === null) return [];\r\n\r\n\tconst source = envModuleSource(config.env.options, pathToFileURL(resolved).href);\r\n\treturn ['--import', `data:text/javascript,${encodeURIComponent(source)}`];\r\n}\r\n\r\n/**\r\n * `node` arguments that register the runtime plugins of the installed modules (`ctx.addPlugin`) before the entry\r\n * runs, for the build tools the entry transform cannot reach. `@wolfstar/http-framework` and every plugin are resolved\r\n * from the project first, with the `import` condition (both are ESM), because a `data:` URL cannot resolve bare\r\n * specifiers; the framework is the bot's own copy, so `Client.use` reaches the `Client` the bot constructs. When the\r\n * framework is not installed nothing is preloaded, and the bot's own import of it reports the missing install.\r\n */\r\nexport function moduleImportArgs(config: ResolvedStarsConfig): string[] {\r\n\tconst plugins = config.runtime?.plugins ?? [];\r\n\tif (plugins.length === 0 || !UNTRANSFORMED_TOOLS.has(config.build.tool)) return [];\r\n\r\n\tconst url = pathToFileURL(`${config.root}/package.json`).href;\r\n\tlet framework: string;\r\n\ttry {\r\n\t\tframework = resolveSync('@wolfstar/http-framework', { url });\r\n\t} catch {\r\n\t\treturn [];\r\n\t}\r\n\r\n\tconst source = modulesModuleSource(plugins, {\r\n\t\tframework,\r\n\t\tresolve: (from) => {\r\n\t\t\tif (from.startsWith('file:')) return from;\r\n\t\t\tif (isAbsolute(from)) return pathToFileURL(from).href;\r\n\t\t\ttry {\r\n\t\t\t\treturn resolveSync(from, { url });\r\n\t\t\t} catch {\r\n\t\t\t\tthrow cliDiagnostics.DEPENDENCY_MISSING({\r\n\t\t\t\t\tname: from,\r\n\t\t\t\t\troot: config.root,\r\n\t\t\t\t\thint: 'Install the package of the module that registers this plugin.'\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t});\r\n\treturn ['--import', `data:text/javascript,${encodeURIComponent(source)}`];\r\n}\r\n","import { ModuleError, setupModules } from '@wolfstar/kit';\r\nimport type { ResolvedStarsConfig } from '@wolfstar/schema';\r\nimport { envModuleSource, modulesModuleSource } from '@wolfstar/vite-server/internal';\r\nimport { resolve as resolveModule } from 'mlly';\r\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\r\nimport type { Diagnostic } from 'nostics';\r\nimport { isAbsolute, join, resolve } from 'node:path';\r\nimport { pathToFileURL } from 'node:url';\r\nimport { cliDiagnostics } from './diagnostics.js';\r\nimport { UNTRANSFORMED_TOOLS } from './env-import.js';\r\nimport type { StarsHookable } from './hooks.js';\r\nimport { findInstalledVersion } from './project.js';\r\nimport { readOwnPackageJson } from './version.js';\r\n\r\n/**\r\n * Where a module specifier is imported from: a relative or absolute path is a file of the project, a `file:` URL is\r\n * itself, anything else is a package resolved from the project root — with `mlly`, honouring the `import` condition,\r\n * because installed modules are ESM-only packages a CommonJS `require.resolve` cannot see.\r\n */\r\nasync function resolveSpecifier(root: string, specifier: string): Promise<string> {\r\n\tif (specifier.startsWith('file:')) return specifier;\r\n\tif (specifier.startsWith('.') || isAbsolute(specifier)) return pathToFileURL(resolve(root, specifier)).href;\r\n\treturn resolveModule(specifier, { url: pathToFileURL(`${root}/package.json`).href });\r\n}\r\n\r\n/**\r\n * Runs `setup` of every module in `modules` (see `@wolfstar/kit`) and returns the configuration carrying what they\r\n * contributed: `runtime`, and `imports.presets` extended by `ctx.addImports`. Without modules the configuration is\r\n * returned as it is.\r\n */\r\nexport async function installModules(config: ResolvedStarsConfig, hooks: StarsHookable): Promise<ResolvedStarsConfig> {\r\n\tif (config.modules.length === 0) return config;\r\n\r\n\ttry {\r\n\t\tconst runtime = await setupModules({\r\n\t\t\tconfig,\r\n\t\t\thooks,\r\n\t\t\tversions: { framework: findInstalledVersion(config.root, '@wolfstar/http-framework'), stars: readOwnPackageJson().version },\r\n\t\t\tload: async (specifier) => import(await resolveSpecifier(config.root, specifier))\r\n\t\t});\r\n\r\n\t\tconst presets = [...config.imports.presets, ...runtime.imports.filter((preset) => !config.imports.presets.includes(preset))];\r\n\t\treturn { ...config, runtime, imports: { ...config.imports, presets } };\r\n\t} catch (error) {\r\n\t\tif (error instanceof ModuleError) {\r\n\t\t\tthrow cliDiagnostics.MODULE_FAILED({ module: error.moduleName, reason: error.code, message: error.message, cause: error });\r\n\t\t}\r\n\r\n\t\tthrow error;\r\n\t}\r\n}\r\n\r\n/**\r\n * The warning for a project whose runtime plugins reach production only through a `node --import` preload, `null`\r\n * otherwise. It is not one of `config.warnings`: `stars dev` preloads the plugins itself, so there it would be noise\r\n * on every start. `stars build` and `stars prepare` report it.\r\n */\r\nexport function modulesPreloadWarning(config: ResolvedStarsConfig): Diagnostic | null {\r\n\tif (!needsPreload(config)) return null;\r\n\treturn cliDiagnostics.MODULES_PRELOAD_REQUIRED({\r\n\t\ttool: config.build.tool,\r\n\t\tplugins: [...new Set(config.runtime.plugins.map((plugin) => plugin.module))].join(', ')\r\n\t});\r\n}\r\n\r\n/** A build tool the entry transform cannot reach, with runtime plugins to register: they need a `node --import` preload. */\r\nfunction needsPreload(config: ResolvedStarsConfig): boolean {\r\n\treturn UNTRANSFORMED_TOOLS.has(config.build.tool) && (config.runtime?.plugins.length ?? 0) > 0;\r\n}\r\n\r\nexport interface ModulesPreloadResult {\r\n\t/** Absolute path of the preload file. */\r\n\tpath: string;\r\n\tstatus: 'written' | 'up-to-date' | 'outdated';\r\n}\r\n\r\n/**\r\n * Writes `.stars/modules.mjs`, the production counterpart of the preload `stars dev` passes to `node`: `node --import\r\n * ./.stars/modules.mjs <entry>` registers the runtime plugins of the installed modules for the build tools whose entry\r\n * cannot be transformed (`tsc`, `none`). Its specifiers are bare, so they resolve from the project's `node_modules`\r\n * like the bot's own imports. `null` when there is nothing to register.\r\n *\r\n * With `env` enabled it is preceded by `.stars/env.mjs`, a separate module imported first: imports of one module are\r\n * all evaluated before its body runs, so the environment could not be loaded ahead of the plugins from the same file,\r\n * and a plugin reading `process.env` while it is imported would see nothing.\r\n */\r\nexport async function prepareModulesPreload(config: ResolvedStarsConfig, check = false): Promise<ModulesPreloadResult | null> {\r\n\tif (!needsPreload(config)) return null;\r\n\r\n\tconst directory = join(config.root, '.stars');\r\n\tconst path = join(directory, 'modules.mjs');\r\n\tconst withEnv = config.env?.enabled === true;\r\n\t// An absolute path is a `file:` URL in the import, like in `moduleImportArgs`: Node rejects a Windows path there.\r\n\tconst plugins = modulesModuleSource(config.runtime.plugins, { resolve: (from) => (isAbsolute(from) ? pathToFileURL(from).href : from) });\r\n\tconst files = [\r\n\t\t{ path, content: withEnv ? `import \"./env.mjs\";\\n${plugins}` : plugins },\r\n\t\t...(withEnv ? [{ path: join(directory, 'env.mjs'), content: envModuleSource(config.env.options) }] : [])\r\n\t];\r\n\r\n\tif (check) {\r\n\t\tconst current = await Promise.all(files.map(async (file) => (await readFile(file.path, 'utf-8').catch(() => null)) === file.content));\r\n\t\treturn { path, status: current.every(Boolean) ? 'up-to-date' : 'outdated' };\r\n\t}\r\n\r\n\tawait mkdir(directory, { recursive: true });\r\n\tawait Promise.all(files.map((file) => writeFile(file.path, file.content)));\r\n\treturn { path, status: 'written' };\r\n}\r\n","import { readProjectEnvFiles, type ResolvedStarsConfig } from '@wolfstar/schema';\r\nimport { execFileSync } from 'node:child_process';\r\nimport { resolveBinary } from './project.js';\r\n\r\n/**\r\n * The variables the bot will load, for the CLI's own lookups (Discord credentials for the tunnel). With the default\r\n * loader these are the project's env files, read from `env.path`/`env.env`. With `loader: 'varlock'` they are what\r\n * `varlock load` resolves from the project's `.env.schema` — a dotenv file may be stale or absent there — and nothing\r\n * when varlock cannot be run, rather than values the bot never sees.\r\n */\r\nexport function readProjectEnv(config: ResolvedStarsConfig): Record<string, string> {\r\n\tconst { path, env = 'development', loader } = config.env.options;\r\n\tif (loader !== 'varlock') return readProjectEnvFiles(config.root, env, { path });\r\n\r\n\tconst binary = resolveBinary(config.root, 'varlock', 'varlock');\r\n\tif (binary === null) return {};\r\n\r\n\ttry {\r\n\t\t// The way the bot loads it: `@wolfstar/env-utilities` runs `varlock/auto-load` with no `--env` (it ignores\r\n\t\t// `env.env` with varlock), in the environment `stars dev` gives the bot.\r\n\t\tconst output = execFileSync(process.execPath, [binary, 'load', '--format', 'json'], {\r\n\t\t\tcwd: config.root,\r\n\t\t\t// Same order as `createSupervisor`: `NODE_ENV` is forced to development after `dev.env`, so it can't differ.\r\n\t\t\tenv: { ...process.env, ...config.dev.env, NODE_ENV: 'development' },\r\n\t\t\tencoding: 'utf8',\r\n\t\t\tstdio: ['ignore', 'pipe', 'ignore'],\r\n\t\t\ttimeout: 30_000\r\n\t\t});\r\n\t\tconst values = JSON.parse(output) as Record<string, unknown>;\r\n\t\treturn Object.fromEntries(\r\n\t\t\tObject.entries(values)\r\n\t\t\t\t.filter(([, value]) => value !== undefined && value !== null)\r\n\t\t\t\t.map(([key, value]) => [key, String(value)])\r\n\t\t);\r\n\t} catch {\r\n\t\treturn {};\r\n\t}\r\n}\r\n","import {\r\n\tloadConfigFile,\r\n\tresolveStarsConfig,\r\n\ttype LoadStarsConfigOptions,\r\n\ttype ResolveConfigOptions,\r\n\ttype ResolvedStarsConfig,\r\n\ttype StarsHookName,\r\n\ttype StarsHooks\r\n} from '@wolfstar/schema';\r\nimport { createHooks, type Hookable } from 'hookable';\r\nimport { installModules } from './modules.js';\r\nimport { readProjectEnv } from './project-env.js';\r\n\r\nexport type StarsHookable = Hookable<StarsHooks>;\r\n\r\n/** What each configuration loaded by {@link loadProject} was resolved from, so `env:options` can re-resolve it. */\r\nconst sources = new WeakMap<ResolvedStarsConfig, ResolveConfigOptions>();\r\n\r\n/** Registers the `hooks` of `stars.config` on a fresh `hookable` instance. */\r\nexport function createStarsHooks(config: ResolvedStarsConfig): StarsHookable {\r\n\tconst hooks = createHooks<StarsHooks>();\r\n\tfor (const [name, callbacks] of Object.entries(config.hooks) as [StarsHookName, readonly StarsHooks[StarsHookName][]][]) {\r\n\t\tfor (const callback of callbacks) hooks.hook(name, callback);\r\n\t}\r\n\r\n\treturn hooks;\r\n}\r\n\r\n/** Loads `stars.config`, registers its hooks and runs `config:resolved`. */\r\nexport async function loadProject(options: LoadStarsConfigOptions): Promise<{ config: ResolvedStarsConfig; hooks: StarsHookable }> {\r\n\tconst cwd = options.cwd ?? process.cwd();\r\n\tconst loaded = await loadConfigFile({ cwd, configFile: options.configFile });\r\n\tconst source: ResolveConfigOptions = { cwd, configFile: loaded.configFile, config: loaded.config, env: options.env };\r\n\tconst resolved = resolveStarsConfig(source);\r\n\tconst hooks = createStarsHooks(resolved);\r\n\t// Modules install before `config:resolved`, so that hook already sees what they contributed.\r\n\tconst config = await installModules(resolved, hooks);\r\n\tsources.set(config, source);\r\n\r\n\tawait hooks.callHook('config:resolved', config);\r\n\treturn { config, hooks };\r\n}\r\n\r\n/**\r\n * Runs `env:options` on a copy of the resolved `env` options and returns a configuration carrying the result, which\r\n * is what the builders write into the entry. The resolved configuration itself is left untouched.\r\n *\r\n * When the hook changes the options, the configuration is resolved again with them, so everything read from the env\r\n * files — the default `dev.url` port above all — matches what the bot will load.\r\n */\r\nexport async function applyEnvOptions(config: ResolvedStarsConfig, hooks: StarsHookable): Promise<ResolvedStarsConfig> {\r\n\tif (!config.env.enabled) return config;\r\n\r\n\tconst options = { ...config.env.options };\r\n\tawait hooks.callHook('env:options', options, config);\r\n\r\n\tconst source = sources.get(config);\r\n\tif (source === undefined || JSON.stringify(options) === JSON.stringify(config.env.options)) {\r\n\t\treturn { ...config, env: { ...config.env, options } };\r\n\t}\r\n\r\n\treturn reresolve(config, source, { config: { ...source.config, env: { ...options, enabled: true } } });\r\n}\r\n\r\n/**\r\n * With `loader: 'varlock'`, resolves the configuration again with the variables `varlock load` returns, so the\r\n * defaults `stars.config` derives from the environment — the `dev.url` port — match what the bot loads. Every other\r\n * configuration is returned as-is: the schema reads its env files directly.\r\n */\r\nexport function withProjectEnv(config: ResolvedStarsConfig): ResolvedStarsConfig {\r\n\tconst source = sources.get(config);\r\n\tif (source === undefined || !config.env.enabled || config.env.options.loader !== 'varlock') return config;\r\n\treturn reresolve(config, source, { projectEnv: readProjectEnv(config) });\r\n}\r\n\r\nfunction reresolve(previous: ResolvedStarsConfig, source: ResolveConfigOptions, change: Partial<ResolveConfigOptions>): ResolvedStarsConfig {\r\n\tconst next = { ...source, ...change };\r\n\tconst resolved = resolveStarsConfig(next);\r\n\t// Modules ran once, against the first resolution: what they contributed carries over to the new one.\r\n\tconst config = { ...resolved, runtime: previous.runtime, imports: { ...resolved.imports, presets: previous.imports.presets } };\r\n\tsources.set(config, next);\r\n\treturn config;\r\n}\r\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"info-C1Kx_4Og.js","names":[],"sources":["../src/commands/info.ts"],"sourcesContent":["import { displayPath, type ResolvedStarsConfig, type StarsEnvSetupOptions } from '@wolfstar/schema';\r\nimport { defineCommand } from 'citty';\r\nimport { createColors } from 'colorette';\r\nimport { arch, platform } from 'node:os';\r\nimport { relative } from 'node:path';\r\nimport { projectArgs, resolveCwd, type ProjectArgs } from '../utils/args.js';\r\nimport { applyEnvOptions, loadProject } from '../utils/hooks.js';\r\nimport { modulesPreloadWarning } from '../utils/modules.js';\r\nimport { resolveOutputMode, shouldUseColor } from '../utils/output-mode.js';\r\nimport { findInstalledVersion } from '../utils/project.js';\r\nimport { readOwnPackageJson } from '../utils/version.js';\r\n\r\nexport interface InfoOptions extends ProjectArgs {\r\n\tjson?: boolean;\r\n\tstdout?: NodeJS.WritableStream;\r\n}\r\n\r\nexport interface ProjectInfo {\r\n\tcli: { version: string; node: string; platform: string; outputMode: 'tui' | 'plain' };\r\n\tproject: {\r\n\t\tcwd: string;\r\n\t\troot: string;\r\n\t\tconfigFile: string | null;\r\n\t\tname: string | null;\r\n\t\tversion: string | null;\r\n\t\tentry: string;\r\n\t\tframeworkVersion: string | null;\r\n\t};\r\n\tbuild: ResolvedStarsConfig['build'];\r\n\tdev: ResolvedStarsConfig['dev'];\r\n\tcodegen: ResolvedStarsConfig['codegen'];\r\n\timports: ResolvedStarsConfig['imports'];\r\n\texperimental: ResolvedStarsConfig['experimental'];\r\n\tfuture: ResolvedStarsConfig['future'];\r\n\tenv: ResolvedStarsConfig['env'];\r\n\t/** The names of the hooks registered in `stars.config`, flattened (`build:done`). */\r\n\thooks: string[];\r\n\t/** Non-fatal configuration diagnostics, as `CODE: message`. */\r\n\twarnings: string[];\r\n\t/**\r\n\t * The option names set in the `tsdown`/`vite` blocks. Only the names: the values hold plugins and callbacks,\r\n\t * which neither serialize to JSON nor read usefully on a terminal.\r\n\t */\r\n\toptions: { tsdown: string[]; vite: string[] };\r\n}\r\n\r\nexport function collectInfo(config: ResolvedStarsConfig): ProjectInfo {\r\n\treturn {\r\n\t\tcli: {\r\n\t\t\tversion: readOwnPackageJson().version,\r\n\t\t\tnode: process.version,\r\n\t\t\tplatform: `${platform()} ${arch()}`,\r\n\t\t\toutputMode: resolveOutputMode()\r\n\t\t},\r\n\t\tproject: {\r\n\t\t\tcwd: config.cwd,\r\n\t\t\troot: config.root,\r\n\t\t\tconfigFile: config.configFile,\r\n\t\t\tname: config.packageJson?.name ?? null,\r\n\t\t\tversion: config.packageJson?.version ?? null,\r\n\t\t\tentry: config.entry,\r\n\t\t\tframeworkVersion: findInstalledVersion(config.root, '@wolfstar/http-framework')\r\n\t\t},\r\n\t\tbuild: config.build,\r\n\t\tdev: config.dev,\r\n\t\tcodegen: config.codegen,\r\n\t\timports: config.imports,\r\n\t\texperimental: config.experimental,\r\n\t\tfuture: config.future,\r\n\t\tenv: config.env,\r\n\t\thooks: Object.keys(config.hooks),\r\n\t\twarnings: [...config.warnings, modulesPreloadWarning(config)]\r\n\t\t\t.filter((warning) => warning !== null)\r\n\t\t\t.map((warning) => `${warning.code}: ${warning.message}`),\r\n\t\toptions: { tsdown: Object.keys(config.tsdown), vite: Object.keys(config.vite) }\r\n\t};\r\n}\r\n\r\nexport function formatInfo(info: ProjectInfo, useColor: boolean): string {\r\n\tconst colors = createColors({ useColor });\r\n\tconst { root } = info.project;\r\n\tconst show = (path: string | null) => (path === null ? colors.dim('none') : displayPath(root, path));\r\n\tconst row = (label: string, value: string) => ` ${colors.dim(label.padEnd(12))}${value}`;\r\n\tconst section = (title: string, rows: string[]) => [colors.bold(title), ...rows].join('\\n');\r\n\r\n\treturn [\r\n\t\tsection(`stars ${colors.green(`v${info.cli.version}`)}`, [\r\n\t\t\trow('node', info.cli.node),\r\n\t\t\trow('platform', info.cli.platform),\r\n\t\t\trow('output', info.cli.outputMode),\r\n\t\t\trow(\r\n\t\t\t\t'framework',\r\n\t\t\t\tinfo.project.frameworkVersion\r\n\t\t\t\t\t? `@wolfstar/http-framework v${info.project.frameworkVersion}`\r\n\t\t\t\t\t: colors.yellow('@wolfstar/http-framework not installed')\r\n\t\t\t)\r\n\t\t]),\r\n\t\tsection('Project', [\r\n\t\t\trow(\r\n\t\t\t\t'name',\r\n\t\t\t\tinfo.project.name\r\n\t\t\t\t\t? `${info.project.name}${info.project.version ? colors.dim(` v${info.project.version}`) : ''}`\r\n\t\t\t\t\t: colors.dim('unnamed')\r\n\t\t\t),\r\n\t\t\trow('root', root),\r\n\t\t\trow(\r\n\t\t\t\t'config',\r\n\t\t\t\tinfo.project.configFile ? relative(root, info.project.configFile) || info.project.configFile : colors.dim('none (defaults)')\r\n\t\t\t),\r\n\t\t\trow('entry', show(info.project.entry))\r\n\t\t]),\r\n\t\tsection('Build', [\r\n\t\t\trow('tool', info.build.tool),\r\n\t\t\t// Which file the build tool is configured from: its own, or this project's `stars.config`.\r\n\t\t\trow('config', info.build.configFile ? show(info.build.configFile) : colors.dim('stars.config')),\r\n\t\t\trow('options', describeOptions(info, colors)),\r\n\t\t\trow('outDir', show(info.build.outDir)),\r\n\t\t\trow('tsconfig', show(info.build.tsconfig)),\r\n\t\t\trow('runs', show(info.build.output))\r\n\t\t]),\r\n\t\tsection('Dev', [\r\n\t\t\trow('watch', info.dev.watch.map(show).join(', ')),\r\n\t\t\trow('debounce', `${info.dev.debounce}ms`),\r\n\t\t\trow('node args', info.dev.nodeArgs.join(' ') || colors.dim('none')),\r\n\t\t\trow('args', info.dev.args.join(' ') || colors.dim('none')),\r\n\t\t\trow('url', info.dev.url ?? colors.dim('unknown, set dev.url or HTTP_PORT')),\r\n\t\t\trow('health', info.dev.health ?? colors.dim('none')),\r\n\t\t\trow(\r\n\t\t\t\t'typecheck',\r\n\t\t\t\tinfo.dev.typecheck.enabled ? `${info.dev.typecheck.checker} → ${show(info.dev.typecheck.tsconfig)}` : colors.dim('disabled')\r\n\t\t\t),\r\n\t\t\trow('tunnel', describeTunnel(info.dev.tunnel, colors)),\r\n\t\t\trow('log file', info.dev.logFile ? show(info.dev.logFile) : colors.dim('disabled'))\r\n\t\t]),\r\n\t\tsection('Codegen', [\r\n\t\t\trow('i18n', info.codegen.i18n ? `${show(info.codegen.i18n.locales)} → ${show(info.codegen.i18n.output)}` : colors.dim('disabled'))\r\n\t\t]),\r\n\t\tsection('Future', [\r\n\t\t\trow('compat', `v${info.future.compatibilityVersion} defaults`),\r\n\t\t\t...info.warnings.map((warning) => row('warning', colors.yellow(warning)))\r\n\t\t]),\r\n\t\tsection('Env', [row('register', info.env.enabled ? colors.green(describeEnvOptions(info.env.options)) : colors.dim('disabled'))]),\r\n\t\tsection('Hooks', [row('registered', info.hooks.join(', ') || colors.dim('none'))]),\r\n\t\tsection('Experimental', [\r\n\t\t\trow('vite', flag(info.experimental.enableVite, colors)),\r\n\t\t\trow('nitro', flag(info.experimental.enableNitro, colors)),\r\n\t\t\t...(info.experimental.enableNitro ? [row('nitro preset', info.experimental.nitro.preset)] : []),\r\n\t\t\trow('external', flag(info.experimental.enableExternalVite, colors))\r\n\t\t]),\r\n\t\tsection('Imports', [\r\n\t\t\trow('auto', info.imports.enabled ? colors.green('enabled') : colors.dim('disabled')),\r\n\t\t\trow('dirs', info.imports.dirs.map(show).join(', ')),\r\n\t\t\trow('presets', info.imports.presets.join(', ') || colors.dim('none')),\r\n\t\t\trow('dts', show(info.imports.dts))\r\n\t\t])\r\n\t].join('\\n\\n');\r\n}\r\n\r\nfunction describeOptions(info: ProjectInfo, colors: ReturnType<typeof createColors>): string {\r\n\tconst names = info.build.tool === 'vite' ? info.options.vite : info.options.tsdown;\r\n\treturn names.length > 0 ? names.join(', ') : colors.dim('none');\r\n}\r\n\r\nfunction describeEnvOptions(options: Readonly<StarsEnvSetupOptions>): string {\r\n\tconst entries = Object.entries(options).map(([key, value]) => `${key} ${String(value)}`);\r\n\treturn entries.length > 0 ? `enabled (${entries.join(', ')})` : 'enabled';\r\n}\r\n\r\nfunction flag(enabled: boolean, colors: ReturnType<typeof createColors>): string {\r\n\treturn enabled ? colors.green('enabled') : colors.dim('disabled');\r\n}\r\n\r\nfunction describeTunnel(tunnel: ResolvedStarsConfig['dev']['tunnel'], colors: ReturnType<typeof createColors>): string {\r\n\tswitch (tunnel.mode) {\r\n\t\tcase 'quick':\r\n\t\t\treturn 'cloudflared quick tunnel';\r\n\t\tcase 'url':\r\n\t\t\treturn tunnel.url;\r\n\t\tdefault:\r\n\t\t\treturn colors.dim('disabled');\r\n\t}\r\n}\r\n\r\nexport async function runInfo(options: InfoOptions): Promise<void> {\r\n\tconst stdout = options.stdout ?? process.stdout;\r\n\tconst project = await loadProject({ cwd: resolveCwd(options), configFile: options.config });\r\n\t// What the build would use: `env:options` may change the env files.\r\n\tconst config = await applyEnvOptions(project.config, project.hooks);\r\n\tconst info = collectInfo(config);\r\n\tstdout.write(`${options.json ? JSON.stringify(info, null, 2) : formatInfo(info, shouldUseColor())}\\n`);\r\n}\r\n\r\nexport default defineCommand({\r\n\tmeta: {\r\n\t\tname: 'info',\r\n\t\tdescription: 'Print the resolved project configuration and environment'\r\n\t},\r\n\targs: {\r\n\t\t...projectArgs,\r\n\t\tjson: {\r\n\t\t\ttype: 'boolean',\r\n\t\t\tdescription: 'Print machine-readable JSON',\r\n\t\t\tdefault: false\r\n\t\t}\r\n\t},\r\n\tasync run({ args }) {\r\n\t\tawait runInfo({ config: args.config, cwd: args.cwd, json: args.json });\r\n\t}\r\n});\r\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"locales-BzOLRBVg.js","names":[],"sources":["../src/builders/index.ts","../src/utils/locales.ts"],"sourcesContent":["import type { ResolvedStarsConfig } from '@wolfstar/schema';\r\nimport type { StarsHookable } from '../utils/hooks.js';\r\nimport type { Builder } from './types.js';\r\n\r\n/**\r\n * Creates the builder for `build.tool`. `hooks` reach the builders that expose hooks of their own (`tsdown:options`).\r\n */\r\nexport async function createBuilder(config: ResolvedStarsConfig, hooks?: StarsHookable): Promise<Builder> {\r\n\t// The project runs its own build, so the CLI only watches what it writes (see `ExternalBuilder`) — including when\r\n\t// it is driving `vite build` with its own `nitro()` plugin itself; `build.output` already points at Nitro's\r\n\t// `server/index.mjs` in that case (see `resolveBuild`).\r\n\tif (config.experimental.enableExternalVite) {\r\n\t\tconst { ExternalBuilder } = await import('./external.js');\r\n\t\treturn new ExternalBuilder(config);\r\n\t}\r\n\r\n\t// Nitro is itself a Vite plugin — there is no separate `nitro build` step — so it is handled before the\r\n\t// `build.tool` switch below, the same way `enableExternalVite` is.\r\n\tif (config.experimental.enableNitro) {\r\n\t\tconst { NitroBuilder } = await import('./nitro.js');\r\n\t\treturn new NitroBuilder(config);\r\n\t}\r\n\r\n\tswitch (config.build.tool) {\r\n\t\tcase 'tsdown': {\r\n\t\t\tconst { TsdownBuilder } = await import('./tsdown.js');\r\n\t\t\treturn new TsdownBuilder(config, hooks);\r\n\t\t}\r\n\t\tcase 'vite': {\r\n\t\t\tconst { ViteBuilder } = await import('./vite.js');\r\n\t\t\treturn new ViteBuilder(config);\r\n\t\t}\r\n\t\tcase 'tsc': {\r\n\t\t\tconst { TscBuilder } = await import('./tsc.js');\r\n\t\t\treturn new TscBuilder(config);\r\n\t\t}\r\n\t\tcase 'none': {\r\n\t\t\tconst { NoneBuilder } = await import('./none.js');\r\n\t\t\treturn new NoneBuilder(config);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport type { Builder, BuilderEvents, BuildOutcome } from './types.js';\r\n","import { EventEmitter } from 'node:events';\r\nimport { cpSync, existsSync, mkdirSync, rmSync } from 'node:fs';\r\nimport { dirname, join, relative } from 'node:path';\r\nimport type { ResolvedStarsConfig } from '@wolfstar/schema';\r\nimport type { LogLevel } from './log-buffer.js';\r\n\r\nexport interface LocalesEvents {\r\n\tchange: [];\r\n\tlog: [level: LogLevel, text: string];\r\n}\r\n\r\n/** Keeps the conventional `src/locales` data directory next to the compiled application. */\r\nexport class Locales extends EventEmitter<LocalesEvents> {\r\n\treadonly source: string;\r\n\treadonly destination: string;\r\n\t#watcher: { close(): Promise<void> } | null = null;\r\n\r\n\tpublic constructor(private readonly config: ResolvedStarsConfig) {\r\n\t\tsuper();\r\n\t\tthis.source = join(config.root, 'src', 'locales');\r\n\t\tthis.destination = join(config.build.outDir, 'locales');\r\n\t}\r\n\r\n\tpublic copy(): boolean {\r\n\t\tif (this.config.build.tool === 'none' || !existsSync(this.source)) return false;\r\n\t\tmkdirSync(this.destination, { recursive: true });\r\n\t\tcpSync(this.source, this.destination, { recursive: true, force: true });\r\n\t\treturn true;\r\n\t}\r\n\r\n\tpublic async watch(): Promise<void> {\r\n\t\tif (this.config.build.tool === 'none' || !existsSync(this.source) || this.#watcher) return;\r\n\t\tconst { watch } = await import('chokidar');\r\n\t\tconst watcher = watch(this.source, { ignoreInitial: true });\r\n\t\tthis.#watcher = watcher;\r\n\r\n\t\twatcher.on('all', (event, path) => {\r\n\t\t\ttry {\r\n\t\t\t\tconst target = join(this.destination, relative(this.source, path));\r\n\t\t\t\tif (event === 'unlink' || event === 'unlinkDir') rmSync(target, { recursive: event === 'unlinkDir', force: true });\r\n\t\t\t\telse if (existsSync(path)) {\r\n\t\t\t\t\tmkdirSync(dirname(target), { recursive: true });\r\n\t\t\t\t\tcpSync(path, target, { recursive: event === 'addDir', force: true });\r\n\t\t\t\t}\r\n\t\t\t\tthis.emit('change');\r\n\t\t\t} catch (error) {\r\n\t\t\t\tthis.emit('log', 'error', `Failed to copy locales: ${error instanceof Error ? error.message : String(error)}`);\r\n\t\t\t}\r\n\t\t});\r\n\t\twatcher.on('error', (error) => this.emit('log', 'error', error instanceof Error ? error.message : String(error)));\r\n\t\tawait new Promise<void>((resolve) => watcher.once('ready', resolve));\r\n\t}\r\n\r\n\tpublic async close(): Promise<void> {\r\n\t\tconst watcher = this.#watcher;\r\n\t\tthis.#watcher = null;\r\n\t\tawait watcher?.close();\r\n\t}\r\n}\r\n"],"mappings":";;;;;;;;AAOA,eAAsB,cAAc,QAA6B,OAAyC;CAIzG,IAAI,OAAO,aAAa,oBAAoB;EAC3C,MAAM,EAAE,oBAAoB,MAAM,OAAO;EACzC,OAAO,IAAI,gBAAgB,MAAM;CAClC;CAIA,IAAI,OAAO,aAAa,aAAa;EACpC,MAAM,EAAE,iBAAiB,MAAM,OAAO;EACtC,OAAO,IAAI,aAAa,MAAM;CAC/B;CAEA,QAAQ,OAAO,MAAM,MAArB;EACC,KAAK,UAAU;GACd,MAAM,EAAE,kBAAkB,MAAM,OAAO;GACvC,OAAO,IAAI,cAAc,QAAQ,KAAK;EACvC;EACA,KAAK,QAAQ;GACZ,MAAM,EAAE,gBAAgB,MAAM,OAAO;GACrC,OAAO,IAAI,YAAY,MAAM;EAC9B;EACA,KAAK,OAAO;GACX,MAAM,EAAE,eAAe,MAAM,OAAO;GACpC,OAAO,IAAI,WAAW,MAAM;EAC7B;EACA,KAAK,QAAQ;GACZ,MAAM,EAAE,gBAAgB,MAAM,OAAO;GACrC,OAAO,IAAI,YAAY,MAAM;EAC9B;CACD;AACD;;;;;AC7BA,IAAa,UAAb,cAA6B,aAA4B;CAKpB;CAJpC,AAAS;CACT,AAAS;CACT,WAA8C;CAE9C,AAAO,YAAY,AAAiB,QAA6B;EAChE,MAAM;EAD6B;EAEnC,KAAK,SAAS,KAAK,OAAO,MAAM,OAAO,SAAS;EAChD,KAAK,cAAc,KAAK,OAAO,MAAM,QAAQ,SAAS;CACvD;CAEA,AAAO,OAAgB;EACtB,IAAI,KAAK,OAAO,MAAM,SAAS,UAAU,CAAC,WAAW,KAAK,MAAM,GAAG,OAAO;EAC1E,UAAU,KAAK,aAAa,EAAE,WAAW,KAAK,CAAC;EAC/C,OAAO,KAAK,QAAQ,KAAK,aAAa;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC;EACtE,OAAO;CACR;CAEA,MAAa,QAAuB;EACnC,IAAI,KAAK,OAAO,MAAM,SAAS,UAAU,CAAC,WAAW,KAAK,MAAM,KAAK,KAAK,UAAU;EACpF,MAAM,EAAE,UAAU,MAAM,OAAO;EAC/B,MAAM,UAAU,MAAM,KAAK,QAAQ,EAAE,eAAe,KAAK,CAAC;EAC1D,KAAK,WAAW;EAEhB,QAAQ,GAAG,QAAQ,OAAO,SAAS;GAClC,IAAI;IACH,MAAM,SAAS,KAAK,KAAK,aAAa,SAAS,KAAK,QAAQ,IAAI,CAAC;IACjE,IAAI,UAAU,YAAY,UAAU,aAAa,OAAO,QAAQ;KAAE,WAAW,UAAU;KAAa,OAAO;IAAK,CAAC;SAC5G,IAAI,WAAW,IAAI,GAAG;KAC1B,UAAU,QAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;KAC9C,OAAO,MAAM,QAAQ;MAAE,WAAW,UAAU;MAAU,OAAO;KAAK,CAAC;IACpE;IACA,KAAK,KAAK,QAAQ;GACnB,SAAS,OAAO;IACf,KAAK,KAAK,OAAO,SAAS,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG;GAC9G;EACD,CAAC;EACD,QAAQ,GAAG,UAAU,UAAU,KAAK,KAAK,OAAO,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,CAAC;EAChH,MAAM,IAAI,SAAe,YAAY,QAAQ,KAAK,SAAS,OAAO,CAAC;CACpE;CAEA,MAAa,QAAuB;EACnC,MAAM,UAAU,KAAK;EACrB,KAAK,WAAW;EAChB,MAAM,SAAS,MAAM;CACtB;AACD"}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { EventEmitter } from "node:events";
|
|
2
|
-
import { stripVTControlCharacters } from "node:util";
|
|
3
|
-
|
|
4
|
-
//#region src/utils/log-buffer.ts
|
|
5
|
-
/**
|
|
6
|
-
* A bounded, in-memory log store shared by the dev service and its renderers.
|
|
7
|
-
*/
|
|
8
|
-
var LogBuffer = class extends EventEmitter {
|
|
9
|
-
capacity;
|
|
10
|
-
#entries = [];
|
|
11
|
-
#nextId = 1;
|
|
12
|
-
constructor(capacity = 2e3) {
|
|
13
|
-
super();
|
|
14
|
-
this.capacity = capacity;
|
|
15
|
-
}
|
|
16
|
-
push(input) {
|
|
17
|
-
const entry = {
|
|
18
|
-
id: this.#nextId++,
|
|
19
|
-
time: Date.now(),
|
|
20
|
-
...input
|
|
21
|
-
};
|
|
22
|
-
this.#entries.push(entry);
|
|
23
|
-
if (this.#entries.length > this.capacity) this.#entries.splice(0, this.#entries.length - this.capacity);
|
|
24
|
-
this.emit("entry", entry);
|
|
25
|
-
return entry;
|
|
26
|
-
}
|
|
27
|
-
entries() {
|
|
28
|
-
return this.#entries;
|
|
29
|
-
}
|
|
30
|
-
filter(filter) {
|
|
31
|
-
const query = filter.query?.toLowerCase() ?? null;
|
|
32
|
-
return this.#entries.filter((entry) => (!filter.source || entry.source === filter.source) && (!filter.level || matchesLevel(entry.level, filter.level)) && (!query || entry.text.toLowerCase().includes(query)));
|
|
33
|
-
}
|
|
34
|
-
clear() {
|
|
35
|
-
this.#entries = [];
|
|
36
|
-
this.emit("clear");
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
const LEVEL_ORDER = {
|
|
40
|
-
debug: 0,
|
|
41
|
-
info: 1,
|
|
42
|
-
success: 1,
|
|
43
|
-
warn: 2,
|
|
44
|
-
error: 3
|
|
45
|
-
};
|
|
46
|
-
/**
|
|
47
|
-
* Whether `level` is at least as severe as `minimum`.
|
|
48
|
-
*/
|
|
49
|
-
function matchesLevel(level, minimum) {
|
|
50
|
-
return LEVEL_ORDER[level] >= LEVEL_ORDER[minimum];
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Whether an application stderr line only continues the preceding JavaScript error. Stack frames and the fields
|
|
54
|
-
* Node prints after an `Error` are useful log lines, but they must not each increment the panel's error counter.
|
|
55
|
-
*/
|
|
56
|
-
function isErrorDetail(entry) {
|
|
57
|
-
if (entry.source !== "app" || entry.level !== "error") return false;
|
|
58
|
-
const text = stripVTControlCharacters(entry.text);
|
|
59
|
-
return /^\s+at\s/.test(text) || /^\s+(?:type|path|code|cause|errno|syscall|address|port):/.test(text) || /^\s*}\s*$/.test(text) || !text.trim();
|
|
60
|
-
}
|
|
61
|
-
/** stderr is a transport, not a severity: Node and many loggers also send warnings there. */
|
|
62
|
-
function classifyAppLine(text, fallback) {
|
|
63
|
-
const plain = stripVTControlCharacters(text);
|
|
64
|
-
if (/\b(?:Error|ERROR|FATAL)\b|\bERR_[A-Z_]+\b/.test(plain)) return "error";
|
|
65
|
-
if (/\b(?:Warning|WARN|WARNING|DeprecationWarning|ExperimentalWarning)\b/.test(plain) || /^\(node:\d+\).*warning/i.test(plain)) return "warn";
|
|
66
|
-
if (/^\s*(?:\(Use .*--trace-warnings|\[(?:info|debug)\]|INFO\b|DEBUG\b|[◇ℹ✔])/.test(plain)) return "info";
|
|
67
|
-
return fallback;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
//#endregion
|
|
71
|
-
export { classifyAppLine as n, isErrorDetail as r, LogBuffer as t };
|
|
72
|
-
//# sourceMappingURL=log-buffer-CY82aqnb.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"log-buffer-CY82aqnb.js","names":[],"sources":["../src/utils/log-buffer.ts"],"sourcesContent":["import { EventEmitter } from 'node:events';\r\nimport { stripVTControlCharacters } from 'node:util';\r\n\r\nexport type LogSource = 'stars' | 'build' | 'app' | 'tsc' | 'tunnel';\r\nexport type LogLevel = import('@wolfstar/schema').BuilderLogLevel;\r\n\r\nexport interface LogEntry {\r\n\treadonly id: number;\r\n\treadonly time: number;\r\n\treadonly source: LogSource;\r\n\treadonly level: LogLevel;\r\n\treadonly text: string;\r\n}\r\n\r\nexport interface LogFilter {\r\n\tsource?: LogSource | null;\r\n\tlevel?: LogLevel | null;\r\n\tquery?: string | null;\r\n}\r\n\r\nexport type LogInput = Omit<LogEntry, 'id' | 'time'>;\r\n\r\n/**\r\n * A bounded, in-memory log store shared by the dev service and its renderers.\r\n */\r\nexport class LogBuffer extends EventEmitter<{ entry: [LogEntry]; clear: [] }> {\r\n\t#entries: LogEntry[] = [];\r\n\t#nextId = 1;\r\n\r\n\tpublic constructor(public readonly capacity = 2000) {\r\n\t\tsuper();\r\n\t}\r\n\r\n\tpublic push(input: LogInput): LogEntry {\r\n\t\tconst entry: LogEntry = { id: this.#nextId++, time: Date.now(), ...input };\r\n\t\tthis.#entries.push(entry);\r\n\t\tif (this.#entries.length > this.capacity) this.#entries.splice(0, this.#entries.length - this.capacity);\r\n\t\tthis.emit('entry', entry);\r\n\t\treturn entry;\r\n\t}\r\n\r\n\tpublic entries(): readonly LogEntry[] {\r\n\t\treturn this.#entries;\r\n\t}\r\n\r\n\tpublic filter(filter: LogFilter): LogEntry[] {\r\n\t\tconst query = filter.query?.toLowerCase() ?? null;\r\n\t\treturn this.#entries.filter(\r\n\t\t\t(entry) =>\r\n\t\t\t\t(!filter.source || entry.source === filter.source) &&\r\n\t\t\t\t(!filter.level || matchesLevel(entry.level, filter.level)) &&\r\n\t\t\t\t(!query || entry.text.toLowerCase().includes(query))\r\n\t\t);\r\n\t}\r\n\r\n\tpublic clear(): void {\r\n\t\tthis.#entries = [];\r\n\t\tthis.emit('clear');\r\n\t}\r\n}\r\n\r\nconst LEVEL_ORDER: Record<LogLevel, number> = { debug: 0, info: 1, success: 1, warn: 2, error: 3 };\r\n\r\n/**\r\n * Whether `level` is at least as severe as `minimum`.\r\n */\r\nexport function matchesLevel(level: LogLevel, minimum: LogLevel): boolean {\r\n\treturn LEVEL_ORDER[level] >= LEVEL_ORDER[minimum];\r\n}\r\n\r\n/**\r\n * Whether an application stderr line only continues the preceding JavaScript error. Stack frames and the fields\r\n * Node prints after an `Error` are useful log lines, but they must not each increment the panel's error counter.\r\n */\r\nexport function isErrorDetail(entry: Pick<LogEntry, 'source' | 'level' | 'text'>): boolean {\r\n\tif (entry.source !== 'app' || entry.level !== 'error') return false;\r\n\tconst text = stripVTControlCharacters(entry.text);\r\n\treturn /^\\s+at\\s/.test(text) || /^\\s+(?:type|path|code|cause|errno|syscall|address|port):/.test(text) || /^\\s*}\\s*$/.test(text) || !text.trim();\r\n}\r\n\r\n/** stderr is a transport, not a severity: Node and many loggers also send warnings there. */\r\nexport function classifyAppLine(text: string, fallback: LogLevel): LogLevel {\r\n\tconst plain = stripVTControlCharacters(text);\r\n\tif (/\\b(?:Error|ERROR|FATAL)\\b|\\bERR_[A-Z_]+\\b/.test(plain)) return 'error';\r\n\tif (/\\b(?:Warning|WARN|WARNING|DeprecationWarning|ExperimentalWarning)\\b/.test(plain) || /^\\(node:\\d+\\).*warning/i.test(plain)) return 'warn';\r\n\tif (/^\\s*(?:\\(Use .*--trace-warnings|\\[(?:info|debug)\\]|INFO\\b|DEBUG\\b|[◇ℹ✔])/.test(plain)) return 'info';\r\n\treturn fallback;\r\n}\r\n"],"mappings":";;;;;;;AAyBA,IAAa,YAAb,cAA+B,aAA+C;CAI1C;CAHnC,WAAuB,CAAC;CACxB,UAAU;CAEV,AAAO,YAAY,AAAgB,WAAW,KAAM;EACnD,MAAM;EAD4B;CAEnC;CAEA,AAAO,KAAK,OAA2B;EACtC,MAAM,QAAkB;GAAE,IAAI,KAAK;GAAW,MAAM,KAAK,IAAI;GAAG,GAAG;EAAM;EACzE,KAAK,SAAS,KAAK,KAAK;EACxB,IAAI,KAAK,SAAS,SAAS,KAAK,UAAU,KAAK,SAAS,OAAO,GAAG,KAAK,SAAS,SAAS,KAAK,QAAQ;EACtG,KAAK,KAAK,SAAS,KAAK;EACxB,OAAO;CACR;CAEA,AAAO,UAA+B;EACrC,OAAO,KAAK;CACb;CAEA,AAAO,OAAO,QAA+B;EAC5C,MAAM,QAAQ,OAAO,OAAO,YAAY,KAAK;EAC7C,OAAO,KAAK,SAAS,QACnB,WACC,CAAC,OAAO,UAAU,MAAM,WAAW,OAAO,YAC1C,CAAC,OAAO,SAAS,aAAa,MAAM,OAAO,OAAO,KAAK,OACvD,CAAC,SAAS,MAAM,KAAK,YAAY,CAAC,CAAC,SAAS,KAAK,EACpD;CACD;CAEA,AAAO,QAAc;EACpB,KAAK,WAAW,CAAC;EACjB,KAAK,KAAK,OAAO;CAClB;AACD;AAEA,MAAM,cAAwC;CAAE,OAAO;CAAG,MAAM;CAAG,SAAS;CAAG,MAAM;CAAG,OAAO;AAAE;;;;AAKjG,SAAgB,aAAa,OAAiB,SAA4B;CACzE,OAAO,YAAY,UAAU,YAAY;AAC1C;;;;;AAMA,SAAgB,cAAc,OAA6D;CAC1F,IAAI,MAAM,WAAW,SAAS,MAAM,UAAU,SAAS,OAAO;CAC9D,MAAM,OAAO,yBAAyB,MAAM,IAAI;CAChD,OAAO,WAAW,KAAK,IAAI,KAAK,2DAA2D,KAAK,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK;AAC/I;;AAGA,SAAgB,gBAAgB,MAAc,UAA8B;CAC3E,MAAM,QAAQ,yBAAyB,IAAI;CAC3C,IAAI,4CAA4C,KAAK,KAAK,GAAG,OAAO;CACpE,IAAI,sEAAsE,KAAK,KAAK,KAAK,0BAA0B,KAAK,KAAK,GAAG,OAAO;CACvI,IAAI,2EAA2E,KAAK,KAAK,GAAG,OAAO;CACnG,OAAO;AACR"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nitro-yjqZBh5L.js","names":["ServerBuilder"],"sources":["../src/builders/nitro.ts"],"sourcesContent":["import { NitroBuilder as ServerBuilder } from '@wolfstar/nitro-server';\r\nimport type { ResolvedStarsConfig } from '@wolfstar/schema';\r\nimport { pluginRegistrations } from '../utils/plugin-registrations.js';\r\nimport { importFromProject } from '../utils/project.js';\r\n\r\n/** Connect the server integration to the CLI's diagnostics and plugin discovery. */\r\nexport class NitroBuilder extends ServerBuilder {\r\n\tpublic constructor(config: ResolvedStarsConfig) {\r\n\t\tsuper(config, { importFromProject, pluginRegistrations });\r\n\t}\r\n}\r\n"],"mappings":";;;;;;AAMA,IAAa,eAAb,cAAkCA,eAAc;CAC/C,AAAO,YAAY,QAA6B;EAC/C,MAAM,QAAQ;GAAE;GAAmB;EAAoB,CAAC;CACzD;AACD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plain-B6z85uQP.js","names":[],"sources":["../src/dev/tui/plain.ts"],"sourcesContent":["import { createColors } from 'colorette';\r\nimport type { DevService } from '../dev-service.js';\r\nimport type { LogEntry } from '../../utils/log-buffer.js';\r\n\r\nexport interface PlainRendererOptions {\r\n\tstdout?: NodeJS.WritableStream;\r\n\tcolor?: boolean;\r\n\t/** Whether to attach process signal handlers. */\r\n\tsignals?: boolean;\r\n}\r\n\r\nexport interface Renderer {\r\n\t/** Starts rendering. Resolves when the user asks to quit (or never, in plain mode without signals). */\r\n\tstart(): Promise<void>;\r\n\t/** Stops rendering and restores the terminal. */\r\n\tstop(): void;\r\n}\r\n\r\n/**\r\n * Line-oriented renderer for non-interactive terminals, CI and redirected output.\r\n */\r\nexport function createPlainRenderer(service: DevService, options: PlainRendererOptions = {}): Renderer {\r\n\tconst stdout = options.stdout ?? process.stdout;\r\n\tconst colors = createColors({ useColor: options.color ?? false });\r\n\tconst write = (text: string) => stdout.write(`${text}\\n`);\r\n\r\n\tconst prefixes = {\r\n\t\tstars: colors.cyan('stars'),\r\n\t\tbuild: colors.magenta('build'),\r\n\t\ttsc: colors.blue('tsc'),\r\n\t\ttunnel: colors.yellow('tunnel'),\r\n\t\tapp: null\r\n\t} as const;\r\n\r\n\tconst onEntry = (entry: LogEntry) => {\r\n\t\tconst prefix = prefixes[entry.source];\r\n\t\tif (!prefix) {\r\n\t\t\twrite(entry.text);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst paint =\r\n\t\t\tentry.level === 'error'\r\n\t\t\t\t? colors.red\r\n\t\t\t\t: entry.level === 'warn'\r\n\t\t\t\t\t? colors.yellow\r\n\t\t\t\t\t: entry.level === 'success'\r\n\t\t\t\t\t\t? colors.green\r\n\t\t\t\t\t\t: (value: string) => value;\r\n\t\twrite(`${prefix} ${paint(entry.text)}`);\r\n\t};\r\n\r\n\tconst onClear = () => write(`${prefixes.stars} logs cleared`);\r\n\r\n\treturn {\r\n\t\tstart() {\r\n\t\t\tservice.logs.on('entry', onEntry);\r\n\t\t\tservice.logs.on('clear', onClear);\r\n\t\t\treturn new Promise<void>(() => {});\r\n\t\t},\r\n\t\tstop() {\r\n\t\t\tservice.logs.off('entry', onEntry);\r\n\t\t\tservice.logs.off('clear', onClear);\r\n\t\t}\r\n\t};\r\n}\r\n"],"mappings":";;;;;;AAqBA,SAAgB,oBAAoB,SAAqB,UAAgC,CAAC,GAAa;CACtG,MAAM,SAAS,QAAQ,UAAU,QAAQ;CACzC,MAAM,SAAS,aAAa,EAAE,UAAU,QAAQ,SAAS,MAAM,CAAC;CAChE,MAAM,SAAS,SAAiB,OAAO,MAAM,GAAG,KAAK,GAAG;CAExD,MAAM,WAAW;EAChB,OAAO,OAAO,KAAK,OAAO;EAC1B,OAAO,OAAO,QAAQ,OAAO;EAC7B,KAAK,OAAO,KAAK,KAAK;EACtB,QAAQ,OAAO,OAAO,QAAQ;EAC9B,KAAK;CACN;CAEA,MAAM,WAAW,UAAoB;EACpC,MAAM,SAAS,SAAS,MAAM;EAC9B,IAAI,CAAC,QAAQ;GACZ,MAAM,MAAM,IAAI;GAChB;EACD;EAEA,MAAM,QACL,MAAM,UAAU,UACb,OAAO,MACP,MAAM,UAAU,SACf,OAAO,SACP,MAAM,UAAU,YACf,OAAO,SACN,UAAkB;EACzB,MAAM,GAAG,OAAO,GAAG,MAAM,MAAM,IAAI,GAAG;CACvC;CAEA,MAAM,gBAAgB,MAAM,GAAG,SAAS,MAAM,cAAc;CAE5D,OAAO;EACN,QAAQ;GACP,QAAQ,KAAK,GAAG,SAAS,OAAO;GAChC,QAAQ,KAAK,GAAG,SAAS,OAAO;GAChC,OAAO,IAAI,cAAoB,CAAC,CAAC;EAClC;EACA,OAAO;GACN,QAAQ,KAAK,IAAI,SAAS,OAAO;GACjC,QAAQ,KAAK,IAAI,SAAS,OAAO;EAClC;CACD;AACD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prepare-Cb45Z4re.js","names":[],"sources":["../src/commands/prepare.ts"],"sourcesContent":["import { displayPath } from '@wolfstar/schema';\r\nimport { defineCommand } from 'citty';\r\nimport { createColors } from 'colorette';\r\nimport { projectArgs, resolveCwd, type ProjectArgs } from '../utils/args.js';\r\nimport { cliDiagnostics } from '../utils/diagnostics.js';\r\nimport { shouldUseColor } from '../utils/output-mode.js';\r\nimport { loadProject } from '../utils/hooks.js';\r\nimport { prepareProject, reportWarnings } from './_shared.js';\r\n\r\nexport { prepareProject } from './_shared.js';\r\n\r\nexport interface PrepareTaskOptions extends ProjectArgs {\r\n\tcheck?: boolean;\r\n\tjson?: boolean;\r\n\tstdout?: NodeJS.WritableStream;\r\n}\r\n\r\n/**\r\n * Generates `.stars/tsconfig.json` and `imports.dts` (see {@link StarsImportsConfig} in `@wolfstar/schema`), the way `nuxt\r\n * prepare` regenerates `.nuxt/imports.d.ts`. Run automatically by `stars dev` and `stars build` before the first\r\n * build; `--check` fails instead of writing, for CI.\r\n */\r\nexport async function runPrepare(options: PrepareTaskOptions): Promise<void> {\r\n\tconst stdout = options.stdout ?? process.stdout;\r\n\tconst colors = createColors({ useColor: shouldUseColor() && !options.json });\r\n\tconst { config, hooks } = await loadProject({ cwd: resolveCwd(options), configFile: options.config });\r\n\tawait reportWarnings(config, (text) => process.stderr.write(`${text}\\n`));\r\n\tconst result = await prepareProject(config, hooks, Boolean(options.check));\r\n\r\n\tif (options.json) {\r\n\t\tstdout.write(`${JSON.stringify(result, null, 2)}\\n`);\r\n\t} else {\r\n\t\tconst paintConfig = result.tsconfig.status === 'outdated' ? colors.red : colors.green;\r\n\t\tstdout.write(`${colors.dim('stars')} tsconfig: ${paintConfig(result.tsconfig.status)} ${displayPath(config.root, result.tsconfig.path)}\\n`);\r\n\t\tif (result.modules) {\r\n\t\t\tconst paint = result.modules.status === 'outdated' ? colors.red : colors.green;\r\n\t\t\tstdout.write(`${colors.dim('stars')} modules: ${paint(result.modules.status)} ${displayPath(config.root, result.modules.path)}\\n`);\r\n\t\t}\r\n\t\tif (result.enabled) {\r\n\t\t\tconst paint = result.status === 'outdated' ? colors.red : colors.green;\r\n\t\t\tstdout.write(`${colors.dim('stars')} imports: ${paint(result.status)} ${displayPath(config.root, result.dts)}\\n`);\r\n\t\t}\r\n\t}\r\n\r\n\tif (result.status === 'outdated' || result.tsconfig.status === 'outdated' || result.modules?.status === 'outdated') {\r\n\t\tthrow cliDiagnostics.PREPARE_OUTDATED({});\r\n\t}\r\n}\r\n\r\nexport default defineCommand({\r\n\tmeta: {\r\n\t\tname: 'prepare',\r\n\t\tdescription: 'Generate TypeScript configuration and auto imports declarations'\r\n\t},\r\n\targs: {\r\n\t\t...projectArgs,\r\n\t\tcheck: {\r\n\t\t\ttype: 'boolean',\r\n\t\t\tdescription: 'Fail when the generated files are out of date instead of writing it',\r\n\t\t\tdefault: false\r\n\t\t},\r\n\t\tjson: {\r\n\t\t\ttype: 'boolean',\r\n\t\t\tdescription: 'Print machine-readable JSON',\r\n\t\t\tdefault: false\r\n\t\t}\r\n\t},\r\n\tasync run({ args }) {\r\n\t\tawait runPrepare({ config: args.config, cwd: args.cwd, check: args.check, json: args.json });\r\n\t}\r\n});\r\n"],"mappings":";;;;;;;;;;;;;;AAsBA,eAAsB,WAAW,SAA4C;CAC5E,MAAM,SAAS,QAAQ,UAAU,QAAQ;CACzC,MAAM,SAAS,aAAa,EAAE,UAAU,eAAe,KAAK,CAAC,QAAQ,KAAK,CAAC;CAC3E,MAAM,EAAE,QAAQ,UAAU,MAAM,YAAY;EAAE,KAAK,WAAW,OAAO;EAAG,YAAY,QAAQ;CAAO,CAAC;CACpG,MAAM,eAAe,SAAS,SAAS,QAAQ,OAAO,MAAM,GAAG,KAAK,GAAG,CAAC;CACxE,MAAM,SAAS,MAAM,eAAe,QAAQ,OAAO,QAAQ,QAAQ,KAAK,CAAC;CAEzE,IAAI,QAAQ,MACX,OAAO,MAAM,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,GAAG;MAC7C;EACN,MAAM,cAAc,OAAO,SAAS,WAAW,aAAa,OAAO,MAAM,OAAO;EAChF,OAAO,MAAM,GAAG,OAAO,IAAI,OAAO,EAAE,aAAa,YAAY,OAAO,SAAS,MAAM,EAAE,GAAG,YAAY,OAAO,MAAM,OAAO,SAAS,IAAI,EAAE,GAAG;EAC1I,IAAI,OAAO,SAAS;GACnB,MAAM,QAAQ,OAAO,QAAQ,WAAW,aAAa,OAAO,MAAM,OAAO;GACzE,OAAO,MAAM,GAAG,OAAO,IAAI,OAAO,EAAE,YAAY,MAAM,OAAO,QAAQ,MAAM,EAAE,GAAG,YAAY,OAAO,MAAM,OAAO,QAAQ,IAAI,EAAE,GAAG;EAClI;EACA,IAAI,OAAO,SAAS;GACnB,MAAM,QAAQ,OAAO,WAAW,aAAa,OAAO,MAAM,OAAO;GACjE,OAAO,MAAM,GAAG,OAAO,IAAI,OAAO,EAAE,YAAY,MAAM,OAAO,MAAM,EAAE,GAAG,YAAY,OAAO,MAAM,OAAO,GAAG,EAAE,GAAG;EACjH;CACD;CAEA,IAAI,OAAO,WAAW,cAAc,OAAO,SAAS,WAAW,cAAc,OAAO,SAAS,WAAW,YACvG,MAAM,eAAe,iBAAiB,CAAC,CAAC;AAE1C;AAEA,sBAAe,cAAc;CAC5B,MAAM;EACL,MAAM;EACN,aAAa;CACd;CACA,MAAM;EACL,GAAG;EACH,OAAO;GACN,MAAM;GACN,aAAa;GACb,SAAS;EACV;EACA,MAAM;GACL,MAAM;GACN,aAAa;GACb,SAAS;EACV;CACD;CACA,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,WAAW;GAAE,QAAQ,KAAK;GAAQ,KAAK,KAAK;GAAK,OAAO,KAAK;GAAO,MAAM,KAAK;EAAK,CAAC;CAC5F;AACD,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"project-D-8VIcyF.js","names":[],"sources":["../src/utils/project.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\r\nimport { createRequire } from 'node:module';\r\nimport { dirname, join } from 'node:path';\r\nimport { pathToFileURL } from 'node:url';\r\nimport { cliDiagnostics } from './diagnostics.js';\r\n\r\n/**\r\n * Resolves a module id from the project root, the way the project itself would.\r\n */\r\nexport function resolveFromProject(root: string, id: string): string | null {\r\n\ttry {\r\n\t\treturn createRequire(join(root, 'package.json')).resolve(id);\r\n\t} catch {\r\n\t\treturn null;\r\n\t}\r\n}\r\n\r\n/**\r\n * Imports a module from the project root, failing with an actionable error when it is not installed.\r\n */\r\nexport async function importFromProject<T>(root: string, id: string, hint: string): Promise<T> {\r\n\tconst resolved = resolveFromProject(root, id);\r\n\tif (!resolved) {\r\n\t\tthrow cliDiagnostics.DEPENDENCY_MISSING({ name: id, root, hint });\r\n\t}\r\n\r\n\treturn (await import(pathToFileURL(resolved).href)) as T;\r\n}\r\n\r\n/**\r\n * Resolves an executable a package declares in its `package.json#bin`, from the project's own `node_modules`.\r\n *\r\n * Going through `bin` rather than a hardcoded path is what makes this work across layouts: TypeScript 7 hides\r\n * `lib/tsc.js` behind its `exports` map, and packages move their entry points between releases.\r\n */\r\nexport function resolveBinary(root: string, packageName: string, binName: string): string | null {\r\n\tconst packageJsonPath = resolveFromProject(root, `${packageName}/package.json`);\r\n\tif (!packageJsonPath) return null;\r\n\r\n\ttry {\r\n\t\tconst packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as { bin?: string | Record<string, string> };\r\n\t\tconst bin = typeof packageJson.bin === 'string' ? packageJson.bin : packageJson.bin?.[binName];\r\n\t\treturn bin ? join(dirname(packageJsonPath), bin) : null;\r\n\t} catch {\r\n\t\treturn null;\r\n\t}\r\n}\r\n\r\n/**\r\n * Finds the version of an installed package by walking `node_modules` up from `root`.\r\n */\r\nexport function findInstalledVersion(root: string, name: string): string | null {\r\n\tlet directory = root;\r\n\tfor (;;) {\r\n\t\tconst file = join(directory, 'node_modules', name, 'package.json');\r\n\t\tif (existsSync(file)) {\r\n\t\t\ttry {\r\n\t\t\t\tconst parsed = JSON.parse(readFileSync(file, 'utf-8')) as { version?: string };\r\n\t\t\t\treturn parsed.version ?? null;\r\n\t\t\t} catch {\r\n\t\t\t\treturn null;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst parent = dirname(directory);\r\n\t\tif (parent === directory) return null;\r\n\t\tdirectory = parent;\r\n\t}\r\n}\r\n"],"mappings":";;;;;;;;;;AASA,SAAgB,mBAAmB,MAAc,IAA2B;CAC3E,IAAI;EACH,OAAO,cAAc,KAAK,MAAM,cAAc,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC5D,QAAQ;EACP,OAAO;CACR;AACD;;;;AAKA,eAAsB,kBAAqB,MAAc,IAAY,MAA0B;CAC9F,MAAM,WAAW,mBAAmB,MAAM,EAAE;CAC5C,IAAI,CAAC,UACJ,MAAM,eAAe,mBAAmB;EAAE,MAAM;EAAI;EAAM;CAAK,CAAC;CAGjE,OAAQ,MAAM,OAAO,cAAc,QAAQ,CAAC,CAAC;AAC9C;;;;;;;AAQA,SAAgB,cAAc,MAAc,aAAqB,SAAgC;CAChG,MAAM,kBAAkB,mBAAmB,MAAM,GAAG,YAAY,cAAc;CAC9E,IAAI,CAAC,iBAAiB,OAAO;CAE7B,IAAI;EACH,MAAM,cAAc,KAAK,MAAM,aAAa,iBAAiB,OAAO,CAAC;EACrE,MAAM,MAAM,OAAO,YAAY,QAAQ,WAAW,YAAY,MAAM,YAAY,MAAM;EACtF,OAAO,MAAM,KAAK,QAAQ,eAAe,GAAG,GAAG,IAAI;CACpD,QAAQ;EACP,OAAO;CACR;AACD;;;;AAKA,SAAgB,qBAAqB,MAAc,MAA6B;CAC/E,IAAI,YAAY;CAChB,SAAS;EACR,MAAM,OAAO,KAAK,WAAW,gBAAgB,MAAM,cAAc;EACjE,IAAI,WAAW,IAAI,GAClB,IAAI;GAEH,OADe,KAAK,MAAM,aAAa,MAAM,OAAO,CACxC,CAAC,CAAC,WAAW;EAC1B,QAAQ;GACP,OAAO;EACR;EAGD,MAAM,SAAS,QAAQ,SAAS;EAChC,IAAI,WAAW,WAAW,OAAO;EACjC,YAAY;CACb;AACD"}
|
package/dist/run-BiLZqib3.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"run-BiLZqib3.js","names":["_runCommand"],"sources":["../src/commands/index.ts","../src/main.ts","../src/run.ts"],"sourcesContent":["import type { CommandDef } from 'citty';\r\n\r\n// citty types each command by its own arguments; the registry needs the erased form.\r\n// oxlint-disable-next-line typescript/no-explicit-any\r\ntype AnyCommand = CommandDef<any>;\r\n\r\nexport const commands: Record<string, () => Promise<AnyCommand>> = {\r\n\tdev: () => import('./dev.js').then((module) => module.default),\r\n\tbuild: () => import('./build.js').then((module) => module.default),\r\n\tinfo: () => import('./info.js').then((module) => module.default),\r\n\tcodegen: () => import('./codegen.js').then((module) => module.default),\r\n\tprepare: () => import('./prepare.js').then((module) => module.default),\r\n\tcommands: () => import('./commands.js').then((module) => module.default)\r\n};\r\n","import { defineCommand, type CommandDef } from 'citty';\r\nimport { commands } from './commands/index.js';\r\nimport { readOwnPackageJson } from './utils/version.js';\r\n\r\n// citty types each command by its own arguments; the registry needs the erased form.\r\n// oxlint-disable-next-line typescript/no-explicit-any\r\ntype AnyCommand = CommandDef<any>;\r\n\r\nconst packageJson = readOwnPackageJson();\r\n\r\nexport const main = defineCommand({\r\n\tmeta: {\r\n\t\tname: 'stars',\r\n\t\tversion: packageJson.version,\r\n\t\tdescription: packageJson.description\r\n\t},\r\n\tsubCommands: commands\r\n}) as AnyCommand;\r\n","import { renderUsage, runCommand as _runCommand, type CommandDef } from 'citty';\r\nimport process from 'node:process';\r\nimport { commands } from './commands/index.js';\r\nimport { main } from './main.js';\r\nimport { exitCodeOf, formatError } from './utils/errors.js';\r\nimport { readOwnPackageJson } from './utils/version.js';\r\n\r\n// citty types each command by its own arguments; the registry needs the erased form.\r\n// oxlint-disable-next-line typescript/no-explicit-any\r\ntype AnyCommand = CommandDef<any>;\r\n\r\n/**\r\n * Walks the command names of `stars <command> [<subcommand>] --help` so nested commands (`stars commands clean`)\r\n * render their own usage instead of their parent's.\r\n */\r\nasync function resolveHelpTarget(names: string[]): Promise<AnyCommand | null> {\r\n\tconst [first, ...rest] = names;\r\n\tif (!first || !Object.hasOwn(commands, first)) return null;\r\n\r\n\tlet command = await commands[first]!();\r\n\tfor (const name of rest) {\r\n\t\tconst resolved = typeof command.subCommands === 'function' ? await command.subCommands() : await command.subCommands;\r\n\t\tconst child: unknown = (resolved as Record<string, unknown> | undefined)?.[name];\r\n\t\tif (!child) break;\r\n\t\tcommand = (typeof child === 'function' ? await child() : child) as AnyCommand;\r\n\t}\r\n\r\n\treturn command;\r\n}\r\n\r\nexport async function runMain(argv: string[] = process.argv.slice(2)): Promise<void> {\r\n\tif (argv.includes('--version') || argv.includes('-V')) {\r\n\t\tconsole.log(readOwnPackageJson().version);\r\n\t\tprocess.exit(0);\r\n\t}\r\n\r\n\tif (argv.length === 0 || argv.includes('--help') || argv.includes('-h')) {\r\n\t\t// citty's showUsage logs through consola, which is muted in some environments; render and print directly.\r\n\t\tconst command = await resolveHelpTarget(argv.filter((argument) => !argument.startsWith('-')));\r\n\t\tconsole.log(await (command ? renderUsage(command, main) : renderUsage(main)));\r\n\t\tprocess.exit(0);\r\n\t}\r\n\r\n\ttry {\r\n\t\tawait _runCommand(main, { rawArgs: argv });\r\n\t} catch (error) {\r\n\t\tconsole.error(await formatError(error));\r\n\t\tprocess.exit(exitCodeOf(error));\r\n\t}\r\n}\r\n"],"mappings":";;;;;;AAMA,MAAa,WAAsD;CAClE,WAAW,OAAO,oBAAW,CAAC,MAAM,WAAW,OAAO,OAAO;CAC7D,aAAa,OAAO,sBAAa,CAAC,MAAM,WAAW,OAAO,OAAO;CACjE,YAAY,OAAO,qBAAY,CAAC,MAAM,WAAW,OAAO,OAAO;CAC/D,eAAe,OAAO,wBAAe,CAAC,MAAM,WAAW,OAAO,OAAO;CACrE,eAAe,OAAO,wBAAe,CAAC,MAAM,WAAW,OAAO,OAAO;CACrE,gBAAgB,OAAO,yBAAgB,CAAC,MAAM,WAAW,OAAO,OAAO;AACxE;;;;ACLA,MAAM,cAAc,mBAAmB;AAEvC,MAAa,OAAO,cAAc;CACjC,MAAM;EACL,MAAM;EACN,SAAS,YAAY;EACrB,aAAa,YAAY;CAC1B;CACA,aAAa;AACd,CAAC;;;;;;;;ACFD,eAAe,kBAAkB,OAA6C;CAC7E,MAAM,CAAC,OAAO,GAAG,QAAQ;CACzB,IAAI,CAAC,SAAS,CAAC,OAAO,OAAO,UAAU,KAAK,GAAG,OAAO;CAEtD,IAAI,UAAU,MAAM,SAAS,MAAM,CAAE;CACrC,KAAK,MAAM,QAAQ,MAAM;EAExB,MAAM,SADW,OAAO,QAAQ,gBAAgB,aAAa,MAAM,QAAQ,YAAY,IAAI,MAAM,QAAQ,YACzE,GAA2C;EAC3E,IAAI,CAAC,OAAO;EACZ,UAAW,OAAO,UAAU,aAAa,MAAM,MAAM,IAAI;CAC1D;CAEA,OAAO;AACR;AAEA,eAAsB,QAAQ,OAAiB,QAAQ,KAAK,MAAM,CAAC,GAAkB;CACpF,IAAI,KAAK,SAAS,WAAW,KAAK,KAAK,SAAS,IAAI,GAAG;EACtD,QAAQ,IAAI,mBAAmB,CAAC,CAAC,OAAO;EACxC,QAAQ,KAAK,CAAC;CACf;CAEA,IAAI,KAAK,WAAW,KAAK,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,GAAG;EAExE,MAAM,UAAU,MAAM,kBAAkB,KAAK,QAAQ,aAAa,CAAC,SAAS,WAAW,GAAG,CAAC,CAAC;EAC5F,QAAQ,IAAI,OAAO,UAAU,YAAY,SAAS,IAAI,IAAI,YAAY,IAAI,EAAE;EAC5E,QAAQ,KAAK,CAAC;CACf;CAEA,IAAI;EACH,MAAMA,WAAY,MAAM,EAAE,SAAS,KAAK,CAAC;CAC1C,SAAS,OAAO;EACf,QAAQ,MAAM,MAAM,YAAY,KAAK,CAAC;EACtC,QAAQ,KAAK,WAAW,KAAK,CAAC;CAC/B;AACD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"theme-3Fc_LI-2.js","names":[],"sources":["../src/utils/theme.ts"],"sourcesContent":["import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';\r\nimport { homedir } from 'node:os';\r\nimport { dirname, join } from 'node:path';\r\n\r\n/** Every theme a user can pick, in the order the picker lists them. `auto` follows the terminal background. */\r\nexport const THEME_SETTINGS = ['auto', 'dark', 'light', 'dark-daltonized', 'light-daltonized', 'dark-ansi', 'light-ansi'] as const;\r\nexport type ThemeSetting = (typeof THEME_SETTINGS)[number];\r\nexport type ThemeName = Exclude<ThemeSetting, 'auto'>;\r\n\r\n/**\r\n * Semantic colour roles the TUI paints with, instead of hardcoded colour names. `undefined` leaves the terminal's own\r\n * foreground colour, which is the only legible choice for body text on both dark and light backgrounds.\r\n */\r\nexport interface Theme {\r\n\t/** The wordmark, progress bar and selection marker. */\r\n\tbrand: string;\r\n\turl: string;\r\n\ttunnel: string;\r\n\t/** Something is still building or starting. */\r\n\tbusy: string;\r\n\tsuccess: string;\r\n\twarning: string;\r\n\terror: string;\r\n\ttext: string | undefined;\r\n\t/** Foreground of a badge painted on `success`, `warning` or `busy`. */\r\n\tonBright: string;\r\n\t/** Foreground of a badge painted on `error`. */\r\n\tonError: string;\r\n}\r\n\r\nexport type ThemeToken = keyof Theme;\r\n\r\nexport const THEMES: Readonly<Record<ThemeName, Theme>> = {\r\n\tdark: {\r\n\t\tbrand: '#4ade80',\r\n\t\turl: '#22d3ee',\r\n\t\ttunnel: '#e879f9',\r\n\t\tbusy: '#facc15',\r\n\t\tsuccess: '#4ade80',\r\n\t\twarning: '#facc15',\r\n\t\terror: '#f87171',\r\n\t\ttext: undefined,\r\n\t\tonBright: '#000000',\r\n\t\tonError: '#000000'\r\n\t},\r\n\tlight: {\r\n\t\tbrand: '#15803d',\r\n\t\turl: '#0e7490',\r\n\t\ttunnel: '#a21caf',\r\n\t\tbusy: '#a16207',\r\n\t\tsuccess: '#15803d',\r\n\t\twarning: '#a16207',\r\n\t\terror: '#b91c1c',\r\n\t\ttext: undefined,\r\n\t\tonBright: '#ffffff',\r\n\t\tonError: '#ffffff'\r\n\t},\r\n\t// Okabe-Ito palette: blue/orange carry the good/bad distinction instead of green/red.\r\n\t'dark-daltonized': {\r\n\t\tbrand: '#56b4e9',\r\n\t\turl: '#56b4e9',\r\n\t\ttunnel: '#cc79a7',\r\n\t\tbusy: '#f0e442',\r\n\t\tsuccess: '#56b4e9',\r\n\t\twarning: '#e69f00',\r\n\t\terror: '#ff8a3d',\r\n\t\ttext: undefined,\r\n\t\tonBright: '#000000',\r\n\t\tonError: '#000000'\r\n\t},\r\n\t'light-daltonized': {\r\n\t\tbrand: '#0072b2',\r\n\t\turl: '#0072b2',\r\n\t\ttunnel: '#8e3b76',\r\n\t\tbusy: '#8a6500',\r\n\t\tsuccess: '#0072b2',\r\n\t\twarning: '#8a6500',\r\n\t\terror: '#b84a00',\r\n\t\ttext: undefined,\r\n\t\tonBright: '#ffffff',\r\n\t\tonError: '#ffffff'\r\n\t},\r\n\t// The 16 ANSI colours only, so the terminal's own palette decides what they look like.\r\n\t'dark-ansi': {\r\n\t\tbrand: 'greenBright',\r\n\t\turl: 'cyanBright',\r\n\t\ttunnel: 'magentaBright',\r\n\t\tbusy: 'yellowBright',\r\n\t\tsuccess: 'greenBright',\r\n\t\twarning: 'yellowBright',\r\n\t\terror: 'redBright',\r\n\t\ttext: undefined,\r\n\t\tonBright: 'black',\r\n\t\tonError: 'black'\r\n\t},\r\n\t'light-ansi': {\r\n\t\tbrand: 'green',\r\n\t\turl: 'cyan',\r\n\t\ttunnel: 'magenta',\r\n\t\tbusy: 'yellow',\r\n\t\tsuccess: 'green',\r\n\t\twarning: 'yellow',\r\n\t\terror: 'red',\r\n\t\ttext: undefined,\r\n\t\tonBright: 'white',\r\n\t\tonError: 'white'\r\n\t}\r\n};\r\n\r\nexport function isThemeSetting(value: unknown): value is ThemeSetting {\r\n\treturn typeof value === 'string' && (THEME_SETTINGS as readonly string[]).includes(value);\r\n}\r\n\r\n/**\r\n * Guesses whether the terminal background is light from `COLORFGBG` (`foreground;background`, set by rxvt, Konsole and\r\n * others). Without it the terminal is assumed dark, which matches most developer setups.\r\n */\r\nexport function detectTerminalBackground(env: NodeJS.ProcessEnv = process.env): 'dark' | 'light' {\r\n\tconst background = env.COLORFGBG?.split(';').at(-1);\r\n\tif (background === undefined || !/^\\d+$/.test(background)) return 'dark';\r\n\tconst index = Number(background);\r\n\treturn index === 7 || index === 15 ? 'light' : 'dark';\r\n}\r\n\r\nexport function resolveTheme(setting: ThemeSetting, env: NodeJS.ProcessEnv = process.env): ThemeName {\r\n\treturn setting === 'auto' ? detectTerminalBackground(env) : setting;\r\n}\r\n\r\nexport interface ThemeSettingSources {\r\n\t/** `--theme`. */\r\n\tflag?: string;\r\n\tenv?: NodeJS.ProcessEnv;\r\n\t/** The theme saved by the picker. */\r\n\tsaved?: ThemeSetting;\r\n}\r\n\r\n/**\r\n * Precedence: `--theme` › `STARS_THEME` › the saved preference › `auto`. An unknown `STARS_THEME` is ignored, since an\r\n * environment variable should not stop the dev server; an unknown `--theme` is the caller's to reject.\r\n */\r\nexport function resolveThemeSetting({ flag, env = process.env, saved }: ThemeSettingSources): ThemeSetting {\r\n\tif (isThemeSetting(flag)) return flag;\r\n\tconst fromEnv = env.STARS_THEME?.trim().toLowerCase();\r\n\tif (isThemeSetting(fromEnv)) return fromEnv;\r\n\treturn saved ?? 'auto';\r\n}\r\n\r\n/** Where preferences live: `$STARS_CONFIG_DIR`, else `$XDG_CONFIG_HOME/stars`, `%APPDATA%\\stars` or `~/.config/stars`. */\r\nexport function preferencesPath(env: NodeJS.ProcessEnv = process.env): string {\r\n\tconst directory =\r\n\t\tenv.STARS_CONFIG_DIR ??\r\n\t\tjoin((env.XDG_CONFIG_HOME || (process.platform === 'win32' ? env.APPDATA : undefined)) ?? join(homedir(), '.config'), 'stars');\r\n\treturn join(directory, 'preferences.json');\r\n}\r\n\r\nexport function readSavedTheme(env: NodeJS.ProcessEnv = process.env): ThemeSetting | undefined {\r\n\ttry {\r\n\t\tconst { theme } = JSON.parse(readFileSync(preferencesPath(env), 'utf8')) as { theme?: unknown };\r\n\t\treturn isThemeSetting(theme) ? theme : undefined;\r\n\t} catch {\r\n\t\treturn undefined;\r\n\t}\r\n}\r\n\r\n/** Persists the theme, keeping any other preference in the file. Returns whether it could be written. */\r\nexport function saveTheme(setting: ThemeSetting, env: NodeJS.ProcessEnv = process.env): boolean {\r\n\tconst path = preferencesPath(env);\r\n\ttry {\r\n\t\tlet existing: Record<string, unknown> = {};\r\n\t\ttry {\r\n\t\t\tconst parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));\r\n\t\t\tif (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) existing = parsed as Record<string, unknown>;\r\n\t\t} catch {\r\n\t\t\t// No file yet, or a corrupt one: start over.\r\n\t\t}\r\n\t\tmkdirSync(dirname(path), { recursive: true });\r\n\t\twriteFileSync(path, `${JSON.stringify({ ...existing, theme: setting }, null, '\\t')}\\n`);\r\n\t\treturn true;\r\n\t} catch {\r\n\t\treturn false;\r\n\t}\r\n}\r\n"],"mappings":"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"}
|
package/dist/tsc-B931Ezh7.js
DELETED
package/dist/tsc-DEBcwIO0.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tsc-DEBcwIO0.js","names":[],"sources":["../src/utils/process-supervisor.ts","../src/builders/tsc.ts"],"sourcesContent":["import { spawn, type ChildProcess } from 'node:child_process';\r\nimport { EventEmitter } from 'node:events';\r\n\r\nexport type ProcessState = 'idle' | 'starting' | 'running' | 'stopping' | 'stopped' | 'crashed';\r\n\r\nexport interface ProcessExit {\r\n\tcode: number | null;\r\n\tsignal: NodeJS.Signals | null;\r\n\t/** Whether the exit was requested through {@link ProcessSupervisor.stop}. */\r\n\trequested: boolean;\r\n}\r\n\r\nexport interface ProcessSupervisorOptions {\r\n\tcommand: string;\r\n\targs: readonly string[];\r\n\tcwd: string;\r\n\tenv: NodeJS.ProcessEnv;\r\n\t/** Milliseconds to wait after `SIGTERM` before sending `SIGKILL`. */\r\n\tkillTimeout: number;\r\n}\r\n\r\nexport interface ProcessSupervisorEvents {\r\n\tstate: [state: ProcessState];\r\n\tstdout: [line: string];\r\n\tstderr: [line: string];\r\n\texit: [exit: ProcessExit];\r\n\terror: [error: Error];\r\n}\r\n\r\n/**\r\n * Owns a single child process: starts it, streams its output line by line and stops it gracefully.\r\n */\r\nexport class ProcessSupervisor extends EventEmitter<ProcessSupervisorEvents> {\r\n\t#child: ChildProcess | null = null;\r\n\t#state: ProcessState = 'idle';\r\n\t#startedAt: number | null = null;\r\n\t#stopping: Promise<void> | null = null;\r\n\r\n\tpublic constructor(private readonly options: ProcessSupervisorOptions) {\r\n\t\tsuper();\r\n\t}\r\n\r\n\tpublic get state(): ProcessState {\r\n\t\treturn this.#state;\r\n\t}\r\n\r\n\tpublic get pid(): number | null {\r\n\t\treturn this.#child?.pid ?? null;\r\n\t}\r\n\r\n\tpublic get startedAt(): number | null {\r\n\t\treturn this.#startedAt;\r\n\t}\r\n\r\n\tpublic get running(): boolean {\r\n\t\treturn this.#state === 'starting' || this.#state === 'running';\r\n\t}\r\n\r\n\tpublic start(): void {\r\n\t\tif (this.#child) throw new Error('The process is already running, call stop() or restart() first.');\r\n\r\n\t\tconst { command, args, cwd, env } = this.options;\r\n\t\tthis.#setState('starting');\r\n\r\n\t\tconst child = spawn(command, args, { cwd, env, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });\r\n\t\tthis.#child = child;\r\n\t\tthis.#startedAt = Date.now();\r\n\r\n\t\tlet requested = false;\r\n\t\tconst stdout = createLineSplitter((line) => this.emit('stdout', line));\r\n\t\tconst stderr = createLineSplitter((line) => this.emit('stderr', line));\r\n\t\tchild.stdout?.on('data', stdout.push);\r\n\t\tchild.stderr?.on('data', stderr.push);\r\n\r\n\t\tchild.once('spawn', () => {\r\n\t\t\tif (this.#child === child) this.#setState('running');\r\n\t\t});\r\n\r\n\t\tchild.once('error', (error) => {\r\n\t\t\tthis.emit('error', error);\r\n\t\t});\r\n\r\n\t\tchild.once('exit', (code, signal) => {\r\n\t\t\tstdout.flush();\r\n\t\t\tstderr.flush();\r\n\t\t\trequested = this.#state === 'stopping';\r\n\t\t\tthis.#child = null;\r\n\t\t\tthis.#startedAt = null;\r\n\t\t\tthis.#setState(requested || code === 0 ? 'stopped' : 'crashed');\r\n\t\t\tthis.emit('exit', { code, signal, requested });\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Sends `SIGTERM`, escalates to `SIGKILL` after `killTimeout` and resolves once the process exited.\r\n\t */\r\n\tpublic stop(): Promise<void> {\r\n\t\tconst child = this.#child;\r\n\t\tif (!child) return Promise.resolve();\r\n\t\tif (this.#stopping) return this.#stopping;\r\n\r\n\t\tthis.#setState('stopping');\r\n\t\tthis.#stopping = new Promise<void>((resolve) => {\r\n\t\t\tconst timer = setTimeout(() => {\r\n\t\t\t\tif (child.exitCode === null && child.signalCode === null) child.kill('SIGKILL');\r\n\t\t\t}, this.options.killTimeout);\r\n\t\t\ttimer.unref();\r\n\r\n\t\t\tchild.once('exit', () => {\r\n\t\t\t\tclearTimeout(timer);\r\n\t\t\t\tthis.#stopping = null;\r\n\t\t\t\tresolve();\r\n\t\t\t});\r\n\r\n\t\t\tif (!child.kill('SIGTERM')) {\r\n\t\t\t\tclearTimeout(timer);\r\n\t\t\t\tthis.#stopping = null;\r\n\t\t\t\tresolve();\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\treturn this.#stopping;\r\n\t}\r\n\r\n\t/**\r\n\t * Sends `SIGKILL` right away, without waiting for the process to exit. Used to force a shutdown that is taking too long.\r\n\t */\r\n\tpublic kill(): void {\r\n\t\tconst child = this.#child;\r\n\t\tif (child && child.exitCode === null && child.signalCode === null) child.kill('SIGKILL');\r\n\t}\r\n\r\n\tpublic async restart(): Promise<void> {\r\n\t\tawait this.stop();\r\n\t\tthis.start();\r\n\t}\r\n\r\n\t#setState(state: ProcessState): void {\r\n\t\tif (this.#state === state) return;\r\n\t\tthis.#state = state;\r\n\t\tthis.emit('state', state);\r\n\t}\r\n}\r\n\r\n/**\r\n * Splits a byte stream into complete lines, keeping the trailing partial line until the next chunk.\r\n */\r\nexport function createLineSplitter(onLine: (line: string) => void) {\r\n\tlet remainder = '';\r\n\treturn {\r\n\t\tpush(chunk: Buffer | string) {\r\n\t\t\tremainder += chunk.toString();\r\n\t\t\tconst lines = remainder.split(/\\r?\\n/);\r\n\t\t\tremainder = lines.pop() ?? '';\r\n\t\t\tfor (const line of lines) onLine(line);\r\n\t\t},\r\n\t\tflush() {\r\n\t\t\tif (remainder.length > 0) onLine(remainder);\r\n\t\t\tremainder = '';\r\n\t\t}\r\n\t};\r\n}\r\n","import { spawn, type ChildProcess } from 'node:child_process';\r\nimport { EventEmitter } from 'node:events';\r\nimport type { ResolvedStarsConfig } from '@wolfstar/schema';\r\nimport { cliDiagnostics } from '../utils/diagnostics.js';\r\nimport { createLineSplitter } from '../utils/process-supervisor.js';\r\nimport { resolveBinary } from '../utils/project.js';\r\nimport type { Builder, BuilderEvents, BuildOutcome } from './types.js';\r\n\r\nconst INSTALL_HINT = \"Install it with `pnpm add -D typescript`, or set `build.tool` to 'tsdown' or 'none'.\";\r\nconst WATCH_START = /Starting (incremental )?compilation/;\r\nconst WATCH_DONE = /Found (\\d+) errors?\\. Watching for file changes/;\r\nconst ERROR_LINE = /error TS\\d+:/;\r\n\r\n/**\r\n * Builds through the project's `tsc -b`, parsing its output to report progress.\r\n */\r\nexport class TscBuilder extends EventEmitter<BuilderEvents> implements Builder {\r\n\tpublic readonly tool = 'tsc' as const;\r\n\t#child: ChildProcess | null = null;\r\n\t#startedAt = 0;\r\n\t#firstError: string | null = null;\r\n\r\n\tpublic constructor(private readonly config: ResolvedStarsConfig) {\r\n\t\tsuper();\r\n\t}\r\n\r\n\tpublic build(): Promise<BuildOutcome> {\r\n\t\tconst child = this.#spawn([]);\r\n\t\tthis.#begin();\r\n\r\n\t\treturn new Promise((resolve) => {\r\n\t\t\tchild.once('exit', (code) => {\r\n\t\t\t\tthis.#child = null;\r\n\t\t\t\tresolve(this.#finish(code === 0 ? null : (this.#firstError ?? `tsc exited with code ${code}`)));\r\n\t\t\t});\r\n\t\t});\r\n\t}\r\n\r\n\tpublic watch(): Promise<void> {\r\n\t\tthis.#spawn(['--watch', '--preserveWatchOutput']);\r\n\t\tthis.#begin();\r\n\t\treturn Promise.resolve();\r\n\t}\r\n\r\n\tpublic close(): Promise<void> {\r\n\t\tconst child = this.#child;\r\n\t\tthis.#child = null;\r\n\t\tif (!child || child.exitCode !== null) return Promise.resolve();\r\n\r\n\t\treturn new Promise((resolve) => {\r\n\t\t\tchild.once('exit', () => resolve());\r\n\t\t\tchild.kill();\r\n\t\t});\r\n\t}\r\n\r\n\t#spawn(extraArgs: string[]): ChildProcess {\r\n\t\tconst tsc = resolveTscBinary(this.config.root);\r\n\t\tif (!tsc) throw cliDiagnostics.DEPENDENCY_MISSING({ name: 'typescript', root: this.config.root, hint: INSTALL_HINT });\r\n\r\n\t\tconst child = spawn(process.execPath, [tsc, '-b', this.config.build.tsconfig!, '--pretty', 'false', ...extraArgs], {\r\n\t\t\tcwd: this.config.root,\r\n\t\t\tenv: process.env,\r\n\t\t\tstdio: ['ignore', 'pipe', 'pipe'],\r\n\t\t\twindowsHide: true\r\n\t\t});\r\n\t\tthis.#child = child;\r\n\r\n\t\tconst handleLine = (line: string) => this.#handleLine(line);\r\n\t\tconst stdout = createLineSplitter(handleLine);\r\n\t\tconst stderr = createLineSplitter(handleLine);\r\n\t\tchild.stdout?.on('data', stdout.push);\r\n\t\tchild.stderr?.on('data', stderr.push);\r\n\t\tchild.once('exit', () => {\r\n\t\t\tstdout.flush();\r\n\t\t\tstderr.flush();\r\n\t\t});\r\n\t\tchild.once('error', (error) => this.emit('log', 'error', error.message));\r\n\r\n\t\treturn child;\r\n\t}\r\n\r\n\t#handleLine(line: string): void {\r\n\t\tconst text = line.trim();\r\n\t\tif (text.length === 0) return;\r\n\r\n\t\tif (WATCH_START.test(text)) {\r\n\t\t\tif (this.#startedAt === 0) this.#begin();\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (ERROR_LINE.test(text)) {\r\n\t\t\tthis.#firstError ??= text;\r\n\t\t\tthis.emit('log', 'error', text);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst done = WATCH_DONE.exec(text);\r\n\t\tif (done) {\r\n\t\t\tconst errors = Number(done[1]);\r\n\t\t\tthis.emit('log', errors === 0 ? 'success' : 'error', text);\r\n\t\t\tthis.#finish(errors === 0 ? null : (this.#firstError ?? text));\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tthis.emit('log', 'info', text);\r\n\t}\r\n\r\n\t#begin(): void {\r\n\t\tthis.#firstError = null;\r\n\t\tthis.#startedAt = performance.now();\r\n\t\tthis.emit('start');\r\n\t}\r\n\r\n\t#finish(message: string | null): BuildOutcome {\r\n\t\tconst outcome: BuildOutcome = { ok: message === null, durationMs: Math.round(performance.now() - this.#startedAt), message };\r\n\t\tthis.#startedAt = 0;\r\n\t\tthis.emit(outcome.ok ? 'success' : 'failure', outcome);\r\n\t\treturn outcome;\r\n\t}\r\n}\r\n\r\n/**\r\n * Locates the `tsc` script of the project's TypeScript through its `package.json#bin`, which works for both the\r\n * classic `lib/tsc.js` layout (TypeScript ≤ 6) and the native `bin/tsc` launcher (TypeScript 7, whose `exports` map\r\n * hides `lib/`).\r\n */\r\nexport function resolveTscBinary(root: string): string | null {\r\n\treturn resolveBinary(root, 'typescript', 'tsc');\r\n}\r\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tsdown-DrWXld54.js","names":[],"sources":["../src/builders/tsdown.ts"],"sourcesContent":["import { EventEmitter } from 'node:events';\r\nimport { dirname, extname, relative, resolve } from 'node:path';\r\nimport type { ResolvedStarsConfig } from '@wolfstar/schema';\r\nimport { loadAutoImportsModule } from '../utils/framework-auto-imports.js';\r\nimport type { StarsHookable } from '../utils/hooks.js';\r\nimport { pluginRegistrations } from '../utils/plugin-registrations.js';\r\nimport { importFromProject } from '../utils/project.js';\r\nimport type { Builder, BuilderEvents, BuildOutcome } from './types.js';\r\n\r\ntype TsdownModule = typeof import('tsdown');\r\ntype TsdownLogger = import('tsdown').Logger;\r\ntype TsdownHandle = import('tsdown').TsdownHandle;\r\ntype TsdownInlineConfig = NonNullable<Parameters<TsdownModule['build']>[0]>;\r\ntype TsdownOptions = Record<string, unknown>;\r\ntype AnyFunction = (...args: never[]) => unknown;\r\n\r\nconst INSTALL_HINT = \"Install it with `pnpm add -D tsdown`, or set `build.tool` to 'tsc' or 'none'.\";\r\nconst TYPESCRIPT_EXTENSIONS = new Set(['.ts', '.mts', '.cts']);\r\n/** `./src/lib` and `../shared` are paths; `preact/compat` is a module id and must be left alone. */\r\nconst RELATIVE_PATH = /^\\.\\.?[/\\\\]/;\r\n\r\n/**\r\n * Builds through the project's own `tsdown`, configured from `stars.config`.\r\n *\r\n * From `future.compatibilityVersion` 4 on this is the whole configuration: the entry's directory, `build.outDir` and\r\n * `build.tsconfig` produce the defaults a bot needs, the project's `tsdown` block is layered on top, and the auto\r\n * imports plugin is wired in — one configuration file instead of two. At 3 the project's own `tsdown.config.*` is\r\n * still loaded and everything here is merged over it by `tsdown` itself: scalars from `stars.config` win, and\r\n * `plugins` are appended rather than replaced.\r\n */\r\nexport class TsdownBuilder extends EventEmitter<BuilderEvents> implements Builder {\r\n\tpublic readonly tool = 'tsdown' as const;\r\n\t#handle: TsdownHandle | null = null;\r\n\t#hadError = false;\r\n\t#startedAt = 0;\r\n\r\n\tpublic constructor(\r\n\t\tprivate readonly config: ResolvedStarsConfig,\r\n\t\tprivate readonly hooks?: StarsHookable\r\n\t) {\r\n\t\tsuper();\r\n\t}\r\n\r\n\tpublic async build(): Promise<BuildOutcome> {\r\n\t\tconst tsdown = await this.#load();\r\n\t\tconst options = await this.#options();\r\n\t\tthis.#begin();\r\n\r\n\t\ttry {\r\n\t\t\tthis.#handle = await tsdown.build(options as TsdownInlineConfig);\r\n\t\t\treturn this.#finish(this.#hadError ? 'The build reported errors' : null);\r\n\t\t} catch (error) {\r\n\t\t\treturn this.#finish(error instanceof Error ? error.message : String(error));\r\n\t\t}\r\n\t}\r\n\r\n\tpublic async watch(): Promise<void> {\r\n\t\tconst tsdown = await this.#load();\r\n\t\tconst options = await this.#options();\r\n\r\n\t\tthis.#begin();\r\n\t\tthis.#handle = await tsdown.build(this.#watchOptions(options) as TsdownInlineConfig);\r\n\t}\r\n\r\n\tpublic async close(): Promise<void> {\r\n\t\tconst handle = this.#handle;\r\n\t\tthis.#handle = null;\r\n\t\tawait handle?.watch.close();\r\n\t}\r\n\r\n\t#load(): Promise<TsdownModule> {\r\n\t\treturn importFromProject<TsdownModule>(this.config.root, 'tsdown', INSTALL_HINT);\r\n\t}\r\n\r\n\t/**\r\n\t * The options handed to `tsdown.build()`, with the project's own `tsdown` block already layered on top of the\r\n\t * defaults (and of the plugins `stars` contributes).\r\n\t */\r\n\tasync #options(): Promise<TsdownOptions> {\r\n\t\tconst user = this.config.tsdown as TsdownOptions;\r\n\t\t// A `tsdown.config.*` (or `package.json#tsdown`) is the project's own; `build.configFile` is `null` from\r\n\t\t// compatibility version 4 on, where loading one is a configuration error rather than a fallback.\r\n\t\tconst defaults = this.config.build.configFile === null ? this.#defaults() : {};\r\n\t\tconst plugins = [pluginRegistrations(this.config), ...(await this.#plugins()), ...toArray(user.plugins)];\r\n\t\t// `plugins` and `alias` are added to rather than replaced: a project declaring one of its own would\r\n\t\t// otherwise silently drop the auto imports transform, or every `~`/`@` import in its sources.\r\n\t\tconst alias = { ...(defaults.alias as object), ...this.#alias(user.alias) };\r\n\r\n\t\tconst options: TsdownOptions = {\r\n\t\t\t...defaults,\r\n\t\t\t...user,\r\n\t\t\t...(plugins.length > 0 ? { plugins } : {}),\r\n\t\t\t...(Object.keys(alias).length > 0 ? { alias } : {})\r\n\t\t};\r\n\t\tawait this.hooks?.callHook('tsdown:options', options, this.config);\r\n\r\n\t\treturn {\r\n\t\t\t...options,\r\n\t\t\t// Last, and so not overridable (not even by `tsdown:options`): these are how the CLI talks to `tsdown` rather\r\n\t\t\t// than project build options — the project root it resolves from, its own compact progress UI, and the logger\r\n\t\t\t// that feeds diagnostics to the dev panel. `logLevel` also covers the few lifecycle messages tsdown writes\r\n\t\t\t// through its global logger.\r\n\t\t\tcwd: this.config.root,\r\n\t\t\tlogLevel: 'warn',\r\n\t\t\tcustomLogger: this.#logger()\r\n\t\t};\r\n\t}\r\n\r\n\t/**\r\n\t * What `stars.config` alone says the build is — the configuration a bot would otherwise write out by hand, taken\r\n\t * from the ones the WolfStar bots already keep next to theirs:\r\n\t *\r\n\t * - every source file next to the entry (minus tests), emitted one-to-one (`unbundle`) so the stores keep\r\n\t * loading pieces from `dist/commands` and friends at runtime;\r\n\t * - ESM on `platform: 'node'`, with the extension `build.output` — and so `stars dev`, `package.json#main` and\r\n\t * `node dist/…` — expects;\r\n\t * - sourcemaps and treeshaking on, minification off: a bot is deployed, not shipped, so readable stack traces\r\n\t * are worth more than bytes;\r\n\t * - dependencies left in `node_modules` rather than bundled into the output;\r\n\t * - Nuxt's own alias prefixes: `~` and `@` for the entry's directory, `~~` and `@@` for the project root;\r\n\t * - no declaration files: nothing consumes a bot's `dist/`, and emitting them roughly doubles the build. A\r\n\t * project that wants them sets `tsdown: { dts: true }`.\r\n\t *\r\n\t * Every one of these is overridable through the project's `tsdown` block.\r\n\t */\r\n\t#defaults(): TsdownOptions {\r\n\t\tconst { root, entry, build } = this.config;\r\n\t\tconst source = dirname(entry);\r\n\t\tconst sourceDir = relative(root, source) || '.';\r\n\t\tconst extensions = TYPESCRIPT_EXTENSIONS.has(extname(entry)) ? '{ts,mts,cts}' : '{js,mjs,cjs}';\r\n\r\n\t\treturn {\r\n\t\t\tconfig: false,\r\n\t\t\tentry: [`${sourceDir}/**/*.${extensions}`, `!${sourceDir}/**/*.{test,spec}.${extensions}`],\r\n\t\t\t// The prefixes Nuxt gives every project, pointing at the same two places its own do: the source\r\n\t\t\t// directory and the project root. A project's tsconfig needs the matching `paths` for them to type.\r\n\t\t\talias: { '~': source, '@': source, '~~': root, '@@': root },\r\n\t\t\tformat: 'esm',\r\n\t\t\tplatform: 'node',\r\n\t\t\tunbundle: true,\r\n\t\t\toutDir: build.outDir,\r\n\t\t\toutExtensions: () => ({ js: extname(build.output) }),\r\n\t\t\tsourcemap: true,\r\n\t\t\tclean: true,\r\n\t\t\ttreeshake: true,\r\n\t\t\tminify: false,\r\n\t\t\tdts: false,\r\n\t\t\tdeps: { neverBundle: true },\r\n\t\t\t...(build.tsconfig === null ? {} : { tsconfig: build.tsconfig })\r\n\t\t};\r\n\t}\r\n\r\n\t/**\r\n\t * The project's own aliases, with relative targets resolved against the project root the way every other path in\r\n\t * `stars.config` is. Module ids (`preact/compat`) and absolute paths are passed through untouched.\r\n\t */\r\n\t#alias(alias: unknown): Record<string, unknown> {\r\n\t\tif (alias === null || typeof alias !== 'object' || Array.isArray(alias)) return {};\r\n\r\n\t\treturn Object.fromEntries(\r\n\t\t\tObject.entries(alias as Record<string, unknown>).map(([key, value]) => [\r\n\t\t\t\tkey,\r\n\t\t\t\ttypeof value === 'string' && RELATIVE_PATH.test(value) ? resolve(this.config.root, value) : value\r\n\t\t\t])\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * The auto imports transform, the way `nuxt dev` wires its own into the build rather than asking the project to.\r\n\t * `stars dev`/`stars build` regenerate its declaration file (`stars prepare`) before the first build.\r\n\t */\r\n\tasync #plugins(): Promise<unknown[]> {\r\n\t\tif (!this.config.imports.enabled) return [];\r\n\r\n\t\tconst { autoImports } = await loadAutoImportsModule(this.config.root);\r\n\t\tconst { dirs, presets, exclude, dts } = this.config.imports;\r\n\t\treturn [await autoImports({ root: this.config.root, dirs, presets, exclude, dts })];\r\n\t}\r\n\r\n\t/**\r\n\t * Watch mode reports through the same events a single build does. The project's own `hooks`/`onSuccess` still\r\n\t * run: they are the reason a build is watched at all in some projects.\r\n\t */\r\n\t#watchOptions(options: TsdownOptions): TsdownOptions {\r\n\t\tconst hooks = (options.hooks ?? {}) as Record<string, unknown>;\r\n\t\tconst prepare = hooks['build:prepare'];\r\n\t\tconst before = hooks['build:before'];\r\n\t\tconst done = hooks['build:done'];\r\n\t\tconst success = options.onSuccess;\r\n\r\n\t\treturn {\r\n\t\t\t...options,\r\n\t\t\twatch: true,\r\n\t\t\t// tsdown's build:before runs once when the watcher is configured, not on every rebuild. Rolldown's\r\n\t\t\t// buildStart is the actual per-build boundary, including recovery after a failed compilation.\r\n\t\t\tplugins: [\r\n\t\t\t\t{\r\n\t\t\t\t\tname: 'stars:dev-progress',\r\n\t\t\t\t\tbuildStart: () => {\r\n\t\t\t\t\t\tif (this.#startedAt === 0) this.#begin();\r\n\t\t\t\t\t\tthis.emit('progress', 0.25, 'bundling app');\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\t...toArray(options.plugins)\r\n\t\t\t],\r\n\t\t\thooks: {\r\n\t\t\t\t...hooks,\r\n\t\t\t\t'build:prepare': async (...args: never[]) => {\r\n\t\t\t\t\tif (this.#startedAt === 0) this.#begin();\r\n\t\t\t\t\tif (typeof prepare === 'function') await (prepare as AnyFunction)(...args);\r\n\t\t\t\t},\r\n\t\t\t\t'build:before': async (...args: never[]) => {\r\n\t\t\t\t\tif (typeof before === 'function') await (before as AnyFunction)(...args);\r\n\t\t\t\t},\r\n\t\t\t\t'build:done': async (...args: never[]) => {\r\n\t\t\t\t\tthis.emit('progress', 0.5, 'finishing build');\r\n\t\t\t\t\tif (typeof done === 'function') await (done as AnyFunction)(...args);\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tonSuccess: async (...args: never[]) => {\r\n\t\t\t\tif (typeof success === 'function') await (success as AnyFunction)(...args);\r\n\t\t\t\tthis.#finish(null);\r\n\t\t\t}\r\n\t\t};\r\n\t}\r\n\r\n\t#begin(): void {\r\n\t\tthis.#hadError = false;\r\n\t\tthis.#startedAt = performance.now();\r\n\t\tthis.emit('start');\r\n\t}\r\n\r\n\t#finish(message: string | null): BuildOutcome {\r\n\t\tconst outcome: BuildOutcome = {\r\n\t\t\tok: message === null && !this.#hadError,\r\n\t\t\tdurationMs: Math.round(performance.now() - this.#startedAt),\r\n\t\t\tmessage\r\n\t\t};\r\n\t\tthis.#startedAt = 0;\r\n\t\tthis.emit(outcome.ok ? 'success' : 'failure', outcome);\r\n\t\treturn outcome;\r\n\t}\r\n\r\n\t#logger(): TsdownLogger {\r\n\t\tconst log = (level: 'info' | 'warn' | 'error' | 'success', args: unknown[]) => {\r\n\t\t\t// tsdown passes its (possibly undefined) name label and other blanks as separate arguments.\r\n\t\t\tconst text = args\r\n\t\t\t\t.filter((argument) => argument !== undefined && argument !== null && argument !== false && argument !== '')\r\n\t\t\t\t.map((argument) => (argument instanceof Error ? (argument.stack ?? argument.message) : String(argument)))\r\n\t\t\t\t.join(' ');\r\n\t\t\tthis.emit('log', level, text);\r\n\t\t};\r\n\r\n\t\tconst warned = new Set<string>();\r\n\t\treturn {\r\n\t\t\t// `stars` owns the build progress and completion messages. Keeping tsdown at `warn` avoids copying its\r\n\t\t\t// entry list, target, output table and completion line into the dev session while preserving diagnostics\r\n\t\t\t// that need action from the project.\r\n\t\t\tlevel: 'warn',\r\n\t\t\tinfo: () => {},\r\n\t\t\twarn: (...args) => log('warn', args),\r\n\t\t\twarnOnce: (...args) => {\r\n\t\t\t\tconst key = args.map(String).join(' ');\r\n\t\t\t\tif (warned.has(key)) return;\r\n\t\t\t\twarned.add(key);\r\n\t\t\t\tlog('warn', args);\r\n\t\t\t},\r\n\t\t\terror: (...args) => {\r\n\t\t\t\tthis.#hadError = true;\r\n\t\t\t\tlog('error', args);\r\n\t\t\t\t// In watch mode tsdown never calls `onSuccess` after an error, report the failure now.\r\n\t\t\t\tif (this.#startedAt !== 0) this.#finish(errorSummary(args));\r\n\t\t\t},\r\n\t\t\tsuccess: () => {},\r\n\t\t\tclearScreen: () => {}\r\n\t\t};\r\n\t}\r\n}\r\n\r\nfunction toArray(value: unknown): unknown[] {\r\n\tif (value === undefined || value === null || value === false) return [];\r\n\treturn Array.isArray(value) ? value : [value];\r\n}\r\n\r\nfunction errorSummary(args: unknown[]): string {\r\n\tconst first = args[0];\r\n\tif (first instanceof Error) return first.message.split('\\n')[0] ?? 'Build failed';\r\n\treturn String(first ?? 'Build failed').split('\\n')[0] ?? 'Build failed';\r\n}\r\n"],"mappings":"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"}
|
package/dist/tui-BRddrLQP.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tui-BRddrLQP.js","names":[],"sources":["../src/dev/tui/ink/theme.tsx","../src/dev/tui/ink/components/HelpOverlay.tsx","../src/dev/tui/ink/hooks/useLogVersion.ts","../src/dev/tui/ink/components/Hints.tsx","../src/dev/tui/ink/components/LogBrowser.tsx","../src/dev/tui/ink/hooks/useDevStatus.ts","../src/dev/tui/ink/hooks/useUptime.ts","../src/dev/tui/panel-logic.ts","../src/dev/tui/ink/components/InfoOverlay.tsx","../src/dev/tui/ink/components/Panel.tsx","../src/dev/tui/ink/hooks/useLogCounters.ts","../src/dev/tui/ink/hooks/useBuildClock.ts","../src/dev/open-url.ts","../src/dev/tui/ink/components/ThemeOverlay.tsx","../src/dev/tui/ink/DevApp.tsx","../src/dev/tui/capture-output.ts","../src/dev/tui/tui.tsx"],"sourcesContent":["import { createContext, useContext, type ReactNode } from 'react';\r\nimport { THEMES, type ThemeName, type ThemeToken } from '../../../utils/theme.js';\r\n\r\ninterface ThemeState {\r\n\t/** Whether the UI may use colour. */\r\n\tcolor: boolean;\r\n\ttheme: ThemeName;\r\n}\r\n\r\n/**\r\n * `stars dev` decides once whether the UI may use colour (`NO_COLOR`, `FORCE_COLOR`, TTY detection) and which theme\r\n * to paint with; every component reads both from here instead of re-deriving them.\r\n */\r\nconst ThemeContext = createContext<ThemeState>({ color: true, theme: 'dark' });\r\n\r\nexport function ThemeProvider({ color, theme, children }: ThemeState & { children: ReactNode }) {\r\n\treturn <ThemeContext value={{ color, theme }}>{children}</ThemeContext>;\r\n}\r\n\r\n/**\r\n * Returns a theme colour only when colour is enabled, so `<Text color={usePaint()('success')}>` degrades to plain text.\r\n */\r\nexport function usePaint(): (token: ThemeToken) => string | undefined {\r\n\tconst { color, theme } = useContext(ThemeContext);\r\n\treturn (token) => (color ? THEMES[theme][token] : undefined);\r\n}\r\n\r\nexport function useColorEnabled(): boolean {\r\n\treturn useContext(ThemeContext).color;\r\n}\r\n","import { Box, Text, useInput } from 'ink';\r\nimport { usePaint } from '../theme.js';\r\n\r\nconst KEYS: [string, string][] = [\r\n\t['r', 'restart the bot now'],\r\n\t['o', 'open the local URL in a browser'],\r\n\t['t', 'toggle the public tunnel'],\r\n\t['i', 'show versions, URLs and session info'],\r\n\t['T', 'pick a colour theme (dark, light, colour-blind friendly, ANSI)'],\r\n\t['l', 'open the logs (scroll, filter by source or level)'],\r\n\t['e', 'jump to the last error, keeping its context'],\r\n\t['c / Ctrl+L', 'clear the log history'],\r\n\t['q / Ctrl+C', 'stop the bot and quit'],\r\n\t['?', 'toggle this help']\r\n];\r\n\r\nexport interface HelpOverlayProps {\r\n\theight: number;\r\n\twidth: number;\r\n\tonClose: () => void;\r\n}\r\n\r\n/** The static keys reference, opened with `?` from the pinned panel. */\r\nexport function HelpOverlay({ height, width, onClose }: HelpOverlayProps) {\r\n\tconst paint = usePaint();\r\n\tuseInput((input, key) => {\r\n\t\tif (!key.ctrl && (key.escape || ['q', 'h', '?'].includes(input))) onClose();\r\n\t});\r\n\r\n\treturn (\r\n\t\t<Box flexDirection=\"column\" height={height}>\r\n\t\t\t<Text bold> keyboard shortcuts</Text>\r\n\t\t\t<Text dimColor>{'─'.repeat(width)}</Text>\r\n\t\t\t{KEYS.slice(0, Math.max(0, height - 3)).map(([key, description]) => (\r\n\t\t\t\t<Text key={key} wrap=\"truncate-end\">\r\n\t\t\t\t\t{' '}\r\n\t\t\t\t\t<Text bold color={paint('text')}>\r\n\t\t\t\t\t\t{key.padEnd(14)}\r\n\t\t\t\t\t</Text>\r\n\t\t\t\t\t<Text dimColor>{description}</Text>\r\n\t\t\t\t</Text>\r\n\t\t\t))}\r\n\t\t\t<Box flexGrow={1} />\r\n\t\t\t<Text dimColor> q close</Text>\r\n\t\t</Box>\r\n\t);\r\n}\r\n","import { useEffect, useState } from 'react';\r\nimport type { LogBuffer } from '../../../../utils/log-buffer.js';\r\n\r\n/** Bumps whenever the buffer changes, so a consumer can re-derive a filtered view without re-filtering on every render. */\r\nexport function useLogVersion(logs: LogBuffer): number {\r\n\tconst [version, setVersion] = useState(0);\r\n\r\n\tuseEffect(() => {\r\n\t\tconst bump = () => setVersion((current) => current + 1);\r\n\t\tlogs.on('entry', bump);\r\n\t\tlogs.on('clear', bump);\r\n\t\tbump();\r\n\t\treturn () => {\r\n\t\t\tlogs.off('entry', bump);\r\n\t\t\tlogs.off('clear', bump);\r\n\t\t};\r\n\t}, [logs]);\r\n\r\n\treturn version;\r\n}\r\n","import { Text } from 'ink';\r\n\r\nexport interface Hint {\r\n\tkey: string;\r\n\tlabel: string;\r\n\tpriority: number;\r\n}\r\n\r\nexport const PANEL_HINTS: Hint[] = [\r\n\t{ key: 'r', label: 'restart', priority: 80 },\r\n\t{ key: 'o', label: 'open', priority: 40 },\r\n\t{ key: 't', label: 'tunnel', priority: 60 },\r\n\t{ key: 'i', label: 'info', priority: 50 },\r\n\t{ key: 'T', label: 'theme', priority: 30 },\r\n\t{ key: 'l', label: 'logs', priority: 70 },\r\n\t{ key: '?', label: 'help', priority: 100 },\r\n\t{ key: 'q', label: 'quit', priority: 90 }\r\n];\r\n\r\n/** Drop the lowest-priority shortcuts first; help and the last error survive narrow panes. */\r\nexport function Hints({ hints, width }: { hints: readonly Hint[]; width: number }) {\r\n\tconst shown = [...hints];\r\n\tconst length = () => shown.reduce((size, hint) => size + hint.key.length + hint.label.length + 4, -2);\r\n\twhile (shown.length > 1 && length() > width) {\r\n\t\tconst weakest = shown.reduce((a, b) => (a.priority <= b.priority ? a : b));\r\n\t\tshown.splice(shown.indexOf(weakest), 1);\r\n\t}\r\n\treturn (\r\n\t\t<Text wrap=\"truncate-end\">\r\n\t\t\t{' '}\r\n\t\t\t{shown.map(({ key, label }, i) => (\r\n\t\t\t\t<Text key={key}>\r\n\t\t\t\t\t{i > 0 && <Text dimColor> · </Text>}\r\n\t\t\t\t\t<Text bold>{key}</Text>\r\n\t\t\t\t\t<Text dimColor>{` ${label}`}</Text>\r\n\t\t\t\t</Text>\r\n\t\t\t))}\r\n\t\t</Text>\r\n\t);\r\n}\r\n","import { Box, Text, useInput } from 'ink';\r\nimport { useMemo, useState } from 'react';\r\nimport { stripVTControlCharacters } from 'node:util';\r\nimport type { DevService } from '../../../dev-service.js';\r\nimport { isErrorDetail, type LogEntry, type LogLevel } from '../../../../utils/log-buffer.js';\r\nimport { useLogVersion } from '../hooks/useLogVersion.js';\r\nimport { usePaint } from '../theme.js';\r\nimport { Hints } from './Hints.js';\r\n\r\nexport interface LogBrowserProps {\r\n\tservice: DevService;\r\n\theight: number;\r\n\twidth: number;\r\n\tlastError?: boolean;\r\n\tonClose: () => void;\r\n\tonCopy?: (text: string) => void;\r\n}\r\n\r\nconst group = (entry: LogEntry) => (entry.source === 'app' ? 'runtime' : entry.source === 'build' || entry.source === 'tsc' ? 'build' : 'cli');\r\n\r\n/** Filterable history, using Nuxt's keys and selecting the last error without discarding its context. */\r\nexport function LogBrowser({ service, height, width, lastError = false, onClose, onCopy }: LogBrowserProps) {\r\n\tconst paint = usePaint();\r\n\tconst [sources, setSources] = useState({ cli: true, build: true, runtime: true });\r\n\tconst [level, setLevel] = useState<LogLevel | null>(null);\r\n\tconst [query, setQuery] = useState('');\r\n\tconst [searching, setSearching] = useState(false);\r\n\tconst [selected, setSelected] = useState<number | null>(() =>\r\n\t\tlastError ? (service.logs.entries().findLast((entry) => entry.level === 'error' && !isErrorDetail(entry))?.id ?? null) : null\r\n\t);\r\n\tconst version = useLogVersion(service.logs);\r\n\tconst entries = useMemo(\r\n\t\t() =>\r\n\t\t\tservice.logs\r\n\t\t\t\t.filter({ level })\r\n\t\t\t\t.filter((entry) => sources[group(entry)] && stripVTControlCharacters(entry.text).toLowerCase().includes(query.toLowerCase())),\r\n\t\t[service, sources, level, query, version]\r\n\t);\r\n\tconst bodyHeight = Math.max(0, height - 3);\r\n\tconst index = entries.findIndex((entry) => entry.id === selected);\r\n\tconst rows = entries.flatMap((entry) =>\r\n\t\tstripVTControlCharacters(entry.text)\r\n\t\t\t.split('\\n')\r\n\t\t\t.map((line, i) => ({\r\n\t\t\t\tentry,\r\n\t\t\t\ttext: i === 0 ? `${new Date(entry.time).toLocaleTimeString()} ${entry.source.padEnd(6)} ${line}` : ` ${line}`\r\n\t\t\t}))\r\n\t);\r\n\tconst selectedStart = rows.findIndex((row) => row.entry.id === selected);\r\n\tconst selectedEnd = rows.findLastIndex((row) => row.entry.id === selected) + 1;\r\n\tconst end =\r\n\t\tindex < 0 ? rows.length : Math.min(rows.length, selectedStart + Math.max(bodyHeight, Math.min(selectedEnd - selectedStart, bodyHeight)));\r\n\tconst visible = rows.slice(Math.max(0, end - bodyHeight), end);\r\n\tconst move = (delta: number) => {\r\n\t\tif (!entries.length) return;\r\n\t\tconst next = index < 0 ? (delta < 0 ? entries.length - 1 : 0) : Math.max(0, Math.min(entries.length - 1, index + delta));\r\n\t\tsetSelected(entries[next]!.id);\r\n\t};\r\n\r\n\tuseInput((input, key) => {\r\n\t\tif (key.ctrl) return;\r\n\t\tif (searching) {\r\n\t\t\tif (key.escape) {\r\n\t\t\t\tsetSearching(false);\r\n\t\t\t\tsetQuery('');\r\n\t\t\t} else if (key.return) setSearching(false);\r\n\t\t\telse if (key.backspace || key.delete) setQuery((value) => [...value].slice(0, -1).join(''));\r\n\t\t\telse if (input && !key.upArrow && !key.downArrow) setQuery((value) => value + input);\r\n\t\t\tsetSelected(null);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (key.escape || input === 'l' || input === 'q') return onClose();\r\n\t\tif (input === '/') return setSearching(true);\r\n\t\tif (input === 'e' || input === 'w' || input === 'a') {\r\n\t\t\tconst next = input === 'e' ? 'error' : input === 'w' ? 'warn' : null;\r\n\t\t\tsetLevel((current) => (current === next ? null : next));\r\n\t\t\treturn setSelected(null);\r\n\t\t}\r\n\t\tif (input === 'c' || input === 'b' || input === 'r') {\r\n\t\t\tconst source = input === 'c' ? 'cli' : input === 'b' ? 'build' : 'runtime';\r\n\t\t\tsetSources((current) => {\r\n\t\t\t\tconst next = { ...current, [source]: !current[source] };\r\n\t\t\t\treturn Object.values(next).some(Boolean) ? next : current;\r\n\t\t\t});\r\n\t\t\treturn setSelected(null);\r\n\t\t}\r\n\t\tif (input === 'x') {\r\n\t\t\tservice.clearLogs();\r\n\t\t\treturn setSelected(null);\r\n\t\t}\r\n\t\tif (key.upArrow || input === 'k') return move(-1);\r\n\t\tif (key.downArrow || input === 'j') return move(1);\r\n\t\tif (key.pageUp) return move(-Math.max(1, bodyHeight));\r\n\t\tif (key.pageDown) return move(Math.max(1, bodyHeight));\r\n\t\tif (key.home || input === 'g') return setSelected(entries[0]?.id ?? null);\r\n\t\tif (key.end || input === 'G') return setSelected(null);\r\n\t\tif ((key.return || input === 'y') && index >= 0) onCopy?.(stripVTControlCharacters(entries[index]!.text));\r\n\t});\r\n\r\n\tconst hints = searching\r\n\t\t? [\r\n\t\t\t\t['enter', 'apply'],\r\n\t\t\t\t['esc', 'cancel']\r\n\t\t\t]\r\n\t\t: [\r\n\t\t\t\t['↑/↓', 'select'],\r\n\t\t\t\t['g/G', 'top/bottom'],\r\n\t\t\t\t['e', 'errors'],\r\n\t\t\t\t['w', 'warnings'],\r\n\t\t\t\t['a', 'all'],\r\n\t\t\t\t['c/b/r', 'sources'],\r\n\t\t\t\t['/', 'search'],\r\n\t\t\t\t['x', 'clear'],\r\n\t\t\t\t['enter', 'copy'],\r\n\t\t\t\t['q', 'close']\r\n\t\t\t];\r\n\treturn (\r\n\t\t<Box flexDirection=\"column\" height={height}>\r\n\t\t\t<Text wrap=\"truncate-end\">\r\n\t\t\t\t{' '}\r\n\t\t\t\t<Text bold>logs</Text>\r\n\t\t\t\t<Text dimColor>{` · ${Object.entries(sources)\r\n\t\t\t\t\t.filter(([, shown]) => shown)\r\n\t\t\t\t\t.map(([source]) => source)\r\n\t\t\t\t\t.join(\r\n\t\t\t\t\t\t'+'\r\n\t\t\t\t\t)} · ${level ? `${level}+ only` : 'all levels'}${query || searching ? ` · search ${query}${searching ? '▏' : ''}` : ''}`}</Text>\r\n\t\t\t</Text>\r\n\t\t\t<Text dimColor>{'─'.repeat(width)}</Text>\r\n\t\t\t<Box flexDirection=\"column\" height={bodyHeight} overflow=\"hidden\">\r\n\t\t\t\t{visible.length === 0 && <Text dimColor> no matching logs</Text>}\r\n\t\t\t\t{visible.map(({ entry, text }, i) => (\r\n\t\t\t\t\t<Text key={`${entry.id}-${i}`} wrap=\"truncate-end\">\r\n\t\t\t\t\t\t<Text color={paint('brand')}>{entry.id === selected ? '▎ ' : ' '}</Text>\r\n\t\t\t\t\t\t<Text\r\n\t\t\t\t\t\t\tcolor={paint(\r\n\t\t\t\t\t\t\t\tentry.level === 'error'\r\n\t\t\t\t\t\t\t\t\t? 'error'\r\n\t\t\t\t\t\t\t\t\t: entry.level === 'warn'\r\n\t\t\t\t\t\t\t\t\t\t? 'warning'\r\n\t\t\t\t\t\t\t\t\t\t: entry.level === 'success'\r\n\t\t\t\t\t\t\t\t\t\t\t? 'success'\r\n\t\t\t\t\t\t\t\t\t\t\t: 'text'\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\tdimColor={isErrorDetail(entry)}\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t{text}\r\n\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t</Text>\r\n\t\t\t\t))}\r\n\t\t\t</Box>\r\n\t\t\t<Hints\r\n\t\t\t\twidth={width}\r\n\t\t\t\thints={hints.map(([key, label], i) => ({ key: key!, label: label!, priority: i === hints.length - 1 ? 100 : hints.length - i }))}\r\n\t\t\t/>\r\n\t\t</Box>\r\n\t);\r\n}\r\n","import { useEffect, useState } from 'react';\r\nimport type { DevService, DevStatus } from '../../../dev-service.js';\r\n\r\n/**\r\n * Mirrors the service's status into React state. The service stays the single source of truth: the UI only\r\n * subscribes to it, exactly like the plain renderer does.\r\n */\r\nexport function useDevStatus(service: DevService): DevStatus {\r\n\tconst [status, setStatus] = useState<DevStatus>(() => service.status);\r\n\r\n\tuseEffect(() => {\r\n\t\tconst onStatus = (next: DevStatus) => setStatus(next);\r\n\t\tservice.on('status', onStatus);\r\n\t\tsetStatus(service.status);\r\n\t\treturn () => {\r\n\t\t\tservice.off('status', onStatus);\r\n\t\t};\r\n\t}, [service]);\r\n\r\n\treturn status;\r\n}\r\n","import { useEffect, useState } from 'react';\r\n\r\n/**\r\n * Re-renders once a second while the bot is up, so the uptime in the header keeps counting.\r\n */\r\nexport function useUptime(startedAt: number | null): number | null {\r\n\tconst [now, setNow] = useState(() => Date.now());\r\n\r\n\tuseEffect(() => {\r\n\t\tif (startedAt === null) return;\r\n\r\n\t\tsetNow(Date.now());\r\n\t\tconst timer = setInterval(() => setNow(Date.now()), 1000);\r\n\t\treturn () => clearInterval(timer);\r\n\t}, [startedAt]);\r\n\r\n\treturn startedAt === null ? null : now - startedAt;\r\n}\r\n","import type { DevStatus } from '../dev-service.js';\r\n\r\nexport type Badge = 'starting' | 'building' | 'restarting' | 'ready' | 'error';\r\n\r\n/**\r\n * The badge and standing description for the panel's status row, mirroring the states Nuxt CLI v4's own dev panel\r\n * cycles through (`STARTING`/`BUILDING`/`RESTART`/`READY`/`ERROR`).\r\n */\r\nexport function describeBadge(status: DevStatus): { badge: Badge; note: string } {\r\n\tif (status.build === 'building') return { badge: status.startedAt === null ? 'starting' : 'building', note: status.progress.message };\r\n\tif (status.process === 'starting') return { badge: 'starting', note: 'starting the bot' };\r\n\tif (status.process === 'stopping') return { badge: 'restarting', note: 'restarting the bot' };\r\n\tif (status.build === 'failed') return { badge: 'error', note: 'build failed, waiting for changes' };\r\n\tif (status.process === 'crashed') return { badge: 'error', note: 'the bot crashed, press r to restart' };\r\n\tif (status.health === 'down') return { badge: 'error', note: 'health check failed' };\r\n\tif (status.typecheck === 'failed') return { badge: 'error', note: 'type check failed, press e to view it' };\r\n\tif (status.process === 'stopped') return { badge: 'error', note: 'the bot stopped, press r to restart' };\r\n\tif (status.progress.fraction < 1) return { badge: 'starting', note: status.progress.message };\r\n\tif (status.process === 'running') return { badge: 'ready', note: 'watching for changes' };\r\n\treturn { badge: 'starting', note: 'waiting for the first build' };\r\n}\r\n\r\n/** Formats a duration the way a dev session reads it: `mm:ss` under an hour, `h:mm:ss` above. */\r\nexport function formatDuration(milliseconds: number): string {\r\n\tconst total = Math.max(0, Math.floor(milliseconds / 1000));\r\n\tconst seconds = total % 60;\r\n\tconst minutes = Math.floor(total / 60) % 60;\r\n\tconst hours = Math.floor(total / 3600);\r\n\tconst pad = (value: number) => value.toString().padStart(2, '0');\r\n\r\n\treturn hours > 0 ? `${hours}:${pad(minutes)}:${pad(seconds)}` : `${pad(minutes)}:${pad(seconds)}`;\r\n}\r\n","import { Box, Text, useInput } from 'ink';\r\nimport type { DevService } from '../../../dev-service.js';\r\nimport { useDevStatus } from '../hooks/useDevStatus.js';\r\nimport { useUptime } from '../hooks/useUptime.js';\r\nimport { formatDuration } from '../../panel-logic.js';\r\n\r\nexport function InfoOverlay({ service, height, width, onClose }: { service: DevService; height: number; width: number; onClose: () => void }) {\r\n\tconst status = useDevStatus(service);\r\n\tconst uptime = useUptime(status.startedAt);\r\n\tuseInput((input, key) => {\r\n\t\tif (!key.ctrl && (key.escape || ['q', 'i'].includes(input))) onClose();\r\n\t});\r\n\tconst lines = [\r\n\t\t['Project', service.config.packageJson?.name ?? 'stars project'],\r\n\t\t['Root', service.config.root],\r\n\t\t['Node', process.version],\r\n\t\t['Builder', service.builder.tool],\r\n\t\t['Local', status.url ?? '—'],\r\n\t\t['Tunnel', status.tunnelUrl ?? status.tunnel],\r\n\t\t['Process', `${status.process}${status.pid ? ` (${status.pid})` : ''}`],\r\n\t\t['Uptime', uptime === null ? '—' : formatDuration(uptime)],\r\n\t\t['Restarts', String(status.restarts)],\r\n\t\t['Health', service.config.dev.health ? status.health : 'not configured (READY reports process state)'],\r\n\t\t['Types', `${status.typecheck}${status.typeErrors ? ` (${status.typeErrors} errors)` : ''}`],\r\n\t\t['Log file', service.config.dev.logFile ?? 'disabled']\r\n\t];\r\n\treturn (\r\n\t\t<Box flexDirection=\"column\" height={height}>\r\n\t\t\t<Text bold wrap=\"truncate-end\">\r\n\t\t\t\t{' '}\r\n\t\t\t\tsession info\r\n\t\t\t</Text>\r\n\t\t\t<Text dimColor>{'─'.repeat(width)}</Text>\r\n\t\t\t{lines.slice(0, Math.max(0, height - 3)).map(([label, value]) => (\r\n\t\t\t\t<Text key={label} wrap=\"truncate-end\">\r\n\t\t\t\t\t{' '}\r\n\t\t\t\t\t<Text bold>{label!.padEnd(10)}</Text>\r\n\t\t\t\t\t<Text dimColor>{value}</Text>\r\n\t\t\t\t</Text>\r\n\t\t\t))}\r\n\t\t\t<Box flexGrow={1} />\r\n\t\t\t<Text dimColor> q close</Text>\r\n\t\t</Box>\r\n\t);\r\n}\r\n","import { Box, Text } from 'ink';\r\nimport type { ReactNode } from 'react';\r\nimport type { ResolvedStarsConfig } from '@wolfstar/schema';\r\nimport type { DevStatus } from '../../../dev-service.js';\r\nimport { readOwnPackageJson } from '../../../../utils/version.js';\r\nimport type { LogCounters } from '../hooks/useLogCounters.js';\r\nimport { describeBadge } from '../../panel-logic.js';\r\nimport { usePaint } from '../theme.js';\r\nimport { Hints, PANEL_HINTS } from './Hints.js';\r\n\r\nexport interface PanelProps {\r\n\tstatus: DevStatus;\r\n\tconfig: ResolvedStarsConfig;\r\n\tcounters: LogCounters;\r\n\tframe: number;\r\n\telapsedMs: number;\r\n\twidth: number;\r\n\theight: number;\r\n\tconfirmQuit: boolean;\r\n}\r\n\r\n/** Nuxt's wordmark / URLs / progress / status / hints layout, with Stars branding. */\r\nexport function Panel({ status, config, counters, frame, elapsedMs, width, height, confirmQuit }: PanelProps) {\r\n\tconst paint = usePaint();\r\n\tconst state = describeBadge(status);\r\n\tconst busy = state.badge !== 'ready' && state.badge !== 'error';\r\n\tconst badge = !busy && counters.errors > 0 ? 'error' : state.badge;\r\n\tconst note = badge === 'error' && state.badge === 'ready' ? 'an error was logged · press e to view it' : state.note;\r\n\tconst filled = Math.round(Math.min(1, Math.max(0, status.progress.fraction)) * 20);\r\n\tconst wordmark = config.dev.banner === false ? [] : (config.dev.banner?.flatMap((line) => line.split('\\n')) ?? [null]);\r\n\tconst blocks: { name: string; content: ReactNode }[] = [\r\n\t\t...wordmark.slice(0, 4).map((line, index) => ({\r\n\t\t\tname: 'wordmark',\r\n\t\t\tcontent: (\r\n\t\t\t\t<Box key={index} justifyContent=\"space-between\">\r\n\t\t\t\t\t<Text wrap=\"truncate-end\">\r\n\t\t\t\t\t\t{' '}\r\n\t\t\t\t\t\t{line === null ? (\r\n\t\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t\t<Text color={paint('brand')}>\r\n\t\t\t\t\t\t\t\t\t{[...'·✦★✦'].map((cell, i) => (\r\n\t\t\t\t\t\t\t\t\t\t<Text key={i} dimColor={busy && i !== frame % 4}>\r\n\t\t\t\t\t\t\t\t\t\t\t{cell}\r\n\t\t\t\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t\t\t\t))}\r\n\t\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t\t\t{' '}\r\n\t\t\t\t\t\t\t\t<Text bold color={paint('brand')}>\r\n\t\t\t\t\t\t\t\t\tStars\r\n\t\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t\t\t<Text dimColor>{` ${readOwnPackageJson().version}`}</Text>\r\n\t\t\t\t\t\t\t</>\r\n\t\t\t\t\t\t) : (\r\n\t\t\t\t\t\t\t<Text color={paint('brand')}>{line}</Text>\r\n\t\t\t\t\t\t)}\r\n\t\t\t\t\t</Text>\r\n\t\t\t\t\t{index === 0 && width >= 60 && badge === 'ready' && status.progress.readyMs !== null && (\r\n\t\t\t\t\t\t<Text dimColor>{`ready in ${(status.progress.readyMs / 1000).toFixed(2)}s `}</Text>\r\n\t\t\t\t\t)}\r\n\t\t\t\t</Box>\r\n\t\t\t)\r\n\t\t})),\r\n\t\t{ name: 'space', content: <Text> </Text> },\r\n\t\t...(status.url\r\n\t\t\t? [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tname: 'urls',\r\n\t\t\t\t\t\tcontent: (\r\n\t\t\t\t\t\t\t<Text wrap=\"truncate-end\">\r\n\t\t\t\t\t\t\t\t{' '}\r\n\t\t\t\t\t\t\t\t<Text dimColor>{'Local '}</Text>\r\n\t\t\t\t\t\t\t\t<Text color={paint('url')} dimColor={busy}>\r\n\t\t\t\t\t\t\t\t\t{status.url}\r\n\t\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t\t\t{busy && <Text color={paint('busy')}>{` ${['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'][frame % 10]}`}</Text>}\r\n\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t)\r\n\t\t\t\t\t}\r\n\t\t\t\t]\r\n\t\t\t: []),\r\n\t\t...(status.tunnelUrl\r\n\t\t\t? [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tname: 'urls',\r\n\t\t\t\t\t\tcontent: (\r\n\t\t\t\t\t\t\t<Text wrap=\"truncate-end\">\r\n\t\t\t\t\t\t\t\t{' '}\r\n\t\t\t\t\t\t\t\t<Text dimColor>{'Tunnel '}</Text>\r\n\t\t\t\t\t\t\t\t<Text color={paint('tunnel')}>{status.tunnelUrl}</Text>\r\n\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t)\r\n\t\t\t\t\t}\r\n\t\t\t\t]\r\n\t\t\t: []),\r\n\t\t{ name: 'space', content: <Text> </Text> },\r\n\t\t{\r\n\t\t\tname: 'summary',\r\n\t\t\tcontent: busy ? (\r\n\t\t\t\t<Text wrap=\"truncate-end\">\r\n\t\t\t\t\t{' '}\r\n\t\t\t\t\t<Text color={paint('brand')}>{'━'.repeat(filled)}</Text>\r\n\t\t\t\t\t<Text dimColor>\r\n\t\t\t\t\t\t{'━'.repeat(20 - filled)}\r\n\t\t\t\t\t\t{` ${Math.round(status.progress.fraction * 100)}% · ${(elapsedMs / 1000).toFixed(1)}s`}\r\n\t\t\t\t\t</Text>\r\n\t\t\t\t</Text>\r\n\t\t\t) : (\r\n\t\t\t\t<Text wrap=\"truncate-end\">\r\n\t\t\t\t\t{' '}\r\n\t\t\t\t\t{counters.warnings > 0 && (\r\n\t\t\t\t\t\t<Text color={paint('warning')}>{`⚠ ${counters.warnings} ${plural(counters.warnings, 'warning')} `}</Text>\r\n\t\t\t\t\t)}\r\n\t\t\t\t\t{counters.errors > 0 && <Text bold color={paint('error')}>{`✖ ${counters.errors} ${plural(counters.errors, 'error')} `}</Text>}\r\n\t\t\t\t\t{counters.errors === 0 && counters.warnings === 0 && (\r\n\t\t\t\t\t\t<Text dimColor>\r\n\t\t\t\t\t\t\t{status.typecheck === 'checking'\r\n\t\t\t\t\t\t\t\t? 'checking types'\r\n\t\t\t\t\t\t\t\t: status.tunnel === 'failed'\r\n\t\t\t\t\t\t\t\t\t? 'tunnel failed · press l to view logs'\r\n\t\t\t\t\t\t\t\t\t: 'logs folded away · press l to view'}\r\n\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t)}\r\n\t\t\t\t</Text>\r\n\t\t\t)\r\n\t\t},\r\n\t\t{ name: 'space', content: <Text> </Text> },\r\n\t\t{\r\n\t\t\tname: 'status',\r\n\t\t\tcontent: (\r\n\t\t\t\t<Text wrap=\"truncate-end\">\r\n\t\t\t\t\t{' '}\r\n\t\t\t\t\t<Text\r\n\t\t\t\t\t\tbold\r\n\t\t\t\t\t\tbackgroundColor={paint(confirmQuit || busy ? 'busy' : badge === 'error' ? 'error' : 'success')}\r\n\t\t\t\t\t\tcolor={paint(badge === 'error' && !confirmQuit ? 'onError' : 'onBright')}\r\n\t\t\t\t\t>{` ${confirmQuit ? 'QUIT?' : badge === 'restarting' ? 'RESTART' : badge.toUpperCase()} `}</Text>\r\n\t\t\t\t\t{' '}\r\n\t\t\t\t\t<Text dimColor>{confirmQuit ? 'press y to confirm, esc to stay' : note}</Text>\r\n\t\t\t\t</Text>\r\n\t\t\t)\r\n\t\t},\r\n\t\t{\r\n\t\t\tname: 'hints',\r\n\t\t\tcontent: confirmQuit ? (\r\n\t\t\t\t<Text> </Text>\r\n\t\t\t) : (\r\n\t\t\t\t<Hints width={width} hints={[...(counters.errors ? [{ key: 'e', label: 'last error', priority: Infinity }] : []), ...PANEL_HINTS]} />\r\n\t\t\t)\r\n\t\t}\r\n\t];\r\n\tlet shown = blocks;\r\n\tconst budget = Math.max(2, Math.min(height, 14));\r\n\tfor (const name of ['space', 'summary', 'urls', 'wordmark']) {\r\n\t\tif (shown.length <= budget) break;\r\n\t\tshown = shown.filter((block) => block.name !== name);\r\n\t}\r\n\tshown = shown.filter((block, i, all) => block.name !== 'space' || (i > 0 && i < all.length - 1 && all[i - 1]?.name !== 'space'));\r\n\treturn (\r\n\t\t<Box flexDirection=\"column\">\r\n\t\t\t{shown.map((block, index) => (\r\n\t\t\t\t<Box key={index} flexDirection=\"column\" height={1}>\r\n\t\t\t\t\t{block.content}\r\n\t\t\t\t</Box>\r\n\t\t\t))}\r\n\t\t</Box>\r\n\t);\r\n}\r\n\r\nfunction plural(count: number, word: string): string {\r\n\treturn count === 1 ? word : `${word}s`;\r\n}\r\n","import { useEffect, useState } from 'react';\r\nimport type { DevService, DevStatus } from '../../../dev-service.js';\r\nimport { isErrorDetail, type LogEntry } from '../../../../utils/log-buffer.js';\r\n\r\nexport interface LogCounters {\r\n\twarnings: number;\r\n\terrors: number;\r\n}\r\n\r\n/**\r\n * Warnings and errors logged since the last successful build, the way Nuxt CLI v4's own panel counts them: the\r\n * badge's job is the current state, this line is what happened getting there.\r\n */\r\nexport function useLogCounters(service: DevService): LogCounters {\r\n\tconst count = () =>\r\n\t\tservice.logs.entries().reduce<LogCounters>(\r\n\t\t\t(total, entry) => ({\r\n\t\t\t\twarnings: total.warnings + Number(entry.level === 'warn'),\r\n\t\t\t\terrors: total.errors + Number(entry.level === 'error' && !isErrorDetail(entry))\r\n\t\t\t}),\r\n\t\t\t{ warnings: 0, errors: 0 }\r\n\t\t);\r\n\tconst [counters, setCounters] = useState<LogCounters>(count);\r\n\r\n\tuseEffect(() => {\r\n\t\tlet previousBuild: DevStatus['build'] = service.status.build;\r\n\t\tlet previousStart = service.status.startedAt;\r\n\r\n\t\tconst onEntry = (entry: LogEntry) => {\r\n\t\t\tif (entry.level === 'warn') setCounters((current) => ({ ...current, warnings: current.warnings + 1 }));\r\n\t\t\telse if (entry.level === 'error' && !isErrorDetail(entry)) setCounters((current) => ({ ...current, errors: current.errors + 1 }));\r\n\t\t};\r\n\r\n\t\tconst onStatus = (status: DevStatus) => {\r\n\t\t\tif (\r\n\t\t\t\t(status.build === 'building' && previousBuild !== 'building' && previousBuild !== 'idle') ||\r\n\t\t\t\t(status.lastRestartReason === 'manual' && status.startedAt !== null && status.startedAt !== previousStart)\r\n\t\t\t)\r\n\t\t\t\tsetCounters({ warnings: 0, errors: 0 });\r\n\t\t\tpreviousBuild = status.build;\r\n\t\t\tpreviousStart = status.startedAt;\r\n\t\t};\r\n\r\n\t\tservice.logs.on('entry', onEntry);\r\n\t\tconst onClear = () => setCounters({ warnings: 0, errors: 0 });\r\n\t\tservice.logs.on('clear', onClear);\r\n\t\tservice.on('status', onStatus);\r\n\t\tsetCounters(count());\r\n\t\treturn () => {\r\n\t\t\tservice.logs.off('entry', onEntry);\r\n\t\t\tservice.logs.off('clear', onClear);\r\n\t\t\tservice.off('status', onStatus);\r\n\t\t};\r\n\t}, [service]);\r\n\r\n\treturn counters;\r\n}\r\n","import { useEffect, useState } from 'react';\r\n\r\n/** The clock moves during a long compiler phase; the percentage only moves on real build events. */\r\nexport function useBuildClock(startedAt: number, active: boolean, reducedMotion: boolean) {\r\n\tconst [now, setNow] = useState(Date.now);\r\n\tuseEffect(() => {\r\n\t\tif (!active) return;\r\n\t\tsetNow(Date.now());\r\n\t\tconst timer = setInterval(() => setNow(Date.now()), reducedMotion ? 1000 : 120);\r\n\t\treturn () => clearInterval(timer);\r\n\t}, [startedAt, active, reducedMotion]);\r\n\tconst elapsedMs = Math.max(0, now - startedAt);\r\n\treturn { elapsedMs, frame: reducedMotion ? 0 : Math.floor(elapsedMs / 120) };\r\n}\r\n","import { execFile } from 'node:child_process';\r\n\r\n/** Called only on an explicit `o` keypress, with no shell interpolation. */\r\nexport function openDevUrl(value: string | null): Promise<void> {\r\n\tif (!value) return Promise.resolve();\r\n\tconst url = new URL(value);\r\n\tif (url.protocol !== 'http:' && url.protocol !== 'https:') return Promise.reject(new Error('Only HTTP(S) URLs can be opened.'));\r\n\tconst [command, args] =\r\n\t\tprocess.platform === 'win32'\r\n\t\t\t? (['rundll32', ['url.dll,FileProtocolHandler', url.href]] as const)\r\n\t\t\t: process.platform === 'darwin'\r\n\t\t\t\t? (['open', [url.href]] as const)\r\n\t\t\t\t: (['xdg-open', [url.href]] as const);\r\n\treturn new Promise((resolve, reject) =>\r\n\t\texecFile(command, [...args], (error) => (error ? reject(new Error(`Could not open the browser: ${error.message}`)) : resolve()))\r\n\t);\r\n}\r\n","import { Box, Text, useInput } from 'ink';\r\nimport { useState } from 'react';\r\nimport { THEME_SETTINGS, THEMES, detectTerminalBackground, type ThemeSetting } from '../../../../utils/theme.js';\r\nimport { useColorEnabled } from '../theme.js';\r\n\r\nconst DESCRIPTIONS: Record<ThemeSetting, string> = {\r\n\tauto: 'match the terminal background',\r\n\tdark: 'for dark terminals',\r\n\tlight: 'for light terminals',\r\n\t'dark-daltonized': 'dark, colour-blind friendly (blue/orange)',\r\n\t'light-daltonized': 'light, colour-blind friendly (blue/orange)',\r\n\t'dark-ansi': 'dark, only your terminal palette',\r\n\t'light-ansi': 'light, only your terminal palette'\r\n};\r\n\r\nexport interface ThemeOverlayProps {\r\n\t/** The theme setting in effect when the picker opened. */\r\n\tcurrent: ThemeSetting;\r\n\theight: number;\r\n\twidth: number;\r\n\t/** Called while moving through the list, so the whole UI previews the highlighted theme. */\r\n\tonPreview: (setting: ThemeSetting) => void;\r\n\tonSelect: (setting: ThemeSetting) => void;\r\n\t/** Closes without saving; the caller restores the theme that was in effect. */\r\n\tonClose: () => void;\r\n}\r\n\r\n/** Like Claude Code's `/theme`: arrows preview live, `Enter` keeps the choice and saves it, `Esc` restores. */\r\nexport function ThemeOverlay({ current, height, width, onPreview, onSelect, onClose }: ThemeOverlayProps) {\r\n\tconst color = useColorEnabled();\r\n\tconst [index, setIndex] = useState(Math.max(0, THEME_SETTINGS.indexOf(current)));\r\n\r\n\tconst move = (delta: number) => {\r\n\t\tconst next = (index + delta + THEME_SETTINGS.length) % THEME_SETTINGS.length;\r\n\t\tsetIndex(next);\r\n\t\tonPreview(THEME_SETTINGS[next]!);\r\n\t};\r\n\r\n\tuseInput((input, key) => {\r\n\t\tif (key.ctrl) return;\r\n\t\tif (key.escape || input === 'q' || input === 'T') return onClose();\r\n\t\tif (key.return) return onSelect(THEME_SETTINGS[index]!);\r\n\t\tif (key.upArrow || input === 'k') return move(-1);\r\n\t\tif (key.downArrow || input === 'j') return move(1);\r\n\t});\r\n\r\n\treturn (\r\n\t\t<Box flexDirection=\"column\" height={height}>\r\n\t\t\t<Text bold> colour theme</Text>\r\n\t\t\t<Text dimColor>{'─'.repeat(width)}</Text>\r\n\t\t\t{THEME_SETTINGS.slice(0, Math.max(0, height - 3)).map((setting, i) => {\r\n\t\t\t\tconst swatch = THEMES[setting === 'auto' ? detectTerminalBackground() : setting];\r\n\t\t\t\treturn (\r\n\t\t\t\t\t<Text key={setting} wrap=\"truncate-end\">\r\n\t\t\t\t\t\t{i === index ? ' ▎ ' : ' '}\r\n\t\t\t\t\t\t<Text bold={i === index}>{setting.padEnd(18)}</Text>\r\n\t\t\t\t\t\t{color && (\r\n\t\t\t\t\t\t\t<Text>\r\n\t\t\t\t\t\t\t\t<Text color={swatch.success}>● </Text>\r\n\t\t\t\t\t\t\t\t<Text color={swatch.warning}>● </Text>\r\n\t\t\t\t\t\t\t\t<Text color={swatch.error}>● </Text>\r\n\t\t\t\t\t\t\t\t<Text color={swatch.url}>● </Text>\r\n\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t<Text dimColor>{` ${DESCRIPTIONS[setting]}${setting === current ? ' (current)' : ''}`}</Text>\r\n\t\t\t\t\t</Text>\r\n\t\t\t\t);\r\n\t\t\t})}\r\n\t\t\t<Box flexGrow={1} />\r\n\t\t\t<Text dimColor> ↑/↓ preview · enter save · esc cancel</Text>\r\n\t\t</Box>\r\n\t);\r\n}\r\n","import { Box, useInput, useWindowSize } from 'ink';\r\nimport { useState } from 'react';\r\nimport type { DevService } from '../../dev-service.js';\r\nimport { HelpOverlay } from './components/HelpOverlay.js';\r\nimport { LogBrowser } from './components/LogBrowser.js';\r\nimport { InfoOverlay } from './components/InfoOverlay.js';\r\nimport { Panel } from './components/Panel.js';\r\nimport { useDevStatus } from './hooks/useDevStatus.js';\r\nimport { useLogCounters } from './hooks/useLogCounters.js';\r\nimport { useBuildClock } from './hooks/useBuildClock.js';\r\nimport { describeBadge } from '../panel-logic.js';\r\nimport { openDevUrl } from '../../open-url.js';\r\nimport { ThemeProvider } from './theme.js';\r\nimport { ThemeOverlay } from './components/ThemeOverlay.js';\r\nimport { resolveTheme, type ThemeSetting } from '../../../utils/theme.js';\r\n\r\nexport interface DevAppProps {\r\n\tservice: DevService;\r\n\tcolor: boolean;\r\n\t/** The theme setting to start with; `auto` follows the terminal background. */\r\n\ttheme: ThemeSetting;\r\n\treducedMotion: boolean;\r\n\t/** Called when the user asks to quit, so the CLI can stop the bot and exit. */\r\n\tonQuit: () => void;\r\n\tonViewChange: (overlay: boolean) => void;\r\n\tonCopy: (text: string) => void;\r\n\t/** Called when the user keeps a theme in the picker, so the CLI can remember it. */\r\n\tonThemeSave: (setting: ThemeSetting) => void;\r\n}\r\n\r\ntype View = 'panel' | 'logs' | 'errors' | 'help' | 'info' | 'theme';\r\n\r\n/**\r\n * A bottom-aligned panel in the normal buffer, with logs folded away. Only the browsable overlays use the\r\n * alternate screen, preserving the terminal's history and the panel when they close.\r\n */\r\nexport function DevApp({ service, color, theme, reducedMotion, onQuit, onViewChange, onCopy, onThemeSave }: DevAppProps) {\r\n\tconst { columns, rows } = useWindowSize();\r\n\tconst [view, setView] = useState<View>('panel');\r\n\tconst [confirmQuit, setConfirmQuit] = useState(false);\r\n\t// `saved` is what Esc restores after previewing other themes in the picker.\r\n\tconst [saved, setSaved] = useState(theme);\r\n\tconst [preview, setPreview] = useState(theme);\r\n\r\n\tconst status = useDevStatus(service);\r\n\tconst counters = useLogCounters(service);\r\n\tconst badge = describeBadge(status).badge;\r\n\tconst busy = badge !== 'ready' && badge !== 'error';\r\n\tconst clock = useBuildClock(status.progress.startedAt, busy && view === 'panel', reducedMotion);\r\n\r\n\tconst width = Math.max(1, columns);\r\n\tconst height = Math.max(2, rows - 1);\r\n\r\n\tconst changeView = (next: View) => {\r\n\t\tonViewChange(next !== 'panel');\r\n\t\tsetView(next);\r\n\t};\r\n\r\n\tuseInput((input, key) => {\r\n\t\tif (key.ctrl && input === 'c') return onQuit();\r\n\t\tif (key.ctrl && input === 'l') return service.clearLogs();\r\n\t\tif (view !== 'panel') return;\r\n\t\tif (confirmQuit) {\r\n\t\t\tif (input === 'y') return onQuit();\r\n\t\t\treturn setConfirmQuit(false);\r\n\t\t}\r\n\t\tif (key.ctrl && input === 'r') return void service.restart('manual');\r\n\t\tif (key.ctrl && input === 'd') return busy ? setConfirmQuit(true) : onQuit();\r\n\r\n\t\tswitch (input) {\r\n\t\t\tcase 'q':\r\n\t\t\t\treturn busy ? setConfirmQuit(true) : onQuit();\r\n\t\t\tcase 'r':\r\n\t\t\t\treturn void service.restart('manual');\r\n\t\t\tcase 'l':\r\n\t\t\t\treturn changeView('logs');\r\n\t\t\tcase 'e':\r\n\t\t\t\treturn changeView('errors');\r\n\t\t\tcase 'c':\r\n\t\t\t\treturn service.clearLogs();\r\n\t\t\tcase 'o':\r\n\t\t\t\treturn void openDevUrl(status.url).catch((error: Error) => service.log('stars', 'warn', error.message));\r\n\t\t\tcase 't':\r\n\t\t\t\treturn void service.toggleTunnel();\r\n\t\t\tcase 'i':\r\n\t\t\t\treturn changeView('info');\r\n\t\t\tcase 'T':\r\n\t\t\t\treturn changeView('theme');\r\n\t\t\tcase 'h':\r\n\t\t\tcase '?':\r\n\t\t\t\treturn changeView('help');\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\t});\r\n\r\n\treturn (\r\n\t\t<ThemeProvider color={color} theme={resolveTheme(preview)}>\r\n\t\t\t<Box width={width} height={height} flexDirection=\"column\" justifyContent={view === 'panel' ? 'flex-end' : 'flex-start'}>\r\n\t\t\t\t{(view === 'logs' || view === 'errors') && (\r\n\t\t\t\t\t<LogBrowser\r\n\t\t\t\t\t\tservice={service}\r\n\t\t\t\t\t\theight={height}\r\n\t\t\t\t\t\twidth={width}\r\n\t\t\t\t\t\tlastError={view === 'errors'}\r\n\t\t\t\t\t\tonCopy={onCopy}\r\n\t\t\t\t\t\tonClose={() => changeView('panel')}\r\n\t\t\t\t\t/>\r\n\t\t\t\t)}\r\n\t\t\t\t{view === 'help' && <HelpOverlay height={height} width={width} onClose={() => changeView('panel')} />}\r\n\t\t\t\t{view === 'info' && <InfoOverlay service={service} height={height} width={width} onClose={() => changeView('panel')} />}\r\n\t\t\t\t{view === 'theme' && (\r\n\t\t\t\t\t<ThemeOverlay\r\n\t\t\t\t\t\tcurrent={saved}\r\n\t\t\t\t\t\theight={height}\r\n\t\t\t\t\t\twidth={width}\r\n\t\t\t\t\t\tonPreview={setPreview}\r\n\t\t\t\t\t\tonSelect={(setting) => {\r\n\t\t\t\t\t\t\tsetSaved(setting);\r\n\t\t\t\t\t\t\tsetPreview(setting);\r\n\t\t\t\t\t\t\tonThemeSave(setting);\r\n\t\t\t\t\t\t\tchangeView('panel');\r\n\t\t\t\t\t\t}}\r\n\t\t\t\t\t\tonClose={() => {\r\n\t\t\t\t\t\t\tsetPreview(saved);\r\n\t\t\t\t\t\t\tchangeView('panel');\r\n\t\t\t\t\t\t}}\r\n\t\t\t\t\t/>\r\n\t\t\t\t)}\r\n\t\t\t\t{view === 'panel' && (\r\n\t\t\t\t\t<Panel\r\n\t\t\t\t\t\tstatus={status}\r\n\t\t\t\t\t\tconfig={service.config}\r\n\t\t\t\t\t\tcounters={counters}\r\n\t\t\t\t\t\t{...clock}\r\n\t\t\t\t\t\twidth={width}\r\n\t\t\t\t\t\theight={height}\r\n\t\t\t\t\t\tconfirmQuit={confirmQuit}\r\n\t\t\t\t\t/>\r\n\t\t\t\t)}\r\n\t\t\t</Box>\r\n\t\t</ThemeProvider>\r\n\t);\r\n}\r\n","import { StringDecoder } from 'node:string_decoder';\r\nimport type { DevService } from '../dev-service.js';\r\nimport { classifyAppLine, type LogLevel } from '../../utils/log-buffer.js';\r\n\r\n/** Capture third-party writes before build plugins run. Ink writes through a separate, unpatched sink. */\r\nexport function captureOutput(service: DevService, stream: NodeJS.WriteStream, fallback: LogLevel): () => void {\r\n\tconst original = stream.write;\r\n\tconst decoder = new StringDecoder('utf8');\r\n\tlet pending = '';\r\n\tconst emit = (text: string) => {\r\n\t\tif (text.trim()) service.log('build', classifyAppLine(text, fallback), text);\r\n\t};\r\n\tconst write: typeof stream.write = (chunk: unknown, encoding?: unknown, callback?: unknown) => {\r\n\t\tpending += typeof chunk === 'string' ? chunk : chunk instanceof Uint8Array ? decoder.write(Buffer.from(chunk)) : String(chunk);\r\n\t\tconst lines = pending.split(/\\r?\\n/);\r\n\t\tpending = lines.pop() ?? '';\r\n\t\tfor (const line of lines) emit(line);\r\n\t\t// A tool without newlines must not grow the capture indefinitely.\r\n\t\tif (pending.length > 65536) {\r\n\t\t\temit(pending);\r\n\t\t\tpending = '';\r\n\t\t}\r\n\t\tconst done = typeof encoding === 'function' ? encoding : callback;\r\n\t\tif (typeof done === 'function') queueMicrotask(() => done());\r\n\t\treturn true;\r\n\t};\r\n\tstream.write = write;\r\n\treturn () => {\r\n\t\tif (stream.write === write) stream.write = original;\r\n\t\temit(pending + decoder.end());\r\n\t\tpending = '';\r\n\t};\r\n}\r\n","import { render } from 'ink';\r\nimport type { DevService } from '../dev-service.js';\r\nimport { DevApp } from './ink/DevApp.js';\r\nimport type { Renderer } from './plain.js';\r\nimport { captureOutput } from './capture-output.js';\r\nimport { isErrorDetail } from '../../utils/log-buffer.js';\r\nimport type { ThemeSetting } from '../../utils/theme.js';\r\n\r\nexport interface TuiRendererOptions {\r\n\tstdout?: NodeJS.WriteStream;\r\n\tstdin?: NodeJS.ReadStream;\r\n\tcolor?: boolean;\r\n\t/** Defaults to `auto`. */\r\n\ttheme?: ThemeSetting;\r\n\t/** Called when the user keeps a theme in the picker. */\r\n\tonThemeSave?: (setting: ThemeSetting) => void;\r\n\t/** Freezes spinners, for `STARS_REDUCED_MOTION=1`. */\r\n\treducedMotion?: boolean;\r\n\t/** Caps how often Ink repaints; the default is Ink's own. */\r\n\tfps?: number;\r\n}\r\n\r\n/**\r\n * A normal-buffer, bottom-aligned panel and alternate-buffer overlays. External output is captured for the log\r\n * browser; the renderer alone writes to the terminal. Switching views and teardown restore the original buffer.\r\n *\r\n * `start()` resolves when the user quits, which is what `stars dev` waits on before shutting the bot down.\r\n */\r\nexport function createTuiRenderer(service: DevService, options: TuiRendererOptions = {}): Renderer {\r\n\tconst stdout = options.stdout ?? process.stdout;\r\n\tconst stdin = options.stdin ?? process.stdin;\r\n\tconst write = stdout.write.bind(stdout);\r\n\t// Bind methods to the real stream (resize subscriptions included), except write which bypasses capture.\r\n\tconst sink = new Proxy(stdout, {\r\n\t\tget(target, property) {\r\n\t\t\tif (property === 'write') return write;\r\n\t\t\tconst value = Reflect.get(target, property, target);\r\n\t\t\treturn typeof value === 'function' ? value.bind(target) : value;\r\n\t\t}\r\n\t});\r\n\tconst restoreOutput =\r\n\t\tstdout === process.stdout ? [captureOutput(service, process.stdout, 'info'), captureOutput(service, process.stderr, 'warn')] : [];\r\n\tlet alternate = false;\r\n\tlet stopped = false;\r\n\tconst switchView = (overlay: boolean) => {\r\n\t\tif (overlay === alternate || stopped) return;\r\n\t\tinstance.clear();\r\n\t\twrite(overlay ? '\\u001B[?1049h\\u001B[H' : '\\u001B[?1049l');\r\n\t\talternate = overlay;\r\n\t};\r\n\r\n\tlet quit!: () => void;\r\n\tconst quitting = new Promise<void>((resolve) => {\r\n\t\tquit = resolve;\r\n\t});\r\n\r\n\tconst instance = render(\r\n\t\t<DevApp\r\n\t\t\tservice={service}\r\n\t\t\tcolor={options.color ?? false}\r\n\t\t\ttheme={options.theme ?? 'auto'}\r\n\t\t\tonThemeSave={options.onThemeSave ?? (() => {})}\r\n\t\t\treducedMotion={options.reducedMotion ?? false}\r\n\t\t\tonQuit={quit}\r\n\t\t\tonViewChange={switchView}\r\n\t\t\tonCopy={(text) => write(`\\u001B]52;c;${Buffer.from(text.slice(0, 65536)).toString('base64')}\\u0007`)}\r\n\t\t/>,\r\n\t\t{\r\n\t\t\tstdout: sink,\r\n\t\t\tstdin,\r\n\t\t\t// `stars dev` owns the shutdown: it stops the bot, then exits with the right code.\r\n\t\t\texitOnCtrlC: false,\r\n\t\t\tpatchConsole: false,\r\n\t\t\t// `createTuiRenderer` only runs once `resolveOutputMode()` already picked 'tui' (never in CI or on a\r\n\t\t\t// non-TTY stdout), so Ink is told to trust that instead of re-deriving it from `process.env.CI`: on a\r\n\t\t\t// CI runner that env var is set even for this package's own test process, which would otherwise force\r\n\t\t\t// Ink's non-interactive mode (no repaint until unmount) despite the fake stdin/stdout looking like a\r\n\t\t\t// real TTY.\r\n\t\t\tinteractive: true,\r\n\t\t\t...(options.fps === undefined ? {} : { maxFps: options.fps })\r\n\t\t}\r\n\t);\r\n\r\n\treturn {\r\n\t\tasync start() {\r\n\t\t\tawait Promise.race([quitting, instance.waitUntilExit()]);\r\n\t\t},\r\n\t\tstop() {\r\n\t\t\tif (stopped) return;\r\n\t\t\tstopped = true;\r\n\t\t\tif (alternate) instance.clear();\r\n\t\t\tinstance.unmount();\r\n\t\t\tif (alternate) write('\\u001B[?1049l');\r\n\t\t\twrite('\\u001B[?25h');\r\n\t\t\tfor (const restore of restoreOutput) restore();\r\n\t\t\t// A fatal startup must not leave the user with only a folded error and no way to read it.\r\n\t\t\tif (service.status.progress.readyMs === null) {\r\n\t\t\t\tconst error = service.logs.entries().findLast((entry) => entry.level === 'error' && !isErrorDetail(entry));\r\n\t\t\t\tif (error) write(`\\n${error.text}\\n`);\r\n\t\t\t}\r\n\t\t\tquit();\r\n\t\t}\r\n\t};\r\n}\r\n\r\nexport { formatDuration } from './panel-logic.js';\r\n"],"mappings":"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"}
|