diff --git a/.changeset/selfish-donuts-approve.md b/.changeset/selfish-donuts-approve.md new file mode 100644 index 000000000000..f5cf4d6f9ebe --- /dev/null +++ b/.changeset/selfish-donuts-approve.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Improves the CLI output of `astro preferences list` to include additional relevant information diff --git a/packages/astro/src/cli/preferences/index.ts b/packages/astro/src/cli/preferences/index.ts index 7f48260fe41f..b7d59b3c83ae 100644 --- a/packages/astro/src/cli/preferences/index.ts +++ b/packages/astro/src/cli/preferences/index.ts @@ -2,7 +2,7 @@ import type yargs from 'yargs-parser'; import type { AstroSettings } from '../../@types/astro.js'; -import { bgGreen, black, bold, dim } from 'kleur/colors'; +import { bgGreen, black, bold, dim, yellow } from 'kleur/colors'; import { fileURLToPath } from 'node:url'; import dlv from 'dlv'; @@ -32,6 +32,9 @@ const PREFERENCES_SUBCOMMANDS = [ ] as const; export type Subcommand = (typeof PREFERENCES_SUBCOMMANDS)[number]; +type AnnotatedValue = { annotation: string; value: string | number | boolean }; +type AnnotatedValues = Record; + function isValidSubcommand(subcommand: string): subcommand is Subcommand { return PREFERENCES_SUBCOMMANDS.includes(subcommand as Subcommand); } @@ -210,24 +213,47 @@ async function resetPreference( return 1; } +function annotate(flat: Record, annotation: string) { + return Object.fromEntries( + Object.entries(flat).map(([key, value]) => [key, { annotation, value }]) + ); +} +function userValues( + flatDefault: Record, + flatProject: Record, + flatGlobal: Record +) { + const result: AnnotatedValues = {}; + for (const key of Object.keys(flatDefault)) { + if (key in flatProject) { + result[key] = { + value: flatProject[key], + annotation: '', + } + if (key in flatGlobal) { + result[key].annotation += ` (also modified globally)`; + } + } else if (key in flatGlobal) { + result[key] = { value: flatGlobal[key], annotation: '(global)' }; + } + } + return result; +} + async function listPreferences(settings: AstroSettings, { location, json }: SubcommandOptions) { if (json) { const resolved = await settings.preferences.getAll(); console.log(JSON.stringify(resolved, null, 2)); return 0; } - const { global, project, defaults } = await settings.preferences.list({ location }); + const { global, project, fromAstroConfig, defaults } = await settings.preferences.list({ + location, + }); const flatProject = flattie(project); const flatGlobal = flattie(global); - const flatUser = Object.assign({}, flatGlobal, flatProject); - for (let key of Object.keys(flatUser)) { - if (!isValidKey(key)) { - delete flatUser[key]; - continue; - } - } - const flatDefault = flattie(defaults); + const flatUser = userValues(flatDefault, flatProject, flatGlobal); + const userKeys = Object.keys(flatUser); if (userKeys.length > 0) { @@ -240,7 +266,7 @@ async function listPreferences(settings: AstroSettings, { location, json }: Subc const message = dim('No preferences set'); console.log(['', badge, '', message].join('\n')); } - const flatUnset = Object.assign({}, flatDefault); + const flatUnset = annotate(Object.assign({}, flatDefault), ''); for (const key of userKeys) { delete flatUnset[key]; } @@ -256,6 +282,16 @@ async function listPreferences(settings: AstroSettings, { location, json }: Subc const message = dim('All preferences have been set'); console.log(['', badge, '', message].join('\n')); } + if ( + fromAstroConfig.devToolbar?.enabled === false && + flatUser['devToolbar.enabled']?.value !== false + ) { + console.log( + yellow( + 'The dev toolbar is currently disabled. To enable it, set devToolbar: {enabled: true} in your astroConfig file.' + ) + ); + } return 0; } @@ -283,22 +319,32 @@ const chars = { bottomRight: '╯', }; -function formatTable( - object: Record, - columnLabels: [string, string] +// this is only used to deternine the column width +function annotatedFormat(mv: AnnotatedValue) { + return mv.annotation ? `${mv.value} ${mv.annotation}` : mv.value.toString(); +} +// this is the real formatting for annotated values +function formatAnnotated( + mv: AnnotatedValue, + style: (value: string | number | boolean) => string = (v) => v.toString() ) { + return mv.annotation ? `${style(mv.value)} ${dim(mv.annotation)}` : style(mv.value); +} +function formatTable(object: Record, columnLabels: [string, string]) { const [colA, colB] = columnLabels; const colALength = [colA, ...Object.keys(object)].reduce(longest, 0) + 3; - const colBLength = [colB, ...Object.values(object)].reduce(longest, 0) + 3; + const colBLength = [colB, ...Object.values(object).map(annotatedFormat)].reduce(longest, 0) + 3; function formatRow( i: number, a: string, - b: string | number | boolean, + b: AnnotatedValue, style: (value: string | number | boolean) => string = (v) => v.toString() ): string { - return `${dim(chars.v)} ${style(a)} ${space(colALength - a.length - 2)} ${dim(chars.v)} ${style( - b - )} ${space(colBLength - b.toString().length - 3)} ${dim(chars.v)}`; + return `${dim(chars.v)} ${style(a)} ${space(colALength - a.length - 2)} ${dim( + chars.v + )} ${formatAnnotated(b, style)} ${space(colBLength - annotatedFormat(b).length - 3)} ${dim( + chars.v + )}`; } const top = dim( `${chars.topLeft}${chars.h.repeat(colALength + 1)}${chars.hBottom}${chars.h.repeat( @@ -315,7 +361,7 @@ function formatTable( chars.hThickCross }${chars.hThick.repeat(colBLength)}${chars.vLeftThick}` ); - const rows: string[] = [top, formatRow(-1, colA, colB, bold), divider]; + const rows: string[] = [top, formatRow(-1, colA, { value: colB, annotation: '' }, bold), divider]; let i = 0; for (const [key, value] of Object.entries(object)) { rows.push(formatRow(i, key, value, (v) => formatWithOptions({ colors: true }, v))); diff --git a/packages/astro/src/preferences/index.ts b/packages/astro/src/preferences/index.ts index fdaba8372db9..d758c405b38f 100644 --- a/packages/astro/src/preferences/index.ts +++ b/packages/astro/src/preferences/index.ts @@ -35,6 +35,7 @@ type DeepPartial = T extends object export type PreferenceKey = DotKeys; export interface PreferenceList extends Record> { + fromAstroConfig: DeepPartial; defaults: Preferences; } @@ -95,8 +96,15 @@ export default function createPreferences(config: AstroConfig): AstroPreferences return { global: stores['global'].getAll(), project: stores['project'].getAll(), + fromAstroConfig: mapFrom(DEFAULT_PREFERENCES, config), defaults: DEFAULT_PREFERENCES, }; + + function mapFrom(defaults: Preferences, astroConfig: Record) { + return Object.fromEntries( + Object.entries(defaults).map(([key, _]) => [key, astroConfig[key]]) + ); + } }, }; }