@wolfstar/cli 2.7.0-next-20261009115919 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{_shared-Bqw7h4O0.js → _shared-BLXTNq89.js} +2 -2
- package/dist/{_shared-Bqw7h4O0.js.map → _shared-BLXTNq89.js.map} +1 -1
- package/dist/{build-BYlgPxAE.js → build-DVF5vcSS.js} +3 -3
- package/dist/{build-BYlgPxAE.js.map → build-DVF5vcSS.js.map} +1 -1
- package/dist/cli.js +1 -1
- package/dist/{codegen-CiDXuBHu.js → codegen-DI263aSx.js} +3 -3
- package/dist/{codegen-CiDXuBHu.js.map → codegen-DI263aSx.js.map} +1 -1
- package/dist/commands-Bd6Dp5Y0.js +3 -0
- package/dist/{commands-CURkZI0f.js → commands-CtucWY2d.js} +4 -4
- package/dist/{commands-CURkZI0f.js.map → commands-CtucWY2d.js.map} +1 -1
- package/dist/commands-D7SFy2_3.js +16 -0
- package/dist/{commands-Chpk8BR8.js.map → commands-D7SFy2_3.js.map} +1 -1
- package/dist/{completions-DBipETDu.js → completions-D_scEKH1.js} +2 -2
- package/dist/{completions-DBipETDu.js.map → completions-D_scEKH1.js.map} +1 -1
- package/dist/{dev-GvuLQzWu.js → dev-CnXgPQ8F.js} +4 -4
- package/dist/{dev-GvuLQzWu.js.map → dev-CnXgPQ8F.js.map} +1 -1
- package/dist/{doctor-C_lTMEjG.js → doctor-BYRkkc5l.js} +4 -4
- package/dist/{doctor-C_lTMEjG.js.map → doctor-BYRkkc5l.js.map} +1 -1
- package/dist/{hooks-DqlScRZA.js → hooks-CzV2YRoJ.js} +4 -3
- package/dist/hooks-CzV2YRoJ.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/{info-BX-As3qN.js → info-DLo6tZT5.js} +3 -3
- package/dist/{info-BX-As3qN.js.map → info-DLo6tZT5.js.map} +1 -1
- package/dist/{local-commands-DkWl97zR.js → local-commands-DKnabUnX.js} +2 -2
- package/dist/{local-commands-DkWl97zR.js.map → local-commands-DKnabUnX.js.map} +1 -1
- package/dist/{prepare-6abxyJeD.js → prepare-DnNsv3TU.js} +3 -3
- package/dist/{prepare-6abxyJeD.js.map → prepare-DnNsv3TU.js.map} +1 -1
- package/dist/{run-DlctD5rb.js → run-BVBqR6hV.js} +2 -2
- package/dist/{run-DlctD5rb.js.map → run-BVBqR6hV.js.map} +1 -1
- package/dist/{tunnel-D3WxypOt.js → tunnel-DlFjqUE7.js} +2 -2
- package/dist/{tunnel-D3WxypOt.js.map → tunnel-DlFjqUE7.js.map} +1 -1
- package/dist/{typecheck-BIscCUNQ.js → typecheck-B2aRagKp.js} +3 -3
- package/dist/{typecheck-BIscCUNQ.js.map → typecheck-B2aRagKp.js.map} +1 -1
- package/package.json +5 -5
- package/dist/commands-Chpk8BR8.js +0 -16
- package/dist/commands-R2m3xweq.js +0 -3
- package/dist/hooks-DqlScRZA.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { r as formatError } from "./errors-COFWKKKw.js";
|
|
2
2
|
import { t as cliDiagnostics } from "./diagnostics-BKc--u_3.js";
|
|
3
3
|
import { t as loadAutoImportsModule } from "./framework-auto-imports-Gu_PXSyr.js";
|
|
4
|
-
import { o as modulesPreloadWarning, s as prepareModulesPreload } from "./hooks-
|
|
4
|
+
import { o as modulesPreloadWarning, s as prepareModulesPreload } from "./hooks-CzV2YRoJ.js";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
6
|
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
7
7
|
import { SPLIT_TSCONFIG_VERSION } from "@wolfstar/schema";
|
|
@@ -219,4 +219,4 @@ async function reportWarnings(config, write, options = {}) {
|
|
|
219
219
|
|
|
220
220
|
//#endregion
|
|
221
221
|
export { reportWarnings as n, findLegacyRootTsconfig as r, prepareProject as t };
|
|
222
|
-
//# sourceMappingURL=_shared-
|
|
222
|
+
//# sourceMappingURL=_shared-BLXTNq89.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_shared-Bqw7h4O0.js","names":[],"sources":["../src/utils/tsconfig.ts","../src/commands/_shared.ts"],"sourcesContent":["import { SPLIT_TSCONFIG_VERSION, 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';\nimport type { Diagnostic } from 'nostics';\nimport { cliDiagnostics } from './diagnostics.js';\n\nconst require = createRequire(import.meta.url);\nconst presetOptions = (ids: string[]) =>\n\tObject.assign({}, ...ids.map((id) => (require(id) as { compilerOptions: Record<string, unknown> }).compilerOptions)) as Record<string, unknown>;\n// Strictness belongs to every project; the decorator options only to the code the bundler compiles.\nconst strictOptions = presetOptions(['@sapphire/ts-config', '@sapphire/ts-config/extra-strict']);\nconst sapphireOptions = presetOptions(['@sapphire/ts-config', '@sapphire/ts-config/extra-strict', '@sapphire/ts-config/decorators']);\n\nexport type TsconfigName = 'tsconfig' | 'app' | 'node';\n\nexport interface TsconfigStatus {\n\t/** `tsconfig` is the single file of compatibility versions below 6, `app` and `node` the split ones. */\n\tname: TsconfigName;\n\tpath: string;\n\tstatus: 'written' | 'up-to-date' | 'outdated';\n}\n\n/** The root config files that run in Node and never go through the bundler. */\nconst NODE_PROJECT_FILES = ['stars.config.*', 'vitest.config.*', 'tsdown.config.*', 'vite.config.*', 'scripts/**/*'] as const;\n\n/**\n * Generates the TypeScript configuration without changing the project's own tsconfig: one extendable\n * `.stars/tsconfig.json` below compatibility version 6, and from 6 the `.stars/tsconfig.app.json` (the bot sources) and\n * `.stars/tsconfig.node.json` (the root files that run in Node) a solution-style `tsconfig.json` references.\n * Returns one status per file.\n */\nexport async function prepareTsconfig(config: ResolvedStarsConfig, check = false): Promise<TsconfigStatus[]> {\n\tif (config.future.compatibilityVersion < SPLIT_TSCONFIG_VERSION) {\n\t\treturn [await emit(config, 'tsconfig', appTsconfig(config, 'tsconfig'), check)];\n\t}\n\n\t// Written for every build tool: the node project is about files Node runs whatever builds the bot. A `tsc` or `none`\n\t// project keeps its own tsconfig for the bot sources, so for it the app file is generated but nothing references it.\n\treturn [await emit(config, 'app', appTsconfig(config, 'app'), check), await emit(config, 'node', nodeTsconfig(config), check)];\n}\n\n/**\n * Reports a root `tsconfig.json` that still extends the single `.stars/tsconfig.json` of compatibility versions below 6,\n * a file `stars prepare` no longer writes from version 6 on. A project moving to 6 updates it once.\n */\nexport async function findLegacyRootTsconfig(config: ResolvedStarsConfig): Promise<Diagnostic | null> {\n\tif (config.future.compatibilityVersion < SPLIT_TSCONFIG_VERSION) return null;\n\n\tconst path = join(config.root, 'tsconfig.json');\n\tconst content = await readFile(path, 'utf-8').catch(() => null);\n\tif (content === null || !/[\"']extends[\"']\\s*:\\s*(?:\\[[^\\]]*)?[\"']\\.\\/\\.stars\\/tsconfig\\.json[\"']/.test(content)) return null;\n\n\treturn cliDiagnostics.TSCONFIG_LEGACY_EXTENDS({ file: relative(config.root, path) || 'tsconfig.json' });\n}\n\nasync function emit(config: ResolvedStarsConfig, name: TsconfigName, compilerConfig: object, check: boolean): Promise<TsconfigStatus> {\n\tconst path = join(config.root, '.stars', name === 'tsconfig' ? 'tsconfig.json' : `tsconfig.${name}.json`);\n\tconst content = `${JSON.stringify(compilerConfig, null, 2)}\\n`;\n\tif (check) {\n\t\tconst existing = await readFile(path, 'utf-8').catch(() => null);\n\t\treturn { name, path, status: existing === content ? 'up-to-date' : 'outdated' };\n\t}\n\tawait mkdir(dirname(path), { recursive: true });\n\tawait writeFile(path, content);\n\treturn { name, path, status: 'written' };\n}\n\n/** What `.stars/tsconfig.json` has always been: the bot sources, with the aliases and the bundler's compiler options. */\nfunction appTsconfig(config: ResolvedStarsConfig, name: TsconfigName) {\n\tconst path = join(config.root, '.stars', name === 'tsconfig' ? 'tsconfig.json' : `tsconfig.${name}.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\treturn {\n\t\tcompilerOptions: {\n\t\t\t...sapphireOptions,\n\t\t\t// Bundlers emit the application; TypeScript only checks it. Keep Node16 emit for tsc.\n\t\t\t...(config.build.tool === 'tsdown' || config.build.tool === 'vite'\n\t\t\t\t? {\n\t\t\t\t\t\tmodule: 'ESNext',\n\t\t\t\t\t\tmoduleResolution: 'Bundler',\n\t\t\t\t\t\tmoduleDetection: 'force',\n\t\t\t\t\t\tisolatedModules: true,\n\t\t\t\t\t\tverbatimModuleSyntax: true,\n\t\t\t\t\t\tallowJs: true,\n\t\t\t\t\t\tallowImportingTsExtensions: true,\n\t\t\t\t\t\tresolvePackageJsonImports: true,\n\t\t\t\t\t\tlib: ['ESNext', 'DOM'],\n\t\t\t\t\t\tnoEmit: true\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\ttarget: 'ES2022',\n\t\t\tforceConsistentCasingInFileNames: true,\n\t\t\tskipLibCheck: true,\n\t\t\ttsBuildInfoFile: name === 'tsconfig' ? './tsconfig.tsbuildinfo' : `./tsconfig.${name}.tsbuildinfo`,\n\t\t\tpaths\n\t\t},\n\t\tinclude: [`${fromGenerated(dirname(config.entry))}/**/*`, ...(config.imports.enabled ? [fromGenerated(config.imports.dts)] : [])],\n\t\texclude: [fromGenerated(join(config.root, 'node_modules')), fromGenerated(config.build.outDir)]\n\t};\n}\n\n/**\n * The root files that run in Node: `stars.config.*`, `vitest.config.*`, `scripts/**` and the like. No DOM, no\n * bundler resolution, no aliases or auto imports (none of it applies to a file Node loads itself), and no decorators.\n */\nfunction nodeTsconfig(config: ResolvedStarsConfig) {\n\tconst path = join(config.root, '.stars', 'tsconfig.node.json');\n\tconst fromGenerated = (target: string) => `./${relative(dirname(path), target).replaceAll('\\\\', '/')}`;\n\tconst source = dirname(config.entry);\n\tconst include = NODE_PROJECT_FILES.map((pattern) => fromGenerated(join(config.root, pattern)));\n\t// A custom `--config` file name is not covered by the globs.\n\tif (config.configFile !== null) include.push(fromGenerated(config.configFile));\n\n\treturn {\n\t\tcompilerOptions: {\n\t\t\t...strictOptions,\n\t\t\ttarget: 'ES2022',\n\t\t\tmodule: 'NodeNext',\n\t\t\tmoduleResolution: 'NodeNext',\n\t\t\tmoduleDetection: 'force',\n\t\t\tlib: ['ESNext'],\n\t\t\ttypes: ['node'],\n\t\t\tallowJs: true,\n\t\t\tnoEmit: true,\n\t\t\tforceConsistentCasingInFileNames: true,\n\t\t\tskipLibCheck: true,\n\t\t\ttsBuildInfoFile: './tsconfig.node.tsbuildinfo'\n\t\t},\n\t\tinclude: [...new Set(include)],\n\t\t// The two projects must not overlap: the bot sources belong to the app one. An entry in the project root has\n\t\t// no directory of its own to leave out.\n\t\texclude: [\n\t\t\tfromGenerated(join(config.root, 'node_modules')),\n\t\t\tfromGenerated(config.build.outDir),\n\t\t\t...(source === config.root ? [] : [fromGenerated(source)])\n\t\t]\n\t};\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 { findLegacyRootTsconfig, 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 tsconfigs = await prepareTsconfig(config, check);\n\tconst result = {\n\t\t...(await prepareAutoImports(config, check)),\n\t\t// The app config from version 6, the single file below it; `tsconfigs` has every generated file.\n\t\ttsconfig: tsconfigs[0]!,\n\t\ttsconfigs,\n\t\tmodules: await prepareModulesPreload(config, check)\n\t};\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, or a root `tsconfig.json` still extending `.stars/tsconfig.json`), 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 legacyTsconfig = await findLegacyRootTsconfig(config);\n\tif (legacyTsconfig) write(await formatError(legacyTsconfig));\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
|
+
{"version":3,"file":"_shared-BLXTNq89.js","names":[],"sources":["../src/utils/tsconfig.ts","../src/commands/_shared.ts"],"sourcesContent":["import { SPLIT_TSCONFIG_VERSION, 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';\nimport type { Diagnostic } from 'nostics';\nimport { cliDiagnostics } from './diagnostics.js';\n\nconst require = createRequire(import.meta.url);\nconst presetOptions = (ids: string[]) =>\n\tObject.assign({}, ...ids.map((id) => (require(id) as { compilerOptions: Record<string, unknown> }).compilerOptions)) as Record<string, unknown>;\n// Strictness belongs to every project; the decorator options only to the code the bundler compiles.\nconst strictOptions = presetOptions(['@sapphire/ts-config', '@sapphire/ts-config/extra-strict']);\nconst sapphireOptions = presetOptions(['@sapphire/ts-config', '@sapphire/ts-config/extra-strict', '@sapphire/ts-config/decorators']);\n\nexport type TsconfigName = 'tsconfig' | 'app' | 'node';\n\nexport interface TsconfigStatus {\n\t/** `tsconfig` is the single file of compatibility versions below 6, `app` and `node` the split ones. */\n\tname: TsconfigName;\n\tpath: string;\n\tstatus: 'written' | 'up-to-date' | 'outdated';\n}\n\n/** The root config files that run in Node and never go through the bundler. */\nconst NODE_PROJECT_FILES = ['stars.config.*', 'vitest.config.*', 'tsdown.config.*', 'vite.config.*', 'scripts/**/*'] as const;\n\n/**\n * Generates the TypeScript configuration without changing the project's own tsconfig: one extendable\n * `.stars/tsconfig.json` below compatibility version 6, and from 6 the `.stars/tsconfig.app.json` (the bot sources) and\n * `.stars/tsconfig.node.json` (the root files that run in Node) a solution-style `tsconfig.json` references.\n * Returns one status per file.\n */\nexport async function prepareTsconfig(config: ResolvedStarsConfig, check = false): Promise<TsconfigStatus[]> {\n\tif (config.future.compatibilityVersion < SPLIT_TSCONFIG_VERSION) {\n\t\treturn [await emit(config, 'tsconfig', appTsconfig(config, 'tsconfig'), check)];\n\t}\n\n\t// Written for every build tool: the node project is about files Node runs whatever builds the bot. A `tsc` or `none`\n\t// project keeps its own tsconfig for the bot sources, so for it the app file is generated but nothing references it.\n\treturn [await emit(config, 'app', appTsconfig(config, 'app'), check), await emit(config, 'node', nodeTsconfig(config), check)];\n}\n\n/**\n * Reports a root `tsconfig.json` that still extends the single `.stars/tsconfig.json` of compatibility versions below 6,\n * a file `stars prepare` no longer writes from version 6 on. A project moving to 6 updates it once.\n */\nexport async function findLegacyRootTsconfig(config: ResolvedStarsConfig): Promise<Diagnostic | null> {\n\tif (config.future.compatibilityVersion < SPLIT_TSCONFIG_VERSION) return null;\n\n\tconst path = join(config.root, 'tsconfig.json');\n\tconst content = await readFile(path, 'utf-8').catch(() => null);\n\tif (content === null || !/[\"']extends[\"']\\s*:\\s*(?:\\[[^\\]]*)?[\"']\\.\\/\\.stars\\/tsconfig\\.json[\"']/.test(content)) return null;\n\n\treturn cliDiagnostics.TSCONFIG_LEGACY_EXTENDS({ file: relative(config.root, path) || 'tsconfig.json' });\n}\n\nasync function emit(config: ResolvedStarsConfig, name: TsconfigName, compilerConfig: object, check: boolean): Promise<TsconfigStatus> {\n\tconst path = join(config.root, '.stars', name === 'tsconfig' ? 'tsconfig.json' : `tsconfig.${name}.json`);\n\tconst content = `${JSON.stringify(compilerConfig, null, 2)}\\n`;\n\tif (check) {\n\t\tconst existing = await readFile(path, 'utf-8').catch(() => null);\n\t\treturn { name, path, status: existing === content ? 'up-to-date' : 'outdated' };\n\t}\n\tawait mkdir(dirname(path), { recursive: true });\n\tawait writeFile(path, content);\n\treturn { name, path, status: 'written' };\n}\n\n/** What `.stars/tsconfig.json` has always been: the bot sources, with the aliases and the bundler's compiler options. */\nfunction appTsconfig(config: ResolvedStarsConfig, name: TsconfigName) {\n\tconst path = join(config.root, '.stars', name === 'tsconfig' ? 'tsconfig.json' : `tsconfig.${name}.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\treturn {\n\t\tcompilerOptions: {\n\t\t\t...sapphireOptions,\n\t\t\t// Bundlers emit the application; TypeScript only checks it. Keep Node16 emit for tsc.\n\t\t\t...(config.build.tool === 'tsdown' || config.build.tool === 'vite'\n\t\t\t\t? {\n\t\t\t\t\t\tmodule: 'ESNext',\n\t\t\t\t\t\tmoduleResolution: 'Bundler',\n\t\t\t\t\t\tmoduleDetection: 'force',\n\t\t\t\t\t\tisolatedModules: true,\n\t\t\t\t\t\tverbatimModuleSyntax: true,\n\t\t\t\t\t\tallowJs: true,\n\t\t\t\t\t\tallowImportingTsExtensions: true,\n\t\t\t\t\t\tresolvePackageJsonImports: true,\n\t\t\t\t\t\tlib: ['ESNext', 'DOM'],\n\t\t\t\t\t\tnoEmit: true\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t\ttarget: 'ES2022',\n\t\t\tforceConsistentCasingInFileNames: true,\n\t\t\tskipLibCheck: true,\n\t\t\ttsBuildInfoFile: name === 'tsconfig' ? './tsconfig.tsbuildinfo' : `./tsconfig.${name}.tsbuildinfo`,\n\t\t\tpaths\n\t\t},\n\t\tinclude: [`${fromGenerated(dirname(config.entry))}/**/*`, ...(config.imports.enabled ? [fromGenerated(config.imports.dts)] : [])],\n\t\texclude: [fromGenerated(join(config.root, 'node_modules')), fromGenerated(config.build.outDir)]\n\t};\n}\n\n/**\n * The root files that run in Node: `stars.config.*`, `vitest.config.*`, `scripts/**` and the like. No DOM, no\n * bundler resolution, no aliases or auto imports (none of it applies to a file Node loads itself), and no decorators.\n */\nfunction nodeTsconfig(config: ResolvedStarsConfig) {\n\tconst path = join(config.root, '.stars', 'tsconfig.node.json');\n\tconst fromGenerated = (target: string) => `./${relative(dirname(path), target).replaceAll('\\\\', '/')}`;\n\tconst source = dirname(config.entry);\n\tconst include = NODE_PROJECT_FILES.map((pattern) => fromGenerated(join(config.root, pattern)));\n\t// A custom `--config` file name is not covered by the globs.\n\tif (config.configFile !== null) include.push(fromGenerated(config.configFile));\n\n\treturn {\n\t\tcompilerOptions: {\n\t\t\t...strictOptions,\n\t\t\ttarget: 'ES2022',\n\t\t\tmodule: 'NodeNext',\n\t\t\tmoduleResolution: 'NodeNext',\n\t\t\tmoduleDetection: 'force',\n\t\t\tlib: ['ESNext'],\n\t\t\ttypes: ['node'],\n\t\t\tallowJs: true,\n\t\t\tnoEmit: true,\n\t\t\tforceConsistentCasingInFileNames: true,\n\t\t\tskipLibCheck: true,\n\t\t\ttsBuildInfoFile: './tsconfig.node.tsbuildinfo'\n\t\t},\n\t\tinclude: [...new Set(include)],\n\t\t// The two projects must not overlap: the bot sources belong to the app one. An entry in the project root has\n\t\t// no directory of its own to leave out.\n\t\texclude: [\n\t\t\tfromGenerated(join(config.root, 'node_modules')),\n\t\t\tfromGenerated(config.build.outDir),\n\t\t\t...(source === config.root ? [] : [fromGenerated(source)])\n\t\t]\n\t};\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 { findLegacyRootTsconfig, 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 tsconfigs = await prepareTsconfig(config, check);\n\tconst result = {\n\t\t...(await prepareAutoImports(config, check)),\n\t\t// The app config from version 6, the single file below it; `tsconfigs` has every generated file.\n\t\ttsconfig: tsconfigs[0]!,\n\t\ttsconfigs,\n\t\tmodules: await prepareModulesPreload(config, check)\n\t};\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, or a root `tsconfig.json` still extending `.stars/tsconfig.json`), 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 legacyTsconfig = await findLegacyRootTsconfig(config);\n\tif (legacyTsconfig) write(await formatError(legacyTsconfig));\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,8 +1,8 @@
|
|
|
1
1
|
import { i as shouldUseColor } from "./output-mode-Bp7Da8vJ.js";
|
|
2
2
|
import { t as cliDiagnostics } from "./diagnostics-BKc--u_3.js";
|
|
3
3
|
import { n as createBuilder, t as Locales } from "./locales-CnVIXIip.js";
|
|
4
|
-
import { d as projectArgs, f as resolveCwd, n as loadProject, t as applyEnvOptions } from "./hooks-
|
|
5
|
-
import { n as reportWarnings, t as prepareProject } from "./_shared-
|
|
4
|
+
import { d as projectArgs, f as resolveCwd, n as loadProject, t as applyEnvOptions } from "./hooks-CzV2YRoJ.js";
|
|
5
|
+
import { n as reportWarnings, t as prepareProject } from "./_shared-BLXTNq89.js";
|
|
6
6
|
import { defineCommand } from "citty";
|
|
7
7
|
import { displayPath } from "@wolfstar/schema";
|
|
8
8
|
import { createColors } from "colorette";
|
|
@@ -53,4 +53,4 @@ var build_default = defineCommand({
|
|
|
53
53
|
|
|
54
54
|
//#endregion
|
|
55
55
|
export { build_default as default };
|
|
56
|
-
//# sourceMappingURL=build-
|
|
56
|
+
//# sourceMappingURL=build-DVF5vcSS.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-
|
|
1
|
+
{"version":3,"file":"build-DVF5vcSS.js","names":[],"sources":["../src/commands/build.ts"],"sourcesContent":["import { displayPath } from '@wolfstar/schema';\nimport { defineCommand } from 'citty';\nimport { createColors } from 'colorette';\nimport { createBuilder } from '../builders/index.js';\nimport { projectArgs, resolveCwd, type ProjectArgs } from '../utils/args.js';\nimport { cliDiagnostics } from '../utils/diagnostics.js';\nimport { applyEnvOptions, loadProject } from '../utils/hooks.js';\nimport { Locales } from '../utils/locales.js';\nimport { shouldUseColor } from '../utils/output-mode.js';\nimport { prepareProject, reportWarnings } from './_shared.js';\n\nexport interface BuildTaskOptions extends ProjectArgs {\n\tstdout?: NodeJS.WritableStream;\n}\n\nexport async function runBuild(options: BuildTaskOptions): Promise<void> {\n\tconst stdout = options.stdout ?? process.stdout;\n\tconst colors = createColors({ useColor: shouldUseColor() });\n\tconst { config: resolved, hooks } = await loadProject({ cwd: resolveCwd(options), configFile: options.config });\n\tawait reportWarnings(resolved, (text) => process.stderr.write(`${text}\\n`));\n\n\tif (resolved.build.tool === 'none') {\n\t\tawait prepareProject(resolved, hooks);\n\t\tstdout.write(`${colors.dim('stars')} nothing to build, ${displayPath(resolved.root, resolved.entry)} runs as-is (build.tool is 'none')\\n`);\n\t\treturn;\n\t}\n\n\t// Same hook order as `stars dev`: `env:options` and `builder:created` before `prepare:*`.\n\tconst config = await applyEnvOptions(resolved, hooks);\n\tconst builder = await createBuilder(config, hooks);\n\tawait hooks.callHook('builder:created', builder, config);\n\tawait prepareProject(config, hooks);\n\tbuilder.on('log', (level, text) => {\n\t\tconst paint = level === 'error' ? colors.red : level === 'warn' ? colors.yellow : (value: string) => value;\n\t\tstdout.write(`${paint(text)}\\n`);\n\t});\n\n\tstdout.write(`${colors.dim('stars')} building with ${colors.bold(config.build.tool)}…\\n`);\n\tawait hooks.callHook('build:before', config);\n\tconst outcome = await builder.build();\n\tawait hooks.callHook('build:done', outcome, config);\n\tif (!outcome.ok) {\n\t\tthrow cliDiagnostics.BUILD_FAILED({ message: outcome.message ?? '' });\n\t}\n\tnew Locales(config).copy();\n\n\tstdout.write(`${colors.dim('stars')} ${colors.green(`built in ${outcome.durationMs}ms`)} → ${displayPath(config.root, config.build.output)}\\n`);\n}\n\nexport default defineCommand({\n\tmeta: {\n\t\tname: 'build',\n\t\tdescription: 'Build the project once with the configured build tool'\n\t},\n\targs: { ...projectArgs },\n\tasync run({ args }) {\n\t\tawait runBuild({ config: args.config, cwd: args.cwd });\n\t}\n});\n"],"mappings":";;;;;;;;;;AAeA,eAAsB,SAAS,SAA0C;CACxE,MAAM,SAAS,QAAQ,UAAU,QAAQ;CACzC,MAAM,SAAS,aAAa,EAAE,UAAU,eAAe,EAAE,CAAC;CAC1D,MAAM,EAAE,QAAQ,UAAU,UAAU,MAAM,YAAY;EAAE,KAAK,WAAW,OAAO;EAAG,YAAY,QAAQ;CAAO,CAAC;CAC9G,MAAM,eAAe,WAAW,SAAS,QAAQ,OAAO,MAAM,GAAG,KAAK,GAAG,CAAC;CAE1E,IAAI,SAAS,MAAM,SAAS,QAAQ;EACnC,MAAM,eAAe,UAAU,KAAK;EACpC,OAAO,MAAM,GAAG,OAAO,IAAI,OAAO,EAAE,qBAAqB,YAAY,SAAS,MAAM,SAAS,KAAK,EAAE,qCAAqC;EACzI;CACD;CAGA,MAAM,SAAS,MAAM,gBAAgB,UAAU,KAAK;CACpD,MAAM,UAAU,MAAM,cAAc,QAAQ,KAAK;CACjD,MAAM,MAAM,SAAS,mBAAmB,SAAS,MAAM;CACvD,MAAM,eAAe,QAAQ,KAAK;CAClC,QAAQ,GAAG,QAAQ,OAAO,SAAS;EAClC,MAAM,QAAQ,UAAU,UAAU,OAAO,MAAM,UAAU,SAAS,OAAO,UAAU,UAAkB;EACrG,OAAO,MAAM,GAAG,MAAM,IAAI,EAAE,GAAG;CAChC,CAAC;CAED,OAAO,MAAM,GAAG,OAAO,IAAI,OAAO,EAAE,iBAAiB,OAAO,KAAK,OAAO,MAAM,IAAI,EAAE,IAAI;CACxF,MAAM,MAAM,SAAS,gBAAgB,MAAM;CAC3C,MAAM,UAAU,MAAM,QAAQ,MAAM;CACpC,MAAM,MAAM,SAAS,cAAc,SAAS,MAAM;CAClD,IAAI,CAAC,QAAQ,IACZ,MAAM,eAAe,aAAa,EAAE,SAAS,QAAQ,WAAW,GAAG,CAAC;CAErE,IAAI,QAAQ,MAAM,CAAC,CAAC,KAAK;CAEzB,OAAO,MAAM,GAAG,OAAO,IAAI,OAAO,EAAE,GAAG,OAAO,MAAM,YAAY,QAAQ,WAAW,GAAG,EAAE,KAAK,YAAY,OAAO,MAAM,OAAO,MAAM,MAAM,EAAE,GAAG;AAC/I;AAEA,oBAAe,cAAc;CAC5B,MAAM;EACL,MAAM;EACN,aAAa;CACd;CACA,MAAM,EAAE,GAAG,YAAY;CACvB,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,SAAS;GAAE,QAAQ,KAAK;GAAQ,KAAK,KAAK;EAAI,CAAC;CACtD;AACD,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { i as shouldUseColor } from "./output-mode-Bp7Da8vJ.js";
|
|
2
2
|
import { t as cliDiagnostics } from "./diagnostics-BKc--u_3.js";
|
|
3
3
|
import { i as resolveFromProject } from "./project-EJyKro-M.js";
|
|
4
|
-
import { d as projectArgs, f as resolveCwd, n as loadProject, r as withProjectEnv, t as applyEnvOptions } from "./hooks-
|
|
5
|
-
import { t as readLocalCommands } from "./local-commands-
|
|
4
|
+
import { d as projectArgs, f as resolveCwd, n as loadProject, r as withProjectEnv, t as applyEnvOptions } from "./hooks-CzV2YRoJ.js";
|
|
5
|
+
import { t as readLocalCommands } from "./local-commands-DKnabUnX.js";
|
|
6
6
|
import { defineCommand } from "citty";
|
|
7
7
|
import { dirname, join } from "node:path";
|
|
8
8
|
import { displayPath } from "@wolfstar/schema";
|
|
@@ -259,4 +259,4 @@ var codegen_default = defineCommand({
|
|
|
259
259
|
|
|
260
260
|
//#endregion
|
|
261
261
|
export { codegen_default as default };
|
|
262
|
-
//# sourceMappingURL=codegen-
|
|
262
|
+
//# sourceMappingURL=codegen-DI263aSx.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen-CiDXuBHu.js","names":[],"sources":["../src/utils/command-types.ts","../src/commands/codegen.ts"],"sourcesContent":["import type { CommandData, CommandSnapshot } from '../dev/bridge.js';\n\n/** `ApplicationCommandOptionType`, which the CLI cannot import: it has no dependency on `discord-api-types`. */\nconst OptionType = {\n\tSubcommand: 1,\n\tSubcommandGroup: 2,\n\tString: 3,\n\tInteger: 4,\n\tBoolean: 5,\n\tUser: 6,\n\tChannel: 7,\n\tRole: 8,\n\tMentionable: 9,\n\tNumber: 10,\n\tAttachment: 11\n} as const;\n\n/** `ApplicationCommandType.ChatInput`: the only type with options, and the one a command without `type` is. */\nconst CHAT_INPUT = 1;\n\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/;\n\ninterface OptionData {\n\tname: string;\n\ttype: number;\n\trequired?: boolean;\n\tchoices?: { value: string | number }[];\n\tchannel_types?: number[];\n\toptions?: OptionData[];\n}\n\ninterface Rendering {\n\t/** Set once something refers to `TransformedArguments`, which the file then has to import. */\n\tusesResolvedTypes: boolean;\n}\n\n/**\n * The declaration file `stars codegen` writes for the commands a project registers: one `CommandOptionsRegistry` entry\n * (`Command.OptionsOf<'path'>`) per leaf, that is a command without subcommands, `parent sub` or `parent group sub`.\n *\n * It reads the JSON Discord receives rather than the builders, so what the handler is typed with cannot drift from what\n * is registered, and loops and factories need no special care. The option types point at the framework's\n * `TransformedArguments`, which is what the router resolves them to, instead of repeating those shapes here.\n *\n * Context menu commands have no options and are skipped. A path registered more than once (a command restricted to\n * several guilds is the same command in each) keeps its first definition, global commands first. The output depends\n * on nothing but the commands, in sorted order, so `stars codegen --check` is a string comparison.\n */\nexport function generateCommandTypes(snapshot: CommandSnapshot): string {\n\tconst entries = new Map<string, OptionData[]>();\n\tconst scopes = [\n\t\tsnapshot.global,\n\t\t...Object.keys(snapshot.guilds)\n\t\t\t.sort()\n\t\t\t.map((guild) => snapshot.guilds[guild])\n\t];\n\tfor (const commands of scopes) {\n\t\tfor (const command of commands) collectLeaves(command, entries);\n\t}\n\n\tconst rendering: Rendering = { usesResolvedTypes: false };\n\tconst lines = [...entries.keys()].sort().map((path) => ` ${renderEntry(path, entries.get(path)!, rendering)}`);\n\n\treturn [\n\t\t'// This file is automatically generated by `stars codegen`, do not edit it.',\n\t\t'/* eslint-disable */',\n\t\t'/* oxlint-disable */',\n\t\t'// oxfmt-ignore',\n\t\t'// prettier-ignore',\n\t\trendering.usesResolvedTypes ? \"import type { TransformedArguments } from '@wolfstar/http-framework';\" : 'export {};',\n\t\t'',\n\t\t'// oxfmt-ignore',\n\t\t'// prettier-ignore',\n\t\t\"declare module '@wolfstar/http-framework' {\",\n\t\t' interface CommandOptionsRegistry {',\n\t\t...lines,\n\t\t' }',\n\t\t'}',\n\t\t''\n\t].join('\\n');\n}\n\nfunction collectLeaves(command: CommandData, entries: Map<string, OptionData[]>): void {\n\tif ((command.type ?? CHAT_INPUT) !== CHAT_INPUT) return;\n\n\tconst options = (command.options ?? []) as OptionData[];\n\tconst add = (path: string, leaf: OptionData[] | undefined) => {\n\t\tif (!entries.has(path)) entries.set(path, leaf ?? []);\n\t};\n\n\tif (!options.some((option) => option.type === OptionType.Subcommand || option.type === OptionType.SubcommandGroup)) {\n\t\tadd(command.name, options);\n\t\treturn;\n\t}\n\n\tfor (const option of options) {\n\t\tif (option.type === OptionType.Subcommand) {\n\t\t\tadd(`${command.name} ${option.name}`, option.options);\n\t\t} else if (option.type === OptionType.SubcommandGroup) {\n\t\t\tfor (const sub of option.options ?? []) {\n\t\t\t\tif (sub.type === OptionType.Subcommand) add(`${command.name} ${option.name} ${sub.name}`, sub.options);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Only the first line of an entry is indented by the caller: the options go on lines of their own. */\nfunction renderEntry(path: string, options: readonly OptionData[], rendering: Rendering): string {\n\tconst sorted = [...options].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));\n\tconst properties = sorted.map((option) => ` ${key(option.name)}${option.required ? '' : '?'}: ${renderOption(option, rendering)};`);\n\treturn properties.length === 0 ? `${quote(path)}: {};` : `${quote(path)}: {\\n${properties.join('\\n')}\\n };`;\n}\n\nfunction renderOption(option: OptionData, rendering: Rendering): string {\n\tconst resolved = (name: string) => {\n\t\trendering.usesResolvedTypes = true;\n\t\treturn `TransformedArguments.${name}`;\n\t};\n\n\tswitch (option.type) {\n\t\tcase OptionType.String:\n\t\tcase OptionType.Integer:\n\t\tcase OptionType.Number: {\n\t\t\tconst fallback = option.type === OptionType.String ? 'string' : 'number';\n\t\t\tif (!option.choices?.length) return fallback;\n\t\t\tconst values = option.choices.map((choice) => (typeof choice.value === 'string' ? quote(choice.value) : String(choice.value)));\n\t\t\treturn [...new Set(values)].join(' | ');\n\t\t}\n\t\tcase OptionType.Boolean:\n\t\t\treturn 'boolean';\n\t\tcase OptionType.User:\n\t\t\treturn resolved('User');\n\t\tcase OptionType.Role:\n\t\t\treturn resolved('Role');\n\t\tcase OptionType.Mentionable:\n\t\t\treturn resolved('Mentionable');\n\t\tcase OptionType.Attachment:\n\t\t\treturn resolved('Attachment');\n\t\tcase OptionType.Channel: {\n\t\t\tconst channel = resolved('Channel');\n\t\t\tif (!option.channel_types?.length) return channel;\n\t\t\t// `ChannelType` is not imported on purpose: its members are the numbers they are in the payload.\n\t\t\tconst types = [...new Set(option.channel_types)].sort((a, b) => a - b).join(' | ');\n\t\t\treturn `${channel} & { type: Extract<${channel}['type'], ${types}> }`;\n\t\t}\n\t\tdefault:\n\t\t\t// An option type Discord added after this was written: the handler still gets something.\n\t\t\treturn 'unknown';\n\t}\n}\n\nfunction key(name: string): string {\n\treturn IDENTIFIER.test(name) ? name : quote(name);\n}\n\nfunction quote(value: string): string {\n\tconst escaped = value\n\t\t.replaceAll('\\\\', '\\\\\\\\')\n\t\t.replaceAll(\"'\", \"\\\\'\")\n\t\t.replaceAll('\\n', '\\\\n')\n\t\t.replaceAll('\\r', '\\\\r')\n\t\t.replaceAll('
', '\\\\u2028')\n\t\t.replaceAll('
', '\\\\u2029');\n\treturn `'${escaped}'`;\n}\n","import { displayPath, type ResolvedStarsConfig } from '@wolfstar/schema';\nimport { applyEnvOptions, loadProject, withProjectEnv } from '../utils/hooks.js';\nimport { defineCommand } from 'citty';\nimport { createColors } from 'colorette';\nimport { spawn } from 'node:child_process';\nimport { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { projectArgs, resolveCwd, type ProjectArgs } from '../utils/args.js';\nimport type { CommandSnapshot } from '../dev/bridge.js';\nimport { generateCommandTypes } from '../utils/command-types.js';\nimport { cliDiagnostics } from '../utils/diagnostics.js';\nimport { shouldUseColor } from '../utils/output-mode.js';\nimport { readLocalCommands } from '../utils/local-commands.js';\nimport { resolveFromProject } from '../utils/project.js';\n\nexport interface CodegenTaskOptions extends ProjectArgs {\n\tcheck?: boolean;\n\tjson?: boolean;\n\tstdout?: NodeJS.WritableStream;\n\t/** Overrides the commands read from the built bot, for tests. */\n\tcommands?: CommandSnapshot;\n}\n\nexport interface CodegenResult {\n\tgenerator: 'i18n' | 'commands';\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 project = await loadProject({ cwd: resolveCwd(options), configFile: options.config });\n\tconst { config } = project;\n\tconst results: CodegenResult[] = [];\n\n\tif (config.codegen.i18n) results.push(await runI18n(config, Boolean(options.check)));\n\tif (config.codegen.commands) {\n\t\t// What the bot is started with: `env:options` (and varlock) may pick other env files than the defaults.\n\t\tconst botConfig = withProjectEnv(await applyEnvOptions(config, project.hooks));\n\t\tresults.push(await runCommands(botConfig, Boolean(options.check), options.commands));\n\t}\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\n/**\n * Types the options of the commands the project registers. The commands are read from the built bot, the way\n * `stars commands diff` reads them: nothing connects to Discord, but the bot still runs its own env setup, so `--check`\n * in CI needs placeholders for the values it reads while starting (`DISCORD_CLIENT_ID`, `DISCORD_PUBLIC_KEY`, ...).\n */\nasync function runCommands(config: ResolvedStarsConfig, check: boolean, local?: CommandSnapshot): Promise<CodegenResult> {\n\tconst { output } = config.codegen.commands!;\n\tconst generated = generateCommandTypes(local ?? (await readLocalCommands(config)));\n\n\tif (!check) {\n\t\tawait mkdir(dirname(output), { recursive: true });\n\t\tawait writeFile(output, generated);\n\t\treturn { generator: 'commands', output, status: 'written' };\n\t}\n\n\tconst actual = await readFile(output, 'utf-8').catch(() => null);\n\treturn { generator: 'commands', output, status: generated === actual ? 'up-to-date' : 'outdated' };\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, command options)'\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
|
+
{"version":3,"file":"codegen-DI263aSx.js","names":[],"sources":["../src/utils/command-types.ts","../src/commands/codegen.ts"],"sourcesContent":["import type { CommandData, CommandSnapshot } from '../dev/bridge.js';\n\n/** `ApplicationCommandOptionType`, which the CLI cannot import: it has no dependency on `discord-api-types`. */\nconst OptionType = {\n\tSubcommand: 1,\n\tSubcommandGroup: 2,\n\tString: 3,\n\tInteger: 4,\n\tBoolean: 5,\n\tUser: 6,\n\tChannel: 7,\n\tRole: 8,\n\tMentionable: 9,\n\tNumber: 10,\n\tAttachment: 11\n} as const;\n\n/** `ApplicationCommandType.ChatInput`: the only type with options, and the one a command without `type` is. */\nconst CHAT_INPUT = 1;\n\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/;\n\ninterface OptionData {\n\tname: string;\n\ttype: number;\n\trequired?: boolean;\n\tchoices?: { value: string | number }[];\n\tchannel_types?: number[];\n\toptions?: OptionData[];\n}\n\ninterface Rendering {\n\t/** Set once something refers to `TransformedArguments`, which the file then has to import. */\n\tusesResolvedTypes: boolean;\n}\n\n/**\n * The declaration file `stars codegen` writes for the commands a project registers: one `CommandOptionsRegistry` entry\n * (`Command.OptionsOf<'path'>`) per leaf, that is a command without subcommands, `parent sub` or `parent group sub`.\n *\n * It reads the JSON Discord receives rather than the builders, so what the handler is typed with cannot drift from what\n * is registered, and loops and factories need no special care. The option types point at the framework's\n * `TransformedArguments`, which is what the router resolves them to, instead of repeating those shapes here.\n *\n * Context menu commands have no options and are skipped. A path registered more than once (a command restricted to\n * several guilds is the same command in each) keeps its first definition, global commands first. The output depends\n * on nothing but the commands, in sorted order, so `stars codegen --check` is a string comparison.\n */\nexport function generateCommandTypes(snapshot: CommandSnapshot): string {\n\tconst entries = new Map<string, OptionData[]>();\n\tconst scopes = [\n\t\tsnapshot.global,\n\t\t...Object.keys(snapshot.guilds)\n\t\t\t.sort()\n\t\t\t.map((guild) => snapshot.guilds[guild])\n\t];\n\tfor (const commands of scopes) {\n\t\tfor (const command of commands) collectLeaves(command, entries);\n\t}\n\n\tconst rendering: Rendering = { usesResolvedTypes: false };\n\tconst lines = [...entries.keys()].sort().map((path) => ` ${renderEntry(path, entries.get(path)!, rendering)}`);\n\n\treturn [\n\t\t'// This file is automatically generated by `stars codegen`, do not edit it.',\n\t\t'/* eslint-disable */',\n\t\t'/* oxlint-disable */',\n\t\t'// oxfmt-ignore',\n\t\t'// prettier-ignore',\n\t\trendering.usesResolvedTypes ? \"import type { TransformedArguments } from '@wolfstar/http-framework';\" : 'export {};',\n\t\t'',\n\t\t'// oxfmt-ignore',\n\t\t'// prettier-ignore',\n\t\t\"declare module '@wolfstar/http-framework' {\",\n\t\t' interface CommandOptionsRegistry {',\n\t\t...lines,\n\t\t' }',\n\t\t'}',\n\t\t''\n\t].join('\\n');\n}\n\nfunction collectLeaves(command: CommandData, entries: Map<string, OptionData[]>): void {\n\tif ((command.type ?? CHAT_INPUT) !== CHAT_INPUT) return;\n\n\tconst options = (command.options ?? []) as OptionData[];\n\tconst add = (path: string, leaf: OptionData[] | undefined) => {\n\t\tif (!entries.has(path)) entries.set(path, leaf ?? []);\n\t};\n\n\tif (!options.some((option) => option.type === OptionType.Subcommand || option.type === OptionType.SubcommandGroup)) {\n\t\tadd(command.name, options);\n\t\treturn;\n\t}\n\n\tfor (const option of options) {\n\t\tif (option.type === OptionType.Subcommand) {\n\t\t\tadd(`${command.name} ${option.name}`, option.options);\n\t\t} else if (option.type === OptionType.SubcommandGroup) {\n\t\t\tfor (const sub of option.options ?? []) {\n\t\t\t\tif (sub.type === OptionType.Subcommand) add(`${command.name} ${option.name} ${sub.name}`, sub.options);\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** Only the first line of an entry is indented by the caller: the options go on lines of their own. */\nfunction renderEntry(path: string, options: readonly OptionData[], rendering: Rendering): string {\n\tconst sorted = [...options].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));\n\tconst properties = sorted.map((option) => ` ${key(option.name)}${option.required ? '' : '?'}: ${renderOption(option, rendering)};`);\n\treturn properties.length === 0 ? `${quote(path)}: {};` : `${quote(path)}: {\\n${properties.join('\\n')}\\n };`;\n}\n\nfunction renderOption(option: OptionData, rendering: Rendering): string {\n\tconst resolved = (name: string) => {\n\t\trendering.usesResolvedTypes = true;\n\t\treturn `TransformedArguments.${name}`;\n\t};\n\n\tswitch (option.type) {\n\t\tcase OptionType.String:\n\t\tcase OptionType.Integer:\n\t\tcase OptionType.Number: {\n\t\t\tconst fallback = option.type === OptionType.String ? 'string' : 'number';\n\t\t\tif (!option.choices?.length) return fallback;\n\t\t\tconst values = option.choices.map((choice) => (typeof choice.value === 'string' ? quote(choice.value) : String(choice.value)));\n\t\t\treturn [...new Set(values)].join(' | ');\n\t\t}\n\t\tcase OptionType.Boolean:\n\t\t\treturn 'boolean';\n\t\tcase OptionType.User:\n\t\t\treturn resolved('User');\n\t\tcase OptionType.Role:\n\t\t\treturn resolved('Role');\n\t\tcase OptionType.Mentionable:\n\t\t\treturn resolved('Mentionable');\n\t\tcase OptionType.Attachment:\n\t\t\treturn resolved('Attachment');\n\t\tcase OptionType.Channel: {\n\t\t\tconst channel = resolved('Channel');\n\t\t\tif (!option.channel_types?.length) return channel;\n\t\t\t// `ChannelType` is not imported on purpose: its members are the numbers they are in the payload.\n\t\t\tconst types = [...new Set(option.channel_types)].sort((a, b) => a - b).join(' | ');\n\t\t\treturn `${channel} & { type: Extract<${channel}['type'], ${types}> }`;\n\t\t}\n\t\tdefault:\n\t\t\t// An option type Discord added after this was written: the handler still gets something.\n\t\t\treturn 'unknown';\n\t}\n}\n\nfunction key(name: string): string {\n\treturn IDENTIFIER.test(name) ? name : quote(name);\n}\n\nfunction quote(value: string): string {\n\tconst escaped = value\n\t\t.replaceAll('\\\\', '\\\\\\\\')\n\t\t.replaceAll(\"'\", \"\\\\'\")\n\t\t.replaceAll('\\n', '\\\\n')\n\t\t.replaceAll('\\r', '\\\\r')\n\t\t.replaceAll('
', '\\\\u2028')\n\t\t.replaceAll('
', '\\\\u2029');\n\treturn `'${escaped}'`;\n}\n","import { displayPath, type ResolvedStarsConfig } from '@wolfstar/schema';\nimport { applyEnvOptions, loadProject, withProjectEnv } from '../utils/hooks.js';\nimport { defineCommand } from 'citty';\nimport { createColors } from 'colorette';\nimport { spawn } from 'node:child_process';\nimport { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { projectArgs, resolveCwd, type ProjectArgs } from '../utils/args.js';\nimport type { CommandSnapshot } from '../dev/bridge.js';\nimport { generateCommandTypes } from '../utils/command-types.js';\nimport { cliDiagnostics } from '../utils/diagnostics.js';\nimport { shouldUseColor } from '../utils/output-mode.js';\nimport { readLocalCommands } from '../utils/local-commands.js';\nimport { resolveFromProject } from '../utils/project.js';\n\nexport interface CodegenTaskOptions extends ProjectArgs {\n\tcheck?: boolean;\n\tjson?: boolean;\n\tstdout?: NodeJS.WritableStream;\n\t/** Overrides the commands read from the built bot, for tests. */\n\tcommands?: CommandSnapshot;\n}\n\nexport interface CodegenResult {\n\tgenerator: 'i18n' | 'commands';\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 project = await loadProject({ cwd: resolveCwd(options), configFile: options.config });\n\tconst { config } = project;\n\tconst results: CodegenResult[] = [];\n\n\tif (config.codegen.i18n) results.push(await runI18n(config, Boolean(options.check)));\n\tif (config.codegen.commands) {\n\t\t// What the bot is started with: `env:options` (and varlock) may pick other env files than the defaults.\n\t\tconst botConfig = withProjectEnv(await applyEnvOptions(config, project.hooks));\n\t\tresults.push(await runCommands(botConfig, Boolean(options.check), options.commands));\n\t}\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\n/**\n * Types the options of the commands the project registers. The commands are read from the built bot, the way\n * `stars commands diff` reads them: nothing connects to Discord, but the bot still runs its own env setup, so `--check`\n * in CI needs placeholders for the values it reads while starting (`DISCORD_CLIENT_ID`, `DISCORD_PUBLIC_KEY`, ...).\n */\nasync function runCommands(config: ResolvedStarsConfig, check: boolean, local?: CommandSnapshot): Promise<CodegenResult> {\n\tconst { output } = config.codegen.commands!;\n\tconst generated = generateCommandTypes(local ?? (await readLocalCommands(config)));\n\n\tif (!check) {\n\t\tawait mkdir(dirname(output), { recursive: true });\n\t\tawait writeFile(output, generated);\n\t\treturn { generator: 'commands', output, status: 'written' };\n\t}\n\n\tconst actual = await readFile(output, 'utf-8').catch(() => null);\n\treturn { generator: 'commands', output, status: generated === actual ? 'up-to-date' : 'outdated' };\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, command options)'\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,9 +1,9 @@
|
|
|
1
1
|
import { i as shouldUseColor } from "./output-mode-Bp7Da8vJ.js";
|
|
2
2
|
import { t as cliDiagnostics } from "./diagnostics-BKc--u_3.js";
|
|
3
|
-
import { d as projectArgs, f as resolveCwd, n as loadProject, r as withProjectEnv, t as applyEnvOptions } from "./hooks-
|
|
4
|
-
import { t as readLocalCommands } from "./local-commands-
|
|
3
|
+
import { d as projectArgs, f as resolveCwd, n as loadProject, r as withProjectEnv, t as applyEnvOptions } from "./hooks-CzV2YRoJ.js";
|
|
4
|
+
import { t as readLocalCommands } from "./local-commands-DKnabUnX.js";
|
|
5
5
|
import { i as matchesDeployed, n as diffCommands, t as describeCommand } from "./command-diff-BK912Hjc.js";
|
|
6
|
-
import { i as readDiscordCredentials } from "./tunnel-
|
|
6
|
+
import { i as readDiscordCredentials } from "./tunnel-DlFjqUE7.js";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
import { createColors } from "colorette";
|
|
9
9
|
|
|
@@ -457,4 +457,4 @@ var commands_default = defineCommand({
|
|
|
457
457
|
|
|
458
458
|
//#endregion
|
|
459
459
|
export { commands_default as default };
|
|
460
|
-
//# sourceMappingURL=commands-
|
|
460
|
+
//# sourceMappingURL=commands-CtucWY2d.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands-CURkZI0f.js","names":[],"sources":["../src/utils/discord.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 { 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
|
+
{"version":3,"file":"commands-CtucWY2d.js","names":[],"sources":["../src/utils/discord.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 { 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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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/commands/index.ts
|
|
2
|
+
const commands = {
|
|
3
|
+
dev: () => import("./dev-CnXgPQ8F.js").then((module) => module.default),
|
|
4
|
+
build: () => import("./build-DVF5vcSS.js").then((module) => module.default),
|
|
5
|
+
info: () => import("./info-DLo6tZT5.js").then((module) => module.default),
|
|
6
|
+
codegen: () => import("./codegen-DI263aSx.js").then((module) => module.default),
|
|
7
|
+
prepare: () => import("./prepare-DnNsv3TU.js").then((module) => module.default),
|
|
8
|
+
typecheck: () => import("./typecheck-B2aRagKp.js").then((module) => module.default),
|
|
9
|
+
commands: () => import("./commands-CtucWY2d.js").then((module) => module.default),
|
|
10
|
+
doctor: () => import("./doctor-BYRkkc5l.js").then((module) => module.default),
|
|
11
|
+
completions: () => import("./completions-D_scEKH1.js").then((module) => module.default)
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { commands as t };
|
|
16
|
+
//# sourceMappingURL=commands-D7SFy2_3.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands-
|
|
1
|
+
{"version":3,"file":"commands-D7SFy2_3.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\ttypecheck: () => import('./typecheck.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,iBAAiB,OAAO,0BAAiB,CAAC,MAAM,WAAW,OAAO,OAAO;CACzE,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"}
|
|
@@ -138,7 +138,7 @@ function generateCompletions(shell, commands) {
|
|
|
138
138
|
return GENERATORS[shell](commands);
|
|
139
139
|
}
|
|
140
140
|
async function runCompletions(options) {
|
|
141
|
-
const { commands } = await import("./commands-
|
|
141
|
+
const { commands } = await import("./commands-Bd6Dp5Y0.js");
|
|
142
142
|
(options.stdout ?? process.stdout).write(generateCompletions(options.shell, await describeCommands(commands)));
|
|
143
143
|
}
|
|
144
144
|
var completions_default = defineCommand({
|
|
@@ -158,4 +158,4 @@ var completions_default = defineCommand({
|
|
|
158
158
|
|
|
159
159
|
//#endregion
|
|
160
160
|
export { completions_default as default };
|
|
161
|
-
//# sourceMappingURL=completions-
|
|
161
|
+
//# sourceMappingURL=completions-D_scEKH1.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"completions-DBipETDu.js","names":[],"sources":["../src/commands/completions.ts"],"sourcesContent":["import { defineCommand, type ArgsDef, type CommandDef } from 'citty';\nimport { cliDiagnostics } from '../utils/diagnostics.js';\n\n// citty types each command by its own arguments; the tree only needs the erased form.\n// oxlint-disable-next-line typescript/no-explicit-any\ntype AnyCommand = CommandDef<any>;\n\nexport interface CompletionFlag {\n\tname: string;\n\tdescription: string;\n\t/** Short forms, without the dash (`c` for `-c`). */\n\taliases: string[];\n\t/** A boolean that is on by default also has a `--no-<name>` form. */\n\tnegatable: boolean;\n}\n\nexport interface CompletionCommand {\n\tname: string;\n\tdescription: string;\n\tflags: CompletionFlag[];\n\tsubcommands: CompletionCommand[];\n}\n\nexport const SHELLS = ['bash', 'zsh', 'fish'] as const;\nexport type Shell = (typeof SHELLS)[number];\n\nasync function resolve<T>(value: T | Promise<T> | (() => T | Promise<T>) | undefined): Promise<T | undefined> {\n\treturn typeof value === 'function' ? (value as () => T | Promise<T>)() : value;\n}\n\n/** Walks the commands the CLI registers, so the completions never drift from what `--help` prints. */\nexport async function describeCommands(commands: Record<string, () => Promise<AnyCommand>>): Promise<CompletionCommand[]> {\n\tconst describe = async (name: string, command: AnyCommand): Promise<CompletionCommand> => {\n\t\tconst meta = (await resolve(command.meta)) ?? {};\n\t\tconst args = ((await resolve(command.args)) ?? {}) as ArgsDef;\n\t\tconst children = ((await resolve(command.subCommands)) ?? {}) as Record<string, AnyCommand | (() => Promise<AnyCommand>)>;\n\t\treturn {\n\t\t\tname,\n\t\t\tdescription: meta.description ?? '',\n\t\t\tflags: Object.entries(args)\n\t\t\t\t.filter(([, arg]) => arg.type !== 'positional')\n\t\t\t\t.map(([flag, arg]) => ({\n\t\t\t\t\tname: flag,\n\t\t\t\t\tdescription: arg.description ?? '',\n\t\t\t\t\taliases: [(arg as { alias?: string | string[] }).alias ?? []].flat(),\n\t\t\t\t\tnegatable: arg.type === 'boolean' && arg.default === true\n\t\t\t\t})),\n\t\t\tsubcommands: await Promise.all(Object.entries(children).map(async ([child, value]) => describe(child, (await resolve(value))!)))\n\t\t};\n\t};\n\n\treturn Promise.all(Object.entries(commands).map(async ([name, load]) => describe(name, await load())));\n}\n\n/** Every spelling of a flag: `--name`, `--no-name` when it can be switched off, and its short forms. */\nconst spellings = (flag: CompletionFlag) => [\n\t`--${flag.name}`,\n\t...(flag.negatable ? [`--no-${flag.name}`] : []),\n\t...flag.aliases.map((alias) => (alias.length === 1 ? `-${alias}` : `--${alias}`))\n];\n\nconst flagsOf = (command: CompletionCommand) => [...command.flags.flatMap(spellings), '--help'].join(' ');\n\nfunction bash(commands: readonly CompletionCommand[]): string {\n\tconst cases = commands.map((command) => {\n\t\tif (command.subcommands.length === 0) return `\\t\\t${command.name}) words=\"${flagsOf(command)}\" ;;`;\n\t\tconst nested = command.subcommands.map((child) => `\\t\\t\\t\\t${child.name}) words=\"${flagsOf(child)}\" ;;`).join('\\n');\n\t\treturn [\n\t\t\t`\\t\\t${command.name})`,\n\t\t\t// The subcommand is the first of its names after the command: options of the parent may come before it.\n\t\t\t'\\t\\t\\tsub=\"\"',\n\t\t\t'\\t\\t\\tfor ((i = 2; i < COMP_CWORD; i++)); do',\n\t\t\t`\\t\\t\\t\\tcase \"\\${COMP_WORDS[i]}\" in ${command.subcommands.map((child) => child.name).join('|')}) sub=\"\\${COMP_WORDS[i]}\"; break ;; esac`,\n\t\t\t'\\t\\t\\tdone',\n\t\t\t'\\t\\t\\tcase \"$sub\" in',\n\t\t\tnested,\n\t\t\t`\\t\\t\\t\\t*) words=\"${command.subcommands.map((child) => child.name).join(' ')} ${flagsOf(command)}\" ;;`,\n\t\t\t'\\t\\t\\tesac ;;'\n\t\t].join('\\n');\n\t});\n\n\treturn `# stars completions for bash. Load them with: eval \"$(stars completions bash)\"\n_stars() {\n\tlocal cur words sub i\n\tcur=\"\\${COMP_WORDS[COMP_CWORD]}\"\n\tif [ \"$COMP_CWORD\" -eq 1 ]; then\n\t\twords=\"${commands.map((command) => command.name).join(' ')} --help --version\"\n\telse\n\t\tcase \"\\${COMP_WORDS[1]}\" in\n${cases.join('\\n')}\n\t\t\t*) words=\"\" ;;\n\t\tesac\n\tfi\n\tCOMPREPLY=($(compgen -W \"$words\" -- \"$cur\"))\n}\ncomplete -o default -F _stars stars\n`;\n}\n\nconst quote = (text: string) => `'${text.replaceAll(\"'\", \"'\\\\''\")}'`;\n/** A zsh `_describe` entry: the colon separates the value from its description, so one in the text is escaped. */\nconst described = (name: string, description: string) => quote(`${name}:${description.replaceAll(':', '\\\\:')}`);\n\nfunction zsh(commands: readonly CompletionCommand[]): string {\n\tconst flags = (command: CompletionCommand) =>\n\t\t[\n\t\t\t...command.flags.flatMap((flag) => spellings(flag).map((spelling) => described(spelling, flag.description))),\n\t\t\tdescribed('--help', 'Show the usage')\n\t\t].join(' ');\n\tconst cases = commands.map((command) => {\n\t\tif (command.subcommands.length === 0) return `\\t\\t${command.name}) items=(${flags(command)}) ;;`;\n\t\tconst nested = command.subcommands.map((child) => `\\t\\t\\t\\t${child.name}) items=(${flags(child)}) ;;`).join('\\n');\n\t\tconst children = command.subcommands.map((child) => described(child.name, child.description)).join(' ');\n\t\treturn [\n\t\t\t`\\t\\t${command.name})`,\n\t\t\t'\\t\\t\\tsub=\"\"',\n\t\t\t'\\t\\t\\tfor word in ${words[3,CURRENT-1]}; do',\n\t\t\t`\\t\\t\\t\\tcase \"$word\" in ${command.subcommands.map((child) => child.name).join('|')}) sub=\"$word\"; break ;; esac`,\n\t\t\t'\\t\\t\\tdone',\n\t\t\t'\\t\\t\\tcase \"$sub\" in',\n\t\t\tnested,\n\t\t\t`\\t\\t\\t\\t*) items=(${children} ${flags(command)}) ;;`,\n\t\t\t'\\t\\t\\tesac ;;'\n\t\t].join('\\n');\n\t});\n\n\treturn `#compdef stars\n# stars completions for zsh. Load them with: eval \"$(stars completions zsh)\"\n_stars() {\n\tlocal -a items\n\tlocal sub word\n\tif (( CURRENT == 2 )); then\n\t\titems=(${commands.map((command) => described(command.name, command.description)).join(' ')})\n\telse\n\t\tcase \"$words[2]\" in\n${cases.join('\\n')}\n\t\tesac\n\tfi\n\t_describe 'stars' items\n}\ncompdef _stars stars\n`;\n}\n\nfunction fishFlag(condition: string, flag: CompletionFlag): string[] {\n\tconst short = flag.aliases\n\t\t.filter((alias) => alias.length === 1)\n\t\t.map((alias) => ` -s ${alias}`)\n\t\t.join('');\n\tconst line = (name: string) => `complete -c stars -n \"${condition}\" -l ${name}${name === flag.name ? short : ''} -d ${quote(flag.description)}`;\n\treturn [line(flag.name), ...(flag.negatable ? [line(`no-${flag.name}`)] : [])];\n}\n\nfunction fish(commands: readonly CompletionCommand[]): string {\n\tconst lines = ['# stars completions for fish. Load them with: stars completions fish | source', 'complete -c stars -f'];\n\tconst names = commands.map((command) => command.name).join(' ');\n\tfor (const command of commands) {\n\t\tlines.push(`complete -c stars -n \"not __fish_seen_subcommand_from ${names}\" -a ${command.name} -d ${quote(command.description)}`);\n\t\tconst children = command.subcommands.map((child) => child.name).join(' ');\n\t\tfor (const flag of command.flags) lines.push(...fishFlag(`__fish_seen_subcommand_from ${command.name}`, flag));\n\n\t\tfor (const child of command.subcommands) {\n\t\t\tlines.push(\n\t\t\t\t`complete -c stars -n \"__fish_seen_subcommand_from ${command.name}; and not __fish_seen_subcommand_from ${children}\" -a ${child.name} -d ${quote(child.description)}`\n\t\t\t);\n\t\t\tfor (const flag of child.flags.filter((candidate) => !command.flags.some((own) => own.name === candidate.name))) {\n\t\t\t\tlines.push(...fishFlag(`__fish_seen_subcommand_from ${command.name}; and __fish_seen_subcommand_from ${child.name}`, flag));\n\t\t\t}\n\t\t}\n\t}\n\n\treturn `${lines.join('\\n')}\\n`;\n}\n\nconst GENERATORS: Record<Shell, (commands: readonly CompletionCommand[]) => string> = { bash, zsh, fish };\n\n/** The completion script of a shell, for the given commands. */\nexport function generateCompletions(shell: string, commands: readonly CompletionCommand[]): string {\n\tif (!(SHELLS as readonly string[]).includes(shell)) throw cliDiagnostics.UNKNOWN_SHELL({ shell });\n\treturn GENERATORS[shell as Shell](commands);\n}\n\nexport interface CompletionsOptions {\n\tshell: string;\n\tstdout?: NodeJS.WritableStream;\n}\n\nexport async function runCompletions(options: CompletionsOptions): Promise<void> {\n\t// Imported here: the registry imports this module, as it does every command.\n\tconst { commands } = await import('./index.js');\n\t(options.stdout ?? process.stdout).write(generateCompletions(options.shell, await describeCommands(commands)));\n}\n\nexport default defineCommand({\n\tmeta: {\n\t\tname: 'completions',\n\t\tdescription: 'Print the shell completion script for bash, zsh or fish'\n\t},\n\targs: {\n\t\tshell: {\n\t\t\ttype: 'positional',\n\t\t\tdescription: `The shell to print completions for: ${SHELLS.join(', ')}`,\n\t\t\trequired: true\n\t\t}\n\t},\n\tasync run({ args }) {\n\t\tawait runCompletions({ shell: args.shell });\n\t}\n});\n"],"mappings":";;;;AAuBA,MAAa,SAAS;CAAC;CAAQ;CAAO;AAAM;AAG5C,eAAe,QAAW,OAAoF;CAC7G,OAAO,OAAO,UAAU,aAAc,MAA+B,IAAI;AAC1E;;AAGA,eAAsB,iBAAiB,UAAmF;CACzH,MAAM,WAAW,OAAO,MAAc,YAAoD;EACzF,MAAM,OAAQ,MAAM,QAAQ,QAAQ,IAAI,KAAM,CAAC;EAC/C,MAAM,OAAS,MAAM,QAAQ,QAAQ,IAAI,KAAM,CAAC;EAChD,MAAM,WAAa,MAAM,QAAQ,QAAQ,WAAW,KAAM,CAAC;EAC3D,OAAO;GACN;GACA,aAAa,KAAK,eAAe;GACjC,OAAO,OAAO,QAAQ,IAAI,CAAC,CACzB,QAAQ,GAAG,SAAS,IAAI,SAAS,YAAY,CAAC,CAC9C,KAAK,CAAC,MAAM,UAAU;IACtB,MAAM;IACN,aAAa,IAAI,eAAe;IAChC,SAAS,CAAE,IAAsC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK;IACnE,WAAW,IAAI,SAAS,aAAa,IAAI,YAAY;GACtD,EAAE;GACH,aAAa,MAAM,QAAQ,IAAI,OAAO,QAAQ,QAAQ,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,WAAW,SAAS,OAAQ,MAAM,QAAQ,KAAK,CAAG,CAAC,CAAC;EAChI;CACD;CAEA,OAAO,QAAQ,IAAI,OAAO,QAAQ,QAAQ,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,UAAU,SAAS,MAAM,MAAM,KAAK,CAAC,CAAC,CAAC;AACtG;;AAGA,MAAM,aAAa,SAAyB;CAC3C,KAAK,KAAK;CACV,GAAI,KAAK,YAAY,CAAC,QAAQ,KAAK,MAAM,IAAI,CAAC;CAC9C,GAAG,KAAK,QAAQ,KAAK,UAAW,MAAM,WAAW,IAAI,IAAI,UAAU,KAAK,OAAQ;AACjF;AAEA,MAAM,WAAW,YAA+B,CAAC,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG,QAAQ,CAAC,CAAC,KAAK,GAAG;AAExG,SAAS,KAAK,UAAgD;CAC7D,MAAM,QAAQ,SAAS,KAAK,YAAY;EACvC,IAAI,QAAQ,YAAY,WAAW,GAAG,OAAO,OAAO,QAAQ,KAAK,WAAW,QAAQ,OAAO,EAAE;EAC7F,MAAM,SAAS,QAAQ,YAAY,KAAK,UAAU,WAAW,MAAM,KAAK,WAAW,QAAQ,KAAK,EAAE,KAAK,CAAC,CAAC,KAAK,IAAI;EAClH,OAAO;GACN,OAAO,QAAQ,KAAK;GAEpB;GACA;GACA,uCAAuC,QAAQ,YAAY,KAAK,UAAU,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG,EAAE;GAChG;GACA;GACA;GACA,qBAAqB,QAAQ,YAAY,KAAK,UAAU,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG,EAAE,GAAG,QAAQ,OAAO,EAAE;GAClG;EACD,CAAC,CAAC,KAAK,IAAI;CACZ,CAAC;CAED,OAAO;;;;;WAKG,SAAS,KAAK,YAAY,QAAQ,IAAI,CAAC,CAAC,KAAK,GAAG,EAAE;;;EAG3D,MAAM,KAAK,IAAI,EAAE;;;;;;;;AAQnB;AAEA,MAAM,SAAS,SAAiB,IAAI,KAAK,WAAW,KAAK,OAAO,EAAE;;AAElE,MAAM,aAAa,MAAc,gBAAwB,MAAM,GAAG,KAAK,GAAG,YAAY,WAAW,KAAK,KAAK,GAAG;AAE9G,SAAS,IAAI,UAAgD;CAC5D,MAAM,SAAS,YACd,CACC,GAAG,QAAQ,MAAM,SAAS,SAAS,UAAU,IAAI,CAAC,CAAC,KAAK,aAAa,UAAU,UAAU,KAAK,WAAW,CAAC,CAAC,GAC3G,UAAU,UAAU,gBAAgB,CACrC,CAAC,CAAC,KAAK,GAAG;CACX,MAAM,QAAQ,SAAS,KAAK,YAAY;EACvC,IAAI,QAAQ,YAAY,WAAW,GAAG,OAAO,OAAO,QAAQ,KAAK,WAAW,MAAM,OAAO,EAAE;EAC3F,MAAM,SAAS,QAAQ,YAAY,KAAK,UAAU,WAAW,MAAM,KAAK,WAAW,MAAM,KAAK,EAAE,KAAK,CAAC,CAAC,KAAK,IAAI;EAChH,MAAM,WAAW,QAAQ,YAAY,KAAK,UAAU,UAAU,MAAM,MAAM,MAAM,WAAW,CAAC,CAAC,CAAC,KAAK,GAAG;EACtG,OAAO;GACN,OAAO,QAAQ,KAAK;GACpB;GACA;GACA,2BAA2B,QAAQ,YAAY,KAAK,UAAU,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG,EAAE;GACpF;GACA;GACA;GACA,qBAAqB,SAAS,GAAG,MAAM,OAAO,EAAE;GAChD;EACD,CAAC,CAAC,KAAK,IAAI;CACZ,CAAC;CAED,OAAO;;;;;;WAMG,SAAS,KAAK,YAAY,UAAU,QAAQ,MAAM,QAAQ,WAAW,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;;;EAG3F,MAAM,KAAK,IAAI,EAAE;;;;;;;AAOnB;AAEA,SAAS,SAAS,WAAmB,MAAgC;CACpE,MAAM,QAAQ,KAAK,QACjB,QAAQ,UAAU,MAAM,WAAW,CAAC,CAAC,CACrC,KAAK,UAAU,OAAO,OAAO,CAAC,CAC9B,KAAK,EAAE;CACT,MAAM,QAAQ,SAAiB,yBAAyB,UAAU,OAAO,OAAO,SAAS,KAAK,OAAO,QAAQ,GAAG,MAAM,MAAM,KAAK,WAAW;CAC5I,OAAO,CAAC,KAAK,KAAK,IAAI,GAAG,GAAI,KAAK,YAAY,CAAC,KAAK,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,CAAE;AAC9E;AAEA,SAAS,KAAK,UAAgD;CAC7D,MAAM,QAAQ,CAAC,iFAAiF,sBAAsB;CACtH,MAAM,QAAQ,SAAS,KAAK,YAAY,QAAQ,IAAI,CAAC,CAAC,KAAK,GAAG;CAC9D,KAAK,MAAM,WAAW,UAAU;EAC/B,MAAM,KAAK,yDAAyD,MAAM,OAAO,QAAQ,KAAK,MAAM,MAAM,QAAQ,WAAW,GAAG;EAChI,MAAM,WAAW,QAAQ,YAAY,KAAK,UAAU,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG;EACxE,KAAK,MAAM,QAAQ,QAAQ,OAAO,MAAM,KAAK,GAAG,SAAS,+BAA+B,QAAQ,QAAQ,IAAI,CAAC;EAE7G,KAAK,MAAM,SAAS,QAAQ,aAAa;GACxC,MAAM,KACL,qDAAqD,QAAQ,KAAK,wCAAwC,SAAS,OAAO,MAAM,KAAK,MAAM,MAAM,MAAM,WAAW,GACnK;GACA,KAAK,MAAM,QAAQ,MAAM,MAAM,QAAQ,cAAc,CAAC,QAAQ,MAAM,MAAM,QAAQ,IAAI,SAAS,UAAU,IAAI,CAAC,GAC7G,MAAM,KAAK,GAAG,SAAS,+BAA+B,QAAQ,KAAK,oCAAoC,MAAM,QAAQ,IAAI,CAAC;EAE5H;CACD;CAEA,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE;AAC5B;AAEA,MAAM,aAAgF;CAAE;CAAM;CAAK;AAAK;;AAGxG,SAAgB,oBAAoB,OAAe,UAAgD;CAClG,IAAI,CAAE,OAA6B,SAAS,KAAK,GAAG,MAAM,eAAe,cAAc,EAAE,MAAM,CAAC;CAChG,OAAO,WAAW,MAAe,CAAC,QAAQ;AAC3C;AAOA,eAAsB,eAAe,SAA4C;CAEhF,MAAM,EAAE,aAAa,MAAM,OAAO;CAClC,CAAC,QAAQ,UAAU,QAAQ,OAAM,CAAE,MAAM,oBAAoB,QAAQ,OAAO,MAAM,iBAAiB,QAAQ,CAAC,CAAC;AAC9G;AAEA,0BAAe,cAAc;CAC5B,MAAM;EACL,MAAM;EACN,aAAa;CACd;CACA,MAAM,EACL,OAAO;EACN,MAAM;EACN,aAAa,uCAAuC,OAAO,KAAK,IAAI;EACpE,UAAU;CACX,EACD;CACA,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,eAAe,EAAE,OAAO,KAAK,MAAM,CAAC;CAC3C;AACD,CAAC"}
|
|
1
|
+
{"version":3,"file":"completions-D_scEKH1.js","names":[],"sources":["../src/commands/completions.ts"],"sourcesContent":["import { defineCommand, type ArgsDef, type CommandDef } from 'citty';\nimport { cliDiagnostics } from '../utils/diagnostics.js';\n\n// citty types each command by its own arguments; the tree only needs the erased form.\n// oxlint-disable-next-line typescript/no-explicit-any\ntype AnyCommand = CommandDef<any>;\n\nexport interface CompletionFlag {\n\tname: string;\n\tdescription: string;\n\t/** Short forms, without the dash (`c` for `-c`). */\n\taliases: string[];\n\t/** A boolean that is on by default also has a `--no-<name>` form. */\n\tnegatable: boolean;\n}\n\nexport interface CompletionCommand {\n\tname: string;\n\tdescription: string;\n\tflags: CompletionFlag[];\n\tsubcommands: CompletionCommand[];\n}\n\nexport const SHELLS = ['bash', 'zsh', 'fish'] as const;\nexport type Shell = (typeof SHELLS)[number];\n\nasync function resolve<T>(value: T | Promise<T> | (() => T | Promise<T>) | undefined): Promise<T | undefined> {\n\treturn typeof value === 'function' ? (value as () => T | Promise<T>)() : value;\n}\n\n/** Walks the commands the CLI registers, so the completions never drift from what `--help` prints. */\nexport async function describeCommands(commands: Record<string, () => Promise<AnyCommand>>): Promise<CompletionCommand[]> {\n\tconst describe = async (name: string, command: AnyCommand): Promise<CompletionCommand> => {\n\t\tconst meta = (await resolve(command.meta)) ?? {};\n\t\tconst args = ((await resolve(command.args)) ?? {}) as ArgsDef;\n\t\tconst children = ((await resolve(command.subCommands)) ?? {}) as Record<string, AnyCommand | (() => Promise<AnyCommand>)>;\n\t\treturn {\n\t\t\tname,\n\t\t\tdescription: meta.description ?? '',\n\t\t\tflags: Object.entries(args)\n\t\t\t\t.filter(([, arg]) => arg.type !== 'positional')\n\t\t\t\t.map(([flag, arg]) => ({\n\t\t\t\t\tname: flag,\n\t\t\t\t\tdescription: arg.description ?? '',\n\t\t\t\t\taliases: [(arg as { alias?: string | string[] }).alias ?? []].flat(),\n\t\t\t\t\tnegatable: arg.type === 'boolean' && arg.default === true\n\t\t\t\t})),\n\t\t\tsubcommands: await Promise.all(Object.entries(children).map(async ([child, value]) => describe(child, (await resolve(value))!)))\n\t\t};\n\t};\n\n\treturn Promise.all(Object.entries(commands).map(async ([name, load]) => describe(name, await load())));\n}\n\n/** Every spelling of a flag: `--name`, `--no-name` when it can be switched off, and its short forms. */\nconst spellings = (flag: CompletionFlag) => [\n\t`--${flag.name}`,\n\t...(flag.negatable ? [`--no-${flag.name}`] : []),\n\t...flag.aliases.map((alias) => (alias.length === 1 ? `-${alias}` : `--${alias}`))\n];\n\nconst flagsOf = (command: CompletionCommand) => [...command.flags.flatMap(spellings), '--help'].join(' ');\n\nfunction bash(commands: readonly CompletionCommand[]): string {\n\tconst cases = commands.map((command) => {\n\t\tif (command.subcommands.length === 0) return `\\t\\t${command.name}) words=\"${flagsOf(command)}\" ;;`;\n\t\tconst nested = command.subcommands.map((child) => `\\t\\t\\t\\t${child.name}) words=\"${flagsOf(child)}\" ;;`).join('\\n');\n\t\treturn [\n\t\t\t`\\t\\t${command.name})`,\n\t\t\t// The subcommand is the first of its names after the command: options of the parent may come before it.\n\t\t\t'\\t\\t\\tsub=\"\"',\n\t\t\t'\\t\\t\\tfor ((i = 2; i < COMP_CWORD; i++)); do',\n\t\t\t`\\t\\t\\t\\tcase \"\\${COMP_WORDS[i]}\" in ${command.subcommands.map((child) => child.name).join('|')}) sub=\"\\${COMP_WORDS[i]}\"; break ;; esac`,\n\t\t\t'\\t\\t\\tdone',\n\t\t\t'\\t\\t\\tcase \"$sub\" in',\n\t\t\tnested,\n\t\t\t`\\t\\t\\t\\t*) words=\"${command.subcommands.map((child) => child.name).join(' ')} ${flagsOf(command)}\" ;;`,\n\t\t\t'\\t\\t\\tesac ;;'\n\t\t].join('\\n');\n\t});\n\n\treturn `# stars completions for bash. Load them with: eval \"$(stars completions bash)\"\n_stars() {\n\tlocal cur words sub i\n\tcur=\"\\${COMP_WORDS[COMP_CWORD]}\"\n\tif [ \"$COMP_CWORD\" -eq 1 ]; then\n\t\twords=\"${commands.map((command) => command.name).join(' ')} --help --version\"\n\telse\n\t\tcase \"\\${COMP_WORDS[1]}\" in\n${cases.join('\\n')}\n\t\t\t*) words=\"\" ;;\n\t\tesac\n\tfi\n\tCOMPREPLY=($(compgen -W \"$words\" -- \"$cur\"))\n}\ncomplete -o default -F _stars stars\n`;\n}\n\nconst quote = (text: string) => `'${text.replaceAll(\"'\", \"'\\\\''\")}'`;\n/** A zsh `_describe` entry: the colon separates the value from its description, so one in the text is escaped. */\nconst described = (name: string, description: string) => quote(`${name}:${description.replaceAll(':', '\\\\:')}`);\n\nfunction zsh(commands: readonly CompletionCommand[]): string {\n\tconst flags = (command: CompletionCommand) =>\n\t\t[\n\t\t\t...command.flags.flatMap((flag) => spellings(flag).map((spelling) => described(spelling, flag.description))),\n\t\t\tdescribed('--help', 'Show the usage')\n\t\t].join(' ');\n\tconst cases = commands.map((command) => {\n\t\tif (command.subcommands.length === 0) return `\\t\\t${command.name}) items=(${flags(command)}) ;;`;\n\t\tconst nested = command.subcommands.map((child) => `\\t\\t\\t\\t${child.name}) items=(${flags(child)}) ;;`).join('\\n');\n\t\tconst children = command.subcommands.map((child) => described(child.name, child.description)).join(' ');\n\t\treturn [\n\t\t\t`\\t\\t${command.name})`,\n\t\t\t'\\t\\t\\tsub=\"\"',\n\t\t\t'\\t\\t\\tfor word in ${words[3,CURRENT-1]}; do',\n\t\t\t`\\t\\t\\t\\tcase \"$word\" in ${command.subcommands.map((child) => child.name).join('|')}) sub=\"$word\"; break ;; esac`,\n\t\t\t'\\t\\t\\tdone',\n\t\t\t'\\t\\t\\tcase \"$sub\" in',\n\t\t\tnested,\n\t\t\t`\\t\\t\\t\\t*) items=(${children} ${flags(command)}) ;;`,\n\t\t\t'\\t\\t\\tesac ;;'\n\t\t].join('\\n');\n\t});\n\n\treturn `#compdef stars\n# stars completions for zsh. Load them with: eval \"$(stars completions zsh)\"\n_stars() {\n\tlocal -a items\n\tlocal sub word\n\tif (( CURRENT == 2 )); then\n\t\titems=(${commands.map((command) => described(command.name, command.description)).join(' ')})\n\telse\n\t\tcase \"$words[2]\" in\n${cases.join('\\n')}\n\t\tesac\n\tfi\n\t_describe 'stars' items\n}\ncompdef _stars stars\n`;\n}\n\nfunction fishFlag(condition: string, flag: CompletionFlag): string[] {\n\tconst short = flag.aliases\n\t\t.filter((alias) => alias.length === 1)\n\t\t.map((alias) => ` -s ${alias}`)\n\t\t.join('');\n\tconst line = (name: string) => `complete -c stars -n \"${condition}\" -l ${name}${name === flag.name ? short : ''} -d ${quote(flag.description)}`;\n\treturn [line(flag.name), ...(flag.negatable ? [line(`no-${flag.name}`)] : [])];\n}\n\nfunction fish(commands: readonly CompletionCommand[]): string {\n\tconst lines = ['# stars completions for fish. Load them with: stars completions fish | source', 'complete -c stars -f'];\n\tconst names = commands.map((command) => command.name).join(' ');\n\tfor (const command of commands) {\n\t\tlines.push(`complete -c stars -n \"not __fish_seen_subcommand_from ${names}\" -a ${command.name} -d ${quote(command.description)}`);\n\t\tconst children = command.subcommands.map((child) => child.name).join(' ');\n\t\tfor (const flag of command.flags) lines.push(...fishFlag(`__fish_seen_subcommand_from ${command.name}`, flag));\n\n\t\tfor (const child of command.subcommands) {\n\t\t\tlines.push(\n\t\t\t\t`complete -c stars -n \"__fish_seen_subcommand_from ${command.name}; and not __fish_seen_subcommand_from ${children}\" -a ${child.name} -d ${quote(child.description)}`\n\t\t\t);\n\t\t\tfor (const flag of child.flags.filter((candidate) => !command.flags.some((own) => own.name === candidate.name))) {\n\t\t\t\tlines.push(...fishFlag(`__fish_seen_subcommand_from ${command.name}; and __fish_seen_subcommand_from ${child.name}`, flag));\n\t\t\t}\n\t\t}\n\t}\n\n\treturn `${lines.join('\\n')}\\n`;\n}\n\nconst GENERATORS: Record<Shell, (commands: readonly CompletionCommand[]) => string> = { bash, zsh, fish };\n\n/** The completion script of a shell, for the given commands. */\nexport function generateCompletions(shell: string, commands: readonly CompletionCommand[]): string {\n\tif (!(SHELLS as readonly string[]).includes(shell)) throw cliDiagnostics.UNKNOWN_SHELL({ shell });\n\treturn GENERATORS[shell as Shell](commands);\n}\n\nexport interface CompletionsOptions {\n\tshell: string;\n\tstdout?: NodeJS.WritableStream;\n}\n\nexport async function runCompletions(options: CompletionsOptions): Promise<void> {\n\t// Imported here: the registry imports this module, as it does every command.\n\tconst { commands } = await import('./index.js');\n\t(options.stdout ?? process.stdout).write(generateCompletions(options.shell, await describeCommands(commands)));\n}\n\nexport default defineCommand({\n\tmeta: {\n\t\tname: 'completions',\n\t\tdescription: 'Print the shell completion script for bash, zsh or fish'\n\t},\n\targs: {\n\t\tshell: {\n\t\t\ttype: 'positional',\n\t\t\tdescription: `The shell to print completions for: ${SHELLS.join(', ')}`,\n\t\t\trequired: true\n\t\t}\n\t},\n\tasync run({ args }) {\n\t\tawait runCompletions({ shell: args.shell });\n\t}\n});\n"],"mappings":";;;;AAuBA,MAAa,SAAS;CAAC;CAAQ;CAAO;AAAM;AAG5C,eAAe,QAAW,OAAoF;CAC7G,OAAO,OAAO,UAAU,aAAc,MAA+B,IAAI;AAC1E;;AAGA,eAAsB,iBAAiB,UAAmF;CACzH,MAAM,WAAW,OAAO,MAAc,YAAoD;EACzF,MAAM,OAAQ,MAAM,QAAQ,QAAQ,IAAI,KAAM,CAAC;EAC/C,MAAM,OAAS,MAAM,QAAQ,QAAQ,IAAI,KAAM,CAAC;EAChD,MAAM,WAAa,MAAM,QAAQ,QAAQ,WAAW,KAAM,CAAC;EAC3D,OAAO;GACN;GACA,aAAa,KAAK,eAAe;GACjC,OAAO,OAAO,QAAQ,IAAI,CAAC,CACzB,QAAQ,GAAG,SAAS,IAAI,SAAS,YAAY,CAAC,CAC9C,KAAK,CAAC,MAAM,UAAU;IACtB,MAAM;IACN,aAAa,IAAI,eAAe;IAChC,SAAS,CAAE,IAAsC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK;IACnE,WAAW,IAAI,SAAS,aAAa,IAAI,YAAY;GACtD,EAAE;GACH,aAAa,MAAM,QAAQ,IAAI,OAAO,QAAQ,QAAQ,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,WAAW,SAAS,OAAQ,MAAM,QAAQ,KAAK,CAAG,CAAC,CAAC;EAChI;CACD;CAEA,OAAO,QAAQ,IAAI,OAAO,QAAQ,QAAQ,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,UAAU,SAAS,MAAM,MAAM,KAAK,CAAC,CAAC,CAAC;AACtG;;AAGA,MAAM,aAAa,SAAyB;CAC3C,KAAK,KAAK;CACV,GAAI,KAAK,YAAY,CAAC,QAAQ,KAAK,MAAM,IAAI,CAAC;CAC9C,GAAG,KAAK,QAAQ,KAAK,UAAW,MAAM,WAAW,IAAI,IAAI,UAAU,KAAK,OAAQ;AACjF;AAEA,MAAM,WAAW,YAA+B,CAAC,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG,QAAQ,CAAC,CAAC,KAAK,GAAG;AAExG,SAAS,KAAK,UAAgD;CAC7D,MAAM,QAAQ,SAAS,KAAK,YAAY;EACvC,IAAI,QAAQ,YAAY,WAAW,GAAG,OAAO,OAAO,QAAQ,KAAK,WAAW,QAAQ,OAAO,EAAE;EAC7F,MAAM,SAAS,QAAQ,YAAY,KAAK,UAAU,WAAW,MAAM,KAAK,WAAW,QAAQ,KAAK,EAAE,KAAK,CAAC,CAAC,KAAK,IAAI;EAClH,OAAO;GACN,OAAO,QAAQ,KAAK;GAEpB;GACA;GACA,uCAAuC,QAAQ,YAAY,KAAK,UAAU,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG,EAAE;GAChG;GACA;GACA;GACA,qBAAqB,QAAQ,YAAY,KAAK,UAAU,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG,EAAE,GAAG,QAAQ,OAAO,EAAE;GAClG;EACD,CAAC,CAAC,KAAK,IAAI;CACZ,CAAC;CAED,OAAO;;;;;WAKG,SAAS,KAAK,YAAY,QAAQ,IAAI,CAAC,CAAC,KAAK,GAAG,EAAE;;;EAG3D,MAAM,KAAK,IAAI,EAAE;;;;;;;;AAQnB;AAEA,MAAM,SAAS,SAAiB,IAAI,KAAK,WAAW,KAAK,OAAO,EAAE;;AAElE,MAAM,aAAa,MAAc,gBAAwB,MAAM,GAAG,KAAK,GAAG,YAAY,WAAW,KAAK,KAAK,GAAG;AAE9G,SAAS,IAAI,UAAgD;CAC5D,MAAM,SAAS,YACd,CACC,GAAG,QAAQ,MAAM,SAAS,SAAS,UAAU,IAAI,CAAC,CAAC,KAAK,aAAa,UAAU,UAAU,KAAK,WAAW,CAAC,CAAC,GAC3G,UAAU,UAAU,gBAAgB,CACrC,CAAC,CAAC,KAAK,GAAG;CACX,MAAM,QAAQ,SAAS,KAAK,YAAY;EACvC,IAAI,QAAQ,YAAY,WAAW,GAAG,OAAO,OAAO,QAAQ,KAAK,WAAW,MAAM,OAAO,EAAE;EAC3F,MAAM,SAAS,QAAQ,YAAY,KAAK,UAAU,WAAW,MAAM,KAAK,WAAW,MAAM,KAAK,EAAE,KAAK,CAAC,CAAC,KAAK,IAAI;EAChH,MAAM,WAAW,QAAQ,YAAY,KAAK,UAAU,UAAU,MAAM,MAAM,MAAM,WAAW,CAAC,CAAC,CAAC,KAAK,GAAG;EACtG,OAAO;GACN,OAAO,QAAQ,KAAK;GACpB;GACA;GACA,2BAA2B,QAAQ,YAAY,KAAK,UAAU,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG,EAAE;GACpF;GACA;GACA;GACA,qBAAqB,SAAS,GAAG,MAAM,OAAO,EAAE;GAChD;EACD,CAAC,CAAC,KAAK,IAAI;CACZ,CAAC;CAED,OAAO;;;;;;WAMG,SAAS,KAAK,YAAY,UAAU,QAAQ,MAAM,QAAQ,WAAW,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;;;EAG3F,MAAM,KAAK,IAAI,EAAE;;;;;;;AAOnB;AAEA,SAAS,SAAS,WAAmB,MAAgC;CACpE,MAAM,QAAQ,KAAK,QACjB,QAAQ,UAAU,MAAM,WAAW,CAAC,CAAC,CACrC,KAAK,UAAU,OAAO,OAAO,CAAC,CAC9B,KAAK,EAAE;CACT,MAAM,QAAQ,SAAiB,yBAAyB,UAAU,OAAO,OAAO,SAAS,KAAK,OAAO,QAAQ,GAAG,MAAM,MAAM,KAAK,WAAW;CAC5I,OAAO,CAAC,KAAK,KAAK,IAAI,GAAG,GAAI,KAAK,YAAY,CAAC,KAAK,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,CAAE;AAC9E;AAEA,SAAS,KAAK,UAAgD;CAC7D,MAAM,QAAQ,CAAC,iFAAiF,sBAAsB;CACtH,MAAM,QAAQ,SAAS,KAAK,YAAY,QAAQ,IAAI,CAAC,CAAC,KAAK,GAAG;CAC9D,KAAK,MAAM,WAAW,UAAU;EAC/B,MAAM,KAAK,yDAAyD,MAAM,OAAO,QAAQ,KAAK,MAAM,MAAM,QAAQ,WAAW,GAAG;EAChI,MAAM,WAAW,QAAQ,YAAY,KAAK,UAAU,MAAM,IAAI,CAAC,CAAC,KAAK,GAAG;EACxE,KAAK,MAAM,QAAQ,QAAQ,OAAO,MAAM,KAAK,GAAG,SAAS,+BAA+B,QAAQ,QAAQ,IAAI,CAAC;EAE7G,KAAK,MAAM,SAAS,QAAQ,aAAa;GACxC,MAAM,KACL,qDAAqD,QAAQ,KAAK,wCAAwC,SAAS,OAAO,MAAM,KAAK,MAAM,MAAM,MAAM,WAAW,GACnK;GACA,KAAK,MAAM,QAAQ,MAAM,MAAM,QAAQ,cAAc,CAAC,QAAQ,MAAM,MAAM,QAAQ,IAAI,SAAS,UAAU,IAAI,CAAC,GAC7G,MAAM,KAAK,GAAG,SAAS,+BAA+B,QAAQ,KAAK,oCAAoC,MAAM,QAAQ,IAAI,CAAC;EAE5H;CACD;CAEA,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE;AAC5B;AAEA,MAAM,aAAgF;CAAE;CAAM;CAAK;AAAK;;AAGxG,SAAgB,oBAAoB,OAAe,UAAgD;CAClG,IAAI,CAAE,OAA6B,SAAS,KAAK,GAAG,MAAM,eAAe,cAAc,EAAE,MAAM,CAAC;CAChG,OAAO,WAAW,MAAe,CAAC,QAAQ;AAC3C;AAOA,eAAsB,eAAe,SAA4C;CAEhF,MAAM,EAAE,aAAa,MAAM,OAAO;CAClC,CAAC,QAAQ,UAAU,QAAQ,OAAM,CAAE,MAAM,oBAAoB,QAAQ,OAAO,MAAM,iBAAiB,QAAQ,CAAC,CAAC;AAC9G;AAEA,0BAAe,cAAc;CAC5B,MAAM;EACL,MAAM;EACN,aAAa;CACd;CACA,MAAM,EACL,OAAO;EACN,MAAM;EACN,aAAa,uCAAuC,OAAO,KAAK,IAAI;EACpE,UAAU;CACX,EACD;CACA,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,eAAe,EAAE,OAAO,KAAK,MAAM,CAAC;CAC3C;AACD,CAAC"}
|
|
@@ -4,11 +4,11 @@ import { t as cliDiagnostics } from "./diagnostics-BKc--u_3.js";
|
|
|
4
4
|
import { a as readSavedTheme, c as saveTheme, i as isThemeSetting, n as THEME_SETTINGS, s as resolveThemeSetting } from "./theme-yS2h5dd_.js";
|
|
5
5
|
import { r as ProcessSupervisor } from "./tsc-6su4cT6K.js";
|
|
6
6
|
import { n as createBuilder, t as Locales } from "./locales-CnVIXIip.js";
|
|
7
|
-
import { c as envImportArgs, d as projectArgs, f as resolveCwd, l as moduleImportArgs, n as loadProject, r as withProjectEnv, t as applyEnvOptions, u as collectFlag } from "./hooks-
|
|
8
|
-
import { n as reportWarnings, t as prepareProject } from "./_shared-
|
|
7
|
+
import { c as envImportArgs, d as projectArgs, f as resolveCwd, l as moduleImportArgs, n as loadProject, r as withProjectEnv, t as applyEnvOptions, u as collectFlag } from "./hooks-CzV2YRoJ.js";
|
|
8
|
+
import { n as reportWarnings, t as prepareProject } from "./_shared-BLXTNq89.js";
|
|
9
9
|
import { i as bridgeImportArgs, n as CLI_SOURCE, o as parseBridgeMessage } from "./bridge-DQ3dZ9pm.js";
|
|
10
10
|
import { r as diffSnapshots, t as describeCommand } from "./command-diff-BK912Hjc.js";
|
|
11
|
-
import { t as Tunnel } from "./tunnel-
|
|
11
|
+
import { t as Tunnel } from "./tunnel-DlFjqUE7.js";
|
|
12
12
|
import { a as initialLogView, s as isLogLevel, x as classifyAppLine, y as LogBuffer } from "./log-view-B7uJEnMR.js";
|
|
13
13
|
import { t as Typechecker } from "./typechecker-zjnzC2L_.js";
|
|
14
14
|
import { defineCommand } from "citty";
|
|
@@ -1030,4 +1030,4 @@ var dev_default = defineCommand({
|
|
|
1030
1030
|
|
|
1031
1031
|
//#endregion
|
|
1032
1032
|
export { dev_default as default };
|
|
1033
|
-
//# sourceMappingURL=dev-
|
|
1033
|
+
//# sourceMappingURL=dev-CnXgPQ8F.js.map
|