@wolfstar/cli 2.3.1 → 2.6.0-next-20261007120201
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/README.md +83 -13
- package/dist/{_shared-BIQK0Bhm.js → _shared-CyzTojMA.js} +95 -20
- package/dist/_shared-CyzTojMA.js.map +1 -0
- package/dist/{bridge-BegCt_n2.js → bridge-Cbm0jX9h.js} +3 -236
- package/dist/bridge-Cbm0jX9h.js.map +1 -0
- package/dist/{build-DJcc95Yq.js → build-BbIEbOu3.js} +5 -5
- package/dist/{build-DJcc95Yq.js.map → build-BbIEbOu3.js.map} +1 -1
- package/dist/cli.js +1 -1
- package/dist/codegen-C2PY7RXA.js +262 -0
- package/dist/codegen-C2PY7RXA.js.map +1 -0
- package/dist/commands-3Tgwy6cj.js +16 -0
- package/dist/commands-3Tgwy6cj.js.map +1 -0
- package/dist/commands-3qXbxhXx.js +3 -0
- package/dist/{commands-Bh0K9iWX.js → commands-C-i3qYOz.js} +5 -93
- package/dist/commands-C-i3qYOz.js.map +1 -0
- package/dist/{completions-DMPlZ0S1.js → completions-Cs6YbuXO.js} +3 -3
- package/dist/{completions-DMPlZ0S1.js.map → completions-Cs6YbuXO.js.map} +1 -1
- package/dist/{dev-Owu3e3AO.js → dev-9YvzhtkU.js} +22 -215
- package/dist/dev-9YvzhtkU.js.map +1 -0
- package/dist/{diagnostics-BysbNnPD.js → diagnostics-Dn3CXa8J.js} +11 -2
- package/dist/diagnostics-Dn3CXa8J.js.map +1 -0
- package/dist/{doctor-DEtAAknK.js → doctor-CMGfbXS5.js} +15 -7
- package/dist/doctor-CMGfbXS5.js.map +1 -0
- package/dist/{hooks-Cy6F2bhH.js → hooks-D_RVS0ba.js} +13 -5
- package/dist/hooks-D_RVS0ba.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{info-CKJVMWIT.js → info-eXsx1AfE.js} +5 -4
- package/dist/info-eXsx1AfE.js.map +1 -0
- package/dist/local-commands-CGBjc8KJ.js +95 -0
- package/dist/local-commands-CGBjc8KJ.js.map +1 -0
- package/dist/{locales-BJAP4HYf.js → locales-BzyEMQnX.js} +5 -5
- package/dist/{locales-BJAP4HYf.js.map → locales-BzyEMQnX.js.map} +1 -1
- package/dist/{nitro-B8u1iVgf.js → nitro-DufOgx8s.js} +2 -2
- package/dist/{nitro-B8u1iVgf.js.map → nitro-DufOgx8s.js.map} +1 -1
- package/dist/{prepare-BM93i3Rm.js → prepare-DKH0UIYA.js} +12 -8
- package/dist/prepare-DKH0UIYA.js.map +1 -0
- package/dist/{project-zlQStwsf.js → project-DBqQMFCk.js} +14 -3
- package/dist/project-DBqQMFCk.js.map +1 -0
- package/dist/{run-CHqwvZXf.js → run-DlNY1QM1.js} +2 -2
- package/dist/{run-CHqwvZXf.js.map → run-DlNY1QM1.js.map} +1 -1
- package/dist/tsc-9yHyx0L6.js +3 -0
- package/dist/{tsc-puVAcwmo.js → tsc-BArammxe.js} +3 -3
- package/dist/{tsc-puVAcwmo.js.map → tsc-BArammxe.js.map} +1 -1
- package/dist/{tsdown-Dwt3JhPw.js → tsdown-2i5h88vT.js} +2 -2
- package/dist/{tsdown-Dwt3JhPw.js.map → tsdown-2i5h88vT.js.map} +1 -1
- package/dist/{tui-nldGSD4c.js → tui-CB_qk2Z1.js} +2 -2
- package/dist/{tui-nldGSD4c.js.map → tui-CB_qk2Z1.js.map} +1 -1
- package/dist/tunnel-BNV5cuJz.js +236 -0
- package/dist/tunnel-BNV5cuJz.js.map +1 -0
- package/dist/typecheck-p_2rj9lL.js +66 -0
- package/dist/typecheck-p_2rj9lL.js.map +1 -0
- package/dist/typechecker-C3UOI2LF.js +213 -0
- package/dist/typechecker-C3UOI2LF.js.map +1 -0
- package/dist/{vite-YZUtv2Hk.js → vite-C5CN3xUu.js} +2 -2
- package/dist/{vite-YZUtv2Hk.js.map → vite-C5CN3xUu.js.map} +1 -1
- package/package.json +9 -9
- package/dist/_shared-BIQK0Bhm.js.map +0 -1
- package/dist/bridge-BegCt_n2.js.map +0 -1
- package/dist/codegen-aJSyPz-J.js +0 -124
- package/dist/codegen-aJSyPz-J.js.map +0 -1
- package/dist/commands-Bh0K9iWX.js.map +0 -1
- package/dist/commands-BlDTDvFO.js +0 -3
- package/dist/commands-CSB-pjgs.js +0 -15
- package/dist/commands-CSB-pjgs.js.map +0 -1
- package/dist/dev-Owu3e3AO.js.map +0 -1
- package/dist/diagnostics-BysbNnPD.js.map +0 -1
- package/dist/doctor-DEtAAknK.js.map +0 -1
- package/dist/hooks-Cy6F2bhH.js.map +0 -1
- package/dist/info-CKJVMWIT.js.map +0 -1
- package/dist/prepare-BM93i3Rm.js.map +0 -1
- package/dist/project-zlQStwsf.js.map +0 -1
- package/dist/tsc-C5l5TQGC.js +0 -3
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_shared-BIQK0Bhm.js","names":[],"sources":["../src/utils/tsconfig.ts","../src/commands/_shared.ts"],"sourcesContent":["import type { ResolvedStarsConfig } from '@wolfstar/schema';\nimport { createRequire } from 'node:module';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join, relative, resolve } from 'node:path';\n\nconst require = createRequire(import.meta.url);\nconst sapphireOptions = Object.assign(\n\t{},\n\t...['@sapphire/ts-config', '@sapphire/ts-config/extra-strict', '@sapphire/ts-config/decorators'].map(\n\t\t(id) => (require(id) as { compilerOptions: Record<string, unknown> }).compilerOptions\n\t)\n) as Record<string, unknown>;\n\n/** Generates an extendable config without changing the project's own tsconfig. */\nexport async function prepareTsconfig(config: ResolvedStarsConfig, check = false) {\n\tconst path = join(config.root, '.stars', 'tsconfig.json');\n\tconst fromGenerated = (target: string) => `./${relative(dirname(path), target).replaceAll('\\\\', '/')}`;\n\tconst paths: Record<string, string[]> = {};\n\tif (config.build.tool === 'tsdown') {\n\t\tconst source = dirname(config.entry);\n\t\tconst defaults = config.build.configFile === null ? { '~': source, '@': source, '~~': config.root, '@@': config.root } : {};\n\t\tconst aliases = { ...defaults, ...(config.tsdown.alias as Record<string, unknown> | undefined) };\n\t\tfor (const [alias, target] of Object.entries(aliases)) {\n\t\t\t// Module redirects belong to the bundler; only filesystem targets become TypeScript paths.\n\t\t\tif (typeof target !== 'string' || (!isAbsolute(target) && !/^\\.\\.?[/\\\\]/.test(target))) continue;\n\t\t\tconst resolved = fromGenerated(resolve(config.root, target));\n\t\t\tpaths[alias] = [resolved];\n\t\t\tpaths[`${alias}/*`] = [`${resolved}/*`];\n\t\t}\n\t} else if (config.experimental.enableNitro) {\n\t\t// `NitroBuilder` turns on Vite's native `resolve.tsconfigPaths` (see https://nitro.build/examples/import-alias),\n\t\t// which reads these `paths` straight out of the generated tsconfig — no `tsdown.alias` equivalent to merge\n\t\t// with, `vite`/Nitro projects only have this file's own `compilerOptions.paths` to extend or replace.\n\t\tconst source = dirname(config.entry);\n\t\tconst defaults = { '~': source, '@': source, '~~': config.root, '@@': config.root };\n\t\tfor (const [alias, target] of Object.entries(defaults)) {\n\t\t\tconst resolved = fromGenerated(resolve(config.root, target));\n\t\t\tpaths[alias] = [resolved];\n\t\t\tpaths[`${alias}/*`] = [`${resolved}/*`];\n\t\t}\n\t}\n\tconst content = `${JSON.stringify(\n\t\t{\n\t\t\tcompilerOptions: {\n\t\t\t\t...sapphireOptions,\n\t\t\t\t// Bundlers emit the application; TypeScript only checks it. Keep Node16 emit for tsc.\n\t\t\t\t...(config.build.tool === 'tsdown' || config.build.tool === 'vite'\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tmodule: 'ESNext',\n\t\t\t\t\t\t\tmoduleResolution: 'Bundler',\n\t\t\t\t\t\t\tmoduleDetection: 'force',\n\t\t\t\t\t\t\tisolatedModules: true,\n\t\t\t\t\t\t\tverbatimModuleSyntax: true,\n\t\t\t\t\t\t\tallowJs: true,\n\t\t\t\t\t\t\tallowImportingTsExtensions: true,\n\t\t\t\t\t\t\tresolvePackageJsonImports: true,\n\t\t\t\t\t\t\tlib: ['ESNext', 'DOM'],\n\t\t\t\t\t\t\tnoEmit: true\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\ttarget: 'ES2022',\n\t\t\t\tforceConsistentCasingInFileNames: true,\n\t\t\t\tskipLibCheck: true,\n\t\t\t\ttsBuildInfoFile: './tsconfig.tsbuildinfo',\n\t\t\t\tpaths\n\t\t\t},\n\t\t\tinclude: [`${fromGenerated(dirname(config.entry))}/**/*`, ...(config.imports.enabled ? [fromGenerated(config.imports.dts)] : [])],\n\t\t\texclude: [fromGenerated(join(config.root, 'node_modules')), fromGenerated(config.build.outDir)]\n\t\t},\n\t\tnull,\n\t\t2\n\t)}\\n`;\n\tif (check) {\n\t\tconst existing = await readFile(path, 'utf-8').catch(() => null);\n\t\treturn { path, status: existing === content ? ('up-to-date' as const) : ('outdated' as const) };\n\t}\n\tawait mkdir(dirname(path), { recursive: true });\n\tawait writeFile(path, content);\n\treturn { path, status: 'written' as const };\n}\n","import type { ResolvedStarsConfig } from '@wolfstar/schema';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { loadAutoImportsModule } from '../utils/framework-auto-imports.js';\nimport { formatError } from '../utils/errors.js';\nimport type { StarsHookable } from '../utils/hooks.js';\nimport { modulesPreloadWarning, prepareModulesPreload } from '../utils/modules.js';\nimport { prepareTsconfig } from '../utils/tsconfig.js';\n\nexport type PrepareResult =\n\t| { enabled: false; dts: null; status: null }\n\t| { enabled: true; dts: string; status: 'written' | 'up-to-date' | 'outdated' };\n\n/**\n * Regenerates `imports.dts` unconditionally, used by `stars dev`/`stars build` before the first build so the\n * declaration file exists (and is current) even when the user never ran `stars prepare` themselves.\n */\nexport async function prepareAutoImports(config: ResolvedStarsConfig, check = false): Promise<PrepareResult> {\n\tif (!config.imports.enabled) return { enabled: false, dts: null, status: null };\n\n\tconst { dirs, presets, exclude, dts } = config.imports;\n\tconst { generateAutoImportsDts } = await loadAutoImportsModule(config.root);\n\tconst content = await generateAutoImportsDts({ root: config.root, dirs, presets, exclude });\n\n\tif (check) {\n\t\tconst existing = await readFile(dts, 'utf-8').catch(() => null);\n\t\treturn { enabled: true, dts, status: existing === content ? 'up-to-date' : 'outdated' };\n\t}\n\n\tawait mkdir(dirname(dts), { recursive: true });\n\tawait writeFile(dts, content);\n\treturn { enabled: true, dts, status: 'written' };\n}\n\n/** Prepares TypeScript configuration and auto import declarations before building. */\nexport async function prepareProject(config: ResolvedStarsConfig, hooks?: StarsHookable, check = false) {\n\tawait hooks?.callHook('prepare:before', config);\n\tconst tsconfig = await prepareTsconfig(config, check);\n\tconst result = { ...(await prepareAutoImports(config, check)), tsconfig, modules: await prepareModulesPreload(config, check) };\n\tawait hooks?.callHook('prepare:done', config, { dts: result.dts, status: result.status });\n\treturn result;\n}\n\n/**\n * Prints the non-fatal configuration diagnostics (e.g. an end-of-life compatibility version), and, unless `production`\n * is `false` (`stars dev`, which does that itself), what a production start of the project still needs to do.\n */\nexport async function reportWarnings(\n\tconfig: ResolvedStarsConfig,\n\twrite: (text: string) => void,\n\toptions: { production?: boolean } = {}\n): Promise<void> {\n\tfor (const warning of config.warnings) write(await formatError(warning));\n\n\tconst preload = options.production === false ? null : modulesPreloadWarning(config);\n\tif (preload) write(await formatError(preload));\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bridge-BegCt_n2.js","names":[],"sources":["../src/dev/tunnel.ts","../src/dev/bridge.ts"],"sourcesContent":["import type { ResolvedStarsConfig, ResolvedTunnelConfig } from '@wolfstar/schema';\nimport { readProjectEnv } from '../utils/project-env.js';\nimport { EventEmitter } from 'node:events';\nimport { startTunnel, type Tunnel as UntunTunnel } from 'untun';\nimport type { LogLevel } from '../utils/log-buffer.js';\n\nexport type TunnelState = 'off' | 'starting' | 'up' | 'failed';\n\nconst SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP'] as const;\n\nfunction isCloudflaredExit(reason: unknown): reason is Error {\n\treturn reason instanceof Error && reason.message.startsWith('cloudflared exited (');\n}\n\nexport interface TunnelEvents {\n\tlog: [level: LogLevel, text: string];\n\tstate: [state: TunnelState, url: string | null];\n}\n\nexport interface TunnelOptions {\n\t/** Override for tests. */\n\tstartTunnel?: typeof startTunnel;\n}\n\n/**\n * Exposes the bot's interactions endpoint publicly while `stars dev` runs.\n *\n * `dev.tunnel: true` opens a `cloudflared` quick tunnel via `untun` (it changes on every run); a configured https\n * URL is only probed, since the user already serves it. Writing the URL to the Discord application is opt-in\n * through `dev.tunnel.updateEndpoint`, because it edits a live application.\n */\nexport class Tunnel extends EventEmitter<TunnelEvents> {\n\t#startTunnel: typeof startTunnel;\n\t#tunnel: UntunTunnel | null = null;\n\t#state: TunnelState = 'off';\n\t#url: string | null = null;\n\t#wanted = false;\n\t#rejectionGuard: ((reason: unknown) => void) | null = null;\n\n\tpublic constructor(\n\t\tprivate readonly config: ResolvedStarsConfig,\n\t\toptions: TunnelOptions = {}\n\t) {\n\t\tsuper();\n\t\tthis.#startTunnel = options.startTunnel ?? startTunnel;\n\t}\n\n\tpublic get state(): TunnelState {\n\t\treturn this.#state;\n\t}\n\n\t/** The public URL of the interactions endpoint, `null` until the tunnel is up. */\n\tpublic get url(): string | null {\n\t\treturn this.#url;\n\t}\n\n\tpublic async start(forceQuick = false): Promise<void> {\n\t\tif (this.#state === 'starting' || this.#state === 'up') return;\n\t\tconst configured = this.config.dev.tunnel;\n\t\tconst tunnel: ResolvedTunnelConfig =\n\t\t\tforceQuick && configured.mode === 'off' ? { mode: 'quick', path: '/', updateEndpoint: false } : configured;\n\t\tif (tunnel.mode === 'off') return;\n\n\t\tthis.#wanted = true;\n\t\tthis.#setState('starting', null);\n\t\tconst url = tunnel.mode === 'url' ? await this.#useConfiguredUrl(tunnel) : await this.#openQuickTunnel();\n\t\tif (!url || !this.#wanted) return;\n\n\t\tthis.#setState('up', endpointUrl(url, tunnel.path));\n\t\tthis.emit('log', 'success', `Tunnel ready at ${this.#url}`);\n\t\tif (tunnel.updateEndpoint) await this.#updateInteractionsEndpoint(this.#url!);\n\t}\n\n\t/** Toggles the configured tunnel, opening a quick tunnel when the project did not configure one. */\n\tpublic toggle(): Promise<void> {\n\t\treturn this.#state === 'starting' || this.#state === 'up' ? this.close() : this.start(true);\n\t}\n\n\tpublic async close(): Promise<void> {\n\t\tthis.#wanted = false;\n\t\tconst tunnel = this.#tunnel;\n\t\tthis.#tunnel = null;\n\t\tthis.#setState('off', null);\n\t\t// Without a tunnel, `#openQuickTunnel` is still waiting for one and closes it (then releases the guard) when it arrives.\n\t\tif (!tunnel) return;\n\t\ttry {\n\t\t\tawait tunnel.close();\n\t\t} finally {\n\t\t\tthis.#releaseRejectionGuard();\n\t\t}\n\t}\n\n\tasync #useConfiguredUrl(tunnel: Extract<ResolvedTunnelConfig, { mode: 'url' }>): Promise<string | null> {\n\t\tconst reachable = await probe(endpointUrl(tunnel.url, tunnel.path));\n\t\tif (!reachable) {\n\t\t\tthis.emit('log', 'warn', `${tunnel.url} did not answer; make sure it forwards to ${this.config.dev.url ?? 'the bot'}`);\n\t\t}\n\n\t\treturn tunnel.url;\n\t}\n\n\tasync #openQuickTunnel(): Promise<string | null> {\n\t\tconst target = this.config.dev.url;\n\t\tif (!target) {\n\t\t\tthis.emit('log', 'error', 'A quick tunnel needs `dev.url` to know what to forward to');\n\t\t\tthis.#setState('failed', null);\n\t\t\treturn null;\n\t\t}\n\n\t\tthis.emit('log', 'info', 'Opening a cloudflared quick tunnel…');\n\t\tthis.#installRejectionGuard();\n\n\t\ttry {\n\t\t\tconst tunnel = await this.#startWithoutSignalHandlers(target);\n\t\t\tif (!this.#wanted) {\n\t\t\t\tawait tunnel?.close();\n\t\t\t\tthis.#releaseRejectionGuard();\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (!tunnel) {\n\t\t\t\tthis.emit('log', 'error', 'cloudflared setup was cancelled');\n\t\t\t\tthis.#setState('failed', null);\n\t\t\t\tthis.#releaseRejectionGuard();\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tthis.#tunnel = tunnel;\n\t\t\treturn await tunnel.getURL();\n\t\t} catch (error) {\n\t\t\tthis.#releaseRejectionGuard();\n\t\t\t// Closing the tunnel makes cloudflared exit, which `untun` reports as a failure: that is not one.\n\t\t\tif (!this.#wanted) return null;\n\t\t\tthis.emit('log', 'error', `cloudflared failed: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\tthis.#setState('failed', null);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * `untun` adds its own `SIGINT`/`SIGTERM`/`SIGHUP` listeners that call `process.exit()` once cloudflared is closed,\n\t * which races `stars dev`'s graceful shutdown (it closes the tunnel through {@link close} anyway), so they are removed.\n\t */\n\tasync #startWithoutSignalHandlers(target: string): Promise<UntunTunnel | undefined> {\n\t\tconst before = SIGNALS.map((signal) => new Set(process.listeners(signal)));\n\t\ttry {\n\t\t\treturn await this.#startTunnel({ url: target, acceptCloudflareNotice: true });\n\t\t} finally {\n\t\t\tSIGNALS.forEach((signal, index) => {\n\t\t\t\tfor (const listener of process.listeners(signal)) {\n\t\t\t\t\tif (!before[index]!.has(listener)) process.off(signal, listener);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * `untun` rejects a promise per connection when cloudflared exits and never handles it (and its location pattern\n\t * does not match lowercase codes such as `mxp03`, so that promise is never settled before), which Node reports as an\n\t * unhandled rejection that ends the process, whenever the tunnel closes. The guard swallows that one error for as\n\t * long as this tunnel exists; anything else it sees is thrown again, as if it was not installed.\n\t */\n\t#installRejectionGuard(): void {\n\t\tif (this.#rejectionGuard) return;\n\n\t\tconst guard = (reason: unknown): void => {\n\t\t\tif (!isCloudflaredExit(reason)) {\n\t\t\t\t// The guard is the only listener, so without this the rejection would be ignored instead of ending the process.\n\t\t\t\tif (process.listeners('unhandledRejection').length === 1) throw reason;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this.#state !== 'up' || !this.#wanted) return;\n\t\t\tthis.#tunnel = null;\n\t\t\tthis.emit('log', 'error', `cloudflared stopped unexpectedly: ${reason.message}`);\n\t\t\tthis.#setState('failed', null);\n\t\t\tthis.#releaseRejectionGuard();\n\t\t};\n\n\t\tthis.#rejectionGuard = guard;\n\t\tprocess.on('unhandledRejection', guard);\n\t}\n\n\t/** Node reports an unhandled rejection after the microtasks that follow it, so the guard has to outlive them. */\n\t#releaseRejectionGuard(): void {\n\t\tconst guard = this.#rejectionGuard;\n\t\tthis.#rejectionGuard = null;\n\t\tif (guard) setImmediate(() => process.off('unhandledRejection', guard));\n\t}\n\n\t/**\n\t * Points the Discord application's interactions endpoint at the tunnel. Discord validates the endpoint with a\n\t * signed ping before accepting it, so the bot has to be up already — this runs after the first successful build.\n\t */\n\tasync #updateInteractionsEndpoint(url: string): Promise<void> {\n\t\tconst credentials = readDiscordCredentials(this.config);\n\t\tif (!credentials) {\n\t\t\tthis.emit('log', 'warn', 'Skipped the interactions endpoint update: DISCORD_TOKEN is not set');\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await fetch('https://discord.com/api/v10/applications/@me', {\n\t\t\t\tmethod: 'PATCH',\n\t\t\t\theaders: { authorization: `Bot ${credentials.token}`, 'content-type': 'application/json' },\n\t\t\t\tbody: JSON.stringify({ interactions_endpoint_url: url }),\n\t\t\t\tsignal: AbortSignal.timeout(10_000)\n\t\t\t});\n\n\t\t\tif (response.ok) this.emit('log', 'success', `Interactions endpoint set to ${url}`);\n\t\t\telse\n\t\t\t\tthis.emit(\n\t\t\t\t\t'log',\n\t\t\t\t\t'error',\n\t\t\t\t\t`Discord rejected the interactions endpoint (${response.status}): ${(await response.text()).slice(0, 300)}`\n\t\t\t\t);\n\t\t} catch (error) {\n\t\t\tthis.emit('log', 'error', `Failed to update the interactions endpoint: ${error instanceof Error ? error.message : String(error)}`);\n\t\t}\n\t}\n\n\t#setState(state: TunnelState, url: string | null): void {\n\t\tthis.#state = state;\n\t\tthis.#url = url;\n\t\tthis.emit('state', state, url);\n\t}\n}\n\n/**\n * Joins the tunnel's origin with the path the interactions endpoint is served on.\n */\nexport function endpointUrl(origin: string, path: string): string {\n\treturn path === '/' ? origin : new URL(path, origin.endsWith('/') ? origin : `${origin}/`).href;\n}\n\nasync function probe(url: string): Promise<boolean> {\n\ttry {\n\t\tconst response = await fetch(url, { method: 'HEAD', signal: AbortSignal.timeout(5000) });\n\t\treturn response.status < 500;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport interface DiscordCredentials {\n\ttoken: string;\n\tapplicationId: string | null;\n}\n\n/**\n * Reads the Discord credentials the CLI needs from the environment, falling back to the project's `.env` files the\n * way the bot itself does once it starts.\n */\nexport function readDiscordCredentials(config: ResolvedStarsConfig, env: NodeJS.ProcessEnv = process.env): DiscordCredentials | null {\n\tconst fromFiles = readProjectEnvFilesCached(config);\n\tconst read = (...keys: string[]): string | null => {\n\t\tfor (const key of keys) {\n\t\t\tconst value = config.dev.env[key] ?? env[key] ?? fromFiles[key];\n\t\t\tif (value) return value;\n\t\t}\n\t\treturn null;\n\t};\n\n\tconst token = read('DISCORD_TOKEN', 'TOKEN');\n\tif (!token) return null;\n\n\treturn { token, applicationId: read('DISCORD_APPLICATION_ID', 'APPLICATION_ID', 'DISCORD_CLIENT_ID', 'CLIENT_ID') };\n}\n\nlet envFileCache: { key: string; values: Record<string, string> } | null = null;\n\n/** The variables the bot loads (see {@link readProjectEnv}), once per project and `env` options. */\nfunction readProjectEnvFilesCached(config: ResolvedStarsConfig): Record<string, string> {\n\tconst key = JSON.stringify([config.root, config.env.options]);\n\tif (envFileCache?.key !== key) envFileCache = { key, values: readProjectEnv(config) };\n\treturn envFileCache.values;\n}\n","import type { ResolvedStarsConfig } from '@wolfstar/schema';\nimport { resolveSync } from 'mlly';\nimport { pathToFileURL } from 'node:url';\nimport { findInstalledVersion } from '../utils/project.js';\n\n/** Marks a message of the bridge, so a bot using the IPC channel for something else is left alone. */\nexport const BRIDGE_SOURCE = 'stars:bridge';\n/** Marks a message `stars dev` sends to the bot. */\nexport const CLI_SOURCE = 'stars:cli';\n/** Set on a bot started only to report the commands it registers (see `readLocalCommands`). */\nexport const DUMP_ENV = 'STARS_COMMANDS_DUMP';\n/** The first `@wolfstar/http-framework` with object plugins (`Client.use({ name, postListen })`), which the bridge is. */\nexport const BRIDGE_FRAMEWORK_VERSION = '6.1.0';\n\n/** An application command as the bot would register it: the JSON body Discord receives. */\nexport interface CommandData {\n\tname: string;\n\ttype?: number;\n\t[key: string]: unknown;\n}\n\nexport interface CommandSnapshot {\n\tglobal: CommandData[];\n\t/** Guild-restricted commands, by guild id. */\n\tguilds: Record<string, CommandData[]>;\n}\n\nexport interface BridgeError {\n\tmessage: string;\n\t/** The first stack frames, without the message line. */\n\tstack: string[];\n}\n\n/**\n * What the bot tells `stars dev` over the IPC channel. The bot's stdout only carries text a level is guessed for; this\n * is everything the dev UI shows that happens inside the bot: hot reloads, requests, dispatches, its commands.\n */\nexport type BridgeMessage =\n\t| { type: 'ready'; clientId: string; port: number | null }\n\t| { type: 'pieces'; store: string; pieces: { name: string; path: string }[] }\n\t| { type: 'hmr'; event: 'start'; paths: string[] }\n\t| { type: 'hmr'; event: 'stop' }\n\t| { type: 'hmr'; event: 'reloaded' | 'loaded' | 'unloaded'; store: string; names: string[]; path: string }\n\t| ({ type: 'hmr'; event: 'error'; path: string } & BridgeError)\n\t| ({ type: 'commands' } & CommandSnapshot)\n\t| { type: 'dispatch'; phase: 'run'; route: string; piece: string }\n\t| { type: 'dispatch'; phase: 'success'; route: string; piece: string; ms: number | null }\n\t| { type: 'dispatch'; phase: 'error'; route: string; piece: string; ms: number | null; error: BridgeError }\n\t| { type: 'request'; method: string; path: string; status: number; ms: number }\n\t| { type: 'refreshed'; ok: true; global: number; guilds: number; cleared: number }\n\t| ({ type: 'refreshed'; ok: false } & BridgeError)\n\t/** A line on a channel of the sender's choice: how a plugin gets its own channel in the dev UI. */\n\t| { type: 'log'; channel: string; level: string; text: string; detail?: string[] };\n\n/** What the CLI asks of the bot. `clearGuilds` are guilds whose last command was removed: nothing registers them any more. */\nexport interface RefreshRequest {\n\tsource: typeof CLI_SOURCE;\n\ttype: 'commands:refresh';\n\tclearGuilds: string[];\n}\n\ntype Loose = Record<string, any>;\n\nconst isString = (value: unknown): value is string => typeof value === 'string';\nconst isNumber = (value: unknown): value is number => typeof value === 'number' && Number.isFinite(value);\nconst isStrings = (value: unknown): value is string[] => Array.isArray(value) && value.every(isString);\nconst isRecord = (value: unknown): value is Loose => value !== null && typeof value === 'object' && !Array.isArray(value);\nconst isCommands = (value: unknown): boolean => Array.isArray(value) && value.every((command) => isRecord(command) && isString(command.name));\nconst isError = (value: Loose): boolean => isString(value.message) && isStrings(value.stack);\n\n/** The shape each message must have. A plugin can send `log`, so nothing here is taken on trust. */\nconst SHAPES: Record<BridgeMessage['type'], (message: Loose) => boolean> = {\n\tready: (message) => isString(message.clientId) && (message.port === null || isNumber(message.port)),\n\tpieces: (message) =>\n\t\tisString(message.store) &&\n\t\tArray.isArray(message.pieces) &&\n\t\tmessage.pieces.every((piece: unknown) => isRecord(piece) && isString(piece.name) && isString(piece.path)),\n\thmr: (message) => {\n\t\tswitch (message.event) {\n\t\t\tcase 'start':\n\t\t\t\treturn isStrings(message.paths);\n\t\t\tcase 'stop':\n\t\t\t\treturn true;\n\t\t\tcase 'error':\n\t\t\t\treturn isString(message.path) && isError(message);\n\t\t\tcase 'reloaded':\n\t\t\tcase 'loaded':\n\t\t\tcase 'unloaded':\n\t\t\t\treturn isString(message.store) && isStrings(message.names) && isString(message.path);\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t},\n\tcommands: (message) => isCommands(message.global) && isRecord(message.guilds) && Object.values(message.guilds).every(isCommands),\n\tdispatch: (message) => {\n\t\tif (!isString(message.route) || !isString(message.piece)) return false;\n\t\tif (message.phase === 'run') return true;\n\t\tif (message.ms !== null && !isNumber(message.ms)) return false;\n\t\treturn message.phase === 'success' || (message.phase === 'error' && isRecord(message.error) && isError(message.error));\n\t},\n\trequest: (message) => isString(message.method) && isString(message.path) && isNumber(message.status) && isNumber(message.ms),\n\trefreshed: (message) =>\n\t\tmessage.ok === true\n\t\t\t? isNumber(message.global) && isNumber(message.guilds) && isNumber(message.cleared)\n\t\t\t: message.ok === false && isError(message),\n\tlog: (message) =>\n\t\tisString(message.channel) &&\n\t\tmessage.channel.length > 0 &&\n\t\tisString(message.level) &&\n\t\tisString(message.text) &&\n\t\t(message.detail === undefined || isStrings(message.detail))\n};\n\n/**\n * Narrows an IPC message to one of the bridge's, `null` for anything else the bot sends and for a bridge message that\n * does not have the shape of its type.\n */\nexport function parseBridgeMessage(value: unknown): BridgeMessage | null {\n\tif (!isRecord(value) || value.source !== BRIDGE_SOURCE || !isString(value.type) || !Object.hasOwn(SHAPES, value.type)) return null;\n\treturn SHAPES[value.type as BridgeMessage['type']](value) ? (value as BridgeMessage) : null;\n}\n\n/**\n * The source of the bridge: a module preloaded into the bot (`node --import`) that registers a plugin on the bot's own\n * `Client` and reports what happens there with `process.send`. It never writes to stdout, and does nothing when the\n * process has no IPC channel, so it is inert outside `stars dev`.\n *\n * It only uses what `@wolfstar/http-framework` already exposes — the client's events, its registry and its stores —\n * which is what keeps `@wolfstar/cli` free of a dependency on the framework: `framework` is the project's own copy.\n */\nexport function bridgeModuleSource(framework: string): string {\n\treturn `import { Client, container } from ${JSON.stringify(framework)};\n\nif (typeof process.send === 'function') {\n\tconst send = (type, data) => {\n\t\ttry {\n\t\t\tprocess.send({ source: ${JSON.stringify(BRIDGE_SOURCE)}, type, ...data });\n\t\t} catch {}\n\t};\n\tconst describe = (error) => ({\n\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\tstack:\n\t\t\terror instanceof Error && typeof error.stack === 'string'\n\t\t\t\t? error.stack.split('\\\\n').slice(1, 6).map((line) => line.trim())\n\t\t\t\t: []\n\t});\n\tconst commandRoute = (context) => {\n\t\tconst data = context.interaction.data ?? {};\n\t\tconst kind = context.interaction.type === 4 ? 'autocomplete' : data.type === 2 ? 'user' : data.type === 3 ? 'message' : 'slash';\n\t\tlet name = String(data.name ?? 'unknown');\n\t\tlet options = data.options;\n\t\twhile (Array.isArray(options) && options.length === 1 && (options[0].type === 1 || options[0].type === 2)) {\n\t\t\tname += ' ' + options[0].name;\n\t\t\toptions = options[0].options;\n\t\t}\n\t\treturn kind + ':' + name;\n\t};\n\tconst handlerRoute = (context) => (context.interaction.type === 5 ? 'modal' : 'component') + ':' + context.handler.name;\n\tconst commandsOf = (client) => {\n\t\tconst guilds = {};\n\t\tfor (const [id, commands] of client.registry.getLoadedGuildCommands()) guilds[id] = commands;\n\t\treturn { global: client.registry.getLoadedGlobalCommands(), guilds };\n\t};\n\tconst snapshot = (client) => {\n\t\ttry {\n\t\t\tsend('commands', commandsOf(client));\n\t\t} catch {}\n\t};\n\n\ttry {\n\t\tClient.use({\n\t\t\tname: 'stars:dev-bridge',\n\t\t\tenforce: 'post',\n\t\t\tpostInitialization(client) {\n\t\t\t\tif (process.env[${JSON.stringify(DUMP_ENV)}] === '1') {\n\t\t\t\t\t// \\`stars commands diff\\` only wants to know what the bot would register: once its pieces are loaded\n\t\t\t\t\t// it has the answer, and exits before it listens or talks to Discord.\n\t\t\t\t\tconst load = client.load.bind(client);\n\t\t\t\t\tclient.load = async (...args) => {\n\t\t\t\t\t\tawait load(...args);\n\t\t\t\t\t\tprocess.send({ source: ${JSON.stringify(BRIDGE_SOURCE)}, type: 'commands', ...commandsOf(client) }, () => process.exit(0));\n\t\t\t\t\t\tawait new Promise(() => {});\n\t\t\t\t\t};\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst started = new WeakMap();\n\t\t\t\tconst track = (prefix, route, pieceOf) => {\n\t\t\t\t\tclient.on(prefix + 'Run', (context) => {\n\t\t\t\t\t\tstarted.set(context.interaction, performance.now());\n\t\t\t\t\t\tsend('dispatch', { phase: 'run', route: route(context), piece: pieceOf(context).name });\n\t\t\t\t\t});\n\t\t\t\t\tconst done = (phase) => (first, second) => {\n\t\t\t\t\t\tconst context = phase === 'error' ? second : first;\n\t\t\t\t\t\tconst at = started.get(context.interaction);\n\t\t\t\t\t\tsend('dispatch', {\n\t\t\t\t\t\t\tphase,\n\t\t\t\t\t\t\troute: route(context),\n\t\t\t\t\t\t\tpiece: pieceOf(context).name,\n\t\t\t\t\t\t\tms: at === undefined ? null : Math.round(performance.now() - at),\n\t\t\t\t\t\t\t...(phase === 'error' ? { error: describe(first) } : {})\n\t\t\t\t\t\t});\n\t\t\t\t\t};\n\t\t\t\t\tclient.on(prefix + 'Success', done('success'));\n\t\t\t\t\tclient.on(prefix + 'Error', done('error'));\n\t\t\t\t};\n\t\t\t\ttrack('command', commandRoute, (context) => context.command);\n\t\t\t\ttrack('autocomplete', commandRoute, (context) => context.command);\n\t\t\t\ttrack('interactionHandler', handlerRoute, (context) => context.handler);\n\n\t\t\t\tconst changed = (event) => (pieces, path) => {\n\t\t\t\t\tconst list = Array.isArray(pieces) ? pieces : [pieces];\n\t\t\t\t\tconst store = list[0]?.store?.name ?? 'pieces';\n\t\t\t\t\tsend('hmr', { event, path, store, names: list.map((piece) => piece.name) });\n\t\t\t\t\tif (store === 'commands') snapshot(client);\n\t\t\t\t};\n\t\t\t\tclient.on('hmrStart', (paths) => send('hmr', { event: 'start', paths }));\n\t\t\t\tclient.on('hmrStop', () => send('hmr', { event: 'stop' }));\n\t\t\t\tclient.on('hmrPieceReloaded', changed('reloaded'));\n\t\t\t\tclient.on('hmrPiecesLoaded', changed('loaded'));\n\t\t\t\tclient.on('hmrPieceUnloaded', changed('unloaded'));\n\t\t\t\tclient.on('hmrError', (error, path) => send('hmr', { event: 'error', path, ...describe(error) }));\n\t\t\t},\n\t\t\tpostListen(client) {\n\t\t\t\tif (process.env[${JSON.stringify(DUMP_ENV)}] === '1') return;\n\t\t\t\tconst server = client.server;\n\t\t\t\tserver?.on?.('request', (request, response) => {\n\t\t\t\t\tconst at = performance.now();\n\t\t\t\t\tresponse.once('finish', () =>\n\t\t\t\t\t\tsend('request', {\n\t\t\t\t\t\t\tmethod: String(request.method),\n\t\t\t\t\t\t\tpath: String(request.url),\n\t\t\t\t\t\t\tstatus: response.statusCode,\n\t\t\t\t\t\t\tms: Math.round(performance.now() - at)\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tfor (const store of container.stores.values()) {\n\t\t\t\t\tsend('pieces', {\n\t\t\t\t\t\tstore: store.name,\n\t\t\t\t\t\tpieces: [...store.values()].map((piece) => ({ name: piece.name, path: piece.location.full }))\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tsnapshot(client);\n\t\t\t\tconst address = server?.address?.();\n\t\t\t\tsend('ready', { clientId: client.id, port: address !== null && typeof address === 'object' ? address.port : null });\n\t\t\t}\n\t\t});\n\n\t\tprocess.on('message', (message) => {\n\t\t\tif (message === null || typeof message !== 'object' || message.source !== ${JSON.stringify(CLI_SOURCE)}) return;\n\t\t\tif (message.type !== 'commands:refresh') return;\n\t\t\tPromise.resolve()\n\t\t\t\t.then(async () => {\n\t\t\t\t\tconst client = container.client;\n\t\t\t\t\tconst global = await client.registry.pushGlobalCommands();\n\t\t\t\t\tconst guilds = await client.registry.pushGuildRestrictedCommands();\n\t\t\t\t\tconst failed = guilds.find((result) => result.status === 'rejected');\n\t\t\t\t\tif (failed) throw failed.reason;\n\t\t\t\t\t// A guild that lost its last command is no longer in the registry, so nothing above overwrote it.\n\t\t\t\t\tconst clear = Array.isArray(message.clearGuilds) ? message.clearGuilds.filter((id) => typeof id === 'string') : [];\n\t\t\t\t\tfor (const id of clear) {\n\t\t\t\t\t\tawait container.rest.put('/applications/' + client.id + '/guilds/' + id + '/commands', { body: [] });\n\t\t\t\t\t}\n\t\t\t\t\tsend('refreshed', { ok: true, global: global.length, guilds: guilds.length, cleared: clear.length });\n\t\t\t\t})\n\t\t\t\t.catch((error) => send('refreshed', { ok: false, ...describe(error) }));\n\t\t});\n\t\t// Listening for messages keeps the channel, and with it the process, alive: a bot that is done must still exit.\n\t\tprocess.channel?.unref?.();\n\t} catch {}\n}\n`;\n}\n\n/**\n * `node` arguments that preload the bridge into the bot. Nothing is preloaded when the project's framework cannot be\n * resolved or predates object plugins: `stars dev` then shows what the bot prints, as it did before the bridge.\n *\n * The framework is resolved from the project with the `import` condition, the way `moduleImportArgs` does, so the\n * plugin lands on the `Client` the bot constructs. A build that bundles the framework into its output (Vite, Nitro)\n * has its own copy, which the preload cannot reach: the bridge stays silent there too.\n */\nexport function bridgeImportArgs(config: ResolvedStarsConfig): string[] {\n\tconst version = findInstalledVersion(config.root, '@wolfstar/http-framework');\n\tif (version === null || !isAtLeast(version, BRIDGE_FRAMEWORK_VERSION)) return [];\n\n\tlet framework: string;\n\ttry {\n\t\tframework = resolveSync('@wolfstar/http-framework', { url: pathToFileURL(`${config.root}/package.json`).href });\n\t} catch {\n\t\treturn [];\n\t}\n\n\treturn ['--import', `data:text/javascript,${encodeURIComponent(bridgeModuleSource(framework))}`];\n}\n\n/** Compares the `major.minor.patch` of two versions; a prerelease counts as its release. */\nexport function isAtLeast(version: string, minimum: string): boolean {\n\tconst parse = (value: string) =>\n\t\tvalue\n\t\t\t.split('-', 1)[0]!\n\t\t\t.split('.')\n\t\t\t.map((part) => Number.parseInt(part, 10) || 0);\n\tconst [a, b] = [parse(version), parse(minimum)];\n\tfor (let index = 0; index < 3; index++) {\n\t\tconst difference = (a[index] ?? 0) - (b[index] ?? 0);\n\t\tif (difference !== 0) return difference > 0;\n\t}\n\n\treturn true;\n}\n"],"mappings":"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"}
|
package/dist/codegen-aJSyPz-J.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { i as shouldUseColor } from "./output-mode-Bp7Da8vJ.js";
|
|
2
|
-
import { t as cliDiagnostics } from "./diagnostics-BysbNnPD.js";
|
|
3
|
-
import { i as resolveFromProject } from "./project-zlQStwsf.js";
|
|
4
|
-
import { d as resolveCwd, n as loadProject, u as projectArgs } from "./hooks-Cy6F2bhH.js";
|
|
5
|
-
import { defineCommand } from "citty";
|
|
6
|
-
import { join } from "node:path";
|
|
7
|
-
import { displayPath } from "@wolfstar/schema";
|
|
8
|
-
import { createColors } from "colorette";
|
|
9
|
-
import { tmpdir } from "node:os";
|
|
10
|
-
import { spawn } from "node:child_process";
|
|
11
|
-
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
12
|
-
|
|
13
|
-
//#region src/commands/codegen.ts
|
|
14
|
-
async function runCodegen(options) {
|
|
15
|
-
const stdout = options.stdout ?? process.stdout;
|
|
16
|
-
const colors = createColors({ useColor: shouldUseColor() && !options.json });
|
|
17
|
-
const { config } = await loadProject({
|
|
18
|
-
cwd: resolveCwd(options),
|
|
19
|
-
configFile: options.config
|
|
20
|
-
});
|
|
21
|
-
const results = [];
|
|
22
|
-
if (config.codegen.i18n) results.push(await runI18n(config, Boolean(options.check)));
|
|
23
|
-
if (options.json) stdout.write(`${JSON.stringify({
|
|
24
|
-
check: Boolean(options.check),
|
|
25
|
-
results
|
|
26
|
-
}, null, 2)}\n`);
|
|
27
|
-
else if (results.length === 0) stdout.write(`${colors.dim("stars")} nothing to generate (no code generators are configured)\n`);
|
|
28
|
-
else for (const result of results) {
|
|
29
|
-
const paint = result.status === "outdated" ? colors.red : colors.green;
|
|
30
|
-
stdout.write(`${colors.dim("stars")} ${result.generator}: ${paint(result.status)} ${displayPath(config.root, result.output)}\n`);
|
|
31
|
-
}
|
|
32
|
-
if (results.some((result) => result.status === "outdated")) throw cliDiagnostics.CODEGEN_OUTDATED({});
|
|
33
|
-
}
|
|
34
|
-
async function runI18n(config, check) {
|
|
35
|
-
const { locales, output } = config.codegen.i18n;
|
|
36
|
-
const cli = resolveFromProject(config.root, "@wolfstar/i18next-type-generator");
|
|
37
|
-
if (!cli) throw cliDiagnostics.DEPENDENCY_MISSING({
|
|
38
|
-
name: "@wolfstar/i18next-type-generator",
|
|
39
|
-
root: config.root,
|
|
40
|
-
hint: "Install it with `pnpm add -D @wolfstar/i18next-type-generator`, or set `codegen.i18n` to false."
|
|
41
|
-
});
|
|
42
|
-
if (!check) {
|
|
43
|
-
await generate(config.root, cli, locales, output);
|
|
44
|
-
return {
|
|
45
|
-
generator: "i18n",
|
|
46
|
-
output,
|
|
47
|
-
status: "written"
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
const directory = await mkdtemp(join(tmpdir(), "stars-codegen-"));
|
|
51
|
-
try {
|
|
52
|
-
const candidate = join(directory, "i18next.d.ts");
|
|
53
|
-
await generate(config.root, cli, locales, candidate);
|
|
54
|
-
const [expected, actual] = await Promise.all([readFile(candidate, "utf-8"), readFile(output, "utf-8").catch(() => null)]);
|
|
55
|
-
return {
|
|
56
|
-
generator: "i18n",
|
|
57
|
-
output,
|
|
58
|
-
status: expected === actual ? "up-to-date" : "outdated"
|
|
59
|
-
};
|
|
60
|
-
} finally {
|
|
61
|
-
await rm(directory, {
|
|
62
|
-
recursive: true,
|
|
63
|
-
force: true
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
function generate(root, cli, locales, output) {
|
|
68
|
-
return new Promise((resolve, reject) => {
|
|
69
|
-
const child = spawn(process.execPath, [
|
|
70
|
-
cli,
|
|
71
|
-
locales,
|
|
72
|
-
output
|
|
73
|
-
], {
|
|
74
|
-
cwd: root,
|
|
75
|
-
stdio: [
|
|
76
|
-
"ignore",
|
|
77
|
-
"ignore",
|
|
78
|
-
"pipe"
|
|
79
|
-
],
|
|
80
|
-
windowsHide: true
|
|
81
|
-
});
|
|
82
|
-
let stderr = "";
|
|
83
|
-
child.stderr?.on("data", (chunk) => stderr += chunk.toString());
|
|
84
|
-
child.once("error", reject);
|
|
85
|
-
child.once("exit", (code) => {
|
|
86
|
-
if (code === 0) resolve();
|
|
87
|
-
else reject(cliDiagnostics.CODEGEN_FAILED({
|
|
88
|
-
code,
|
|
89
|
-
stderr: stderr.trim()
|
|
90
|
-
}));
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
var codegen_default = defineCommand({
|
|
95
|
-
meta: {
|
|
96
|
-
name: "codegen",
|
|
97
|
-
description: "Run the configured code generators (i18next types)"
|
|
98
|
-
},
|
|
99
|
-
args: {
|
|
100
|
-
...projectArgs,
|
|
101
|
-
check: {
|
|
102
|
-
type: "boolean",
|
|
103
|
-
description: "Fail when the generated files are out of date instead of writing them",
|
|
104
|
-
default: false
|
|
105
|
-
},
|
|
106
|
-
json: {
|
|
107
|
-
type: "boolean",
|
|
108
|
-
description: "Print machine-readable JSON",
|
|
109
|
-
default: false
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
async run({ args }) {
|
|
113
|
-
await runCodegen({
|
|
114
|
-
config: args.config,
|
|
115
|
-
cwd: args.cwd,
|
|
116
|
-
check: args.check,
|
|
117
|
-
json: args.json
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
//#endregion
|
|
123
|
-
export { codegen_default as default };
|
|
124
|
-
//# sourceMappingURL=codegen-aJSyPz-J.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codegen-aJSyPz-J.js","names":[],"sources":["../src/commands/codegen.ts"],"sourcesContent":["import { displayPath, type ResolvedStarsConfig } from '@wolfstar/schema';\nimport { loadProject } from '../utils/hooks.js';\nimport { defineCommand } from 'citty';\nimport { createColors } from 'colorette';\nimport { spawn } from 'node:child_process';\nimport { mkdtemp, readFile, rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { projectArgs, resolveCwd, type ProjectArgs } from '../utils/args.js';\nimport { cliDiagnostics } from '../utils/diagnostics.js';\nimport { shouldUseColor } from '../utils/output-mode.js';\nimport { resolveFromProject } from '../utils/project.js';\n\nexport interface CodegenTaskOptions extends ProjectArgs {\n\tcheck?: boolean;\n\tjson?: boolean;\n\tstdout?: NodeJS.WritableStream;\n}\n\nexport interface CodegenResult {\n\tgenerator: 'i18n';\n\toutput: string;\n\tstatus: 'written' | 'up-to-date' | 'outdated';\n}\n\nexport async function runCodegen(options: CodegenTaskOptions): Promise<void> {\n\tconst stdout = options.stdout ?? process.stdout;\n\tconst colors = createColors({ useColor: shouldUseColor() && !options.json });\n\tconst { config } = await loadProject({ cwd: resolveCwd(options), configFile: options.config });\n\tconst results: CodegenResult[] = [];\n\n\tif (config.codegen.i18n) results.push(await runI18n(config, Boolean(options.check)));\n\n\tif (options.json) {\n\t\tstdout.write(`${JSON.stringify({ check: Boolean(options.check), results }, null, 2)}\\n`);\n\t} else if (results.length === 0) {\n\t\tstdout.write(`${colors.dim('stars')} nothing to generate (no code generators are configured)\\n`);\n\t} else {\n\t\tfor (const result of results) {\n\t\t\tconst paint = result.status === 'outdated' ? colors.red : colors.green;\n\t\t\tstdout.write(`${colors.dim('stars')} ${result.generator}: ${paint(result.status)} ${displayPath(config.root, result.output)}\\n`);\n\t\t}\n\t}\n\n\tif (results.some((result) => result.status === 'outdated')) {\n\t\tthrow cliDiagnostics.CODEGEN_OUTDATED({});\n\t}\n}\n\nasync function runI18n(config: ResolvedStarsConfig, check: boolean): Promise<CodegenResult> {\n\tconst { locales, output } = config.codegen.i18n!;\n\tconst cli = resolveFromProject(config.root, '@wolfstar/i18next-type-generator');\n\tif (!cli) {\n\t\tthrow cliDiagnostics.DEPENDENCY_MISSING({\n\t\t\tname: '@wolfstar/i18next-type-generator',\n\t\t\troot: config.root,\n\t\t\thint: 'Install it with `pnpm add -D @wolfstar/i18next-type-generator`, or set `codegen.i18n` to false.'\n\t\t});\n\t}\n\n\tif (!check) {\n\t\tawait generate(config.root, cli, locales, output);\n\t\treturn { generator: 'i18n', output, status: 'written' };\n\t}\n\n\tconst directory = await mkdtemp(join(tmpdir(), 'stars-codegen-'));\n\ttry {\n\t\tconst candidate = join(directory, 'i18next.d.ts');\n\t\tawait generate(config.root, cli, locales, candidate);\n\t\tconst [expected, actual] = await Promise.all([readFile(candidate, 'utf-8'), readFile(output, 'utf-8').catch(() => null)]);\n\t\treturn { generator: 'i18n', output, status: expected === actual ? 'up-to-date' : 'outdated' };\n\t} finally {\n\t\tawait rm(directory, { recursive: true, force: true });\n\t}\n}\n\nfunction generate(root: string, cli: string, locales: string, output: string): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst child = spawn(process.execPath, [cli, locales, output], { cwd: root, stdio: ['ignore', 'ignore', 'pipe'], windowsHide: true });\n\t\tlet stderr = '';\n\t\tchild.stderr?.on('data', (chunk: Buffer) => (stderr += chunk.toString()));\n\t\tchild.once('error', reject);\n\t\tchild.once('exit', (code) => {\n\t\t\tif (code === 0) resolve();\n\t\t\telse reject(cliDiagnostics.CODEGEN_FAILED({ code, stderr: stderr.trim() }));\n\t\t});\n\t});\n}\n\nexport default defineCommand({\n\tmeta: {\n\t\tname: 'codegen',\n\t\tdescription: 'Run the configured code generators (i18next types)'\n\t},\n\targs: {\n\t\t...projectArgs,\n\t\tcheck: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Fail when the generated files are out of date instead of writing them',\n\t\t\tdefault: false\n\t\t},\n\t\tjson: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Print machine-readable JSON',\n\t\t\tdefault: false\n\t\t}\n\t},\n\tasync run({ args }) {\n\t\tawait runCodegen({ config: args.config, cwd: args.cwd, check: args.check, json: args.json });\n\t}\n});\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"commands-Bh0K9iWX.js","names":[],"sources":["../src/utils/discord.ts","../src/utils/local-commands.ts","../src/utils/prompts.ts","../src/commands/commands.ts"],"sourcesContent":["import type { ResolvedStarsConfig } from '@wolfstar/schema';\nimport { cliDiagnostics } from './diagnostics.js';\nimport { readDiscordCredentials } from '../dev/tunnel.js';\n\nconst API = 'https://discord.com/api/v10';\n\nexport interface ApplicationCommand {\n\tid: string;\n\tapplication_id: string;\n\tname: string;\n\tdescription?: string;\n\ttype?: number;\n\tguild_id?: string;\n\tversion?: string;\n}\n\nexport interface DiscordClient {\n\tapplicationId: string;\n\tlistCommands(guildId: string | null): Promise<ApplicationCommand[]>;\n\tdeleteCommand(guildId: string | null, commandId: string): Promise<void>;\n\t/** Replaces every command of the scope with `commands` (Discord's bulk overwrite): what is not listed is deleted. */\n\tputCommands(guildId: string | null, commands: readonly object[]): Promise<ApplicationCommand[]>;\n}\n\nexport const COMMAND_TYPE_NAMES: Record<number, string> = { 1: 'chat input', 2: 'user', 3: 'message' };\n\n/**\n * A minimal Discord REST client for what `stars commands` manages. The credentials come from the environment or the\n * project's `.env`, the same place the bot reads them from once it starts.\n */\nexport function createDiscordClient(config: ResolvedStarsConfig, env: NodeJS.ProcessEnv = process.env): DiscordClient {\n\tconst credentials = readDiscordCredentials(config, env);\n\tif (!credentials) {\n\t\tthrow cliDiagnostics.DISCORD_TOKEN_MISSING({});\n\t}\n\n\tif (!credentials.applicationId) {\n\t\tthrow cliDiagnostics.DISCORD_APPLICATION_ID_MISSING({});\n\t}\n\n\tconst applicationId = credentials.applicationId;\n\tconst scope = (guildId: string | null) =>\n\t\tguildId ? `/applications/${applicationId}/guilds/${guildId}/commands` : `/applications/${applicationId}/commands`;\n\n\tconst request = async (method: string, path: string, payload?: unknown): Promise<unknown> => {\n\t\tconst response = await fetch(`${API}${path}`, {\n\t\t\tmethod,\n\t\t\theaders: { authorization: `Bot ${credentials.token}`, ...(payload === undefined ? {} : { 'content-type': 'application/json' }) },\n\t\t\t...(payload === undefined ? {} : { body: JSON.stringify(payload) }),\n\t\t\tsignal: AbortSignal.timeout(15_000)\n\t\t});\n\n\t\tif (response.status === 204) return null;\n\n\t\tconst body: unknown = await response.json().catch(() => null);\n\t\tif (!response.ok) {\n\t\t\tconst detail = typeof body === 'object' && body !== null && 'message' in body ? String((body as { message: unknown }).message) : '';\n\t\t\tthrow cliDiagnostics.DISCORD_REQUEST_FAILED({ status: response.status, detail });\n\t\t}\n\n\t\treturn body;\n\t};\n\n\treturn {\n\t\tapplicationId,\n\t\tasync listCommands(guildId) {\n\t\t\tconst body = await request('GET', scope(guildId));\n\t\t\treturn Array.isArray(body) ? (body as ApplicationCommand[]) : [];\n\t\t},\n\t\tasync deleteCommand(guildId, commandId) {\n\t\t\tawait request('DELETE', `${scope(guildId)}/${commandId}`);\n\t\t},\n\t\tasync putCommands(guildId, commands) {\n\t\t\tconst body = await request('PUT', scope(guildId), commands);\n\t\t\treturn Array.isArray(body) ? (body as ApplicationCommand[]) : [];\n\t\t}\n\t};\n}\n","import type { ResolvedStarsConfig } from '@wolfstar/schema';\nimport { displayPath } from '@wolfstar/schema';\nimport { spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { BRIDGE_FRAMEWORK_VERSION, bridgeImportArgs, DUMP_ENV, parseBridgeMessage, type CommandSnapshot } from '../dev/bridge.js';\nimport { cliDiagnostics } from './diagnostics.js';\nimport { envImportArgs, moduleImportArgs } from './env-import.js';\n\nexport interface ReadLocalCommandsOptions {\n\t/** Milliseconds the bot gets to load its pieces. */\n\ttimeout?: number;\n}\n\n/**\n * The application commands the project defines, as the bot itself would register them.\n *\n * Commands are declared with builders and decorators that only exist once the bot's modules ran, so nothing short of\n * running them knows the answer. This starts the built bot with the dev bridge in its \"dump\" mode: it loads its\n * pieces, reports its registry over IPC and exits before it listens or talks to Discord.\n *\n * It is a plain start of the bot, not a `stars dev` session: `STARS_DEV` is not set, so commands a project only\n * registers while developing are not part of what `stars commands deploy` deploys.\n */\nexport async function readLocalCommands(config: ResolvedStarsConfig, options: ReadLocalCommandsOptions = {}): Promise<CommandSnapshot> {\n\tif (!existsSync(config.build.output)) {\n\t\tthrow cliDiagnostics.LOCAL_COMMANDS_UNAVAILABLE({\n\t\t\treason: `${displayPath(config.root, config.build.output)} does not exist`,\n\t\t\tfix: 'Run `stars build` first: the commands are read from the built bot.'\n\t\t});\n\t}\n\n\tconst bridge = bridgeImportArgs(config);\n\tif (bridge.length === 0) {\n\t\tthrow cliDiagnostics.LOCAL_COMMANDS_UNAVAILABLE({\n\t\t\treason: `@wolfstar/http-framework ${BRIDGE_FRAMEWORK_VERSION} or later is not installed in ${config.root}`,\n\t\t\tfix: `Install @wolfstar/http-framework@^${BRIDGE_FRAMEWORK_VERSION} in the project.`\n\t\t});\n\t}\n\n\tconst child = spawn(\n\t\tprocess.execPath,\n\t\t[...envImportArgs(config), ...moduleImportArgs(config), ...bridge, ...config.dev.nodeArgs, config.build.output, ...config.dev.args],\n\t\t{\n\t\t\tcwd: config.root,\n\t\t\t// The environment the commands are read under is the caller's: `NODE_ENV=production stars commands deploy`\n\t\t\t// deploys what a production start registers. Unset, it is development, like the project's env files.\n\t\t\tenv: { ...process.env, ...config.dev.env, NODE_ENV: process.env.NODE_ENV ?? 'development', [DUMP_ENV]: '1' },\n\t\t\tstdio: ['ignore', 'ignore', 'pipe', 'ipc'],\n\t\t\twindowsHide: true\n\t\t}\n\t);\n\n\treturn new Promise<CommandSnapshot>((resolve, reject) => {\n\t\tlet stderr = '';\n\t\tlet settled = false;\n\t\tconst finish = (action: () => void) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timer);\n\t\t\taction();\n\t\t};\n\t\tconst unavailable = (reason: string) =>\n\t\t\tcliDiagnostics.LOCAL_COMMANDS_UNAVAILABLE({\n\t\t\t\treason,\n\t\t\t\tfix: 'Check that the bot starts with `stars dev`: it has to construct its `Client` and call `client.load()`.'\n\t\t\t});\n\n\t\tconst timer = setTimeout(() => {\n\t\t\tchild.kill('SIGKILL');\n\t\t\tfinish(() => reject(unavailable('the bot did not load its commands in time')));\n\t\t}, options.timeout ?? 30_000);\n\n\t\tchild.stderr?.on('data', (chunk: Buffer) => (stderr = `${stderr}${chunk.toString()}`.slice(-2000)));\n\t\tlet snapshot: CommandSnapshot | null = null;\n\t\tchild.on('message', (message) => {\n\t\t\tconst parsed = parseBridgeMessage(message);\n\t\t\tif (parsed?.type !== 'commands' || snapshot !== null) return;\n\t\t\tsnapshot = { global: parsed.global, guilds: parsed.guilds };\n\t\t\t// The bot exits on its own once the message is flushed. The answer waits for that: until then the process\n\t\t\t// still holds the project directory (its working directory), which Windows refuses to let go of.\n\t\t\tsetTimeout(() => child.kill('SIGKILL'), 2000).unref();\n\t\t});\n\t\tchild.once('error', (error) => finish(() => reject(unavailable(error.message))));\n\t\tchild.once('exit', (code) => {\n\t\t\tif (snapshot !== null) {\n\t\t\t\tconst commands = snapshot;\n\t\t\t\tfinish(() => resolve(commands));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst detail = stderr.trim().split('\\n').at(-1);\n\t\t\tfinish(() => reject(unavailable(`the bot exited with code ${code} before loading its commands${detail ? ` (${detail})` : ''}`)));\n\t\t});\n\t});\n}\n","import type { Diagnostic } from 'nostics';\nimport type { ApplicationCommand } from './discord.js';\nimport { cliDiagnostics } from './diagnostics.js';\n\nexport interface CommandsPrompt {\n\t/** Asks which of the deployed commands to delete. Returns the chosen ids. */\n\tpick(commands: readonly ApplicationCommand[], scope: string): Promise<string[]>;\n\t/** Final go/no-go before anything is deleted. */\n\tconfirm(message: string): Promise<boolean>;\n}\n\n/**\n * The interactive wizard behind `stars commands clean`: a checklist of what Discord has deployed, then a\n * confirmation, so a destructive cleanup is never one keystroke away. `@clack/prompts` is loaded lazily — the\n * non-interactive paths (`--yes`, `--json`, CI) never pay for it.\n */\nexport function createClackPrompt(): CommandsPrompt {\n\treturn {\n\t\tasync pick(commands, scope) {\n\t\t\tconst { isCancel, multiselect } = await import('@clack/prompts');\n\t\t\tconst answer = await multiselect({\n\t\t\t\tmessage: `Which commands should be deleted from ${scope}?`,\n\t\t\t\toptions: commands.map((command) => ({\n\t\t\t\t\tvalue: command.id,\n\t\t\t\t\tlabel: command.name,\n\t\t\t\t\thint: [describeType(command), command.id].filter(Boolean).join(' · ')\n\t\t\t\t})),\n\t\t\t\trequired: false\n\t\t\t});\n\n\t\t\tif (isCancel(answer)) throw aborted();\n\t\t\treturn answer as string[];\n\t\t},\n\t\tasync confirm(message) {\n\t\t\tconst { confirm, isCancel } = await import('@clack/prompts');\n\t\t\tconst answer = await confirm({ message, initialValue: false });\n\n\t\t\tif (isCancel(answer)) throw aborted();\n\t\t\treturn Boolean(answer);\n\t\t}\n\t};\n}\n\nfunction describeType(command: ApplicationCommand): string {\n\tswitch (command.type) {\n\t\tcase 2:\n\t\t\treturn 'user';\n\t\tcase 3:\n\t\t\treturn 'message';\n\t\tdefault:\n\t\t\treturn 'chat input';\n\t}\n}\n\nfunction aborted(): Diagnostic {\n\treturn cliDiagnostics.ABORTED({});\n}\n","import { applyEnvOptions, loadProject, withProjectEnv } from '../utils/hooks.js';\nimport { defineCommand } from 'citty';\nimport { createColors } from 'colorette';\nimport type { Diagnostic } from 'nostics';\nimport type { ResolvedStarsConfig } from '@wolfstar/schema';\nimport type { CommandData, CommandSnapshot } from '../dev/bridge.js';\nimport { describeCommand, diffCommands, matchesDeployed, type CommandChange } from '../utils/command-diff.js';\nimport { COMMAND_TYPE_NAMES, createDiscordClient, type ApplicationCommand, type DiscordClient } from '../utils/discord.js';\nimport { cliDiagnostics } from '../utils/diagnostics.js';\nimport { readLocalCommands } from '../utils/local-commands.js';\nimport { shouldUseColor } from '../utils/output-mode.js';\nimport { createClackPrompt, type CommandsPrompt } from '../utils/prompts.js';\nimport { projectArgs, resolveCwd, type ProjectArgs } from '../utils/args.js';\n\nexport interface CommandsTaskOptions extends ProjectArgs {\n\t/** A guild id to work on the guild-scoped commands instead of the global ones. */\n\tguild?: string;\n\tjson?: boolean;\n\tstdout?: NodeJS.WritableStream;\n\t/** Overrides the client, for tests. */\n\tclient?: DiscordClient;\n}\n\nexport interface CommandsCleanOptions extends CommandsTaskOptions {\n\t/** Names to delete; without any, the wizard asks which of the deployed commands to remove. */\n\tnames?: string[];\n\t/** Deletes without asking. Required in a non-interactive terminal. */\n\tyes?: boolean;\n\tstdin?: NodeJS.ReadableStream & { isTTY?: boolean };\n\t/** Overrides the interactive wizard, for tests. */\n\tprompt?: CommandsPrompt;\n}\n\nexport interface CommandsDiffOptions extends CommandsTaskOptions {\n\t/** Fails when the deployed commands differ, for CI. */\n\tcheck?: boolean;\n\t/** Overrides the commands read from the built bot, for tests. */\n\tlocal?: CommandSnapshot;\n}\n\nexport interface CommandsDeployOptions extends CommandsDiffOptions {\n\t/** Deploys without asking. Required in a non-interactive terminal. */\n\tyes?: boolean;\n\tstdin?: NodeJS.ReadableStream & { isTTY?: boolean };\n\t/** Overrides the confirmation, for tests. */\n\tprompt?: Pick<CommandsPrompt, 'confirm'>;\n}\n\n/**\n * Lists the application commands Discord currently has deployed, which is not necessarily what the project would\n * register today: renamed and removed commands stay until something deletes them.\n */\nexport async function runCommandsList(options: CommandsTaskOptions): Promise<void> {\n\tconst stdout = options.stdout ?? process.stdout;\n\tconst colors = createColors({ useColor: shouldUseColor() && !options.json });\n\tconst { client, guild } = await connect(options);\n\tconst commands = await client.listCommands(guild);\n\n\tif (options.json) {\n\t\tstdout.write(`${JSON.stringify({ applicationId: client.applicationId, guildId: guild, commands }, null, 2)}\\n`);\n\t\treturn;\n\t}\n\n\tif (commands.length === 0) {\n\t\tstdout.write(`${colors.dim('stars')} no ${guild ? `commands in guild ${guild}` : 'global commands'} are deployed\\n`);\n\t\treturn;\n\t}\n\n\tstdout.write(`${colors.dim('stars')} ${commands.length} ${guild ? `command(s) in guild ${guild}` : 'global command(s)'}\\n`);\n\tfor (const command of commands) stdout.write(` ${colors.bold(describeName(command))} ${colors.dim(command.id)}\\n`);\n}\n\n/**\n * Deletes deployed application commands. Discord keeps whatever was registered last, so this is the way to clear\n * commands a project no longer defines (or a whole guild's test deployment).\n */\nexport async function runCommandsClean(options: CommandsCleanOptions): Promise<void> {\n\tconst stdout = options.stdout ?? process.stdout;\n\tconst colors = createColors({ useColor: shouldUseColor() && !options.json });\n\tconst { client, guild } = await connect(options);\n\tconst deployed = await client.listCommands(guild);\n\tconst wanted = options.names?.filter((name) => name.length > 0) ?? [];\n\n\tconst missing = wanted.filter((name) => !deployed.some((command) => command.name === name));\n\tif (missing.length > 0) {\n\t\tthrow cliDiagnostics.COMMAND_NOT_FOUND({ names: missing.join(', ') });\n\t}\n\n\tif (deployed.length === 0) {\n\t\tif (options.json) stdout.write(`${JSON.stringify({ deleted: [] }, null, 2)}\\n`);\n\t\telse stdout.write(`${colors.dim('stars')} nothing to delete\\n`);\n\t\treturn;\n\t}\n\n\tconst scope = guild ? `guild ${guild}` : 'the global scope';\n\tconst targets = await selectTargets(options, deployed, wanted, scope, stdout, colors);\n\tif (targets.length === 0) {\n\t\tif (options.json) stdout.write(`${JSON.stringify({ deleted: [] }, null, 2)}\\n`);\n\t\telse stdout.write(`${colors.dim('stars')} nothing to delete\\n`);\n\t\treturn;\n\t}\n\n\tfor (const command of targets) {\n\t\tawait client.deleteCommand(guild, command.id);\n\t\tif (!options.json) stdout.write(`${colors.dim('stars')} ${colors.red('deleted')} ${describeName(command)}\\n`);\n\t}\n\n\tif (options.json) stdout.write(`${JSON.stringify({ deleted: targets.map((command) => ({ id: command.id, name: command.name })) }, null, 2)}\\n`);\n}\n\nconst SYMBOLS = { added: '+', removed: '-', changed: '~' } as const;\n\n/**\n * What a deploy of `guild` (or the global scope) would change: the commands the project defines for it against the\n * ones Discord has. A command is `changed` when the project's definition no longer matches (see `matchesDeployed`).\n */\nasync function compare(options: CommandsDiffOptions): Promise<{\n\tclient: DiscordClient;\n\tguild: string | null;\n\tlocal: CommandData[];\n\tchanges: CommandChange[];\n}> {\n\tconst project = await loadProject({ cwd: resolveCwd(options), configFile: options.config });\n\t// What the bot is started with: `env:options` (and varlock) may pick other env files than the defaults.\n\tconst config = withProjectEnv(await applyEnvOptions(project.config, project.hooks));\n\tconst { client, guild } = connectTo(config, options);\n\tconst snapshot = options.local ?? (await readLocalCommands(config));\n\tconst local = guild === null ? snapshot.global : (snapshot.guilds[guild] ?? []);\n\tconst deployed = (await client.listCommands(guild)) as unknown as CommandData[];\n\t// Seen from Discord: what a deploy would add to, change in and remove from the deployed commands.\n\treturn { client, guild, local, changes: diffCommands(deployed, local, guild, (old, next) => matchesDeployed(next, old)) };\n}\n\nfunction writeChanges(stdout: NodeJS.WritableStream, colors: ReturnType<typeof createColors>, changes: readonly CommandChange[]): void {\n\tconst paint = { added: colors.green, removed: colors.red, changed: colors.yellow };\n\tfor (const change of changes) {\n\t\tstdout.write(\n\t\t\t` ${paint[change.kind](`${SYMBOLS[change.kind]} ${describeCommand({ ...change, guild: null })}`)} ${colors.dim(change.kind)}\\n`\n\t\t);\n\t}\n}\n\n/**\n * Compares the commands the project defines with the ones Discord has deployed, without changing anything: what\n * `stars commands deploy` would do. `--check` makes a difference an error, for CI.\n */\nexport async function runCommandsDiff(options: CommandsDiffOptions): Promise<void> {\n\tconst stdout = options.stdout ?? process.stdout;\n\tconst colors = createColors({ useColor: shouldUseColor() && !options.json });\n\tconst { client, guild, changes } = await compare(options);\n\n\tif (options.json) {\n\t\tstdout.write(`${JSON.stringify({ applicationId: client.applicationId, guildId: guild, changes }, null, 2)}\\n`);\n\t} else if (changes.length === 0) {\n\t\tstdout.write(`${colors.dim('stars')} ${guild ? `guild ${guild}` : 'the global scope'} is up to date\\n`);\n\t} else {\n\t\tstdout.write(`${colors.dim('stars')} ${changes.length} difference(s) in ${guild ? `guild ${guild}` : 'the global scope'}\\n`);\n\t\twriteChanges(stdout, colors, changes);\n\t}\n\n\tif (options.check && changes.length > 0) throw cliDiagnostics.COMMANDS_DIFFER({ count: changes.length });\n}\n\n/**\n * Deploys the commands the project defines to Discord with a bulk overwrite: a deployed command the project no\n * longer defines is deleted. It shows what will change and asks first; scripts pass `--yes`.\n */\nexport async function runCommandsDeploy(options: CommandsDeployOptions): Promise<void> {\n\tconst stdout = options.stdout ?? process.stdout;\n\tconst colors = createColors({ useColor: shouldUseColor() && !options.json });\n\tconst { client, guild, local, changes } = await compare(options);\n\tconst scope = guild ? `guild ${guild}` : 'the global scope';\n\n\tif (changes.length === 0) {\n\t\tif (options.json) stdout.write(`${JSON.stringify({ applicationId: client.applicationId, guildId: guild, deployed: 0, changes }, null, 2)}\\n`);\n\t\telse stdout.write(`${colors.dim('stars')} ${scope} is up to date, nothing to deploy\\n`);\n\t\treturn;\n\t}\n\n\tif (!options.json) {\n\t\tstdout.write(`${colors.dim('stars')} deploying to ${scope}\\n`);\n\t\twriteChanges(stdout, colors, changes);\n\t}\n\n\tif (!options.yes) {\n\t\tconst stdin = options.stdin ?? process.stdin;\n\t\t// `--json` owns stdout: a question printed there would end up in front of the document.\n\t\tif (!options.prompt && (!stdin.isTTY || options.json)) throw cliDiagnostics.DEPLOY_CONFIRMATION_REQUIRED({});\n\t\tconst prompt = options.prompt ?? createClackPrompt();\n\t\tif (!(await prompt.confirm(`Overwrite the commands of ${scope} with the ${local.length} the project defines?`))) {\n\t\t\tthrow cliDiagnostics.ABORTED({});\n\t\t}\n\t}\n\n\tconst deployed = await client.putCommands(guild, local);\n\tif (options.json) {\n\t\tstdout.write(`${JSON.stringify({ applicationId: client.applicationId, guildId: guild, deployed: deployed.length, changes }, null, 2)}\\n`);\n\t} else {\n\t\tstdout.write(`${colors.dim('stars')} ${colors.green('deployed')} ${deployed.length} command(s) to ${scope}\\n`);\n\t}\n}\n\n/**\n * Works out what to delete: `--name` (and `--yes`) keep the command scriptable, while a bare `stars commands clean`\n * on a terminal runs the wizard — a checklist of what Discord has deployed, then a confirmation.\n */\nasync function selectTargets(\n\toptions: CommandsCleanOptions,\n\tdeployed: ApplicationCommand[],\n\twanted: string[],\n\tscope: string,\n\tstdout: NodeJS.WritableStream,\n\tcolors: ReturnType<typeof createColors>\n): Promise<ApplicationCommand[]> {\n\tif (wanted.length > 0) {\n\t\tconst named = deployed.filter((command) => wanted.includes(command.name));\n\t\tif (options.yes) return named;\n\n\t\tawait confirmOrThrow(options, stdout, colors, `delete ${colors.bold(String(named.length))} command(s) from ${scope}?`);\n\t\treturn named;\n\t}\n\n\tif (options.yes) return deployed;\n\n\tconst stdin = options.stdin ?? process.stdin;\n\tif (!options.prompt && !stdin.isTTY) throw confirmationRequired();\n\n\tconst prompt = options.prompt ?? createClackPrompt();\n\tconst chosen = new Set(await prompt.pick(deployed, scope));\n\tconst targets = deployed.filter((command) => chosen.has(command.id));\n\tif (targets.length === 0) return [];\n\n\tconst names = targets.map((command) => command.name).join(', ');\n\tif (!(await prompt.confirm(`Delete ${targets.length} command(s) from ${scope}: ${names}?`))) {\n\t\tthrow cliDiagnostics.ABORTED({});\n\t}\n\n\treturn targets;\n}\n\nasync function connect(options: CommandsTaskOptions): Promise<{ client: DiscordClient; guild: string | null }> {\n\tconst { config } = await loadProject({ cwd: resolveCwd(options), configFile: options.config });\n\treturn connectTo(config, options);\n}\n\nfunction connectTo(config: ResolvedStarsConfig, options: CommandsTaskOptions): { client: DiscordClient; guild: string | null } {\n\treturn { client: options.client ?? createDiscordClient(config), guild: options.guild ?? null };\n}\n\nfunction describeName(command: ApplicationCommand): string {\n\tconst type = command.type && command.type !== 1 ? ` (${COMMAND_TYPE_NAMES[command.type] ?? `type ${command.type}`})` : '';\n\treturn `${command.name}${type}`;\n}\n\n/**\n * Deleting deployed commands is not reversible, so a terminal run asks first; scripts pass `--yes`.\n */\nasync function confirmOrThrow(\n\toptions: CommandsCleanOptions,\n\tstdout: NodeJS.WritableStream,\n\tcolors: ReturnType<typeof createColors>,\n\tquestion: string\n): Promise<void> {\n\tif (options.prompt) {\n\t\tif (await options.prompt.confirm(question)) return;\n\t\tthrow cliDiagnostics.ABORTED({});\n\t}\n\n\tconst stdin = options.stdin ?? process.stdin;\n\tif (!stdin.isTTY) throw confirmationRequired();\n\n\tstdout.write(`${colors.dim('stars')} ${question} [y/N] `);\n\treturn new Promise((resolve, reject) => {\n\t\tstdin.setEncoding?.('utf-8');\n\t\tstdin.once('data', (chunk: string) => {\n\t\t\tstdin.pause?.();\n\t\t\tconst answer = chunk.trim().toLowerCase();\n\t\t\tif (answer === 'y' || answer === 'yes') resolve();\n\t\t\telse reject(cliDiagnostics.ABORTED({}));\n\t\t});\n\t\tstdin.resume?.();\n\t});\n}\n\nfunction confirmationRequired(): Diagnostic {\n\treturn cliDiagnostics.CONFIRMATION_REQUIRED({});\n}\n\nconst scopeArgs = {\n\t...projectArgs,\n\tguild: {\n\t\ttype: 'string',\n\t\tdescription: 'Work on a guild’s commands instead of the global ones'\n\t},\n\tjson: {\n\t\ttype: 'boolean',\n\t\tdescription: 'Print machine-readable JSON',\n\t\tdefault: false\n\t}\n} as const;\n\nconst list = defineCommand({\n\tmeta: { name: 'list', description: 'List the application commands Discord has deployed' },\n\targs: scopeArgs,\n\tasync run({ args }) {\n\t\tawait runCommandsList({ config: args.config, cwd: args.cwd, guild: args.guild, json: args.json });\n\t}\n});\n\nconst clean = defineCommand({\n\tmeta: { name: 'clean', description: 'Delete deployed application commands (all of them, or the named ones)' },\n\targs: {\n\t\t...scopeArgs,\n\t\tname: {\n\t\t\ttype: 'string',\n\t\t\tdescription: 'Only delete the command with this name (repeatable)'\n\t\t},\n\t\tyes: {\n\t\t\ttype: 'boolean',\n\t\t\talias: 'y',\n\t\t\tdescription: 'Delete without asking for a confirmation',\n\t\t\tdefault: false\n\t\t}\n\t},\n\tasync run({ args }) {\n\t\tconst names = Array.isArray(args.name) ? args.name : args.name ? [args.name] : [];\n\t\tawait runCommandsClean({ config: args.config, cwd: args.cwd, guild: args.guild, json: args.json, names, yes: args.yes });\n\t}\n});\n\nconst diff = defineCommand({\n\tmeta: { name: 'diff', description: 'Compare the commands the built bot defines with the ones Discord has deployed' },\n\targs: {\n\t\t...scopeArgs,\n\t\tcheck: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Fail when the deployed commands differ, for CI',\n\t\t\tdefault: false\n\t\t}\n\t},\n\tasync run({ args }) {\n\t\tawait runCommandsDiff({ config: args.config, cwd: args.cwd, guild: args.guild, json: args.json, check: args.check });\n\t}\n});\n\nconst deploy = defineCommand({\n\tmeta: { name: 'deploy', description: 'Deploy the commands the built bot defines, replacing the deployed ones' },\n\targs: {\n\t\t...scopeArgs,\n\t\tyes: {\n\t\t\ttype: 'boolean',\n\t\t\talias: 'y',\n\t\t\tdescription: 'Deploy without asking for a confirmation',\n\t\t\tdefault: false\n\t\t}\n\t},\n\tasync run({ args }) {\n\t\tawait runCommandsDeploy({ config: args.config, cwd: args.cwd, guild: args.guild, json: args.json, yes: args.yes });\n\t}\n});\n\nconst SUBCOMMANDS = ['list', 'clean', 'diff', 'deploy'];\n\nexport default defineCommand({\n\tmeta: {\n\t\tname: 'commands',\n\t\tdescription: 'Inspect, compare, deploy and clean the application commands deployed to Discord'\n\t},\n\tsubCommands: { list, clean, diff, deploy },\n\targs: scopeArgs,\n\tasync run({ args, rawArgs }) {\n\t\t// `stars commands` with no subcommand lists, the way `git branch` does.\n\t\tif (rawArgs.some((argument) => SUBCOMMANDS.includes(argument))) return;\n\n\t\tawait runCommandsList({ config: args.config, cwd: args.cwd, guild: args.guild, json: args.json });\n\t}\n});\n"],"mappings":"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"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
//#region src/commands/index.ts
|
|
2
|
-
const commands = {
|
|
3
|
-
dev: () => import("./dev-Owu3e3AO.js").then((module) => module.default),
|
|
4
|
-
build: () => import("./build-DJcc95Yq.js").then((module) => module.default),
|
|
5
|
-
info: () => import("./info-CKJVMWIT.js").then((module) => module.default),
|
|
6
|
-
codegen: () => import("./codegen-aJSyPz-J.js").then((module) => module.default),
|
|
7
|
-
prepare: () => import("./prepare-BM93i3Rm.js").then((module) => module.default),
|
|
8
|
-
commands: () => import("./commands-Bh0K9iWX.js").then((module) => module.default),
|
|
9
|
-
doctor: () => import("./doctor-DEtAAknK.js").then((module) => module.default),
|
|
10
|
-
completions: () => import("./completions-DMPlZ0S1.js").then((module) => module.default)
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
//#endregion
|
|
14
|
-
export { commands as t };
|
|
15
|
-
//# sourceMappingURL=commands-CSB-pjgs.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"commands-CSB-pjgs.js","names":[],"sources":["../src/commands/index.ts"],"sourcesContent":["import type { CommandDef } from 'citty';\n\n// citty types each command by its own arguments; the registry needs the erased form.\n// oxlint-disable-next-line typescript/no-explicit-any\ntype AnyCommand = CommandDef<any>;\n\nexport const commands: Record<string, () => Promise<AnyCommand>> = {\n\tdev: () => import('./dev.js').then((module) => module.default),\n\tbuild: () => import('./build.js').then((module) => module.default),\n\tinfo: () => import('./info.js').then((module) => module.default),\n\tcodegen: () => import('./codegen.js').then((module) => module.default),\n\tprepare: () => import('./prepare.js').then((module) => module.default),\n\tcommands: () => import('./commands.js').then((module) => module.default),\n\tdoctor: () => import('./doctor.js').then((module) => module.default),\n\tcompletions: () => import('./completions.js').then((module) => module.default)\n};\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;CACvE,cAAc,OAAO,uBAAc,CAAC,MAAM,WAAW,OAAO,OAAO;CACnE,mBAAmB,OAAO,4BAAmB,CAAC,MAAM,WAAW,OAAO,OAAO;AAC9E"}
|
package/dist/dev-Owu3e3AO.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dev-Owu3e3AO.js","names":[],"sources":["../src/dev/changed-files.ts","../src/dev/typechecker.ts","../src/dev/dev-service.ts","../src/dev/host.ts","../src/dev/log-file.ts","../src/commands/dev.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { readdirSync, readFileSync, statSync } from 'node:fs';\nimport { basename, extname, join, sep } from 'node:path';\n\nconst SKIPPED_DIRECTORIES = new Set(['node_modules', '.git']);\n/**\n * `tsc -b` rewrites its build info on every build, whatever changed; a source map only ever changes with the file it\n * maps, and is most of what there would be to read.\n */\nconst SKIPPED_FILES = /\\.(?:tsbuildinfo|map)$/;\n\n/** The content hash of every file under the roots, by absolute path. */\nexport type FileSnapshot = ReadonlyMap<string, string>;\n\n/** What was last read of each file, so one that was not touched since is not read again. */\nexport type HashCache = Map<string, { size: number; mtimeMs: number; hash: string }>;\n\n/**\n * Hashes every file under `roots`, skipping `node_modules`, `.git` and everything under `exclude`.\n *\n * The builders only report that a build finished, and a bundler rewrites files it did not change (`tsdown` writes\n * its whole output on every rebuild), so neither an event nor a modification time says what a build changed: two\n * snapshots do (see {@link changedFiles}).\n */\nexport function snapshotFiles(roots: readonly string[], exclude: readonly string[] = [], cache: HashCache = new Map()): FileSnapshot {\n\tconst snapshot = new Map<string, string>();\n\tconst visit = (directory: string) => {\n\t\tlet entries;\n\t\ttry {\n\t\t\tentries = readdirSync(directory, { withFileTypes: true });\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const entry of entries) {\n\t\t\tconst path = join(directory, entry.name);\n\t\t\tif (exclude.some((excluded) => isInside(path, excluded))) continue;\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tif (!SKIPPED_DIRECTORIES.has(entry.name)) visit(path);\n\t\t\t} else if (entry.isFile() && !SKIPPED_FILES.test(entry.name)) {\n\t\t\t\ttry {\n\t\t\t\t\tconst { size, mtimeMs } = statSync(path);\n\t\t\t\t\tconst known = cache.get(path);\n\t\t\t\t\tconst hash =\n\t\t\t\t\t\tknown?.size === size && known.mtimeMs === mtimeMs\n\t\t\t\t\t\t\t? known.hash\n\t\t\t\t\t\t\t: createHash('sha1').update(readFileSync(path)).digest('base64');\n\t\t\t\t\tcache.set(path, { size, mtimeMs, hash });\n\t\t\t\t\tsnapshot.set(path, hash);\n\t\t\t\t} catch {\n\t\t\t\t\t// Removed between the listing and the read: the next build reports it.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tfor (const root of new Set(roots)) visit(root);\n\treturn snapshot;\n}\n\n/** The files that were added, removed, or whose content differs between two snapshots. */\nexport function changedFiles(previous: FileSnapshot, next: FileSnapshot): string[] {\n\tconst changed = [...next].filter(([path, hash]) => previous.get(path) !== hash).map(([path]) => path);\n\tfor (const path of previous.keys()) {\n\t\tif (!next.has(path)) changed.push(path);\n\t}\n\n\treturn changed;\n}\n\nconst PIECE_EXTENSIONS = new Set(['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts']);\n\n/**\n * Whether a file a store has not loaded yet could be a piece, by the rule the stores filter files with: a script\n * that is not a declaration file and whose name does not start with `_`.\n */\nexport function couldBePiece(path: string): boolean {\n\tconst extension = extname(path);\n\treturn PIECE_EXTENSIONS.has(extension) && !path.endsWith('.d.ts') && !basename(path, extension).startsWith('_');\n}\n\n/** Whether `path` is `directory` itself or lies under it. */\nexport function isInside(path: string, directory: string): boolean {\n\treturn path === directory || path.startsWith(directory.endsWith(sep) ? directory : `${directory}${sep}`);\n}\n","import type { ResolvedStarsConfig, StarsTypechecker } from '@wolfstar/schema';\nimport { spawn, type ChildProcess } from 'node:child_process';\nimport { EventEmitter } from 'node:events';\nimport type { Diagnostic } from 'nostics';\nimport { resolveTscBinary } from '../builders/tsc.js';\nimport { cliDiagnostics } from '../utils/diagnostics.js';\nimport type { LogLevel } from '../utils/log-buffer.js';\nimport { createLineSplitter } from '../utils/process-supervisor.js';\nimport { resolveBinary } from '../utils/project.js';\n\nconst WATCH_START = /Starting (incremental )?compilation/;\nconst WATCH_DONE = /Found (\\d+) errors?\\. Watching for file changes/;\nconst ONE_SHOT_DONE = /Found (\\d+) errors?/;\nconst ERROR_LINE = /error TS\\d+:/;\n\nexport type TypecheckState = 'idle' | 'checking' | 'ok' | 'failed';\n\nexport interface TypecheckerEvents {\n\tlog: [level: LogLevel, text: string];\n\tstate: [state: TypecheckState, errors: number];\n}\n\nexport interface TypecheckCommand {\n\t/** The executable, and whether it is a script `node` has to run. */\n\treadonly command: string;\n\treadonly args: readonly string[];\n\treadonly node: boolean;\n\t/** Whether the checker watches the project itself, or has to be re-run after every build. */\n\treadonly watch: boolean;\n}\n\n/**\n * Runs a type checker next to the bot and reports type errors on their own channel, without ever blocking builds or\n * restarts: `stars dev` keeps running whatever the build tool produced, the way Seedcord's `hmr.typecheck` and\n * Vite's `checker` plugin do.\n *\n * `tsc` and `golar` (which forwards to TypeScript) watch the project themselves; `tsz` has no watch mode, so\n * {@link Typechecker.check} re-runs it after every build instead.\n */\nexport class Typechecker extends EventEmitter<TypecheckerEvents> {\n\t#child: ChildProcess | null = null;\n\t#state: TypecheckState = 'idle';\n\t#errors = 0;\n\t#pending = false;\n\n\tpublic constructor(private readonly config: ResolvedStarsConfig) {\n\t\tsuper();\n\t}\n\n\tpublic get state(): TypecheckState {\n\t\treturn this.#state;\n\t}\n\n\tpublic get errors(): number {\n\t\treturn this.#errors;\n\t}\n\n\t/** Whether the checker re-runs per build instead of watching on its own. */\n\tpublic get oneShot(): boolean {\n\t\treturn this.config.dev.typecheck.enabled && !resolveTypecheckCommand(this.config).watch;\n\t}\n\n\tpublic start(): void {\n\t\tif (!this.config.dev.typecheck.enabled) return;\n\t\tthis.#run();\n\t}\n\n\t/**\n\t * Re-runs a checker that cannot watch. Called after every successful build; a run already in flight is replaced,\n\t * so a fast series of builds only leaves the last check standing.\n\t */\n\tpublic check(): void {\n\t\tif (!this.oneShot) return;\n\t\tif (this.#child) {\n\t\t\tthis.#pending = true;\n\t\t\tthis.#child.kill();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#run();\n\t}\n\n\tpublic close(): Promise<void> {\n\t\tconst child = this.#child;\n\t\tthis.#child = null;\n\t\tthis.#pending = false;\n\t\tif (!child || child.exitCode !== null) return Promise.resolve();\n\n\t\treturn new Promise((resolve) => {\n\t\t\tchild.once('exit', () => resolve());\n\t\t\tchild.kill();\n\t\t});\n\t}\n\n\t#run(): void {\n\t\tconst { command, args, node, watch } = resolveTypecheckCommand(this.config);\n\t\tconst child = spawn(node ? process.execPath : command, node ? [command, ...args] : [...args], {\n\t\t\tcwd: this.config.root,\n\t\t\tenv: process.env,\n\t\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\t\twindowsHide: true\n\t\t});\n\t\tthis.#child = child;\n\t\tthis.#setState('checking', 0);\n\n\t\tlet errors = 0;\n\t\tconst handleLine = (line: string) => {\n\t\t\tif (ERROR_LINE.test(line)) errors++;\n\t\t\tthis.#handleLine(line);\n\t\t};\n\n\t\tconst stdout = createLineSplitter(handleLine);\n\t\tconst stderr = createLineSplitter(handleLine);\n\t\tchild.stdout?.on('data', stdout.push);\n\t\tchild.stderr?.on('data', stderr.push);\n\n\t\tchild.once('exit', (code) => {\n\t\t\tstdout.flush();\n\t\t\tstderr.flush();\n\t\t\tthis.#child = null;\n\n\t\t\tif (!watch && this.#state === 'checking') {\n\t\t\t\t// A one-shot checker only reports through its exit code when it prints no summary line.\n\t\t\t\tthis.#setState(code === 0 && errors === 0 ? 'ok' : 'failed', errors);\n\t\t\t}\n\n\t\t\tif (this.#pending) {\n\t\t\t\tthis.#pending = false;\n\t\t\t\tthis.#run();\n\t\t\t}\n\t\t});\n\t\tchild.once('error', (error: NodeJS.ErrnoException) => {\n\t\t\tthis.#child = null;\n\t\t\tthis.emit('log', 'error', error.code === 'ENOENT' ? `${command} is not installed` : error.message);\n\t\t\tthis.#setState('failed', this.#errors);\n\t\t});\n\t}\n\n\t#handleLine(line: string): void {\n\t\tconst text = line.trim();\n\t\tif (text.length === 0) return;\n\n\t\tif (WATCH_START.test(text)) {\n\t\t\tthis.#setState('checking', 0);\n\t\t\treturn;\n\t\t}\n\n\t\tif (ERROR_LINE.test(text)) {\n\t\t\tthis.emit('log', 'error', text);\n\t\t\treturn;\n\t\t}\n\n\t\tconst done = WATCH_DONE.exec(text) ?? ONE_SHOT_DONE.exec(text);\n\t\tif (done) {\n\t\t\tconst errors = Number(done[1]);\n\t\t\tthis.#setState(errors === 0 ? 'ok' : 'failed', errors);\n\t\t\tthis.emit('log', errors === 0 ? 'success' : 'error', errors === 0 ? 'No type errors' : `${errors} type error${errors === 1 ? '' : 's'}`);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.emit('log', 'info', text);\n\t}\n\n\t#setState(state: TypecheckState, errors: number): void {\n\t\tthis.#state = state;\n\t\tthis.#errors = errors;\n\t\tthis.emit('state', state, errors);\n\t}\n}\n\n/**\n * Builds the command line of the configured type checker, resolved from the project's own `node_modules`.\n *\n * @throws {Diagnostic} when the checker is not installed in the project.\n */\nexport function resolveTypecheckCommand(config: ResolvedStarsConfig): TypecheckCommand {\n\tconst { checker, tsconfig } = config.dev.typecheck;\n\tconst project = tsconfig!;\n\n\tswitch (checker) {\n\t\tcase 'golar': {\n\t\t\t// `golar tsc` forwards everything after it to the TypeScript CLI, watch mode included.\n\t\t\tconst golar = resolveBinary(config.root, 'golar', 'golar');\n\t\t\tif (!golar) throw missing(config, 'golar', 'Install it with `pnpm add -D golar`');\n\n\t\t\treturn { command: golar, args: ['tsc', ...WATCH_ARGS, '-p', project], node: true, watch: true };\n\t\t}\n\n\t\tcase 'tsz': {\n\t\t\t// `tsz` is an early, tsc-compatible checker with no watch mode; `try-tsz` is its comparison harness.\n\t\t\tconst tsz = resolveBinary(config.root, '@mohsen-azimi/tsz-dev', 'tsz');\n\t\t\tif (tsz) return { command: tsz, args: ['--noEmit', '-p', project], node: true, watch: false };\n\n\t\t\tconst tryTsz = resolveBinary(config.root, 'try-tsz', 'try-tsz');\n\t\t\tif (tryTsz) return { command: tryTsz, args: ['-p', project], node: true, watch: false };\n\n\t\t\tthrow missing(config, 'tsz', 'Install it with `pnpm add -D @mohsen-azimi/tsz-dev` (or `try-tsz`)');\n\t\t}\n\n\t\tdefault: {\n\t\t\tconst tsc = resolveTscBinary(config.root);\n\t\t\tif (!tsc) throw missing(config, 'typescript', 'Install it with `pnpm add -D typescript`');\n\n\t\t\treturn { command: tsc, args: [...WATCH_ARGS, '-p', project], node: true, watch: true };\n\t\t}\n\t}\n}\n\nconst WATCH_ARGS = ['--noEmit', '--watch', '--preserveWatchOutput', '--pretty', 'false'] as const;\n\nfunction missing(config: ResolvedStarsConfig, name: string, install: string): Diagnostic {\n\treturn cliDiagnostics.DEPENDENCY_MISSING({\n\t\tname,\n\t\troot: config.root,\n\t\thint: `${install}, pick another \\`dev.typecheck.checker\\`, or set \\`dev.typecheck\\` to false.`\n\t});\n}\n\nexport type { StarsTypechecker };\n","import { EventEmitter } from 'node:events';\nimport type { Builder, BuildOutcome } from '../builders/types.js';\nimport { displayPath, type ResolvedStarsConfig, type StarsHooks, type StarsRestartReason } from '@wolfstar/schema';\nimport { describeCommand, diffSnapshots, type CommandChange } from '../utils/command-diff.js';\nimport { envImportArgs, moduleImportArgs } from '../utils/env-import.js';\nimport type { StarsHookable } from '../utils/hooks.js';\nimport { classifyAppLine, LogBuffer, type LogLevel, type LogSource } from '../utils/log-buffer.js';\nimport { Locales } from '../utils/locales.js';\nimport { ProcessSupervisor, type ProcessExit, type ProcessState } from '../utils/process-supervisor.js';\nimport { bridgeImportArgs, CLI_SOURCE, parseBridgeMessage, type BridgeMessage, type CommandSnapshot, type RefreshRequest } from './bridge.js';\nimport { changedFiles, couldBePiece, isInside, snapshotFiles, type FileSnapshot, type HashCache } from './changed-files.js';\nimport { Tunnel, type TunnelState } from './tunnel.js';\nimport { Typechecker, type TypecheckState } from './typechecker.js';\n\nexport type BuildState = 'idle' | 'building' | 'ok' | 'failed';\nexport type HealthState = 'unknown' | 'ok' | 'down';\nexport type RestartReason = StarsRestartReason;\n\n/** A question the dev UI asks the user; {@link DevService.answerPrompt} settles it. */\nexport interface DevPrompt {\n\treadonly kind: 'commands';\n\treadonly changes: readonly CommandChange[];\n}\n\nexport interface LogExtra {\n\t/** The channel to log on instead of the source's own. */\n\tchannel?: string;\n\tdetail?: readonly string[];\n}\n\nexport interface DevStatus {\n\treadonly progress: { readonly fraction: number; readonly message: string; readonly startedAt: number; readonly readyMs: number | null };\n\treadonly process: ProcessState;\n\treadonly build: BuildState;\n\treadonly health: HealthState;\n\treadonly pid: number | null;\n\treadonly startedAt: number | null;\n\treadonly restarts: number;\n\treadonly lastRestartReason: RestartReason | null;\n\treadonly lastBuild: BuildOutcome | null;\n\treadonly lastExit: ProcessExit | null;\n\treadonly url: string | null;\n\treadonly typecheck: TypecheckState;\n\treadonly typeErrors: number;\n\treadonly tunnel: TunnelState;\n\treadonly tunnelUrl: string | null;\n\t/** Whether the running bot reported that it is listening (see the bridge); always `false` without the bridge. */\n\treadonly ready: boolean;\n\t/** The port the bot reported it listens on. */\n\treadonly port: number | null;\n\t/** Whether the running bot reported that it hot reloads its pieces. */\n\treadonly hmr: boolean;\n\t/** Whether the bot was stopped on purpose (the `d` key) and waits for a restart. */\n\treadonly paused: boolean;\n\treadonly prompt: DevPrompt | null;\n}\n\nexport interface DevServiceEvents {\n\tstatus: [status: DevStatus];\n}\n\nexport interface DevServiceOptions {\n\tbuilder: Builder;\n\t/** The `stars.config` hooks; `build:*` and `dev:restart` run from here. */\n\thooks?: StarsHookable;\n\tlogs?: LogBuffer;\n\t/** Overrides for tests. */\n\tsupervisor?: ProcessSupervisor;\n\ttypechecker?: Typechecker;\n\ttunnel?: Tunnel;\n\thealthInterval?: number;\n}\n\n/**\n * The headless heart of `stars dev`: builds, (re)starts the bot and exposes state and logs.\n * Renderers (plain or TUI) only subscribe to it, they never own behaviour.\n */\nexport class DevService extends EventEmitter<DevServiceEvents> {\n\tpublic readonly logs: LogBuffer;\n\tpublic readonly builder: Builder;\n\tpublic readonly supervisor: ProcessSupervisor;\n\tpublic readonly typechecker: Typechecker;\n\tpublic readonly tunnel: Tunnel;\n\tpublic readonly locales: Locales;\n\t/** Whether something can answer a {@link DevPrompt}: the interactive UI sets it, the plain renderer cannot. */\n\tpublic promptable = false;\n\treadonly #hooks: StarsHookable | null;\n\t/** Runs hooks one at a time, so an async `build:done` settles before the next build's hooks or a restart. */\n\t#hookChain: Promise<void> = Promise.resolve();\n\n\t#build: BuildState = 'idle';\n\t#health: HealthState = 'unknown';\n\t#restarts = 0;\n\t#lastRestartReason: RestartReason | null = null;\n\t#lastBuild: BuildOutcome | null = null;\n\t#lastExit: ProcessExit | null = null;\n\t#restartTimer: NodeJS.Timeout | null = null;\n\t#healthTimer: NodeJS.Timeout | null = null;\n\t#pendingReason: RestartReason | null = null;\n\t#stopped = false;\n\t#queue: Promise<void> = Promise.resolve();\n\t#progress = { fraction: 0, message: 'preparing your app', startedAt: Date.now(), readyMs: null as number | null };\n\t#ready = false;\n\t#port: number | null = null;\n\t/** The store paths the running bot watches for hot reloads, empty when it does not. */\n\t#hmrPaths: string[] = [];\n\t#paused = false;\n\t#prompt: DevPrompt | null = null;\n\t/** The commands the bot last reported, kept across restarts: a restart is how most changes arrive. */\n\t#commands: CommandSnapshot | null = null;\n\t/** What the build output held after the previous build, `null` before the first one. */\n\t#files: FileSnapshot | null = null;\n\treadonly #hashes: HashCache = new Map();\n\t/** The files the running bot loaded pieces from: what its hot reload can replace. */\n\t#pieces = new Set<string>();\n\t/** The commands Discord is assumed to have: the first report of the session, then whatever was last deployed. */\n\t#deployed: CommandSnapshot | null = null;\n\t/** A refresh of the commands asked for while the bot was not listening; sent once it is. */\n\t#refreshPending = false;\n\n\tpublic constructor(\n\t\tpublic readonly config: ResolvedStarsConfig,\n\t\toptions: DevServiceOptions\n\t) {\n\t\tsuper();\n\t\tthis.logs = options.logs ?? new LogBuffer();\n\t\tthis.builder = options.builder;\n\t\tthis.supervisor = options.supervisor ?? createSupervisor(config);\n\t\tthis.typechecker = options.typechecker ?? new Typechecker(config);\n\t\tthis.tunnel = options.tunnel ?? new Tunnel(config);\n\t\tthis.locales = new Locales(config);\n\t\tthis.#hooks = options.hooks ?? null;\n\n\t\tthis.builder.on('start', () => {\n\t\t\tthis.#progress = { fraction: 0, message: 'preparing build', startedAt: Date.now(), readyMs: null };\n\t\t\tthis.#setBuild('building');\n\t\t\tvoid this.#startHook('build:before', this.config);\n\t\t});\n\t\tthis.builder.on('progress', (fraction, message) => {\n\t\t\tthis.#progress = { ...this.#progress, fraction: Math.max(this.#progress.fraction, Math.min(0.75, fraction)), message };\n\t\t\tthis.#emitStatus();\n\t\t});\n\t\tthis.builder.on('success', (outcome) => this.#onBuildSuccess(outcome));\n\t\tthis.builder.on('failure', (outcome) => this.#onBuildFailure(outcome));\n\t\tthis.builder.on('log', (level, text) => this.log('build', level, text));\n\n\t\tthis.supervisor.on('state', () => {\n\t\t\tif (this.supervisor.state === 'running') {\n\t\t\t\tthis.#settleProgress();\n\t\t\t\tvoid this.#checkHealth();\n\t\t\t}\n\t\t\tthis.#emitStatus();\n\t\t});\n\t\tthis.supervisor.on('stdout', (line) => this.log('app', classifyAppLine(line, 'info'), line));\n\t\tthis.supervisor.on('stderr', (line) => this.log('app', classifyAppLine(line, 'error'), line));\n\t\tthis.supervisor.on('message', (message) => {\n\t\t\tconst parsed = parseBridgeMessage(message);\n\t\t\tif (parsed === null) return;\n\t\t\ttry {\n\t\t\t\tthis.#onBridge(parsed);\n\t\t\t} catch (error) {\n\t\t\t\t// Whatever the bot sends, it must not take the session down.\n\t\t\t\tthis.log('stars', 'warn', `Ignored a ${parsed.type} message from the bot: ${error instanceof Error ? error.message : String(error)}`);\n\t\t\t}\n\t\t});\n\t\tthis.supervisor.on('error', (error) => this.log('stars', 'error', `Failed to start the bot: ${error.message}`));\n\t\tthis.supervisor.on('exit', (exit) => this.#onExit(exit));\n\n\t\tthis.typechecker.on('log', (level, text) => this.log('tsc', level, text));\n\t\tthis.typechecker.on('state', () => this.#emitStatus());\n\t\tthis.tunnel.on('log', (level, text) => this.log('tunnel', level, text));\n\t\tthis.tunnel.on('state', () => this.#emitStatus());\n\t\tthis.locales.on('log', (level, text) => this.log('build', level, text));\n\t\tthis.locales.on('change', () => {\n\t\t\tif (this.#build === 'ok') this.#scheduleRestart('build');\n\t\t});\n\n\t\tif (config.dev.url && config.dev.health) {\n\t\t\tconst interval = options.healthInterval ?? 5000;\n\t\t\tthis.#healthTimer = setInterval(() => void this.#checkHealth(), interval);\n\t\t\tthis.#healthTimer.unref();\n\t\t}\n\t}\n\n\tpublic get status(): DevStatus {\n\t\treturn {\n\t\t\tprogress: this.#progress,\n\t\t\tprocess: this.supervisor.state,\n\t\t\tbuild: this.#build,\n\t\t\thealth: this.#health,\n\t\t\tpid: this.supervisor.pid,\n\t\t\tstartedAt: this.supervisor.startedAt,\n\t\t\trestarts: this.#restarts,\n\t\t\tlastRestartReason: this.#lastRestartReason,\n\t\t\tlastBuild: this.#lastBuild,\n\t\t\tlastExit: this.#lastExit,\n\t\t\turl: this.config.dev.url,\n\t\t\ttypecheck: this.typechecker.state,\n\t\t\ttypeErrors: this.typechecker.errors,\n\t\t\ttunnel: this.tunnel.state,\n\t\t\ttunnelUrl: this.tunnel.url,\n\t\t\tready: this.#ready,\n\t\t\tport: this.#port,\n\t\t\thmr: this.#hmrPaths.length > 0,\n\t\t\tpaused: this.#paused,\n\t\t\tprompt: this.#prompt\n\t\t};\n\t}\n\n\tpublic log(source: LogSource, level: LogLevel, text: string, extra: LogExtra = {}): void {\n\t\tthis.logs.push({ source, level, text, ...extra });\n\t}\n\n\t/**\n\t * Starts watching; the bot starts after the first successful build.\n\t */\n\tpublic async start(): Promise<void> {\n\t\tthis.#stopped = false;\n\t\tconst entry = displayPath(this.config.root, this.config.entry);\n\t\tthis.log('stars', 'info', this.config.build.tool === 'none' ? `Watching ${entry}` : `Watching ${entry} with ${this.config.build.tool}`);\n\t\tif (this.config.dev.typecheck.enabled) this.typechecker.start();\n\t\tawait this.locales.watch();\n\t\t// The tunnel comes up next to the build: neither waits for the other, and a failed tunnel never stops the bot.\n\t\tvoid this.tunnel.start();\n\t\tawait this.builder.watch();\n\t}\n\n\t/**\n\t * Restarts the bot immediately (used by the `r` key and by `SIGUSR2`).\n\t */\n\tpublic restart(reason: RestartReason = 'manual'): Promise<void> {\n\t\tthis.#clearRestartTimer();\n\t\treturn this.#enqueue(async () => {\n\t\t\tif (this.#stopped) return;\n\t\t\tawait this.#queueHook('dev:restart', reason, this.config);\n\t\t\tif (this.#stopped) return;\n\t\t\tif (reason === 'manual' || reason === 'crash') {\n\t\t\t\tthis.#progress = { fraction: 0, message: 'restarting the bot', startedAt: Date.now(), readyMs: null };\n\t\t\t}\n\t\t\tthis.#lastRestartReason = reason;\n\t\t\tif (this.supervisor.running) {\n\t\t\t\tthis.#restarts++;\n\t\t\t\tthis.log('stars', 'info', `Restarting (${describeReason(reason)})`);\n\t\t\t\tawait this.supervisor.stop();\n\t\t\t} else {\n\t\t\t\tthis.log('stars', 'info', `Starting (${describeReason(reason)})`);\n\t\t\t}\n\n\t\t\tif (this.#stopped) return;\n\t\t\tthis.#progress = { ...this.#progress, fraction: 0.75, message: 'starting the bot' };\n\t\t\tthis.#health = 'unknown';\n\t\t\tthis.#paused = false;\n\t\t\tthis.supervisor.start();\n\t\t\tthis.#emitStatus();\n\t\t});\n\t}\n\n\t/**\n\t * Stops the bot and leaves it stopped (the `d` key): builds keep running, but nothing starts the bot again until\n\t * {@link restart}. For when the bot must be off without ending the session.\n\t */\n\tpublic disconnect(): Promise<void> {\n\t\tthis.#clearRestartTimer();\n\t\treturn this.#enqueue(async () => {\n\t\t\tif (this.#stopped || this.#paused) return;\n\t\t\tthis.#paused = true;\n\t\t\tthis.log('stars', 'info', 'Stopped the bot, press r to start it again');\n\t\t\tawait this.supervisor.stop();\n\t\t\tthis.#emitStatus();\n\t\t});\n\t}\n\n\t/** Settles the pending {@link DevPrompt}: `true` does what it asks, `false` dismisses it. */\n\tpublic answerPrompt(accept: boolean): void {\n\t\tconst prompt = this.#prompt;\n\t\tif (prompt === null) return;\n\t\tthis.#prompt = null;\n\t\tif (accept) this.refreshCommands();\n\t\telse this.log('stars', 'info', 'Kept the deployed commands as they are', { channel: 'commands' });\n\t\tthis.#emitStatus();\n\t}\n\n\t/** Asks the bot to register its commands with Discord again. The bot answers on the `commands` channel. */\n\tpublic refreshCommands(): void {\n\t\t// A bot that is stopped or restarting has no client to register anything with: the refresh waits for it to listen.\n\t\tif (!this.#ready) {\n\t\t\tthis.#refreshPending = true;\n\t\t\tconst when = this.supervisor.running ? 'once the bot is ready' : 'when the bot starts again';\n\t\t\tthis.log('stars', 'info', `Refreshing commands ${when}…`, { channel: 'commands' });\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#refreshPending = false;\n\t\tconst current = this.#commands?.guilds ?? {};\n\t\tconst request: RefreshRequest = {\n\t\t\tsource: CLI_SOURCE,\n\t\t\ttype: 'commands:refresh',\n\t\t\tclearGuilds: Object.keys(this.#deployed?.guilds ?? {}).filter((guild) => !Object.hasOwn(current, guild))\n\t\t};\n\t\tif (this.supervisor.send(request)) {\n\t\t\tthis.log('stars', 'info', 'Refreshing commands…', { channel: 'commands' });\n\t\t} else {\n\t\t\tthis.log('stars', 'warn', 'Could not reach the bot to refresh its commands', { channel: 'commands' });\n\t\t}\n\t}\n\n\t/** Opens or closes the public tunnel (used by the `t` key). */\n\tpublic toggleTunnel(): Promise<void> {\n\t\treturn this.tunnel.toggle();\n\t}\n\n\t/**\n\t * Stops the watcher and the bot. Safe to call more than once.\n\t */\n\tpublic async stop(): Promise<void> {\n\t\tthis.#stopped = true;\n\t\tthis.#clearRestartTimer();\n\t\tif (this.#healthTimer) clearInterval(this.#healthTimer);\n\t\tthis.#healthTimer = null;\n\t\tawait this.#enqueue(async () => {\n\t\t\tawait Promise.allSettled([\n\t\t\t\tthis.builder.close(),\n\t\t\t\tthis.supervisor.stop(),\n\t\t\t\tthis.typechecker.close(),\n\t\t\t\tthis.tunnel.close(),\n\t\t\t\tthis.locales.close()\n\t\t\t]);\n\t\t});\n\t}\n\n\t/**\n\t * Kills the bot and the helper processes without waiting for them. Only for a forced shutdown, {@link stop} is the graceful path.\n\t */\n\tpublic kill(): void {\n\t\tthis.#stopped = true;\n\t\tthis.#clearRestartTimer();\n\t\tthis.supervisor.kill();\n\t\tvoid this.typechecker.close();\n\t\tvoid this.tunnel.close();\n\t}\n\n\tpublic clearLogs(): void {\n\t\tthis.logs.clear();\n\t}\n\n\t#onBuildSuccess(outcome: BuildOutcome): void {\n\t\t// Before the locales are copied: the copy rewrites every file, which is not what the build changed.\n\t\tconst hot = this.#hotReloadable();\n\t\ttry {\n\t\t\tthis.locales.copy();\n\t\t} catch (error) {\n\t\t\tthis.#onBuildFailure({\n\t\t\t\t...outcome,\n\t\t\t\tok: false,\n\t\t\t\tmessage: `Failed to copy locales: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tthis.#lastBuild = outcome;\n\t\tthis.#progress = { ...this.#progress, fraction: 0.75, message: 'starting the bot' };\n\t\tthis.#setBuild('ok');\n\t\t// Only once locales are copied: until then the build is not done, and may still fail.\n\t\tvoid this.#queueHook('build:done', outcome, this.config);\n\t\tif (this.#stopped) return;\n\t\t// A checker without a watch mode (`tsz`) only knows about the change once the build is through.\n\t\tthis.typechecker.check();\n\t\tthis.log('stars', 'success', this.builder.tool === 'none' ? 'Sources changed' : `Build succeeded in ${outcome.durationMs}ms`);\n\t\tif (this.#paused) return;\n\t\tif (hot !== null) {\n\t\t\tfor (const file of hot) this.log('stars', 'trace', `UPDATE ${displayPath(this.config.root, file)}`, { channel: 'hmr' });\n\t\t\tthis.#settleProgress();\n\t\t\tthis.#emitStatus();\n\t\t\treturn;\n\t\t}\n\t\tthis.#scheduleRestart(this.supervisor.state === 'idle' ? 'initial' : 'build');\n\t}\n\n\t/**\n\t * The files the build rewrote when all of them are pieces the running bot hot reloads, `null` when the bot has to\n\t * be restarted instead: it is not running, it does not hot reload, `dev.hmr` is off, nothing changed (a rebuild for\n\t * a reason that cannot be seen from the output), or a file changed that the bot cannot replace. What a build changed\n\t * is the difference in content with the previous output, since a bundler rewrites files it did not change.\n\t *\n\t * The bot replaces the files it loaded pieces from, and loads a new file that could be one. A helper module next to\n\t * the pieces (`_shared.js`, or any file no piece came from) is imported once and stays as it was: changing it\n\t * needs a restart, even though it lies in a store path.\n\t */\n\t#hotReloadable(): string[] | null {\n\t\tif (this.config.dev.hmr === false) return null;\n\n\t\tconst roots = this.config.build.tool === 'none' ? this.config.dev.watch : [this.config.build.outDir];\n\t\tconst previous = this.#files;\n\t\tthis.#files = snapshotFiles(roots, [this.locales.destination], this.#hashes);\n\t\tif (previous === null || this.#hmrPaths.length === 0 || this.supervisor.state !== 'running') return null;\n\n\t\tconst changed = changedFiles(previous, this.#files);\n\t\tconst replaceable = (file: string) =>\n\t\t\tthis.#hmrPaths.some((path) => isInside(file, path)) && (this.#pieces.has(file) || (!previous.has(file) && couldBePiece(file)));\n\t\treturn changed.length > 0 && changed.every(replaceable) ? changed : null;\n\t}\n\n\t#onBuildFailure(outcome: BuildOutcome): void {\n\t\tthis.#lastBuild = outcome;\n\t\tvoid this.#queueHook('build:done', outcome, this.config);\n\t\tthis.#setBuild('failed');\n\t\tthis.#clearRestartTimer();\n\t\tthis.log('stars', 'error', `Build failed${outcome.message ? `: ${outcome.message}` : ''}, waiting for changes`);\n\t}\n\n\t#onExit(exit: ProcessExit): void {\n\t\tthis.#lastExit = exit;\n\t\tthis.#health = 'unknown';\n\t\tthis.#ready = false;\n\t\tthis.#port = null;\n\t\tthis.#hmrPaths = [];\n\t\tthis.#pieces.clear();\n\t\t// A pending prompt stays: the commands still differ from what Discord has, and the next process can deploy them.\n\t\tif (!exit.requested) {\n\t\t\tconst how = exit.signal ? `signal ${exit.signal}` : `code ${exit.code}`;\n\t\t\tthis.log('stars', exit.code === 0 ? 'warn' : 'error', `The bot exited with ${how}, waiting for changes (press r to restart)`);\n\t\t}\n\t\tthis.#emitStatus();\n\t}\n\n\t#scheduleRestart(reason: RestartReason): void {\n\t\tif (this.#paused) return;\n\t\tthis.#pendingReason = reason;\n\t\tthis.#clearRestartTimer();\n\t\tthis.#restartTimer = setTimeout(() => {\n\t\t\tthis.#restartTimer = null;\n\t\t\tconst pending = this.#pendingReason ?? reason;\n\t\t\tthis.#pendingReason = null;\n\t\t\tvoid this.restart(pending);\n\t\t}, this.config.dev.debounce);\n\t}\n\n\t#clearRestartTimer(): void {\n\t\tif (this.#restartTimer) clearTimeout(this.#restartTimer);\n\t\tthis.#restartTimer = null;\n\t}\n\n\t#enqueue(task: () => Promise<void>): Promise<void> {\n\t\tthis.#queue = this.#queue.then(task, task);\n\t\treturn this.#queue;\n\t}\n\n\t#setBuild(state: BuildState): void {\n\t\tif (this.#build === state) return;\n\t\tthis.#build = state;\n\t\tthis.#emitStatus();\n\t}\n\n\tasync #checkHealth(): Promise<void> {\n\t\tif (!this.supervisor.running || !this.config.dev.url || !this.config.dev.health) return;\n\t\tconst pid = this.supervisor.pid;\n\n\t\tlet next: HealthState;\n\t\ttry {\n\t\t\tconst response = await fetch(new URL(this.config.dev.health, this.config.dev.url), { signal: AbortSignal.timeout(2000) });\n\t\t\tnext = response.status < 500 ? 'ok' : 'down';\n\t\t} catch {\n\t\t\tnext = 'down';\n\t\t}\n\n\t\tif (this.#stopped || pid !== this.supervisor.pid) return;\n\t\tif (next !== this.#health) {\n\t\t\tthis.#health = next;\n\t\t\tif (next === 'ok') this.#settleProgress();\n\t\t\tthis.#emitStatus();\n\t\t}\n\t}\n\n\t#settleProgress(): void {\n\t\tif (this.config.dev.health && this.#health !== 'ok') return;\n\t\tif (this.#build !== 'ok') return;\n\t\tthis.#progress = {\n\t\t\t...this.#progress,\n\t\t\tfraction: 1,\n\t\t\tmessage: 'watching for changes',\n\t\t\treadyMs: this.#progress.readyMs ?? Date.now() - this.#progress.startedAt\n\t\t};\n\t}\n\n\t/** Turns what the bot reports over the bridge into log entries and status. */\n\t#onBridge(message: BridgeMessage): void {\n\t\tconst relative = (path: string) => displayPath(this.config.root, path);\n\t\tswitch (message.type) {\n\t\t\tcase 'ready':\n\t\t\t\tthis.#ready = true;\n\t\t\t\tthis.#port = message.port;\n\t\t\t\tthis.log('stars', 'success', message.port === null ? 'The bot is ready' : `Listening on port ${message.port}`, {\n\t\t\t\t\tchannel: 'lifecycle'\n\t\t\t\t});\n\t\t\t\tif (this.#refreshPending) this.refreshCommands();\n\t\t\t\tthis.#emitStatus();\n\t\t\t\treturn;\n\t\t\tcase 'pieces':\n\t\t\t\tfor (const piece of message.pieces) this.#pieces.add(piece.path);\n\t\t\t\tif (message.pieces.length === 0) return;\n\t\t\t\tthis.log('stars', 'debug', `Loaded ${message.store}: ${message.pieces.length} ${message.pieces.length === 1 ? 'piece' : 'pieces'}`, {\n\t\t\t\t\tchannel: message.store === 'commands' ? 'commands' : 'lifecycle',\n\t\t\t\t\tdetail: message.pieces.map((piece) => `${piece.name} ${relative(piece.path)}`)\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\tcase 'hmr':\n\t\t\t\tthis.#onHmr(message);\n\t\t\t\treturn;\n\t\t\tcase 'commands':\n\t\t\t\tthis.#onCommands({ global: message.global, guilds: message.guilds });\n\t\t\t\treturn;\n\t\t\tcase 'dispatch':\n\t\t\t\tif (message.phase === 'run') {\n\t\t\t\t\tthis.log('stars', 'debug', `Processing ${message.route} with ${message.piece}`, { channel: 'interactions' });\n\t\t\t\t} else if (message.phase === 'success') {\n\t\t\t\t\tthis.log('stars', 'trace', `${message.route} handled${formatMs(message.ms)}`, { channel: 'interactions' });\n\t\t\t\t} else {\n\t\t\t\t\tthis.log('stars', 'error', `${message.route} failed${formatMs(message.ms)}: ${message.error.message}`, {\n\t\t\t\t\t\tchannel: 'interactions',\n\t\t\t\t\t\tdetail: message.error.stack\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\tcase 'request':\n\t\t\t\tthis.log('stars', message.status >= 500 ? 'error' : message.status >= 400 ? 'warn' : 'trace', formatRequest(message), {\n\t\t\t\t\tchannel: 'http'\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\tcase 'refreshed':\n\t\t\t\tif (message.ok) {\n\t\t\t\t\tthis.#deployed = this.#commands;\n\t\t\t\t\tconst guilds =\n\t\t\t\t\t\t(message.guilds > 0 ? `, ${message.guilds} guild ${message.guilds === 1 ? 'group' : 'groups'}` : '') +\n\t\t\t\t\t\t(message.cleared > 0 ? `, cleared ${message.cleared} ${message.cleared === 1 ? 'guild' : 'guilds'}` : '');\n\t\t\t\t\tthis.log('stars', 'success', `Deployed ${message.global} global ${message.global === 1 ? 'command' : 'commands'}${guilds}`, {\n\t\t\t\t\t\tchannel: 'commands'\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthis.log('stars', 'error', `Could not refresh the commands: ${message.message}`, { channel: 'commands', detail: message.stack });\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\tcase 'log':\n\t\t\t\tthis.log('app', toLogLevel(message.level), message.text, { channel: message.channel, detail: message.detail });\n\t\t\t\treturn;\n\t\t}\n\t}\n\n\t#onHmr(message: Extract<BridgeMessage, { type: 'hmr' }>): void {\n\t\tconst relative = (path: string) => displayPath(this.config.root, path);\n\t\tif (message.event === 'start') {\n\t\t\tthis.#hmrPaths = message.paths;\n\t\t\tthis.log('stars', 'debug', `Hot reload on, watching ${message.paths.length} ${message.paths.length === 1 ? 'path' : 'paths'}`, {\n\t\t\t\tchannel: 'hmr',\n\t\t\t\tdetail: message.paths.map(relative)\n\t\t\t});\n\t\t\tthis.#emitStatus();\n\t\t\treturn;\n\t\t}\n\n\t\tif (message.event === 'stop') {\n\t\t\t// Nothing in the bot watches any more: the next change needs a restart again.\n\t\t\tthis.#hmrPaths = [];\n\t\t\tthis.log('stars', 'debug', 'Hot reload off', { channel: 'hmr' });\n\t\t\tthis.#emitStatus();\n\t\t\treturn;\n\t\t}\n\n\t\tif (message.event === 'error') {\n\t\t\tthis.log('stars', 'error', `Could not reload ${relative(message.path)}: ${message.message}`, { channel: 'hmr', detail: message.stack });\n\t\t\treturn;\n\t\t}\n\n\t\tif (message.event === 'unloaded') this.#pieces.delete(message.path);\n\t\telse this.#pieces.add(message.path);\n\t\tconst verb = message.event === 'reloaded' ? 'Reloaded' : message.event === 'loaded' ? 'Loaded' : 'Unloaded';\n\t\tthis.log('stars', 'debug', `${verb} ${message.names.join(', ')} from ${relative(message.path)}`, { channel: 'hmr' });\n\t}\n\n\t/**\n\t * Compares the commands the bot registers with the ones it reported before. The first report of a session is the\n\t * baseline; a later one that differs is acted on as `dev.commands.refresh` says.\n\t */\n\t#onCommands(snapshot: CommandSnapshot): void {\n\t\tconst previous = this.#commands;\n\t\tthis.#commands = snapshot;\n\t\tif (previous === null) {\n\t\t\tthis.#deployed = snapshot;\n\t\t\tconst guilds = Object.keys(snapshot.guilds).length;\n\t\t\tthis.log('stars', 'debug', `Loaded commands: ${snapshot.global.length} global, ${guilds} guild ${guilds === 1 ? 'group' : 'groups'}`, {\n\t\t\t\tchannel: 'commands',\n\t\t\t\tdetail: snapshot.global.map((command) => describeCommand({ name: command.name, type: command.type ?? 1, guild: null }))\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst changes = diffSnapshots(previous, snapshot);\n\t\tif (changes.length === 0) return;\n\n\t\tconst detail = changes.map((change) => `${change.kind} ${describeCommand(change)}`);\n\t\tconst mode = this.config.dev.commands?.refresh ?? 'prompt';\n\t\tif (mode === 'auto') {\n\t\t\tthis.log('stars', 'info', 'Commands updated', { channel: 'commands', detail });\n\t\t\tthis.refreshCommands();\n\t\t\treturn;\n\t\t}\n\n\t\tif (mode === 'off' || !this.promptable) {\n\t\t\tthis.log('stars', 'warn', 'Commands updated, Discord still has the previous ones', {\n\t\t\t\tchannel: 'commands',\n\t\t\t\tdetail: [...detail, mode === 'off' ? 'dev.commands.refresh is off' : 'Set dev.commands.refresh to \"auto\" to redeploy without asking']\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// A second change before the first was answered asks once, about all of it.\n\t\tthis.#prompt = { kind: 'commands', changes: mergeChanges(this.#prompt?.changes ?? [], changes) };\n\t\tthis.log('stars', 'info', 'Commands updated', { channel: 'commands', detail });\n\t\tthis.#emitStatus();\n\t}\n\n\t/**\n\t * Runs a hook behind the ones already running (see {@link DevService.#hookChain}), e.g. `dev:close` so shutdown\n\t * waits for an unfinished `build:done`.\n\t */\n\tpublic runHook<Name extends keyof StarsHooks>(name: Name, ...args: Parameters<StarsHooks[Name]>): Promise<void> {\n\t\treturn this.#queueHook(name, ...args);\n\t}\n\n\t/** Queues a hook behind the ones already running; see {@link DevService.#hookChain}. */\n\t#queueHook<Name extends keyof StarsHooks>(name: Name, ...args: Parameters<StarsHooks[Name]>): Promise<void> {\n\t\tthis.#hookChain = this.#hookChain.then(() => this.#callHook(name, ...args));\n\t\treturn this.#hookChain;\n\t}\n\n\t/**\n\t * Starts a hook right away, at the moment it describes, instead of queueing it: `build:before` belongs to the\n\t * builder's `start` boundary, and a builder such as `none` finishes in the same call stack. Its synchronous part\n\t * runs here; later hooks still wait for the rest.\n\t */\n\t#startHook<Name extends keyof StarsHooks>(name: Name, ...args: Parameters<StarsHooks[Name]>): Promise<void> {\n\t\tconst running = this.#callHook(name, ...args);\n\t\tthis.#hookChain = Promise.all([this.#hookChain, running]).then(() => undefined);\n\t\treturn running;\n\t}\n\n\t/**\n\t * Runs a `stars.config` hook. A failing hook is logged rather than thrown: a broken hook must never stop the\n\t * watcher or keep the bot from restarting.\n\t */\n\tasync #callHook<Name extends keyof StarsHooks>(name: Name, ...args: Parameters<StarsHooks[Name]>): Promise<void> {\n\t\tif (this.#hooks === null) return;\n\t\ttry {\n\t\t\tawait this.#hooks.callHook(name, ...args);\n\t\t} catch (error) {\n\t\t\tthis.log('stars', 'error', `Hook ${name} failed: ${error instanceof Error ? error.message : String(error)}`);\n\t\t}\n\t}\n\n\t#emitStatus(): void {\n\t\tthis.emit('status', this.status);\n\t}\n}\n\nexport function createSupervisor(config: ResolvedStarsConfig): ProcessSupervisor {\n\treturn new ProcessSupervisor({\n\t\tcommand: process.execPath,\n\t\targs: [\n\t\t\t...envImportArgs(config),\n\t\t\t...moduleImportArgs(config),\n\t\t\t...bridgeImportArgs(config),\n\t\t\t...config.dev.nodeArgs,\n\t\t\tconfig.build.output,\n\t\t\t...config.dev.args\n\t\t],\n\t\tcwd: config.root,\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t...config.dev.env,\n\t\t\tSTARS_DEV: '1',\n\t\t\tNODE_ENV: 'development',\n\t\t\tFORCE_COLOR: process.env.NO_COLOR !== undefined ? undefined : (process.env.FORCE_COLOR ?? (process.stdout.isTTY ? '1' : undefined))\n\t\t},\n\t\tkillTimeout: config.dev.killTimeout,\n\t\tipc: true\n\t});\n}\n\nfunction formatMs(ms: number | null): string {\n\treturn ms === null ? '' : ` in ${ms}ms`;\n}\n\nfunction formatRequest(message: Extract<BridgeMessage, { type: 'request' }>): string {\n\treturn `${message.method} ${message.path} ${message.status} in ${message.ms}ms`;\n}\n\nconst BRIDGE_LEVELS = new Set<string>(['trace', 'debug', 'info', 'success', 'warn', 'error']);\n\nfunction toLogLevel(level: string): LogLevel {\n\treturn BRIDGE_LEVELS.has(level) ? (level as LogLevel) : 'info';\n}\n\n/** The latest change of each command wins: `added` then `changed` is still one line of the prompt. */\nfunction mergeChanges(previous: readonly CommandChange[], next: readonly CommandChange[]): CommandChange[] {\n\tconst key = (change: CommandChange) => `${change.guild ?? ''}:${change.type}:${change.name}`;\n\tconst merged = new Map(previous.map((change) => [key(change), change]));\n\tfor (const change of next) merged.set(key(change), change);\n\treturn [...merged.values()];\n}\n\nexport function describeReason(reason: RestartReason): string {\n\tswitch (reason) {\n\t\tcase 'initial':\n\t\t\treturn 'first build';\n\t\tcase 'build':\n\t\t\treturn 'sources changed';\n\t\tcase 'manual':\n\t\t\treturn 'manual restart';\n\t\tcase 'crash':\n\t\t\treturn 'after crash';\n\t}\n}\n","import { lookup } from 'node:dns/promises';\n\n/**\n * Resolves `localhost` the way Vite's dev server does: Node's default DNS result order (`dns.lookup('localhost')`)\n * can disagree with the OS's own, \"verbatim\" resolution order — a well known source of a dev URL that prints fine\n * but is not the address the bot actually bound to (e.g. an IPv6-first system where the server listens on IPv4\n * only). When the two disagree this returns the OS's own address instead of the literal `localhost` hostname.\n */\nexport async function resolveLocalhost(): Promise<string> {\n\ttry {\n\t\tconst [ordered, verbatim] = await Promise.all([lookup('localhost'), lookup('localhost', { verbatim: true })]);\n\t\treturn ordered.family === verbatim.family && ordered.address === verbatim.address ? 'localhost' : verbatim.address;\n\t} catch {\n\t\treturn 'localhost';\n\t}\n}\n\n/**\n * Replaces a `localhost` hostname in `url` with {@link resolveLocalhost}'s result. Any other hostname (an explicit\n * `dev.url` override, a LAN address, …) is returned untouched.\n */\nexport async function withResolvedLocalhost(url: string): Promise<string> {\n\tconst parsed = new URL(url);\n\tif (parsed.hostname !== 'localhost') return url;\n\n\tconst host = await resolveLocalhost();\n\tif (host === 'localhost') return url;\n\n\tparsed.hostname = host.includes(':') ? `[${host}]` : host;\n\treturn parsed.href;\n}\n","import { createWriteStream, mkdirSync, readdirSync, rmSync, type WriteStream } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { stripVTControlCharacters } from 'node:util';\nimport type { LogBuffer, LogEntry } from '../utils/log-buffer.js';\n\n/**\n * Mirrors a dev session's logs into a file, so a run can be read back after the terminal UI is gone (the TUI takes\n * over the alternate screen and its scrollback disappears on exit). `dev.logFile` is a single file truncated on every\n * run; `dev.logs.dir` adds one file per run (see {@link runLogFile}).\n */\nexport class LogFileWriter {\n\t#stream: WriteStream | null = null;\n\n\tpublic constructor(\n\t\tpublic readonly file: string,\n\t\tprivate readonly logs: LogBuffer\n\t) {}\n\n\tpublic open(): void {\n\t\tif (this.#stream) return;\n\n\t\tmkdirSync(dirname(this.file), { recursive: true });\n\t\tthis.#stream = createWriteStream(this.file, { flags: 'w' });\n\t\t// A broken pipe or a read-only directory must never take the dev session down with it.\n\t\tthis.#stream.on('error', () => this.close());\n\n\t\tfor (const entry of this.logs.entries()) this.#write(entry);\n\t\tthis.logs.on('entry', this.#write);\n\t}\n\n\tpublic close(): void {\n\t\tconst stream = this.#stream;\n\t\tthis.#stream = null;\n\t\tif (!stream) return;\n\n\t\tthis.logs.off('entry', this.#write);\n\t\tstream.end();\n\t}\n\n\t#write = (entry: LogEntry): void => {\n\t\tthis.#stream?.write(`${formatLogLine(entry)}\\n`);\n\t};\n}\n\n/** One line per entry, then its detail lines indented under it. Never filtered: the file is the whole session. */\nexport function formatLogLine(entry: LogEntry): string {\n\tconst head = `${new Date(entry.time).toISOString()} ${entry.level.padEnd(7)} ${entry.channel.padEnd(12)} ${stripVTControlCharacters(entry.text)}`;\n\treturn [head, ...(entry.detail ?? []).map((line) => ` ${stripVTControlCharacters(line)}`)].join('\\n');\n}\n\nconst RUN_FILE = /^dev-.+\\.log$/;\n\n/**\n * The file of this run inside `dev.logs.dir` (`dev-<timestamp>.log`), after deleting the oldest ones so the directory\n * holds at most `keep` files with the new one. The names sort by time, so no file needs to be opened to order them.\n */\nexport function runLogFile(directory: string, keep: number, now: Date = new Date()): string {\n\tlet existing: string[] = [];\n\ttry {\n\t\texisting = readdirSync(directory)\n\t\t\t.filter((name) => RUN_FILE.test(name))\n\t\t\t.sort();\n\t} catch {\n\t\t// The directory does not exist yet: nothing to prune.\n\t}\n\n\tfor (const name of existing.slice(0, Math.max(0, existing.length - Math.max(0, keep - 1)))) {\n\t\trmSync(join(directory, name), { force: true });\n\t}\n\n\treturn join(directory, `dev-${now.toISOString().replaceAll(':', '-')}.log`);\n}\n","import type { ResolvedStarsConfig } from '@wolfstar/schema';\nimport { defineCommand } from 'citty';\nimport { createBuilder } from '../builders/index.js';\nimport { DevService } from '../dev/dev-service.js';\nimport { withResolvedLocalhost } from '../dev/host.js';\nimport { LogFileWriter, runLogFile } from '../dev/log-file.js';\nimport { initialLogView, isLogLevel } from '../dev/tui/log-view.js';\nimport { collectFlag, projectArgs, resolveCwd, type ProjectArgs } from '../utils/args.js';\nimport { cliDiagnostics } from '../utils/diagnostics.js';\nimport { ExitCode, renderCrashReport } from '../utils/errors.js';\nimport { applyEnvOptions, loadProject, withProjectEnv } from '../utils/hooks.js';\nimport { prefersReducedMotion, resolveOutputMode, shouldUseColor } from '../utils/output-mode.js';\nimport { THEME_SETTINGS, isThemeSetting, readSavedTheme, resolveThemeSetting, saveTheme } from '../utils/theme.js';\nimport { prepareProject, reportWarnings } from './_shared.js';\n\nexport interface DevTaskOptions extends ProjectArgs {\n\ttui?: boolean;\n\t/** `--theme`. */\n\ttheme?: string;\n\t/** `--layout`. */\n\tlayout?: string;\n\t/** `--channel`, each value possibly a comma-separated list. */\n\tchannel?: string[];\n\t/** `--level`. */\n\tlevel?: string;\n}\n\nconst LAYOUTS = ['auto', 'dashboard', 'panel'] as const;\nconst LEVELS = ['trace', 'debug', 'info', 'warn', 'error'] as const;\n\nexport async function runDev(options: DevTaskOptions): Promise<void> {\n\tif (options.theme !== undefined && !isThemeSetting(options.theme)) {\n\t\tthrow cliDiagnostics.INVALID_THEME({ theme: options.theme, themes: THEME_SETTINGS.join(', ') });\n\t}\n\n\tconst layout = options.layout as (typeof LAYOUTS)[number] | undefined;\n\tif (layout !== undefined && !LAYOUTS.includes(layout)) {\n\t\tthrow cliDiagnostics.INVALID_OPTION({ option: '--layout', value: options.layout!, allowed: LAYOUTS.join(', ') });\n\t}\n\n\tif (options.level !== undefined && !isLogLevel(options.level)) {\n\t\tthrow cliDiagnostics.INVALID_OPTION({ option: '--level', value: options.level, allowed: LEVELS.join(', ') });\n\t}\n\n\t// Dev mode applies to config evaluation, build plugins, and the supervised application — not only the child.\n\tprocess.env.NODE_ENV = 'development';\n\tconst project = await loadProject({ cwd: resolveCwd(options), configFile: options.config, env: { ...process.env, NODE_ENV: 'development' } });\n\tconst hooks = project.hooks;\n\t// `env:options` first: it may pick env files with another `HTTP_PORT`, which `dev.url` is derived from.\n\tconst config = await resolveDevConfig(withProjectEnv(await applyEnvOptions(project.config, hooks)));\n\tconst mode = resolveOutputMode({ tui: options.tui });\n\tconst color = shouldUseColor();\n\tconst theme = resolveThemeSetting({ flag: options.theme, saved: readSavedTheme() });\n\n\tconst builder = await createBuilder(config, hooks);\n\tawait hooks.callHook('builder:created', builder, config);\n\tconst service = new DevService(config, { builder, hooks });\n\tawait reportWarnings(config, (text) => service.log('stars', 'warn', text), { production: false });\n\t// The files receive every entry: the filter below only decides what the terminal shows.\n\tconst logFiles = [\n\t\t...(config.dev.logFile ? [config.dev.logFile] : []),\n\t\t...(config.dev.logs?.dir ? [runLogFile(config.dev.logs.dir, config.dev.logs.keep)] : [])\n\t].map((file) => new LogFileWriter(file, service.logs));\n\tfor (const file of logFiles) file.open();\n\tconst filter = initialLogView(config, { channels: options.channel, level: options.level });\n\tconst renderer =\n\t\tmode === 'tui'\n\t\t\t? (await import('../dev/tui/tui.js')).createTuiRenderer(service, {\n\t\t\t\t\tcolor,\n\t\t\t\t\ttheme,\n\t\t\t\t\tlayout,\n\t\t\t\t\tfilter,\n\t\t\t\t\treducedMotion: prefersReducedMotion(),\n\t\t\t\t\tonThemeSave: (setting) => {\n\t\t\t\t\t\tif (!saveTheme(setting)) service.log('stars', 'warn', 'Could not save the theme preference.');\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t: (await import('../dev/tui/plain.js')).createPlainRenderer(service, { color, filter });\n\n\tlet exiting: Promise<never> | null = null;\n\tconst shutdown = (code: ExitCode): Promise<never> => {\n\t\texiting ??= (async () => {\n\t\t\trenderer.stop();\n\t\t\t// A failing hook must not keep the bot running.\n\t\t\t// Behind any hook still running (an async `build:done`), and logged rather than thrown if it fails.\n\t\t\tawait service.runHook('dev:close', config);\n\t\t\tawait service.stop();\n\t\t\tfor (const file of logFiles) file.close();\n\t\t\tprocess.exit(code);\n\t\t})();\n\t\treturn exiting;\n\t};\n\n\t// Like Turborepo: the first signal shuts down gracefully, a second one gives up waiting and kills everything.\n\tlet signalled = false;\n\tconst onSignal = (code: ExitCode) => () => {\n\t\tif (signalled) {\n\t\t\tprocess.stderr.write('\\nForcing shutdown.\\n');\n\t\t\tservice.kill();\n\t\t\tprocess.exit(code);\n\t\t}\n\n\t\tsignalled = true;\n\t\tvoid shutdown(code);\n\t\tprocess.stderr.write('\\nShutting down gracefully, press Ctrl+C again to force quit.\\n');\n\t};\n\n\tprocess.on('SIGINT', onSignal(ExitCode.Interrupted));\n\tprocess.on('SIGTERM', onSignal(ExitCode.Terminated));\n\tprocess.on('SIGHUP', onSignal(ExitCode.Terminated));\n\tif (process.platform !== 'win32') process.on('SIGUSR2', () => void service.restart('manual'));\n\n\tconst finished = renderer.start().then(() => shutdown(ExitCode.Ok));\n\ttry {\n\t\tawait prepareProject(config, hooks);\n\t\tawait service.start();\n\t\tawait hooks.callHook('dev:start', config);\n\t} catch (error) {\n\t\tservice.log('stars', 'error', error instanceof Error ? await renderCrashReport(error, config.root) : String(error));\n\t\tawait shutdown(ExitCode.Error);\n\t}\n\tawait finished;\n}\n\n/**\n * Resolves `dev.url`'s `localhost` to the address that is actually reachable (see {@link withResolvedLocalhost}),\n * the way Vite's dev server does when it starts. Only `stars dev` pays this DNS lookup; `stars info`/`stars build`\n * show or use the unresolved config as-is, since they never talk to the bot.\n */\nasync function resolveDevConfig(config: ResolvedStarsConfig): Promise<ResolvedStarsConfig> {\n\tif (!config.dev.url) return config;\n\n\tconst url = await withResolvedLocalhost(config.dev.url);\n\treturn url === config.dev.url ? config : { ...config, dev: { ...config.dev, url } };\n}\n\nexport default defineCommand({\n\tmeta: {\n\t\tname: 'dev',\n\t\tdescription: 'Build, run and restart the bot on changes'\n\t},\n\targs: {\n\t\t...projectArgs,\n\t\ttui: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Interactive terminal UI; use --no-tui (or STARS_TUI=plain) for plain line output',\n\t\t\tdefault: true\n\t\t},\n\t\ttheme: {\n\t\t\ttype: 'string',\n\t\t\tdescription: `Colour theme of the interactive UI: ${THEME_SETTINGS.join(', ')} (or STARS_THEME; press T in the UI to pick one)`\n\t\t},\n\t\tlayout: {\n\t\t\ttype: 'string',\n\t\t\tdescription: `Layout of the interactive UI: ${LAYOUTS.join(', ')} (defaults to dev.layout; press v in the UI to switch)`\n\t\t},\n\t\tchannel: {\n\t\t\ttype: 'string',\n\t\t\tdescription: 'Only show these log channels at start (repeatable, or comma-separated; defaults to dev.logs.channels)'\n\t\t},\n\t\tlevel: {\n\t\t\ttype: 'string',\n\t\t\tdescription: `Only show this log level and the more severe ones at start: ${LEVELS.join(', ')} (defaults to dev.logs.levels)`\n\t\t}\n\t},\n\tasync run({ args, rawArgs }) {\n\t\tconst channel = collectFlag(rawArgs, 'channel');\n\t\tawait runDev({\n\t\t\tconfig: args.config,\n\t\t\tcwd: args.cwd,\n\t\t\ttui: args.tui ? undefined : false,\n\t\t\ttheme: args.theme,\n\t\t\tlayout: args.layout,\n\t\t\tchannel: channel.length > 0 ? channel : undefined,\n\t\t\tlevel: args.level\n\t\t});\n\t}\n});\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"diagnostics-BysbNnPD.js","names":[],"sources":["../src/utils/diagnostics.ts"],"sourcesContent":["import { defineDiagnostics } from 'nostics';\n\n/**\n * Structured, stable diagnostic codes for everything `@wolfstar/cli` itself rejects (as opposed to `stars.config.*`\n * validation, which is `@wolfstar/http-framework`'s own {@link import('@wolfstar/schema').configDiagnostics}).\n *\n * `reporters` stays empty: `runMain` (`src/run.ts`) is the single place that renders a caught `Diagnostic` to the\n * terminal (`formatError`) and picks its exit code (`exitCodeOf`), so nothing here should print on its own — a\n * command that calls e.g. `runBuild` directly (as the test suite does) gets a plain thrown value instead of stray\n * console output.\n *\n * `why` and `fix` are always given the same, fully-typed params object, even when one of them ignores part of it or\n * neither takes any: a bare `() => value` next to a typed sibling loses nostics' param-type inference (a zero-arg\n * function widens to `unknown` params, erasing the sibling's fields from the merged type).\n */\nexport const cliDiagnostics = defineDiagnostics({\n\tdocsBase: (code) => `https://stars-components.js.org/docs/cli/errors#${code.toLowerCase()}`,\n\treporters: [],\n\tcodes: {\n\t\tPREPARE_OUTDATED: {\n\t\t\twhy: (_p: {}) => 'The generated project files are out of date, run `stars prepare` to update it.'\n\t\t},\n\t\tDISCORD_TOKEN_MISSING: {\n\t\t\twhy: (_p: {}) => 'DISCORD_TOKEN is not set',\n\t\t\tfix: (_p: {}) => 'Set DISCORD_TOKEN in the environment or in the project .env file.'\n\t\t},\n\t\tDISCORD_APPLICATION_ID_MISSING: {\n\t\t\twhy: (_p: {}) => 'The Discord application id is not set',\n\t\t\tfix: (_p: {}) => 'Set DISCORD_APPLICATION_ID (or APPLICATION_ID) in the environment or in the project .env file.'\n\t\t},\n\t\tDISCORD_REQUEST_FAILED: {\n\t\t\twhy: (p: { status: number; detail: string }) => `Discord answered ${p.status}${p.detail ? `: ${p.detail}` : ''}`,\n\t\t\tfix: (p: { status: number; detail: string }) =>\n\t\t\t\tp.status === 401 ? 'Check DISCORD_TOKEN.' : 'Check the application id and the bot permissions.'\n\t\t},\n\t\tBUILD_FAILED: {\n\t\t\twhy: (p: { message: string }) => `Build failed${p.message ? `: ${p.message}` : ''}`\n\t\t},\n\t\tCOMMAND_NOT_FOUND: {\n\t\t\twhy: (p: { names: string }) => `No deployed command is named ${p.names}`,\n\t\t\tfix: (_p: { names: string }) => 'Run `stars commands list` to see what is deployed.'\n\t\t},\n\t\tABORTED: {\n\t\t\twhy: (_p: {}) => 'Aborted'\n\t\t},\n\t\tCONFIRMATION_REQUIRED: {\n\t\t\twhy: (_p: {}) => 'Refusing to delete commands without a confirmation',\n\t\t\tfix: (_p: {}) => 'Pass --yes to delete them, or --name to pick one, from a script.'\n\t\t},\n\t\tDEPLOY_CONFIRMATION_REQUIRED: {\n\t\t\twhy: (_p: {}) => 'Refusing to overwrite the deployed commands without a confirmation',\n\t\t\tfix: (_p: {}) => 'Pass --yes to deploy from a script, or with --json.'\n\t\t},\n\t\tCOMMANDS_DIFFER: {\n\t\t\twhy: (p: { count: number }) => `${p.count} deployed command(s) differ from the ones the project defines`,\n\t\t\tfix: (_p: { count: number }) => 'Run `stars commands deploy` to deploy them.'\n\t\t},\n\t\tLOCAL_COMMANDS_UNAVAILABLE: {\n\t\t\twhy: (p: { reason: string; fix: string }) => `Could not read the commands the project defines: ${p.reason}`,\n\t\t\tfix: (p: { reason: string; fix: string }) => p.fix\n\t\t},\n\t\tDOCTOR_FAILED: {\n\t\t\twhy: (p: { count: number }) => `${p.count} check(s) failed`\n\t\t},\n\t\tUNKNOWN_SHELL: {\n\t\t\twhy: (p: { shell: string }) => `No completions for the shell \\`${p.shell}\\`.`,\n\t\t\tfix: (_p: { shell: string }) => 'Use one of: bash, zsh, fish.'\n\t\t},\n\t\tINVALID_THEME: {\n\t\t\twhy: (p: { theme: string; themes: string }) => `Unknown theme \\`${p.theme}\\`.`,\n\t\t\tfix: (p: { theme: string; themes: string }) => `Use one of: ${p.themes}.`\n\t\t},\n\t\tINVALID_OPTION: {\n\t\t\twhy: (p: { option: string; value: string; allowed: string }) => `Unknown value \\`${p.value}\\` for ${p.option}.`,\n\t\t\tfix: (p: { option: string; value: string; allowed: string }) => `Use one of: ${p.allowed}.`\n\t\t},\n\t\tCODEGEN_OUTDATED: {\n\t\t\twhy: (_p: {}) => 'Generated files are out of date, run `stars codegen` to update them.'\n\t\t},\n\t\tDEPENDENCY_MISSING: {\n\t\t\twhy: (p: { name: string; root: string; hint: string }) => `\"${p.name}\" is not installed in ${p.root}`,\n\t\t\tfix: (p: { name: string; root: string; hint: string }) => p.hint\n\t\t},\n\t\tMODULE_FAILED: {\n\t\t\twhy: (p: { module: string; reason: string; message: string }) => p.message,\n\t\t\tfix: (p: { module: string; reason: string; message: string }) => {\n\t\t\t\tswitch (p.reason) {\n\t\t\t\t\tcase 'MODULE_LOAD_FAILED':\n\t\t\t\t\t\treturn `Install \"${p.module}\" in the project, or fix its specifier in \\`modules\\` in stars.config.`;\n\t\t\t\t\tcase 'MODULE_INCOMPATIBLE':\n\t\t\t\t\t\treturn 'Update the module or @wolfstar/http-framework so their versions match.';\n\t\t\t\t\tcase 'MODULE_INVALID':\n\t\t\t\t\t\treturn 'Export the module with `defineModule` from @wolfstar/kit as the default export.';\n\t\t\t\t\tcase 'MODULE_PLUGIN_INVALID':\n\t\t\t\t\t\treturn 'Pass `ctx.addPlugin` a package specifier, an absolute path or a `file:` URL, and JSON-serialisable options.';\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn 'Fix the error the module threw (see the cause), or remove it from `modules` in stars.config.';\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tMODULES_PRELOAD_REQUIRED: {\n\t\t\twhy: (p: { tool: string; plugins: string }) =>\n\t\t\t\t`The runtime plugins added by modules (${p.plugins}) are registered through \\`node --import\\` with build.tool \"${p.tool}\", which only \\`stars dev\\` does for you`,\n\t\t\tfix: (_p: { tool: string; plugins: string }) =>\n\t\t\t\t'Start the production bot with `node --import ./.stars/modules.mjs <entry>`; `stars prepare` (and `stars build`) writes that file.'\n\t\t},\n\t\tCODEGEN_FAILED: {\n\t\t\twhy: (p: { code: number | null; stderr: string }) => `i18next-type-generator exited with code ${p.code}${p.stderr ? `: ${p.stderr}` : ''}`\n\t\t}\n\t}\n});\n\nexport type CliDiagnosticCode = keyof typeof cliDiagnostics;\n"],"mappings":";;;;;;;;;;;;;;;;AAeA,MAAa,iBAAiB,kBAAkB;CAC/C,WAAW,SAAS,mDAAmD,KAAK,YAAY;CACxF,WAAW,CAAC;CACZ,OAAO;EACN,kBAAkB,EACjB,MAAM,OAAW,iFAClB;EACA,uBAAuB;GACtB,MAAM,OAAW;GACjB,MAAM,OAAW;EAClB;EACA,gCAAgC;GAC/B,MAAM,OAAW;GACjB,MAAM,OAAW;EAClB;EACA,wBAAwB;GACvB,MAAM,MAA0C,oBAAoB,EAAE,SAAS,EAAE,SAAS,KAAK,EAAE,WAAW;GAC5G,MAAM,MACL,EAAE,WAAW,MAAM,yBAAyB;EAC9C;EACA,cAAc,EACb,MAAM,MAA2B,eAAe,EAAE,UAAU,KAAK,EAAE,YAAY,KAChF;EACA,mBAAmB;GAClB,MAAM,MAAyB,gCAAgC,EAAE;GACjE,MAAM,OAA0B;EACjC;EACA,SAAS,EACR,MAAM,OAAW,UAClB;EACA,uBAAuB;GACtB,MAAM,OAAW;GACjB,MAAM,OAAW;EAClB;EACA,8BAA8B;GAC7B,MAAM,OAAW;GACjB,MAAM,OAAW;EAClB;EACA,iBAAiB;GAChB,MAAM,MAAyB,GAAG,EAAE,MAAM;GAC1C,MAAM,OAA0B;EACjC;EACA,4BAA4B;GAC3B,MAAM,MAAuC,oDAAoD,EAAE;GACnG,MAAM,MAAuC,EAAE;EAChD;EACA,eAAe,EACd,MAAM,MAAyB,GAAG,EAAE,MAAM,kBAC3C;EACA,eAAe;GACd,MAAM,MAAyB,kCAAkC,EAAE,MAAM;GACzE,MAAM,OAA0B;EACjC;EACA,eAAe;GACd,MAAM,MAAyC,mBAAmB,EAAE,MAAM;GAC1E,MAAM,MAAyC,eAAe,EAAE,OAAO;EACxE;EACA,gBAAgB;GACf,MAAM,MAA0D,mBAAmB,EAAE,MAAM,SAAS,EAAE,OAAO;GAC7G,MAAM,MAA0D,eAAe,EAAE,QAAQ;EAC1F;EACA,kBAAkB,EACjB,MAAM,OAAW,uEAClB;EACA,oBAAoB;GACnB,MAAM,MAAoD,IAAI,EAAE,KAAK,wBAAwB,EAAE;GAC/F,MAAM,MAAoD,EAAE;EAC7D;EACA,eAAe;GACd,MAAM,MAA2D,EAAE;GACnE,MAAM,MAA2D;IAChE,QAAQ,EAAE,QAAV;KACC,KAAK,sBACJ,OAAO,YAAY,EAAE,OAAO;KAC7B,KAAK,uBACJ,OAAO;KACR,KAAK,kBACJ,OAAO;KACR,KAAK,yBACJ,OAAO;KACR,SACC,OAAO;IACT;GACD;EACD;EACA,0BAA0B;GACzB,MAAM,MACL,yCAAyC,EAAE,QAAQ,8DAA8D,EAAE,KAAK;GACzH,MAAM,OACL;EACF;EACA,gBAAgB,EACf,MAAM,MAA+C,2CAA2C,EAAE,OAAO,EAAE,SAAS,KAAK,EAAE,WAAW,KACvI;CACD;AACD,CAAC"}
|