Skip to content

Commit

Permalink
makes the output of 'astro preferences list' more verbose (#9381)
Browse files Browse the repository at this point in the history
* makes astro preference list more verbose

* adds changeset

* refactor: improve global flag language

* Update .changeset/selfish-donuts-approve.md

---------

Co-authored-by: Nate Moore <nate@astro.build>
Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
  • Loading branch information
3 people committed Jan 18, 2024
1 parent 138ae52 commit 9e01f9c
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/selfish-donuts-approve.md
@@ -0,0 +1,5 @@
---
'astro': patch
---

Improves the CLI output of `astro preferences list` to include additional relevant information
86 changes: 66 additions & 20 deletions packages/astro/src/cli/preferences/index.ts
Expand Up @@ -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';
Expand Down Expand Up @@ -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<string, AnnotatedValue>;

function isValidSubcommand(subcommand: string): subcommand is Subcommand {
return PREFERENCES_SUBCOMMANDS.includes(subcommand as Subcommand);
}
Expand Down Expand Up @@ -210,24 +213,47 @@ async function resetPreference(
return 1;
}

function annotate(flat: Record<string, any>, annotation: string) {
return Object.fromEntries(
Object.entries(flat).map(([key, value]) => [key, { annotation, value }])
);
}
function userValues(
flatDefault: Record<string, string | number | boolean>,
flatProject: Record<string, string | number | boolean>,
flatGlobal: Record<string, string | number | boolean>
) {
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) {
Expand All @@ -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];
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -283,22 +319,32 @@ const chars = {
bottomRight: '╯',
};

function formatTable(
object: Record<string, string | number | boolean>,
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<string, AnnotatedValue>, 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(
Expand All @@ -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)));
Expand Down
8 changes: 8 additions & 0 deletions packages/astro/src/preferences/index.ts
Expand Up @@ -35,6 +35,7 @@ type DeepPartial<T> = T extends object

export type PreferenceKey = DotKeys<Preferences>;
export interface PreferenceList extends Record<PreferenceLocation, DeepPartial<Preferences>> {
fromAstroConfig: DeepPartial<Preferences>;
defaults: Preferences;
}

Expand Down Expand Up @@ -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<string, any>) {
return Object.fromEntries(
Object.entries(defaults).map(([key, _]) => [key, astroConfig[key]])
);
}
},
};
}
Expand Down

0 comments on commit 9e01f9c

Please sign in to comment.