Refactor npm config handling (#24565)
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import type { Argv } from "yargs"
|
||||
import { UI } from "../ui"
|
||||
import * as prompts from "@clack/prompts"
|
||||
import { AppRuntime } from "@/effect/app-runtime"
|
||||
import { Installation } from "../../installation"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import fs from "fs/promises"
|
||||
@@ -58,7 +57,7 @@ export const UninstallCommand = {
|
||||
UI.empty()
|
||||
prompts.intro("Uninstall OpenCode")
|
||||
|
||||
const method = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.method()))
|
||||
const method = await Installation.method()
|
||||
prompts.log.info(`Installation method: ${method}`)
|
||||
|
||||
const targets = await collectRemovalTargets(args, method)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { Argv } from "yargs"
|
||||
import { UI } from "../ui"
|
||||
import * as prompts from "@clack/prompts"
|
||||
import { AppRuntime } from "@/effect/app-runtime"
|
||||
import { Installation } from "../../installation"
|
||||
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
||||
|
||||
@@ -26,7 +25,7 @@ export const UpgradeCommand = {
|
||||
UI.println(UI.logo(" "))
|
||||
UI.empty()
|
||||
prompts.intro("Upgrade")
|
||||
const detectedMethod = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.method()))
|
||||
const detectedMethod = await Installation.method()
|
||||
const method = (args.method as Installation.Method) ?? detectedMethod
|
||||
if (method === "unknown") {
|
||||
prompts.log.error(`opencode is installed to ${process.execPath} and may be managed by a package manager`)
|
||||
@@ -44,9 +43,7 @@ export const UpgradeCommand = {
|
||||
}
|
||||
}
|
||||
prompts.log.info("Using method: " + method)
|
||||
const target = args.target
|
||||
? args.target.replace(/^v/, "")
|
||||
: await AppRuntime.runPromise(Installation.Service.use((svc) => svc.latest()))
|
||||
const target = args.target ? args.target.replace(/^v/, "") : await Installation.latest()
|
||||
|
||||
if (InstallationVersion === target) {
|
||||
prompts.log.warn(`opencode upgrade skipped: ${target} is already installed`)
|
||||
@@ -57,9 +54,7 @@ export const UpgradeCommand = {
|
||||
prompts.log.info(`From ${InstallationVersion} → ${target}`)
|
||||
const spinner = prompts.spinner()
|
||||
spinner.start("Upgrading...")
|
||||
const err = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.upgrade(method, target))).catch(
|
||||
(err) => err,
|
||||
)
|
||||
const err = await Installation.upgrade(method, target).catch((err) => err)
|
||||
if (err) {
|
||||
spinner.stop("Upgrade failed", 1)
|
||||
if (err instanceof Installation.UpgradeFailedError) {
|
||||
|
||||
@@ -8,8 +8,8 @@ import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
||||
export async function upgrade() {
|
||||
const config = await AppRuntime.runPromise(Config.Service.use((cfg) => cfg.getGlobal()))
|
||||
if (config.autoupdate === false || Flag.OPENCODE_DISABLE_AUTOUPDATE) return
|
||||
const method = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.method()))
|
||||
const latest = await AppRuntime.runPromise(Installation.Service.use((svc) => svc.latest(method))).catch(() => {})
|
||||
const method = await Installation.method()
|
||||
const latest = await Installation.latest(method).catch(() => {})
|
||||
if (!latest) return
|
||||
|
||||
if (Flag.OPENCODE_ALWAYS_NOTIFY_UPDATE) {
|
||||
@@ -27,7 +27,7 @@ export async function upgrade() {
|
||||
}
|
||||
|
||||
if (method === "unknown") return
|
||||
await AppRuntime.runPromise(Installation.Service.use((svc) => svc.upgrade(method, latest)))
|
||||
await Installation.upgrade(method, latest)
|
||||
.then(() => Bus.publish(Installation.Event.Updated, { version: latest }))
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
@@ -8,9 +8,10 @@ import z from "zod"
|
||||
import { BusEvent } from "@/bus/bus-event"
|
||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
||||
import { Log } from "../util"
|
||||
|
||||
import { makeRuntime } from "@opencode-ai/core/effect/runtime"
|
||||
import semver from "semver"
|
||||
import { InstallationChannel, InstallationVersion } from "@opencode-ai/core/installation/version"
|
||||
import { NpmConfig } from "@opencode-ai/core/npm-config"
|
||||
|
||||
const log = Log.create({ service: "installation" })
|
||||
|
||||
@@ -132,18 +133,6 @@ export const layer: Layer.Layer<Service, never, HttpClient.HttpClient | ChildPro
|
||||
Effect.catch(() => Effect.succeed({ code: ChildProcessSpawner.ExitCode(1), stdout: "", stderr: "" })),
|
||||
)
|
||||
|
||||
// Use the package manager's resolver so registries, mirrors, auth, proxies, and dist-tags match upgrade behavior.
|
||||
const viewVersion = Effect.fnUntraced(function* (method: "npm" | "pnpm" | "bun", spec: string) {
|
||||
const args = method === "bun" ? ["pm", "view", spec, "version", "--json"] : ["view", spec, "version", "--json"]
|
||||
const result = yield* run([method, ...args])
|
||||
if (result.code !== 0 || !result.stdout.trim()) {
|
||||
return yield* new UpgradeFailedError({
|
||||
stderr: result.stderr || result.stdout || `Failed to resolve ${spec}`,
|
||||
})
|
||||
}
|
||||
return yield* Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.String))(result.stdout)
|
||||
})
|
||||
|
||||
const getBrewFormula = Effect.fnUntraced(function* () {
|
||||
const tapFormula = yield* text(["brew", "list", "--formula", "anomalyco/tap/opencode"])
|
||||
if (tapFormula.includes("opencode")) return "anomalyco/tap/opencode"
|
||||
@@ -235,7 +224,13 @@ export const layer: Layer.Layer<Service, never, HttpClient.HttpClient | ChildPro
|
||||
}
|
||||
|
||||
if (detectedMethod === "npm" || detectedMethod === "bun" || detectedMethod === "pnpm") {
|
||||
return yield* viewVersion(detectedMethod, `opencode-ai@${InstallationChannel}`)
|
||||
const response = yield* httpOk.execute(
|
||||
HttpClientRequest.get(
|
||||
`${yield* NpmConfig.registry(process.cwd())}/opencode-ai/${InstallationChannel}`,
|
||||
).pipe(HttpClientRequest.acceptJson),
|
||||
)
|
||||
const data = yield* HttpClientResponse.schemaBodyJson(NpmPackage)(response)
|
||||
return data.version
|
||||
}
|
||||
|
||||
if (detectedMethod === "choco") {
|
||||
@@ -335,4 +330,10 @@ export const defaultLayer = layer.pipe(
|
||||
Layer.provide(CrossSpawnSpawner.defaultLayer),
|
||||
)
|
||||
|
||||
const { runPromise } = makeRuntime(Service, defaultLayer)
|
||||
|
||||
export const latest = (...args: Parameters<Interface["latest"]>) => runPromise((s) => s.latest(...args))
|
||||
export const method = () => runPromise((s) => s.method())
|
||||
export const upgrade = (...args: Parameters<Interface["upgrade"]>) => runPromise((s) => s.upgrade(...args))
|
||||
|
||||
export * as Installation from "."
|
||||
|
||||
Reference in New Issue
Block a user