Initial commit

This commit is contained in:
Alejandro Martinez
2026-02-12 02:04:10 +01:00
commit f09af719cf
13433 changed files with 2193445 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
import type { PackageManager } from '../definitions.js';
export declare class BunPackageManager implements PackageManager {
readonly name: string;
getPackageVersion(): Promise<string | undefined>;
}

View File

@@ -0,0 +1,9 @@
class BunPackageManager {
name = "bun";
async getPackageVersion() {
return void 0;
}
}
export {
BunPackageManager
};

View File

@@ -0,0 +1,10 @@
import type { AstroConfig } from '../../../types/public/index.js';
import type { Flags } from '../../flags.js';
import type { AstroConfigResolver } from '../definitions.js';
export declare class CliAstroConfigResolver implements AstroConfigResolver {
#private;
constructor({ flags }: {
flags: Flags;
});
resolve(): Promise<AstroConfig>;
}

View File

@@ -0,0 +1,36 @@
import { resolveConfig } from "../../../core/config/config.js";
class CliAstroConfigResolver {
// TODO: find something better
#flags;
constructor({ flags }) {
this.#flags = flags;
}
async resolve() {
const { astroConfig } = await resolveConfig(
// TODO: consider testing flags => astro inline config
{
// Inline-only configs
configFile: typeof this.#flags.config === "string" ? this.#flags.config : void 0,
mode: typeof this.#flags.mode === "string" ? this.#flags.mode : void 0,
logLevel: this.#flags.verbose ? "debug" : this.#flags.silent ? "silent" : void 0,
force: this.#flags.force ? true : void 0,
// Astro user configs
root: typeof this.#flags.root === "string" ? this.#flags.root : void 0,
site: typeof this.#flags.site === "string" ? this.#flags.site : void 0,
base: typeof this.#flags.base === "string" ? this.#flags.base : void 0,
outDir: typeof this.#flags.outDir === "string" ? this.#flags.outDir : void 0,
server: {
port: typeof this.#flags.port === "number" ? this.#flags.port : void 0,
host: typeof this.#flags.host === "string" || typeof this.#flags.host === "boolean" ? this.#flags.host : void 0,
open: typeof this.#flags.open === "string" || typeof this.#flags.open === "boolean" ? this.#flags.open : void 0,
allowedHosts: typeof this.#flags.allowedHosts === "string" ? this.#flags.allowedHosts.split(",") : typeof this.#flags.allowedHosts === "boolean" && this.#flags.allowedHosts === true ? this.#flags.allowedHosts : []
}
},
"info"
);
return astroConfig;
}
}
export {
CliAstroConfigResolver
};

View File

@@ -0,0 +1,13 @@
import type { Logger } from '../../../core/logger/core.js';
import type { CommandExecutor, OperatingSystemProvider } from '../../definitions.js';
import type { Clipboard, Prompt } from '../definitions.js';
export declare class CliClipboard implements Clipboard {
#private;
constructor({ operatingSystemProvider, commandExecutor, logger, prompt, }: {
operatingSystemProvider: OperatingSystemProvider;
commandExecutor: CommandExecutor;
logger: Logger;
prompt: Prompt;
});
copy(text: string): Promise<void>;
}

View File

@@ -0,0 +1,78 @@
async function getExecInputForPlatform({
platform,
commandExecutor
}) {
if (platform === "darwin") {
return ["pbcopy"];
}
if (platform === "win32") {
return ["clip"];
}
const unixCommands = [
["xclip", ["-selection", "clipboard"]],
["wl-copy", []]
];
for (const [unixCommand, unixArgs] of unixCommands) {
try {
const { stdout } = await commandExecutor.execute("which", [unixCommand]);
if (stdout.trim()) {
return [unixCommand, unixArgs];
}
} catch {
continue;
}
}
return null;
}
class CliClipboard {
#operatingSystemProvider;
#commandExecutor;
#logger;
#prompt;
constructor({
operatingSystemProvider,
commandExecutor,
logger,
prompt
}) {
this.#operatingSystemProvider = operatingSystemProvider;
this.#commandExecutor = commandExecutor;
this.#logger = logger;
this.#prompt = prompt;
}
async copy(text) {
text = text.trim();
const platform = this.#operatingSystemProvider.name;
const input = await getExecInputForPlatform({
platform,
commandExecutor: this.#commandExecutor
});
if (!input) {
this.#logger.warn("SKIP_FORMAT", "Clipboard command not found!");
this.#logger.info("SKIP_FORMAT", "Please manually copy the text above.");
return;
}
if (!await this.#prompt.confirm({
message: "Copy to clipboard?",
defaultValue: true
})) {
return;
}
try {
const [command, args] = input;
await this.#commandExecutor.execute(command, args, {
input: text,
stdio: ["pipe", "ignore", "ignore"]
});
this.#logger.info("SKIP_FORMAT", "Copied to clipboard!");
} catch {
this.#logger.error(
"SKIP_FORMAT",
"Sorry, something went wrong! Please copy the text above manually."
);
}
}
}
export {
CliClipboard
};

