Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
757e868
refactor(cli): info
florian-lefebvre Oct 23, 2025
74908ca
Merge branch 'main' into refactor/cli-info
florian-lefebvre Oct 23, 2025
997042a
feat: change abstraction
florian-lefebvre Oct 23, 2025
86fd0b6
feat: wiring
florian-lefebvre Oct 23, 2025
9595356
feat: package managers
florian-lefebvre Oct 23, 2025
e571f29
feat: formatter
florian-lefebvre Oct 23, 2025
aa96e4e
wip
florian-lefebvre Oct 24, 2025
3d2b471
Merge branch 'main' into refactor/cli-info
florian-lefebvre Oct 29, 2025
b0d4025
fix: build
florian-lefebvre Oct 29, 2025
29bc8b6
fix: misc
florian-lefebvre Oct 29, 2025
e7e9160
fix: copy to clipboard without styles
florian-lefebvre Oct 29, 2025
1f95d34
feat: unify
florian-lefebvre Oct 29, 2025
6763db7
feat: move
florian-lefebvre Oct 29, 2025
1eac498
Merge branch 'main' into refactor/cli-info
florian-lefebvre Oct 29, 2025
572f3e1
chore: format
florian-lefebvre Oct 29, 2025
6f09256
feat: misc
florian-lefebvre Oct 29, 2025
52d7655
Merge branch 'main' into refactor/cli-info
florian-lefebvre Oct 30, 2025
6fb919c
fix: build
florian-lefebvre Oct 30, 2025
a607b92
fix: tests
florian-lefebvre Oct 30, 2025
537030d
Merge branch 'main' into refactor/cli-info
florian-lefebvre Oct 31, 2025
aae49fc
fix: test
florian-lefebvre Oct 31, 2025
2d6fa7c
fix: db tests
florian-lefebvre Oct 31, 2025
c960238
fix: test
florian-lefebvre Oct 31, 2025
e96b67f
feat: improve perf
florian-lefebvre Oct 31, 2025
ac96b46
fix
florian-lefebvre Oct 31, 2025
8264e47
Merge branch 'main' into refactor/cli-info
florian-lefebvre Nov 11, 2025
fcd9816
Merge branch 'main' into refactor/cli-info
florian-lefebvre Nov 13, 2025
5835582
Merge branch 'main' into refactor/cli-info
florian-lefebvre Nov 14, 2025
68ec32b
chore: comment
florian-lefebvre Nov 14, 2025
22e4269
feat: new abstraction
florian-lefebvre Nov 14, 2025
7e31d56
feat: test
florian-lefebvre Nov 14, 2025
fd14128
feat: test
florian-lefebvre Nov 14, 2025
32409c5
chore: format
florian-lefebvre Nov 14, 2025
7e965ab
Merge branch 'main' into refactor/cli-info
florian-lefebvre Nov 17, 2025
28e5698
feat: tests
florian-lefebvre Nov 17, 2025
7600655
fix: tests
florian-lefebvre Nov 17, 2025
2acaaf6
Merge branch 'main' into refactor/cli-info
florian-lefebvre Nov 17, 2025
a395292
feat: add tests
florian-lefebvre Nov 17, 2025
4b5d5eb
Merge branch 'main' into refactor/cli-info
florian-lefebvre Nov 18, 2025
1726423
fix: test
florian-lefebvre Nov 18, 2025
83fc29f
feat: add tests
florian-lefebvre Nov 18, 2025
1d4c8c2
feat: add tests
florian-lefebvre Nov 18, 2025
945e94d
feat: add tests
florian-lefebvre Nov 18, 2025
ee5332a
chore: changeset
florian-lefebvre Nov 18, 2025
1ded1f7
feedback
florian-lefebvre Nov 18, 2025
ee13ad6
error handling
florian-lefebvre Nov 18, 2025
43767d8
document
florian-lefebvre Nov 18, 2025
bb5dcb9
feat: rename
florian-lefebvre Nov 18, 2025
9dc1805
fix: lint
florian-lefebvre Nov 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fancy-cases-act.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Improves `astro info`
1 change: 1 addition & 0 deletions packages/astro/src/cli/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { AstroInlineConfig } from '../types/public/config.js';
// Alias for now, but allows easier migration to node's `parseArgs` in the future.
export type Flags = Arguments;

