mirror of
https://github.com/withastro/astro.git
synced 2024-12-16 21:46:22 -05:00
Use node parseArgs instead of yargs-parser and arg (#11645)
* wip * done * Add changeset * Format * Update * Fix houston * Fix test * Fix test
This commit is contained in:
parent
a23c69d0d0
commit
849e4c6c23
35 changed files with 224 additions and 216 deletions
6
.changeset/fifty-stingrays-flow.md
Normal file
6
.changeset/fifty-stingrays-flow.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
'astro': patch
|
||||
'@astrojs/db': patch
|
||||
---
|
||||
|
||||
Refactors internally to use `node:util` `parseArgs` instead of `yargs-parser`
|
7
.changeset/rude-queens-shop.md
Normal file
7
.changeset/rude-queens-shop.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
'create-astro': patch
|
||||
'@astrojs/upgrade': patch
|
||||
---
|
||||
|
||||
Refactors internally to use `node:util` `parseArgs` instead of `arg`
|
||||
|
|
@ -181,7 +181,6 @@
|
|||
"vite": "^5.4.0",
|
||||
"vitefu": "^0.2.5",
|
||||
"which-pm": "^3.0.0",
|
||||
"yargs-parser": "^21.1.1",
|
||||
"zod": "^3.23.8",
|
||||
"zod-to-json-schema": "^3.23.2"
|
||||
},
|
||||
|
@ -206,7 +205,6 @@
|
|||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/prompts": "^2.4.9",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@types/yargs-parser": "^21.0.3",
|
||||
"astro-scripts": "workspace:*",
|
||||
"cheerio": "1.0.0",
|
||||
"eol": "^0.9.1",
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* eslint-disable no-console */
|
||||
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { parseArgs } from 'node:util';
|
||||
import { bold, cyan, dim } from 'kleur/colors';
|
||||
import yargs from 'yargs-parser';
|
||||
import { loadFixture } from '../test/test-utils.js';
|
||||
import { generatePosts } from './scripts/generate-posts.mjs';
|
||||
|
||||
|
@ -40,7 +40,7 @@ async function benchmark({ fixtures, templates, numPosts }) {
|
|||
// Test the build performance for content collections across multiple file types (md, mdx, mdoc)
|
||||
(async function benchmarkAll() {
|
||||
try {
|
||||
const flags = yargs(process.argv.slice(2));
|
||||
const { values: flags } = parseArgs({ strict: false });
|
||||
const test = Array.isArray(flags.test)
|
||||
? flags.test
|
||||
: typeof flags.test === 'string'
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/yargs-parser": "^21.0.3",
|
||||
"kleur": "^4.1.5",
|
||||
"yargs-parser": "^21.1.1"
|
||||
"kleur": "^4.1.5"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import ora from 'ora';
|
|||
import preferredPM from 'preferred-pm';
|
||||
import prompts from 'prompts';
|
||||
import maxSatisfying from 'semver/ranges/max-satisfying.js';
|
||||
import type yargs from 'yargs-parser';
|
||||
import {
|
||||
loadTSConfig,
|
||||
resolveConfig,
|
||||
|
@ -29,14 +28,14 @@ import { appendForwardSlash } from '../../core/path.js';
|
|||
import { apply as applyPolyfill } from '../../core/polyfill.js';
|
||||
import { ensureProcessNodeEnv, parseNpmName } from '../../core/util.js';
|
||||
import { eventCliSession, telemetry } from '../../events/index.js';
|
||||
import { createLoggerFromFlags, flagsToAstroInlineConfig } from '../flags.js';
|
||||
import { type Flags, createLoggerFromFlags, flagsToAstroInlineConfig } from '../flags.js';
|
||||
import { fetchPackageJson, fetchPackageVersions } from '../install-package.js';
|
||||
import { generate, parse, t, visit } from './babel.js';
|
||||
import { ensureImport } from './imports.js';
|
||||
import { wrapDefaultExport } from './wrapper.js';
|
||||
|
||||
interface AddOptions {
|
||||
flags: yargs.Arguments;
|
||||
flags: Flags;
|
||||
}
|
||||
|
||||
interface IntegrationInfo {
|
||||
|
@ -143,7 +142,7 @@ export async function add(names: string[], { flags }: AddOptions) {
|
|||
}
|
||||
|
||||
// Some packages might have a common alias! We normalize those here.
|
||||
const cwd = flags.root;
|
||||
const cwd = inlineConfig.root;
|
||||
const logger = createLoggerFromFlags(flags);
|
||||
const integrationNames = names.map((name) => (ALIASES.has(name) ? ALIASES.get(name)! : name));
|
||||
const integrations = await validateIntegrations(integrationNames);
|
||||
|
@ -249,7 +248,7 @@ export async function add(names: string[], { flags }: AddOptions) {
|
|||
|
||||
const rawConfigPath = await resolveConfigPath({
|
||||
root: rootPath,
|
||||
configFile: flags.config,
|
||||
configFile: inlineConfig.configFile,
|
||||
fs: fsMod,
|
||||
});
|
||||
let configURL = rawConfigPath ? pathToFileURL(rawConfigPath) : undefined;
|
||||
|
@ -580,7 +579,7 @@ async function updateAstroConfig({
|
|||
}: {
|
||||
configURL: URL;
|
||||
ast: t.File;
|
||||
flags: yargs.Arguments;
|
||||
flags: Flags;
|
||||
logger: Logger;
|
||||
logAdapterInstructions: boolean;
|
||||
}): Promise<UpdateResult> {
|
||||
|
@ -717,7 +716,7 @@ async function tryToInstallIntegrations({
|
|||
}: {
|
||||
integrations: IntegrationInfo[];
|
||||
cwd?: string;
|
||||
flags: yargs.Arguments;
|
||||
flags: Flags;
|
||||
logger: Logger;
|
||||
}): Promise<UpdateResult> {
|
||||
const installCommand = await getInstallIntegrationsCommand({ integrations, cwd, logger });
|
||||
|
@ -893,7 +892,7 @@ async function updateTSConfig(
|
|||
cwd = process.cwd(),
|
||||
logger: Logger,
|
||||
integrationsInfo: IntegrationInfo[],
|
||||
flags: yargs.Arguments,
|
||||
flags: Flags,
|
||||
): Promise<UpdateResult> {
|
||||
const integrations = integrationsInfo.map(
|
||||
(integration) => integration.id as frameworkWithTSSettings,
|
||||
|
@ -996,7 +995,7 @@ function parseIntegrationName(spec: string) {
|
|||
return { scope, name, tag };
|
||||
}
|
||||
|
||||
async function askToContinue({ flags }: { flags: yargs.Arguments }): Promise<boolean> {
|
||||
async function askToContinue({ flags }: { flags: Flags }): Promise<boolean> {
|
||||
if (flags.yes || flags.y) return true;
|
||||
|
||||
const response = await prompts({
|
||||
|
@ -1038,7 +1037,7 @@ function getDiffContent(input: string, output: string): string | null {
|
|||
async function setupIntegrationConfig(opts: {
|
||||
root: URL;
|
||||
logger: Logger;
|
||||
flags: yargs.Arguments;
|
||||
flags: Flags;
|
||||
integrationName: string;
|
||||
possibleConfigFiles: string[];
|
||||
defaultConfigFile: string;
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import type yargs from 'yargs-parser';
|
||||
import _build from '../../core/build/index.js';
|
||||
import { printHelp } from '../../core/messages.js';
|
||||
import { flagsToAstroInlineConfig } from '../flags.js';
|
||||
import { type Flags, flagsToAstroInlineConfig } from '../flags.js';
|
||||
|
||||
interface BuildOptions {
|
||||
flags: yargs.Arguments;
|
||||
flags: Flags;
|
||||
}
|
||||
|
||||
export async function build({ flags }: BuildOptions) {
|
||||
|
@ -25,5 +24,5 @@ export async function build({ flags }: BuildOptions) {
|
|||
|
||||
const inlineConfig = flagsToAstroInlineConfig(flags);
|
||||
|
||||
await _build(inlineConfig, { force: flags.force ?? false });
|
||||
await _build(inlineConfig, { force: !!flags.force });
|
||||
}
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
import path from 'node:path';
|
||||
import type { Arguments } from 'yargs-parser';
|
||||
import { ensureProcessNodeEnv } from '../../core/util.js';
|
||||
import { createLoggerFromFlags, flagsToAstroInlineConfig } from '../flags.js';
|
||||
import { type Flags, createLoggerFromFlags, flagsToAstroInlineConfig } from '../flags.js';
|
||||
import { getPackage } from '../install-package.js';
|
||||
|
||||
export async function check(flags: Arguments) {
|
||||
export async function check(flags: Flags) {
|
||||
ensureProcessNodeEnv('production');
|
||||
const logger = createLoggerFromFlags(flags);
|
||||
const getPackageOpts = { skipAsk: flags.yes || flags.y, cwd: flags.root };
|
||||
const getPackageOpts = {
|
||||
skipAsk: !!flags.yes || !!flags.y,
|
||||
cwd: typeof flags.root == 'string' ? flags.root : undefined,
|
||||
};
|
||||
const checkPackage = await getPackage<typeof import('@astrojs/check')>(
|
||||
'@astrojs/check',
|
||||
logger,
|
||||
|
|
|
@ -1,18 +1,26 @@
|
|||
import type { Arguments } from 'yargs-parser';
|
||||
import type { AstroConfig } from '../../@types/astro.js';
|
||||
import { resolveConfig } from '../../core/config/config.js';
|
||||
import { apply as applyPolyfill } from '../../core/polyfill.js';
|
||||
import { createLoggerFromFlags, flagsToAstroInlineConfig } from '../flags.js';
|
||||
import { type Flags, createLoggerFromFlags, flagsToAstroInlineConfig } from '../flags.js';
|
||||
import { getPackage } from '../install-package.js';
|
||||
|
||||
interface YargsArguments {
|
||||
_: Array<string | number>;
|
||||
'--'?: Array<string | number>;
|
||||
[argName: string]: any;
|
||||
}
|
||||
|
||||
type DBPackage = {
|
||||
cli: (args: { flags: Arguments; config: AstroConfig }) => unknown;
|
||||
cli: (args: { flags: YargsArguments; config: AstroConfig }) => unknown;
|
||||
};
|
||||
|
||||
export async function db({ flags }: { flags: Arguments }) {
|
||||
export async function db({ positionals, flags }: { positionals: string[]; flags: Flags }) {
|
||||
applyPolyfill();
|
||||
const logger = createLoggerFromFlags(flags);
|
||||
const getPackageOpts = { skipAsk: flags.yes || flags.y, cwd: flags.root };
|
||||
const getPackageOpts = {
|
||||
skipAsk: !!flags.yes || !!flags.y,
|
||||
cwd: typeof flags.root == 'string' ? flags.root : undefined,
|
||||
};
|
||||
const dbPackage = await getPackage<DBPackage>('@astrojs/db', logger, getPackageOpts, []);
|
||||
|
||||
if (!dbPackage) {
|
||||
|
@ -27,5 +35,10 @@ export async function db({ flags }: { flags: Arguments }) {
|
|||
const inlineConfig = flagsToAstroInlineConfig(flags);
|
||||
const { astroConfig } = await resolveConfig(inlineConfig, 'build');
|
||||
|
||||
await cli({ flags, config: astroConfig });
|
||||
const yargsArgs: YargsArguments = {
|
||||
_: positionals,
|
||||
...flags,
|
||||
};
|
||||
|
||||
await cli({ flags: yargsArgs, config: astroConfig });
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import { cyan } from 'kleur/colors';
|
||||
import type yargs from 'yargs-parser';
|
||||
import devServer from '../../core/dev/index.js';
|
||||
import { printHelp } from '../../core/messages.js';
|
||||
import { flagsToAstroInlineConfig } from '../flags.js';
|
||||
import { type Flags, flagsToAstroInlineConfig } from '../flags.js';
|
||||
|
||||
interface DevOptions {
|
||||
flags: yargs.Arguments;
|
||||
flags: Flags;
|
||||
}
|
||||
|
||||
export async function dev({ flags }: DevOptions) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import type yargs from 'yargs-parser';
|
||||
import { printHelp } from '../../core/messages.js';
|
||||
import type { Flags } from '../flags.js';
|
||||
import { openInBrowser } from './open.js';
|
||||
|
||||
interface DocsOptions {
|
||||
flags: yargs.Arguments;
|
||||
flags: Flags;
|
||||
}
|
||||
|
||||
export async function docs({ flags }: DocsOptions) {
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import type { Arguments as Flags } from 'yargs-parser';
|
||||
import type { parseArgs } from 'node:util';
|
||||
import type { AstroInlineConfig } from '../@types/astro.js';
|
||||
import { type LogOptions, Logger } from '../core/logger/core.js';
|
||||
import { nodeLogDestination } from '../core/logger/node.js';
|
||||
|
||||
export type ParsedArgsResult = ReturnType<typeof parseArgs>;
|
||||
export type Flags = ParsedArgsResult['values'];
|
||||
|
||||
export function flagsToAstroInlineConfig(flags: Flags): AstroInlineConfig {
|
||||
return {
|
||||
// Inline-only configs
|
||||
|
@ -16,7 +19,7 @@ export function flagsToAstroInlineConfig(flags: Flags): AstroInlineConfig {
|
|||
base: typeof flags.base === 'string' ? flags.base : undefined,
|
||||
outDir: typeof flags.outDir === 'string' ? flags.outDir : undefined,
|
||||
server: {
|
||||
port: typeof flags.port === 'number' ? flags.port : undefined,
|
||||
port: typeof flags.port === 'string' ? Number(flags.port) : undefined,
|
||||
host:
|
||||
typeof flags.host === 'string' || typeof flags.host === 'boolean' ? flags.host : undefined,
|
||||
open:
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { parseArgs } from 'node:util';
|
||||
/* eslint-disable no-console */
|
||||
import * as colors from 'kleur/colors';
|
||||
import yargs from 'yargs-parser';
|
||||
import { ASTRO_VERSION } from '../core/constants.js';
|
||||
import type { ParsedArgsResult } from './flags.js';
|
||||
|
||||
type CLICommand =
|
||||
| 'help'
|
||||
|
@ -65,9 +66,9 @@ function printVersion() {
|
|||
}
|
||||
|
||||
/** Determine which command the user requested */
|
||||
function resolveCommand(flags: yargs.Arguments): CLICommand {
|
||||
const cmd = flags._[2] as string;
|
||||
if (flags.version) return 'version';
|
||||
function resolveCommand(args: ParsedArgsResult): CLICommand {
|
||||
const cmd = args.positionals[2] as string;
|
||||
if (args.values.version) return 'version';
|
||||
|
||||
const supportedCommands = new Set([
|
||||
'add',
|
||||
|
@ -97,7 +98,9 @@ function resolveCommand(flags: yargs.Arguments): CLICommand {
|
|||
* NOTE: This function provides no error handling, so be sure
|
||||
* to present user-friendly error output where the fn is called.
|
||||
**/
|
||||
async function runCommand(cmd: string, flags: yargs.Arguments) {
|
||||
async function runCommand(cmd: string, args: ParsedArgsResult) {
|
||||
const flags = args.values;
|
||||
|
||||
// These commands can run directly without parsing the user config.
|
||||
switch (cmd) {
|
||||
case 'help':
|
||||
|
@ -120,7 +123,7 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
|
|||
// Do not track session start, since the user may be trying to enable,
|
||||
// disable, or modify telemetry settings.
|
||||
const { update } = await import('./telemetry/index.js');
|
||||
const subcommand = flags._[3]?.toString();
|
||||
const subcommand = args.positionals[3];
|
||||
await update(subcommand, { flags });
|
||||
return;
|
||||
}
|
||||
|
@ -131,7 +134,7 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
|
|||
}
|
||||
case 'preferences': {
|
||||
const { preferences } = await import('./preferences/index.js');
|
||||
const [subcommand, key, value] = flags._.slice(3).map((v) => v.toString());
|
||||
const [subcommand, key, value] = args.positionals.slice(3);
|
||||
const exitCode = await preferences(subcommand, key, value, { flags });
|
||||
return process.exit(exitCode);
|
||||
}
|
||||
|
@ -151,7 +154,7 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
|
|||
switch (cmd) {
|
||||
case 'add': {
|
||||
const { add } = await import('./add/index.js');
|
||||
const packages = flags._.slice(3) as string[];
|
||||
const packages = args.positionals.slice(3);
|
||||
await add(packages, { flags });
|
||||
return;
|
||||
}
|
||||
|
@ -161,7 +164,7 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
|
|||
case 'link':
|
||||
case 'init': {
|
||||
const { db } = await import('./db/index.js');
|
||||
await db({ flags });
|
||||
await db({ positionals: args.positionals, flags });
|
||||
return;
|
||||
}
|
||||
case 'dev': {
|
||||
|
@ -201,11 +204,21 @@ async function runCommand(cmd: string, flags: yargs.Arguments) {
|
|||
}
|
||||
|
||||
/** The primary CLI action */
|
||||
export async function cli(args: string[]) {
|
||||
const flags = yargs(args, { boolean: ['global'], alias: { g: 'global' } });
|
||||
const cmd = resolveCommand(flags);
|
||||
export async function cli(argv: string[]) {
|
||||
const args = parseArgs({
|
||||
args: argv,
|
||||
allowPositionals: true,
|
||||
strict: false,
|
||||
options: {
|
||||
global: { type: 'boolean', short: 'g' },
|
||||
host: { type: 'string' }, // Can be boolean too, which is covered by `strict: false`
|
||||
open: { type: 'string' }, // Can be boolean too, which is covered by `strict: false`
|
||||
// TODO: Add more flags here
|
||||
},
|
||||
});
|
||||
const cmd = resolveCommand(args);
|
||||
try {
|
||||
await runCommand(cmd, flags);
|
||||
await runCommand(cmd, args);
|
||||
} catch (err) {
|
||||
const { throwAndExit } = await import('./throw-and-exit.js');
|
||||
await throwAndExit(cmd, err);
|
||||
|
|
|
@ -3,15 +3,14 @@ import { arch, platform } from 'node:os';
|
|||
/* eslint-disable no-console */
|
||||
import * as colors from 'kleur/colors';
|
||||
import prompts from 'prompts';
|
||||
import type yargs from 'yargs-parser';
|
||||
import type { AstroConfig, AstroUserConfig } from '../../@types/astro.js';
|
||||
import { resolveConfig } from '../../core/config/index.js';
|
||||
import { ASTRO_VERSION } from '../../core/constants.js';
|
||||
import { apply as applyPolyfill } from '../../core/polyfill.js';
|
||||
import { flagsToAstroInlineConfig } from '../flags.js';
|
||||
import { type Flags, flagsToAstroInlineConfig } from '../flags.js';
|
||||
|
||||
interface InfoOptions {
|
||||
flags: yargs.Arguments;
|
||||
flags: Flags;
|
||||
}
|
||||
|
||||
export async function getInfoOutput({
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* eslint-disable no-console */
|
||||
import type yargs from 'yargs-parser';
|
||||
import type { AstroSettings } from '../../@types/astro.js';
|
||||
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
@ -15,10 +14,10 @@ import * as msg from '../../core/messages.js';
|
|||
import { apply as applyPolyfill } from '../../core/polyfill.js';
|
||||
import { DEFAULT_PREFERENCES } from '../../preferences/defaults.js';
|
||||
import { type PreferenceKey, coerce, isValidKey } from '../../preferences/index.js';
|
||||
import { createLoggerFromFlags, flagsToAstroInlineConfig } from '../flags.js';
|
||||
import { type Flags, createLoggerFromFlags, flagsToAstroInlineConfig } from '../flags.js';
|
||||
|
||||
interface PreferencesOptions {
|
||||
flags: yargs.Arguments;
|
||||
flags: Flags;
|
||||
}
|
||||
|
||||
const PREFERENCES_SUBCOMMANDS = [
|
||||
|
@ -77,7 +76,7 @@ export async function preferences(
|
|||
const settings = await createSettings(astroConfig, fileURLToPath(astroConfig.root));
|
||||
const opts: SubcommandOptions = {
|
||||
location: flags.global ? 'global' : undefined,
|
||||
json: flags.json,
|
||||
json: !!flags.json,
|
||||
};
|
||||
|
||||
if (subcommand === 'list') {
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import { cyan } from 'kleur/colors';
|
||||
import type yargs from 'yargs-parser';
|
||||
import { printHelp } from '../../core/messages.js';
|
||||
import previewServer from '../../core/preview/index.js';
|
||||
import { flagsToAstroInlineConfig } from '../flags.js';
|
||||
import { type Flags, flagsToAstroInlineConfig } from '../flags.js';
|
||||
|
||||
interface PreviewOptions {
|
||||
flags: yargs.Arguments;
|
||||
flags: Flags;
|
||||
}
|
||||
|
||||
export async function preview({ flags }: PreviewOptions) {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import type yargs from 'yargs-parser';
|
||||
import { printHelp } from '../../core/messages.js';
|
||||
import _sync from '../../core/sync/index.js';
|
||||
import { flagsToAstroInlineConfig } from '../flags.js';
|
||||
import { type Flags, flagsToAstroInlineConfig } from '../flags.js';
|
||||
|
||||
interface SyncOptions {
|
||||
flags: yargs.Arguments;
|
||||
flags: Flags;
|
||||
}
|
||||
|
||||
export async function sync({ flags }: SyncOptions) {
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/* eslint-disable no-console */
|
||||
import type yargs from 'yargs-parser';
|
||||
import * as msg from '../../core/messages.js';
|
||||
import { telemetry } from '../../events/index.js';
|
||||
import { createLoggerFromFlags } from '../flags.js';
|
||||
import { type Flags, createLoggerFromFlags } from '../flags.js';
|
||||
|
||||
interface TelemetryOptions {
|
||||
flags: yargs.Arguments;
|
||||
flags: Flags;
|
||||
}
|
||||
|
||||
export async function notify() {
|
||||
|
|
|
@ -2,14 +2,12 @@ import fs from 'node:fs';
|
|||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import * as colors from 'kleur/colors';
|
||||
import type { Arguments as Flags } from 'yargs-parser';
|
||||
import { ZodError } from 'zod';
|
||||
import type {
|
||||
AstroConfig,
|
||||
AstroInlineConfig,
|
||||
AstroInlineOnlyConfig,
|
||||
AstroUserConfig,
|
||||
CLIFlags,
|
||||
} from '../../@types/astro.js';
|
||||
import { eventConfigError, telemetry } from '../../events/index.js';
|
||||
import { trackAstroConfigZodError } from '../errors/errors.js';
|
||||
|
@ -19,23 +17,6 @@ import { mergeConfig } from './merge.js';
|
|||
import { validateConfig } from './validate.js';
|
||||
import { loadConfigWithVite } from './vite-load.js';
|
||||
|
||||
/** Convert the generic "yargs" flag object into our own, custom TypeScript object. */
|
||||
// NOTE: This function will be removed in a later PR. Use `flagsToAstroInlineConfig` instead.
|
||||
// All CLI related flow should be located in the `packages/astro/src/cli` directory.
|
||||
export function resolveFlags(flags: Partial<Flags>): CLIFlags {
|
||||
return {
|
||||
root: typeof flags.root === 'string' ? flags.root : undefined,
|
||||
site: typeof flags.site === 'string' ? flags.site : undefined,
|
||||
base: typeof flags.base === 'string' ? flags.base : undefined,
|
||||
port: typeof flags.port === 'number' ? flags.port : undefined,
|
||||
config: typeof flags.config === 'string' ? flags.config : undefined,
|
||||
host:
|
||||
typeof flags.host === 'string' || typeof flags.host === 'boolean' ? flags.host : undefined,
|
||||
open:
|
||||
typeof flags.open === 'string' || typeof flags.open === 'boolean' ? flags.open : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveRoot(cwd?: string | URL): string {
|
||||
if (cwd instanceof URL) {
|
||||
cwd = fileURLToPath(cwd);
|
||||
|
@ -66,7 +47,7 @@ async function search(fsMod: typeof fs, root: string) {
|
|||
|
||||
interface ResolveConfigPathOptions {
|
||||
root: string;
|
||||
configFile?: string;
|
||||
configFile?: string | false;
|
||||
fs: typeof fs;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ export {
|
|||
configPaths,
|
||||
resolveConfig,
|
||||
resolveConfigPath,
|
||||
resolveFlags,
|
||||
resolveRoot,
|
||||
} from './config.js';
|
||||
export { createNodeLogger } from './logging.js';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import os from 'node:os';
|
||||
import { parseArgs } from 'node:util';
|
||||
import { type Task, prompt } from '@astrojs/cli-kit';
|
||||
import { random } from '@astrojs/cli-kit/utils';
|
||||
import arg from 'arg';
|
||||
|
||||
import getSeasonalData from '../data/seasonal.js';
|
||||
import { getName, getVersion } from '../messages.js';
|
||||
|
@ -33,47 +33,44 @@ export interface Context {
|
|||
}
|
||||
|
||||
export async function getContext(argv: string[]): Promise<Context> {
|
||||
const flags = arg(
|
||||
{
|
||||
'--template': String,
|
||||
'--ref': String,
|
||||
'--yes': Boolean,
|
||||
'--no': Boolean,
|
||||
'--install': Boolean,
|
||||
'--no-install': Boolean,
|
||||
'--git': Boolean,
|
||||
'--no-git': Boolean,
|
||||
'--typescript': String,
|
||||
'--skip-houston': Boolean,
|
||||
'--dry-run': Boolean,
|
||||
'--help': Boolean,
|
||||
'--fancy': Boolean,
|
||||
|
||||
'-y': '--yes',
|
||||
'-n': '--no',
|
||||
'-h': '--help',
|
||||
const args = parseArgs({
|
||||
args: argv,
|
||||
allowPositionals: true,
|
||||
strict: false,
|
||||
options: {
|
||||
template: { type: 'string' },
|
||||
ref: { type: 'string' },
|
||||
yes: { type: 'boolean', short: 'y' },
|
||||
no: { type: 'boolean', short: 'n' },
|
||||
install: { type: 'boolean' },
|
||||
'no-install': { type: 'boolean' },
|
||||
git: { type: 'boolean' },
|
||||
'no-git': { type: 'boolean' },
|
||||
typescript: { type: 'string' },
|
||||
'skip-houston': { type: 'boolean' },
|
||||
'dry-run': { type: 'boolean' },
|
||||
help: { type: 'boolean', short: 'h' },
|
||||
fancy: { type: 'boolean' },
|
||||
},
|
||||
{ argv, permissive: true },
|
||||
);
|
||||
});
|
||||
|
||||
const packageManager = detectPackageManager() ?? 'npm';
|
||||
let cwd = flags['_'][0];
|
||||
const projectName = args.positionals[0];
|
||||
let {
|
||||
'--help': help = false,
|
||||
'--template': template,
|
||||
'--no': no,
|
||||
'--yes': yes,
|
||||
'--install': install,
|
||||
'--no-install': noInstall,
|
||||
'--git': git,
|
||||
'--no-git': noGit,
|
||||
'--typescript': typescript,
|
||||
'--fancy': fancy,
|
||||
'--skip-houston': skipHouston,
|
||||
'--dry-run': dryRun,
|
||||
'--ref': ref,
|
||||
} = flags;
|
||||
let projectName = cwd;
|
||||
help,
|
||||
template,
|
||||
no,
|
||||
yes,
|
||||
install,
|
||||
'no-install': noInstall,
|
||||
git,
|
||||
'no-git': noGit,
|
||||
typescript,
|
||||
fancy,
|
||||
'skip-houston': skipHouston,
|
||||
'dry-run': dryRun,
|
||||
ref,
|
||||
} = args.values;
|
||||
|
||||
if (no) {
|
||||
yes = false;
|
||||
|
@ -82,10 +79,26 @@ export async function getContext(argv: string[]): Promise<Context> {
|
|||
if (typescript == undefined) typescript = 'strict';
|
||||
}
|
||||
|
||||
skipHouston = typeof skipHouston == 'boolean' ? skipHouston : undefined;
|
||||
skipHouston =
|
||||
((os.platform() === 'win32' && !fancy) || skipHouston) ??
|
||||
[yes, no, install, git, typescript].some((v) => v !== undefined);
|
||||
|
||||
// We use `strict: false` in `parseArgs` to allow unknown options, but Node also
|
||||
// simply doesn't guarantee the types anymore, so we need to validate ourselves :(
|
||||
help = !!help;
|
||||
template = typeof template == 'string' ? template : undefined;
|
||||
no = !!no;
|
||||
yes = !!yes;
|
||||
install = !!install;
|
||||
noInstall = !!noInstall;
|
||||
git = !!git;
|
||||
noGit = !!noGit;
|
||||
typescript = typeof typescript == 'string' ? typescript : undefined;
|
||||
fancy = !!fancy;
|
||||
dryRun = !!dryRun;
|
||||
ref = typeof ref == 'string' ? ref : undefined;
|
||||
|
||||
const { messages, hats, ties } = getSeasonalData({ fancy });
|
||||
|
||||
const context: Context = {
|
||||
|
@ -107,7 +120,7 @@ export async function getContext(argv: string[]): Promise<Context> {
|
|||
install: install ?? (noInstall ? false : undefined),
|
||||
git: git ?? (noGit ? false : undefined),
|
||||
typescript,
|
||||
cwd,
|
||||
cwd: projectName,
|
||||
exit(code) {
|
||||
process.exit(code);
|
||||
},
|
||||
|
|
|
@ -81,13 +81,11 @@
|
|||
"ora": "^8.0.1",
|
||||
"prompts": "^2.4.2",
|
||||
"strip-ansi": "^7.1.0",
|
||||
"yargs-parser": "^21.1.1",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/deep-diff": "^1.0.5",
|
||||
"@types/prompts": "^2.4.9",
|
||||
"@types/yargs-parser": "^21.0.3",
|
||||
"astro": "workspace:*",
|
||||
"astro-scripts": "workspace:*",
|
||||
"cheerio": "1.0.0",
|
||||
|
|
|
@ -3,7 +3,6 @@ import { getManagedAppTokenOrExit } from '@astrojs/studio';
|
|||
import { LibsqlError } from '@libsql/client';
|
||||
import type { AstroConfig } from 'astro';
|
||||
import { green } from 'kleur/colors';
|
||||
import type { Arguments } from 'yargs-parser';
|
||||
import {
|
||||
EXEC_DEFAULT_EXPORT_ERROR,
|
||||
EXEC_ERROR,
|
||||
|
@ -16,6 +15,7 @@ import {
|
|||
} from '../../../integration/vite-plugin-db.js';
|
||||
import { bundleFile, importBundledFile } from '../../../load-file.js';
|
||||
import type { DBConfig } from '../../../types.js';
|
||||
import type { YargsArguments } from '../../types.js';
|
||||
|
||||
export async function cmd({
|
||||
astroConfig,
|
||||
|
@ -24,7 +24,7 @@ export async function cmd({
|
|||
}: {
|
||||
astroConfig: AstroConfig;
|
||||
dbConfig: DBConfig;
|
||||
flags: Arguments;
|
||||
flags: YargsArguments;
|
||||
}) {
|
||||
const filePath = flags._[4];
|
||||
if (typeof filePath !== 'string') {
|
||||
|
|
|
@ -7,8 +7,8 @@ import { cyan } from 'kleur/colors';
|
|||
import open from 'open';
|
||||
import ora from 'ora';
|
||||
import prompt from 'prompts';
|
||||
import type { Arguments } from 'yargs-parser';
|
||||
import type { DBConfig } from '../../../types.js';
|
||||
import type { YargsArguments } from '../../types.js';
|
||||
|
||||
const isWebContainer =
|
||||
// Stackblitz heuristic
|
||||
|
@ -21,7 +21,7 @@ export async function cmd({
|
|||
}: {
|
||||
astroConfig: AstroConfig;
|
||||
dbConfig: DBConfig;
|
||||
flags: Arguments;
|
||||
flags: YargsArguments;
|
||||
}) {
|
||||
let session = flags.session;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { getManagedAppTokenOrExit } from '@astrojs/studio';
|
||||
import type { AstroConfig } from 'astro';
|
||||
import prompts from 'prompts';
|
||||
import type { Arguments } from 'yargs-parser';
|
||||
import { safeFetch } from '../../../../runtime/utils.js';
|
||||
import { MIGRATION_VERSION } from '../../../consts.js';
|
||||
import { type DBConfig, type DBSnapshot } from '../../../types.js';
|
||||
|
@ -13,6 +12,7 @@ import {
|
|||
getMigrationQueries,
|
||||
getProductionCurrentSnapshot,
|
||||
} from '../../migration-queries.js';
|
||||
import type { YargsArguments } from '../../types.js';
|
||||
|
||||
export async function cmd({
|
||||
dbConfig,
|
||||
|
@ -20,7 +20,7 @@ export async function cmd({
|
|||
}: {
|
||||
astroConfig: AstroConfig;
|
||||
dbConfig: DBConfig;
|
||||
flags: Arguments;
|
||||
flags: YargsArguments;
|
||||
}) {
|
||||
const isDryRun = flags.dryRun;
|
||||
const isForceReset = flags.forceReset;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { getManagedAppTokenOrExit } from '@astrojs/studio';
|
||||
import type { AstroConfig } from 'astro';
|
||||
import { sql } from 'drizzle-orm';
|
||||
import type { Arguments } from 'yargs-parser';
|
||||
import {
|
||||
createLocalDatabaseClient,
|
||||
createRemoteDatabaseClient,
|
||||
|
@ -11,6 +10,7 @@ import { DB_PATH } from '../../../consts.js';
|
|||
import { SHELL_QUERY_MISSING_ERROR } from '../../../errors.js';
|
||||
import type { DBConfigInput } from '../../../types.js';
|
||||
import { getAstroEnv, getRemoteDatabaseUrl } from '../../../utils.js';
|
||||
import type { YargsArguments } from '../../types.js';
|
||||
|
||||
export async function cmd({
|
||||
flags,
|
||||
|
@ -18,7 +18,7 @@ export async function cmd({
|
|||
}: {
|
||||
dbConfig: DBConfigInput;
|
||||
astroConfig: AstroConfig;
|
||||
flags: Arguments;
|
||||
flags: YargsArguments;
|
||||
}) {
|
||||
const query = flags.query;
|
||||
if (!query) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { getManagedAppTokenOrExit } from '@astrojs/studio';
|
||||
import type { AstroConfig } from 'astro';
|
||||
import type { Arguments } from 'yargs-parser';
|
||||
import type { DBConfig } from '../../../types.js';
|
||||
import {
|
||||
createCurrentSnapshot,
|
||||
|
@ -9,6 +8,7 @@ import {
|
|||
getMigrationQueries,
|
||||
getProductionCurrentSnapshot,
|
||||
} from '../../migration-queries.js';
|
||||
import type { YargsArguments } from '../../types.js';
|
||||
|
||||
export async function cmd({
|
||||
dbConfig,
|
||||
|
@ -16,7 +16,7 @@ export async function cmd({
|
|||
}: {
|
||||
astroConfig: AstroConfig;
|
||||
dbConfig: DBConfig;
|
||||
flags: Arguments;
|
||||
flags: YargsArguments;
|
||||
}) {
|
||||
const isJson = flags.json;
|
||||
const appToken = await getManagedAppTokenOrExit(flags.token);
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import type { AstroConfig } from 'astro';
|
||||
import type { Arguments } from 'yargs-parser';
|
||||
import { resolveDbConfig } from '../load-file.js';
|
||||
import { printHelp } from './print-help.js';
|
||||
import type { YargsArguments } from './types.js';
|
||||
|
||||
export async function cli({
|
||||
flags,
|
||||
config: astroConfig,
|
||||
}: {
|
||||
flags: Arguments;
|
||||
flags: YargsArguments;
|
||||
config: AstroConfig;
|
||||
}) {
|
||||
const args = flags._ as string[];
|
||||
|
|
7
packages/db/src/core/cli/types.ts
Normal file
7
packages/db/src/core/cli/types.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
// Copy of `yargs-parser` `Arguments` type. We don't use `yargs-parser`
|
||||
// in runtime anymore, but our exposed API still relies on this shape.
|
||||
export interface YargsArguments {
|
||||
_: Array<string | number>;
|
||||
'--'?: Array<string | number>;
|
||||
[argName: string]: any;
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import { existsSync } from 'fs';
|
||||
import { parseArgs } from 'node:util';
|
||||
import { dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { type ManagedAppToken, getManagedAppTokenOrExit } from '@astrojs/studio';
|
||||
|
@ -14,7 +15,6 @@ import {
|
|||
loadEnv,
|
||||
mergeConfig,
|
||||
} from 'vite';
|
||||
import parseArgs from 'yargs-parser';
|
||||
import { AstroDbError } from '../../runtime/utils.js';
|
||||
import { CONFIG_FILE_NAMES, DB_PATH } from '../consts.js';
|
||||
import { EXEC_DEFAULT_EXPORT_ERROR, EXEC_ERROR } from '../errors.js';
|
||||
|
@ -72,8 +72,8 @@ function astroDBIntegration(): AstroIntegration {
|
|||
if (command === 'preview') return;
|
||||
|
||||
let dbPlugin: VitePlugin | undefined = undefined;
|
||||
const args = parseArgs(process.argv.slice(3));
|
||||
connectToStudio = process.env.ASTRO_INTERNAL_TEST_REMOTE || args['remote'];
|
||||
const args = parseArgs({ strict: false });
|
||||
connectToStudio = !!process.env.ASTRO_INTERNAL_TEST_REMOTE || !!args.values.remote;
|
||||
|
||||
if (connectToStudio) {
|
||||
appToken = await getManagedAppTokenOrExit();
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { pathToFileURL } from 'node:url';
|
||||
import { parseArgs } from 'node:util';
|
||||
import { prompt } from '@astrojs/cli-kit';
|
||||
import arg from 'arg';
|
||||
import detectPackageManager from 'preferred-pm';
|
||||
|
||||
export interface Context {
|
||||
help: boolean;
|
||||
prompt: typeof prompt;
|
||||
version: string;
|
||||
dryRun?: boolean;
|
||||
dryRun: boolean;
|
||||
cwd: URL;
|
||||
stdin?: typeof process.stdin;
|
||||
stdout?: typeof process.stdout;
|
||||
|
@ -28,22 +28,20 @@ export interface PackageInfo {
|
|||
}
|
||||
|
||||
export async function getContext(argv: string[]): Promise<Context> {
|
||||
const flags = arg(
|
||||
{
|
||||
'--dry-run': Boolean,
|
||||
'--help': Boolean,
|
||||
|
||||
'-h': '--help',
|
||||
const args = parseArgs({
|
||||
args: argv,
|
||||
allowPositionals: true,
|
||||
strict: false,
|
||||
options: {
|
||||
'dry-run': { type: 'boolean' },
|
||||
help: { type: 'boolean', short: 'h' },
|
||||
},
|
||||
{ argv, permissive: true },
|
||||
);
|
||||
});
|
||||
|
||||
const packageManager = (await detectPackageManager(process.cwd()))?.name ?? 'npm';
|
||||
const {
|
||||
_: [version = 'latest'] = [],
|
||||
'--help': help = false,
|
||||
'--dry-run': dryRun,
|
||||
} = flags;
|
||||
const version = args.positionals[0] ?? 'latest';
|
||||
const help = !!args.values.help;
|
||||
const dryRun = !!args.values['dry-run'];
|
||||
|
||||
return {
|
||||
help,
|
||||
|
|
|
@ -6,12 +6,12 @@ describe('context', () => {
|
|||
it('no arguments', async () => {
|
||||
const ctx = await getContext([]);
|
||||
assert.equal(ctx.version, 'latest');
|
||||
assert.equal(ctx.dryRun, undefined);
|
||||
assert.equal(ctx.dryRun, false);
|
||||
});
|
||||
it('tag', async () => {
|
||||
const ctx = await getContext(['beta']);
|
||||
assert.equal(ctx.version, 'beta');
|
||||
assert.equal(ctx.dryRun, undefined);
|
||||
assert.equal(ctx.dryRun, false);
|
||||
});
|
||||
it('dry run', async () => {
|
||||
const ctx = await getContext(['--dry-run']);
|
||||
|
|
|
@ -729,9 +729,6 @@ importers:
|
|||
which-pm:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
yargs-parser:
|
||||
specifier: ^21.1.1
|
||||
version: 21.1.1
|
||||
zod:
|
||||
specifier: ^3.23.8
|
||||
version: 3.23.8
|
||||
|
@ -794,9 +791,6 @@ importers:
|
|||
'@types/semver':
|
||||
specifier: ^7.5.8
|
||||
version: 7.5.8
|
||||
'@types/yargs-parser':
|
||||
specifier: ^21.0.3
|
||||
version: 21.0.3
|
||||
astro-scripts:
|
||||
specifier: workspace:*
|
||||
version: link:../../scripts
|
||||
|
@ -1720,15 +1714,9 @@ importers:
|
|||
|
||||
packages/astro/performance:
|
||||
devDependencies:
|
||||
'@types/yargs-parser':
|
||||
specifier: ^21.0.3
|
||||
version: 21.0.3
|
||||
kleur:
|
||||
specifier: ^4.1.5
|
||||
version: 4.1.5
|
||||
yargs-parser:
|
||||
specifier: ^21.1.1
|
||||
version: 21.1.1
|
||||
|
||||
packages/astro/performance/fixtures/md:
|
||||
dependencies:
|
||||
|
@ -4252,9 +4240,6 @@ importers:
|
|||
strip-ansi:
|
||||
specifier: ^7.1.0
|
||||
version: 7.1.0
|
||||
yargs-parser:
|
||||
specifier: ^21.1.1
|
||||
version: 21.1.1
|
||||
zod:
|
||||
specifier: ^3.23.8
|
||||
version: 3.23.8
|
||||
|
@ -4265,9 +4250,6 @@ importers:
|
|||
'@types/prompts':
|
||||
specifier: ^2.4.9
|
||||
version: 2.4.9
|
||||
'@types/yargs-parser':
|
||||
specifier: ^21.0.3
|
||||
version: 21.0.3
|
||||
astro:
|
||||
specifier: workspace:*
|
||||
version: link:../astro
|
||||
|
@ -7529,9 +7511,6 @@ packages:
|
|||
'@types/xml2js@0.4.14':
|
||||
resolution: {integrity: sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==}
|
||||
|
||||
'@types/yargs-parser@21.0.3':
|
||||
resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.0.1':
|
||||
resolution: {integrity: sha512-5g3Y7GDFsJAnY4Yhvk8sZtFfV6YNF2caLzjrRPUBzewjPCaj0yokePB4LJSobyCzGMzjZZYFbwuzbfDHlimXbQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
@ -13410,8 +13389,6 @@ snapshots:
|
|||
dependencies:
|
||||
'@types/node': 18.19.31
|
||||
|
||||
'@types/yargs-parser@21.0.3': {}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.0.1(@typescript-eslint/parser@8.0.1(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4))(eslint@9.9.0(jiti@1.21.0))(typescript@5.5.4)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.11.0
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
import arg from 'arg';
|
||||
import { globby as glob } from 'globby';
|
||||
import { promises as fs, readFileSync } from 'node:fs';
|
||||
import { posix } from 'node:path';
|
||||
import { parseArgs } from 'node:util';
|
||||
import * as tar from 'tar/create';
|
||||
|
||||
const { resolve, dirname, sep, join } = posix;
|
||||
|
||||
/** @type {import('arg').Spec} */
|
||||
const spec = {
|
||||
'--tgz': Boolean,
|
||||
};
|
||||
|
||||
export default async function copy() {
|
||||
let { _: patterns, ['--tgz']: isCompress } = arg(spec);
|
||||
patterns = patterns.slice(1);
|
||||
const args = parseArgs({
|
||||
allowPositionals: true,
|
||||
options: {
|
||||
tgz: { type: 'boolean' },
|
||||
},
|
||||
});
|
||||
const patterns = args.positionals.slice(1);
|
||||
const isCompress = args.values.tgz;
|
||||
|
||||
if (isCompress) {
|
||||
const files = await glob(patterns, { gitignore: true });
|
||||
|
|
|
@ -3,30 +3,32 @@ import { spec } from 'node:test/reporters';
|
|||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { pathToFileURL } from 'node:url';
|
||||
import arg from 'arg';
|
||||
import { parseArgs } from 'node:util';
|
||||
import glob from 'tiny-glob';
|
||||
|
||||
const isCI = !!process.env.CI;
|
||||
const defaultTimeout = isCI ? 1400000 : 600000;
|
||||
|
||||
export default async function test() {
|
||||
const args = arg({
|
||||
'--match': String, // aka --test-name-pattern: https://nodejs.org/api/test.html#filtering-tests-by-name
|
||||
'--only': Boolean, // aka --test-only: https://nodejs.org/api/test.html#only-tests
|
||||
'--parallel': Boolean, // aka --test-concurrency: https://nodejs.org/api/test.html#test-runner-execution-model
|
||||
'--watch': Boolean, // experimental: https://nodejs.org/api/test.html#watch-mode
|
||||
'--timeout': Number, // Test timeout in milliseconds (default: 30000ms)
|
||||
'--setup': String, // Test setup file
|
||||
// Aliases
|
||||
'-m': '--match',
|
||||
'-o': '--only',
|
||||
'-p': '--parallel',
|
||||
'-w': '--watch',
|
||||
'-t': '--timeout',
|
||||
'-s': '--setup',
|
||||
const args = parseArgs({
|
||||
allowPositionals: true,
|
||||
options: {
|
||||
// aka --test-name-pattern: https://nodejs.org/api/test.html#filtering-tests-by-name
|
||||
match: { type: 'string', alias: 'm' },
|
||||
// aka --test-only: https://nodejs.org/api/test.html#only-tests
|
||||
only: { type: 'boolean', alias: 'o' },
|
||||
// aka --test-concurrency: https://nodejs.org/api/test.html#test-runner-execution-model
|
||||
parallel: { type: 'boolean', alias: 'p' },
|
||||
// experimental: https://nodejs.org/api/test.html#watch-mode
|
||||
watch: { type: 'boolean', alias: 'w' },
|
||||
// Test timeout in milliseconds (default: 30000ms)
|
||||
timeout: { type: 'string', alias: 't' },
|
||||
// Test setup file
|
||||
setup: { type: 'string', alias: 's' },
|
||||
},
|
||||
});
|
||||
|
||||
const pattern = args._[1];
|
||||
const pattern = args.positionals[1];
|
||||
if (!pattern) throw new Error('Missing test glob pattern');
|
||||
|
||||
const files = await glob(pattern, { filesOnly: true, absolute: true });
|
||||
|
@ -34,12 +36,12 @@ export default async function test() {
|
|||
// For some reason, the `only` option does not work and we need to explicitly set the CLI flag instead.
|
||||
// Node.js requires opt-in to run .only tests :(
|
||||
// https://nodejs.org/api/test.html#only-tests
|
||||
if (args['--only']) {
|
||||
if (args.values.only) {
|
||||
process.env.NODE_OPTIONS ??= '';
|
||||
process.env.NODE_OPTIONS += ' --test-only';
|
||||
}
|
||||
|
||||
if (!args['--parallel']) {
|
||||
if (!args.values.parallel) {
|
||||
// If not parallel, we create a temporary file that imports all the test files
|
||||
// so that it all runs in a single process.
|
||||
const tempTestFile = path.resolve('./node_modules/.astro/test.mjs');
|
||||
|
@ -56,12 +58,12 @@ export default async function test() {
|
|||
// https://nodejs.org/api/test.html#runoptions
|
||||
run({
|
||||
files,
|
||||
testNamePatterns: args['--match'],
|
||||
concurrency: args['--parallel'],
|
||||
only: args['--only'],
|
||||
setup: args['--setup'],
|
||||
watch: args['--watch'],
|
||||
timeout: args['--timeout'] ?? defaultTimeout, // Node.js defaults to Infinity, so set better fallback
|
||||
testNamePatterns: args.values.match,
|
||||
concurrency: args.values.parallel,
|
||||
only: args.values.only,
|
||||
setup: args.values.setup,
|
||||
watch: args.values.watch,
|
||||
timeout: args.values.timeout ? Number(args.values.timeout) : defaultTimeout, // Node.js defaults to Infinity, so set better fallback
|
||||
})
|
||||
.on('test:fail', () => {
|
||||
// For some reason, a test fail using the JS API does not set an exit code of 1,
|
||||
|
|
Loading…
Reference in a new issue