View File

@@ -0,0 +1,15 @@
import type { AstroConfig } from '../../../types/public/index.js';
import type { AstroVersionProvider, OperatingSystemProvider } from '../../definitions.js';
import type { DebugInfoProvider, NodeVersionProvider, PackageManager } from '../definitions.js';
import type { DebugInfo } from '../domain/debug-info.js';
export declare class CliDebugInfoProvider implements DebugInfoProvider {
#private;
constructor({ config, astroVersionProvider, packageManager, operatingSystemProvider, nodeVersionProvider, }: {
config: Pick<AstroConfig, 'output' | 'adapter' | 'integrations'>;
astroVersionProvider: AstroVersionProvider;
packageManager: PackageManager;
operatingSystemProvider: OperatingSystemProvider;
nodeVersionProvider: NodeVersionProvider;
});
get(): Promise<DebugInfo>;
}

View File

@@ -0,0 +1,57 @@
function withVersion(name, version) {
let result = name;
if (version) {
result += ` (${version})`;
}
return result;
}
class CliDebugInfoProvider {
#config;
#astroVersionProvider;
#packageManager;
#operatingSystemProvider;
#nodeVersionProvider;
constructor({
config,
astroVersionProvider,
packageManager,
operatingSystemProvider,
nodeVersionProvider
}) {
this.#config = config;
this.#astroVersionProvider = astroVersionProvider;
this.#packageManager = packageManager;
this.#operatingSystemProvider = operatingSystemProvider;
this.#nodeVersionProvider = nodeVersionProvider;
}
async get() {
const debugInfo = [
["Astro", `v${this.#astroVersionProvider.version}`],
["Node", this.#nodeVersionProvider.version],
["System", this.#operatingSystemProvider.displayName],
["Package Manager", this.#packageManager.name],
["Output", this.#config.output]
];
const viteVersion = await this.#packageManager.getPackageVersion("vite");
if (viteVersion) {
debugInfo.splice(1, 0, ["Vite", viteVersion]);
}
debugInfo.push([
"Adapter",
this.#config.adapter ? withVersion(
this.#config.adapter.name,
await this.#packageManager.getPackageVersion(this.#config.adapter.name)
) : "none"
]);
const integrations = await Promise.all(
this.#config.integrations.map(
async ({ name }) => withVersion(name, await this.#packageManager.getPackageVersion(name))
)
);
debugInfo.push(["Integrations", integrations.length > 0 ? integrations : "none"]);
return debugInfo;
}
}
export {
CliDebugInfoProvider
};

View File

@@ -0,0 +1,18 @@
import type { AstroConfig } from '../../../types/public/index.js';
import type { AstroVersionProvider, OperatingSystemProvider } from '../../definitions.js';
import type { DebugInfoProvider, NodeVersionProvider, PackageManager } from '../definitions.js';
import type { DebugInfo } from '../domain/debug-info.js';
/**
* Returns debug info without any package versions, to avoid slowing down the dev server
*/
export declare class DevDebugInfoProvider implements DebugInfoProvider {
#private;
constructor({ config, astroVersionProvider, packageManager, operatingSystemProvider, nodeVersionProvider, }: {
config: Pick<AstroConfig, 'output' | 'adapter' | 'integrations'>;
astroVersionProvider: AstroVersionProvider;
packageManager: PackageManager;
operatingSystemProvider: OperatingSystemProvider;
nodeVersionProvider: NodeVersionProvider;
});
get(): Promise<DebugInfo>;
}

View File

@@ -0,0 +1,36 @@
class DevDebugInfoProvider {
#config;
#astroVersionProvider;
#packageManager;
#operatingSystemProvider;
#nodeVersionProvider;
constructor({
config,
astroVersionProvider,
packageManager,
operatingSystemProvider,
nodeVersionProvider
}) {
this.#config = config;
this.#astroVersionProvider = astroVersionProvider;
this.#packageManager = packageManager;
this.#operatingSystemProvider = operatingSystemProvider;
this.#nodeVersionProvider = nodeVersionProvider;
}
async get() {
const debugInfo = [
["Astro", `v${this.#astroVersionProvider.version}`],
["Node", this.#nodeVersionProvider.version],
["System", this.#operatingSystemProvider.displayName],
["Package Manager", this.#packageManager.name],
["Output", this.#config.output],
["Adapter", this.#config.adapter?.name ?? "none"]
];
const integrations = this.#config.integrations.map((integration) => integration.name);
debugInfo.push(["Integrations", integrations.length > 0 ? integrations : "none"]);
return debugInfo;
}
}
export {
DevDebugInfoProvider
};

View File

@@ -0,0 +1,5 @@
import type { PackageManager } from '../definitions.js';
export declare class NoopPackageManager implements PackageManager {
readonly name: string;
getPackageVersion(): Promise<string | undefined>;
}

View File

@@ -0,0 +1,9 @@
class NoopPackageManager {
name = "unknown";
async getPackageVersion() {
return void 0;
}
}
export {
NoopPackageManager
};

View File

@@ -0,0 +1,10 @@
import type { CommandExecutor } from '../../definitions.js';
import type { PackageManager } from '../definitions.js';
export declare class NpmPackageManager implements PackageManager {
#private;
readonly name: string;
constructor({ commandExecutor }: {
commandExecutor: CommandExecutor;
});
getPackageVersion(name: string): Promise<string | undefined>;
}

View File

@@ -0,0 +1,32 @@
class NpmPackageManager {
name = "npm";
#commandExecutor;
constructor({ commandExecutor }) {
this.#commandExecutor = commandExecutor;
}
async getPackageVersion(name) {
try {
const { stdout } = await this.#commandExecutor.execute(
"npm",
["ls", name, "--json", "--depth=1"],
{
shell: true
}
);
const parsedNpmOutput = JSON.parse(stdout);
if (!parsedNpmOutput.dependencies) {
return void 0;
}
if (parsedNpmOutput.dependencies[name]) {
return `v${parsedNpmOutput.dependencies[name].version}`;
}
const astro = parsedNpmOutput.dependencies.astro;
return astro ? `v${astro.dependencies[name].version}` : void 0;
} catch {
return void 0;
}
}
}
export {
NpmPackageManager
};

View File

@@ -0,0 +1,10 @@
import type { CommandExecutor } from '../../definitions.js';
import type { PackageManager } from '../definitions.js';
export declare class PnpmPackageManager implements PackageManager {
#private;
readonly name: string;
constructor({ commandExecutor }: {
commandExecutor: CommandExecutor;
});
getPackageVersion(name: string): Promise<string | undefined>;
}

View File

@@ -0,0 +1,33 @@
function formatPnpmVersionOutput(versionOutput) {
return versionOutput.startsWith("link:") ? "Local" : `v${versionOutput}`;
}
class PnpmPackageManager {
name = "pnpm";
#commandExecutor;
constructor({ commandExecutor }) {
this.#commandExecutor = commandExecutor;
}
async getPackageVersion(name) {
try {
const { stdout } = await this.#commandExecutor.execute("pnpm", ["why", name, "--json"], {
shell: true
});
const parsedOutput = JSON.parse(stdout);
const deps = parsedOutput[0].dependencies;
if (parsedOutput.length === 0 || !deps) {
return void 0;
}
const userProvidedDependency = deps[name];
if (userProvidedDependency) {
return formatPnpmVersionOutput(userProvidedDependency.version);
}
const astroDependency = deps.astro?.dependencies[name];
return astroDependency ? formatPnpmVersionOutput(astroDependency.version) : void 0;
} catch {
return void 0;
}
}
}
export {
PnpmPackageManager
};

View File

@@ -0,0 +1,4 @@
import type { NodeVersionProvider } from '../definitions.js';
export declare class ProcessNodeVersionProvider implements NodeVersionProvider {
readonly version: string;
}

View File

@@ -0,0 +1,6 @@
class ProcessNodeVersionProvider {
version = process.version;
}
export {
ProcessNodeVersionProvider
};

View File

@@ -0,0 +1,4 @@
import type { PackageManagerUserAgentProvider } from '../definitions.js';
export declare class ProcessPackageManagerUserAgentProvider implements PackageManagerUserAgentProvider {
readonly userAgent: string | null;
}

View File

@@ -0,0 +1,7 @@
class ProcessPackageManagerUserAgentProvider {
// https://docs.npmjs.com/cli/v8/using-npm/config#user-agent
userAgent = process.env.npm_config_user_agent ?? null;
}
export {
ProcessPackageManagerUserAgentProvider
};

View File

@@ -0,0 +1,11 @@
import type { Prompt } from '../definitions.js';
export declare class PromptsPrompt implements Prompt {
#private;
constructor({ force }: {
force: boolean;
});
confirm({ message, defaultValue, }: {
message: string;
defaultValue?: boolean;
}): Promise<boolean>;
}

View File

@@ -0,0 +1,25 @@
import prompts from "prompts";
class PromptsPrompt {
#force;
constructor({ force }) {
this.#force = force;
}
async confirm({
message,
defaultValue
}) {
if (this.#force) {
return true;
}
const { value } = await prompts({
type: "confirm",
name: "value",
message,
initial: defaultValue
});
return value;
}
}
export {
PromptsPrompt
};

View File

@@ -0,0 +1,10 @@
import type { TextStyler } from '../../definitions.js';
import type { DebugInfoFormatter } from '../definitions.js';
import type { DebugInfo } from '../domain/debug-info.js';
export declare class StyledDebugInfoFormatter implements DebugInfoFormatter {
#private;
constructor({ textStyler, }: {
textStyler: TextStyler;
});
format(info: DebugInfo): string;
}

View File

@@ -0,0 +1,29 @@
class StyledDebugInfoFormatter {
#textStyler;
#maxPadding = 25;
constructor({
textStyler
}) {
this.#textStyler = textStyler;
}
format(info) {
let output = "";
for (const [label, value] of info) {
const padding = this.#maxPadding - label.length;
const [first, ...rest] = Array.isArray(value) ? value : [value];
let richtext = `
${this.#textStyler.bold(label)}${" ".repeat(padding)}${this.#textStyler.green(first)}`;
if (rest.length > 0) {
for (const entry of rest) {
richtext += `
${" ".repeat(this.#maxPadding)}${this.#textStyler.green(entry)}`;
}
}
output += richtext;
}
return output.trim();
}
}
export {
StyledDebugInfoFormatter
};

View File

@@ -0,0 +1,10 @@
import type { CommandExecutor } from '../../definitions.js';
import type { PackageManager } from '../definitions.js';
export declare class YarnPackageManager implements PackageManager {
#private;
readonly name: string;
constructor({ commandExecutor }: {
commandExecutor: CommandExecutor;
});
getPackageVersion(name: string): Promise<string | undefined>;
}

View File

@@ -0,0 +1,34 @@
function getYarnOutputDepVersion(dependency, outputLine) {
const parsed = JSON.parse(outputLine);
for (const [key, value] of Object.entries(parsed.children)) {
if (key.startsWith(`${dependency}@`)) {
return `v${value.locator.split(":").pop()}`;
}
}
}
class YarnPackageManager {
name = "yarn";
#commandExecutor;
constructor({ commandExecutor }) {
this.#commandExecutor = commandExecutor;
}
async getPackageVersion(name) {
try {
const { stdout } = await this.#commandExecutor.execute("yarn", ["why", name, "--json"], {
shell: true
});
const hasUserDefinition = stdout.includes("workspace:.");
for (const line of stdout.split("\n")) {
if (hasUserDefinition && line.includes("workspace:."))
return getYarnOutputDepVersion(name, line);
if (!hasUserDefinition && line.includes("astro@"))
return getYarnOutputDepVersion(name, line);
}
} catch {
return void 0;
}
}
}
export {
YarnPackageManager
};