refactor: extract shared util package (#37828)
This commit is contained in:
parent
7243bd9e12
commit
e0810753f2
272 changed files with 590 additions and 565 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import { Service, type Endpoint, type EnsureOptions } from "@opencode-ai/client/effect/service"
|
||||
import { ClientError, isUnauthorizedError, OpenCode } from "@opencode-ai/client/promise"
|
||||
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
||||
import { InstallationVersion } from "@opencode-ai/util/installation/version"
|
||||
import { Effect, Redacted } from "effect"
|
||||
import { Env } from "../env"
|
||||
import { ServiceConfig } from "./service-config"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Global } from "@opencode-ai/core/global"
|
||||
import { InstallationChannel, InstallationVersion } from "@opencode-ai/core/installation/version"
|
||||
import { Hash } from "@opencode-ai/core/util/hash"
|
||||
import { Global } from "@opencode-ai/util/global"
|
||||
import { InstallationChannel, InstallationVersion } from "@opencode-ai/util/installation/version"
|
||||
import { Hash } from "@opencode-ai/util/hash"
|
||||
import { Service } from "@opencode-ai/client/effect/service"
|
||||
import { Effect, FileSystem, Option, Schema } from "effect"
|
||||
import { randomBytes } from "crypto"
|
||||
|
|
@ -25,17 +25,21 @@ const decodeInfo = Schema.decodeUnknownEffect(Schema.fromJsonString(Info))
|
|||
const decodeRegistration = Schema.decodeUnknownEffect(Schema.fromJsonString(Service.Info))
|
||||
|
||||
export function filename(channel = InstallationChannel) {
|
||||
if (channel === "latest") return "service.json"
|
||||
if (channel === "local") return "service-local.json"
|
||||
return `service-${Hash.fast(channel)}.json`
|
||||
if (channel === "latest" || channel === "next") return "service.json"
|
||||
return `service-${channel.replace(/[^a-zA-Z0-9._-]/g, "-")}.json`
|
||||
}
|
||||
|
||||
export function defaultPort(channel = InstallationChannel) {
|
||||
if (channel === "latest") return 0xc0de
|
||||
if (channel === "latest" || channel === "next") return 0xc0de
|
||||
if (channel === "local") return 0xc0df
|
||||
return 10_000 + (Number.parseInt(Hash.fast(channel).slice(0, 8), 16) % 50_000)
|
||||
}
|
||||
|
||||
export function legacyFilename(channel = InstallationChannel) {
|
||||
if (channel === "latest" || channel === "local") return
|
||||
return `service-${Hash.fast(channel)}.json`
|
||||
}
|
||||
|
||||
export function versionBelongsToChannel(
|
||||
version: string | undefined,
|
||||
channel = InstallationChannel,
|
||||
|
|
@ -54,7 +58,6 @@ export const migrateRegistration = Effect.fnUntraced(function* (
|
|||
channel = InstallationChannel,
|
||||
installedVersion = InstallationVersion,
|
||||
) {
|
||||
if (channel === "latest" || channel === "local") return
|
||||
const fs = yield* FileSystem.FileSystem
|
||||
const text = yield* fs.readFileString(legacy).pipe(Effect.option)
|
||||
if (Option.isNone(text)) return
|
||||
|
|
@ -64,6 +67,14 @@ export const migrateRegistration = Effect.fnUntraced(function* (
|
|||
yield* fs.writeFileString(file, text.value, { flag: "wx", mode: 0o600 }).pipe(Effect.ignore)
|
||||
})
|
||||
|
||||
export const migrateConfig = Effect.fnUntraced(function* (legacy: string, file: string) {
|
||||
const fs = yield* FileSystem.FileSystem
|
||||
const text = yield* fs.readFileString(legacy).pipe(Effect.option)
|
||||
if (Option.isNone(text)) return
|
||||
if (Option.isNone(yield* decodeInfo(text.value).pipe(Effect.option))) return
|
||||
yield* fs.writeFileString(file, text.value, { flag: "wx", mode: 0o600 }).pipe(Effect.ignore)
|
||||
})
|
||||
|
||||
function configKey(key: string): Key {
|
||||
if (key === "hostname" || key === "port" || key === "password") return key
|
||||
throw new Error(`Unknown service config key: ${key}`)
|
||||
|
|
@ -73,18 +84,23 @@ const paths = Effect.gen(function* () {
|
|||
const fs = yield* FileSystem.FileSystem
|
||||
const global = yield* Global.Service
|
||||
const name = filename()
|
||||
const legacy = legacyFilename()
|
||||
const file = path.join(global.state, name)
|
||||
return {
|
||||
fs,
|
||||
file,
|
||||
legacyFile: path.join(global.state, "service.json"),
|
||||
legacyConfigFile: legacy ? path.join(global.config, legacy) : undefined,
|
||||
legacyRegistrationFiles: [
|
||||
...(legacy ? [path.join(global.state, legacy)] : []),
|
||||
...(name !== "service.json" && InstallationChannel !== "local" ? [path.join(global.state, "service.json")] : []),
|
||||
],
|
||||
configFile: path.join(global.config, name),
|
||||
}
|
||||
})
|
||||
|
||||
export const options = Effect.fnUntraced(function* () {
|
||||
const { file, legacyFile } = yield* paths
|
||||
yield* migrateRegistration(legacyFile, file)
|
||||
const { file, legacyRegistrationFiles } = yield* paths
|
||||
yield* Effect.forEach(legacyRegistrationFiles, (legacy) => migrateRegistration(legacy, file))
|
||||
return {
|
||||
file,
|
||||
version: InstallationVersion,
|
||||
|
|
@ -93,7 +109,8 @@ export const options = Effect.fnUntraced(function* () {
|
|||
})
|
||||
|
||||
export const read = Effect.fn("cli.service-config.read")(function* () {
|
||||
const { fs, configFile } = yield* paths
|
||||
const { fs, configFile, legacyConfigFile } = yield* paths
|
||||
if (legacyConfigFile) yield* migrateConfig(legacyConfigFile, configFile)
|
||||
return yield* fs.readFileString(configFile).pipe(
|
||||
Effect.flatMap(decodeInfo),
|
||||
Effect.catch(() => Effect.succeed({} as Info)),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Service, type Endpoint } from "@opencode-ai/client/effect/service"
|
||||
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { CrossSpawnSpawner } from "@opencode-ai/util/cross-spawn-spawner"
|
||||
import { LayerNode } from "@opencode-ai/util/effect/layer-node"
|
||||
import { Deferred, Effect, Schema, Stream } from "effect"
|
||||
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
|
||||
import { randomBytes } from "node:crypto"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
// version-mismatched background service before the TUI attaches.
|
||||
import { createCliRenderer, RGBA, TextAttributes, type CliRenderer, type ThemeMode } from "@opentui/core"
|
||||
import { render, useTerminalDimensions } from "@opentui/solid"
|
||||
import { InstallationVersion } from "@opencode-ai/core/installation/version"
|
||||
import { InstallationVersion } from "@opencode-ai/util/installation/version"
|
||||
import { registerOpencodeSpinner } from "@opencode-ai/tui/component/register-spinner"
|
||||
import { SPINNER_FRAMES } from "@opencode-ai/tui/component/spinner"
|
||||
import { go } from "@opencode-ai/tui/logo"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { Global } from "@opencode-ai/core/global"
|
||||
import { AppProcess } from "@opencode-ai/core/process"
|
||||
import { Global } from "@opencode-ai/util/global"
|
||||
import { AppProcess } from "@opencode-ai/util/process"
|
||||
import {
|
||||
InstallationChannel,
|
||||
InstallationLocal,
|
||||
InstallationVersion,
|
||||
} from "@opencode-ai/core/installation/version"
|
||||
} from "@opencode-ai/util/installation/version"
|
||||
import { Context, Duration, Effect, FileSystem, Layer } from "effect"
|
||||
import { ChildProcess } from "effect/unstable/process"
|
||||
import { parse, type ParseError } from "jsonc-parser"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue