Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: silent programmatic usage #151

Merged
merged 6 commits into from Jun 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Expand Up @@ -49,6 +49,7 @@
"devDependencies": {
"@antfu/eslint-config": "^0.37.0",
"@posva/prompts": "^2.4.4",
"@types/fs-extra": "^11.0.1",
"@types/ini": "^1.3.31",
"@types/node": "^18.15.11",
"@types/which": "^3.0.0",
Expand All @@ -58,6 +59,7 @@
"execa": "^7.1.1",
"fast-glob": "^3.2.12",
"find-up": "^6.3.0",
"fs-extra": "^11.1.1",
"fzf": "^0.5.1",
"ini": "^4.0.0",
"kleur": "^4.1.5",
Expand Down
19 changes: 19 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 8 additions & 4 deletions src/commands/nr.ts
Expand Up @@ -12,15 +12,19 @@ runCli(async (agent, args, ctx) => {

if (args[0] === '-') {
if (!storage.lastRunCommand) {
console.error('No last command found')
process.exit(1)
if (!ctx?.programmatic) {
console.error('No last command found')
process.exit(1)
}

throw new Error('No last command found')
}
args[0] = storage.lastRunCommand
}

if (args.length === 0) {
if (args.length === 0 && !ctx?.programmatic) {
// support https://www.npmjs.com/package/npm-scripts-info conventions
const pkg = getPackageJSON(ctx?.cwd)
const pkg = getPackageJSON(ctx)
const scripts = pkg.scripts || {}
const scriptsInfo = pkg['scripts-info'] || {}

Expand Down
4 changes: 2 additions & 2 deletions src/config.ts
Expand Up @@ -44,9 +44,9 @@ export async function getConfig(): Promise<Config> {
return config
}

export async function getDefaultAgent() {
export async function getDefaultAgent(programmatic?: boolean) {
const { defaultAgent } = await getConfig()
if (defaultAgent === 'prompt' && process.env.CI)
if (defaultAgent === 'prompt' && (programmatic || process.env.CI))
return 'npm'
return defaultAgent
}
Expand Down
7 changes: 4 additions & 3 deletions src/detect.ts
Expand Up @@ -10,10 +10,11 @@ import { cmdExists } from './utils'

export interface DetectOptions {
autoInstall?: boolean
programmatic?: boolean
cwd?: string
}

export async function detect({ autoInstall, cwd }: DetectOptions = {}) {
export async function detect({ autoInstall, programmatic, cwd }: DetectOptions = {}) {
let agent: Agent | null = null
let version: string | null = null

Expand All @@ -38,7 +39,7 @@ export async function detect({ autoInstall, cwd }: DetectOptions = {}) {
agent = 'pnpm@6'
else if (name in AGENTS)
agent = name
else
else if (!programmatic)
console.warn('[ni] Unknown packageManager:', pkg.packageManager)
}
}
Expand All @@ -50,7 +51,7 @@ export async function detect({ autoInstall, cwd }: DetectOptions = {}) {
agent = LOCKS[path.basename(lockPath)]

// auto install
if (agent && !cmdExists(agent.split('@')[0])) {
if (agent && !cmdExists(agent.split('@')[0]) && !programmatic) {
if (!autoInstall) {
console.warn(`[ni] Detected ${agent} but it doesn't seem to be installed.\n`)

Expand Down
12 changes: 9 additions & 3 deletions src/fs.ts
@@ -1,7 +1,9 @@
import { resolve } from 'node:path'
import fs from 'node:fs'
import type { RunnerContext } from './runner'

export function getPackageJSON(cwd = process.cwd()): any {
export function getPackageJSON(ctx?: RunnerContext): any {
const cwd = ctx?.cwd ?? process.cwd()
const path = resolve(cwd, 'package.json')

if (fs.existsSync(path)) {
Expand All @@ -11,8 +13,12 @@ export function getPackageJSON(cwd = process.cwd()): any {
return data
}
catch (e) {
console.warn('Failed to parse package.json')
process.exit(0)
if (!ctx?.programmatic) {
console.warn('Failed to parse package.json')
process.exit(1)
}

throw e
}
}
}
13 changes: 9 additions & 4 deletions src/runner.ts
Expand Up @@ -15,6 +15,7 @@ import { UnsupportedCommand } from './parse'
const DEBUG_SIGN = '?'

export interface RunnerContext {
programmatic?: boolean
hasLock?: boolean
cwd?: string
}
Expand All @@ -27,10 +28,13 @@ export async function runCli(fn: Runner, options: DetectOptions = {}) {
await run(fn, args, options)
}
catch (error) {
if (error instanceof UnsupportedCommand)
if (error instanceof UnsupportedCommand && !options.programmatic)
console.log(c.red(`\u2717 ${error.message}`))

process.exit(1)
if (!options.programmatic)
process.exit(1)

throw error
}
}

Expand All @@ -39,7 +43,7 @@ export async function run(fn: Runner, args: string[], options: DetectOptions = {
if (debug)
remove(args, DEBUG_SIGN)

let cwd = process.cwd()
let cwd = options.cwd ?? process.cwd()
let command

if (args.length === 1 && (args[0] === '--version' || args[0] === '-v')) {
Expand Down Expand Up @@ -71,7 +75,7 @@ export async function run(fn: Runner, args: string[], options: DetectOptions = {
command = await fn(await getGlobalAgent(), args)
}
else {
let agent = await detect({ ...options, cwd }) || await getDefaultAgent()
let agent = await detect({ ...options, cwd }) || await getDefaultAgent(options.programmatic)
if (agent === 'prompt') {
agent = (await prompts({
name: 'agent',
Expand All @@ -83,6 +87,7 @@ export async function run(fn: Runner, args: string[], options: DetectOptions = {
return
}
command = await fn(agent as Agent, args, {
programmatic: options.programmatic,
hasLock: Boolean(agent),
cwd,
})
Expand Down
Empty file.
Empty file.
Empty file.
Empty file.
1 change: 1 addition & 0 deletions test/fixtures/lockfile/unknown/future-package-manager.json
@@ -0,0 +1 @@
{}
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions test/fixtures/packager/bun/package.json
@@ -0,0 +1,3 @@
{
"packageManager": "bun@0"
}
3 changes: 3 additions & 0 deletions test/fixtures/packager/npm/package.json
@@ -0,0 +1,3 @@
{
"packageManager": "npm@7"
}
3 changes: 3 additions & 0 deletions test/fixtures/packager/pnpm/package.json
@@ -0,0 +1,3 @@
{
"packageManager": "pnpm@8"
}
3 changes: 3 additions & 0 deletions test/fixtures/packager/pnpm@6/package.json
@@ -0,0 +1,3 @@
{
"packageManager": "pnpm@6"
}
3 changes: 3 additions & 0 deletions test/fixtures/packager/unknown/package.json
@@ -0,0 +1,3 @@
{
"packageManager": "future-package-manager"
}
3 changes: 3 additions & 0 deletions test/fixtures/packager/yarn/package.json
@@ -0,0 +1,3 @@
{
"packageManager": "yarn@1"
}
3 changes: 3 additions & 0 deletions test/fixtures/packager/yarn@berry/package.json
@@ -0,0 +1,3 @@
{
"packageManager": "yarn@3"
}
29 changes: 29 additions & 0 deletions test/programmatic/__snapshots__/detect.spec.ts.snap
@@ -0,0 +1,29 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`lockfile > bun 1`] = `"bun"`;

exports[`lockfile > npm 1`] = `"npm"`;

exports[`lockfile > pnpm 1`] = `"pnpm"`;

exports[`lockfile > pnpm@6 1`] = `"pnpm"`;

exports[`lockfile > unknown 1`] = `null`;

exports[`lockfile > yarn 1`] = `"yarn"`;

exports[`lockfile > yarn@berry 1`] = `"yarn"`;

exports[`packager > bun 1`] = `"bun"`;

exports[`packager > npm 1`] = `"npm"`;

exports[`packager > pnpm 1`] = `"pnpm"`;

exports[`packager > pnpm@6 1`] = `"pnpm"`;

exports[`packager > unknown 1`] = `null`;

exports[`packager > yarn 1`] = `"yarn"`;

exports[`packager > yarn@berry 1`] = `"yarn"`;