/** @deprecated Use AstroConfigResolver instead */
export function flagsToAstroInlineConfig(flags: Flags): AstroInlineConfig {
return {
// Inline-only configs
Expand Down
62 changes: 59 additions & 3 deletions packages/astro/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,65 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
return;
}
case 'info': {
const { printInfo } = await import('./info/index.js');
await printInfo({ flags });
return;
const [
{ createProcessOperatingSystemProvider },
{ createCliAstroConfigResolver },
{ createProcessPackageManagerUserAgentProvider },
{ createProcessNodeVersionProvider },
{ createCliDebugInfoProvider },
{ createTinyexecCommandExecutor },
{ getPackageManager },
{ createStyledDebugInfoFormatter },
{ createPromptsPrompt },
{ createCliClipboard },
{ createPassthroughTextStyler },
{ infoCommand },
] = await Promise.all([
import('./infra/process-operating-system-provider.js'),
import('./info/infra/cli-astro-config-resolver.js'),
import('./info/infra/process-package-manager-user-agent-provider.js'),
import('./info/infra/process-node-version-provider.js'),
import('./info/infra/cli-debug-info-provider.js'),
import('./infra/tinyexec-command-executor.js'),
import('./info/core/get-package-manager.js'),
import('./info/infra/styled-debug-info-formatter.js'),
import('./info/infra/prompts-prompt.js'),
import('./info/infra/cli-clipboard.js'),
import('./infra/passthrough-text-styler.js'),
import('./info/core/info.js'),
]);
const operatingSystemProvider = createProcessOperatingSystemProvider();
const astroConfigResolver = createCliAstroConfigResolver({ flags });
const commandExecutor = createTinyexecCommandExecutor();
const packageManagerUserAgentProvider = createProcessPackageManagerUserAgentProvider();
const nodeVersionProvider = createProcessNodeVersionProvider();
const debugInfoProvider = createCliDebugInfoProvider({
config: await astroConfigResolver.resolve(),
astroVersionProvider,
operatingSystemProvider,
packageManager: await getPackageManager({
packageManagerUserAgentProvider,
commandExecutor,
}),
nodeVersionProvider,
});
const prompt = createPromptsPrompt({ force: flags.copy });
const clipboard = createCliClipboard({
commandExecutor,
logger,
operatingSystemProvider,
prompt,
});

return await runner.run(infoCommand, {
logger,
debugInfoProvider,
getDebugInfoFormatter: ({ pretty }) =>
createStyledDebugInfoFormatter({
textStyler: pretty ? textStyler : createPassthroughTextStyler(),
}),
clipboard,
});
}
case 'create-key': {
const [{ createCryptoKeyGenerator }, { createKeyCommand }] = await Promise.all([
Expand Down
44 changes: 44 additions & 0 deletions packages/astro/src/cli/info/core/get-package-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { CommandExecutor } from '../../definitions.js';
import type { PackageManager, PackageManagerUserAgentProvider } from '../definitions.js';

interface Options {
packageManagerUserAgentProvider: PackageManagerUserAgentProvider;
commandExecutor: CommandExecutor;
}

export async function getPackageManager({
packageManagerUserAgentProvider,
commandExecutor,
}: Options): Promise<PackageManager> {
const userAgent = packageManagerUserAgentProvider.getUserAgent();
if (!userAgent) {
const { createNoopPackageManager } = await import('../infra/noop-package-manager.js');
return createNoopPackageManager();
}
const specifier = userAgent.split(' ')[0];
const _name = specifier.substring(0, specifier.lastIndexOf('/'));
const name = _name === 'npminstall' ? 'cnpm' : _name;

switch (name) {
case 'pnpm': {
const { createPnpmPackageManager } = await import('../infra/pnpm-package-manager.js');
return createPnpmPackageManager({ commandExecutor });
}
case 'npm': {
const { createNpmPackageManager } = await import('../infra/npm-package-manager.js');
return createNpmPackageManager({ commandExecutor });
}
case 'yarn': {
const { createYarnPackageManager } = await import('../infra/yarn-package-manager.js');
return createYarnPackageManager({ commandExecutor });
}
case 'bun': {
const { createBunPackageManager } = await import('../infra/bun-package-manager.js');
return createBunPackageManager();
}
default: {
const { createNoopPackageManager } = await import('../infra/noop-package-manager.js');
return createNoopPackageManager();
}
}
}
29 changes: 29 additions & 0 deletions packages/astro/src/cli/info/core/info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { Logger } from '../../../core/logger/core.js';
import { defineCommand } from '../../domain/command.js';
import type { Clipboard, DebugInfoFormatter, DebugInfoProvider } from '../definitions.js';

interface Options {
debugInfoProvider: DebugInfoProvider;
getDebugInfoFormatter: (options: { pretty: boolean }) => DebugInfoFormatter;
logger: Logger;
clipboard: Clipboard;
}

export const infoCommand = defineCommand({
help: {
commandName: 'astro info',
tables: {
Flags: [
['--help (-h)', 'See all available flags.'],
['--copy', 'Force copy of the output.'],
],
},
description:
'Reports useful information about your current Astro environment. Useful for providing information when opening an issue.',
},
async run({ debugInfoProvider, getDebugInfoFormatter, logger, clipboard }: Options) {
const debugInfo = await debugInfoProvider.get();
logger.info('SKIP_FORMAT', getDebugInfoFormatter({ pretty: true }).format(debugInfo));
await clipboard.copy(getDebugInfoFormatter({ pretty: false }).format(debugInfo));
},
});
35 changes: 35 additions & 0 deletions packages/astro/src/cli/info/definitions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { AstroConfig } from '../../types/public/index.js';
import type { DebugInfo } from './domain/debug-info.js';

export interface DebugInfoProvider {
get: () => Promise<DebugInfo>;
}

export interface DebugInfoFormatter {
format: (info: DebugInfo) => string;
}

export interface Clipboard {
copy: (text: string) => Promise<void>;
}

export interface PackageManager {
getName: () => string;
getPackageVersion: (name: string) => Promise<string | undefined>;
}

export interface AstroConfigResolver {
resolve: () => Promise<AstroConfig>;
}

export interface Prompt {
confirm: (input: { message: string; defaultValue?: boolean }) => Promise<boolean>;
}

export interface PackageManagerUserAgentProvider {
getUserAgent: () => string | null;
}

export interface NodeVersionProvider {
get: () => string;
}
1 change: 1 addition & 0 deletions packages/astro/src/cli/info/domain/debug-info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type DebugInfo = Array<[string, string | Array<string>]>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this go to info/definitions.ts?

Copy link
Member Author

@florian-lefebvre florian-lefebvre Nov 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. Currently the structure I've been following is:

  • domain/filename.ts: a specific data entity
  • definitions.ts: infrastructure definitions
  • infra/filename.ts: infrastructure implementation
  • core/filename.ts: one function holding some core logic

Copy link
Member

@ematipico ematipico Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't documented anywhere:

  • PR
  • Contribution guidelines
  • comments

You raised a similar PR for fonts now, and I would expect the same infrastructure. Should address this comment first?

i.e. you explained to me the folder structure, but I still don't understand why debug-info.ts must be here... honestly, it's all foggy. Maybe let's raise a PR that explains this folder/business logic structure.

Not a blocker, but something you should consider

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I'll make a follow up PR with guidelines

Loading