Browse Source

refactor: unwrap PluginMeta namespace + self-reexport (#22945)

Kit Langton 5 days ago
parent
commit
974fa1b8b1
1 changed files with 147 additions and 147 deletions
  1. 147 147
      packages/opencode/src/plugin/meta.ts

+ 147 - 147
packages/opencode/src/plugin/meta.ts

@@ -8,181 +8,181 @@ import { Flock } from "@opencode-ai/shared/util/flock"
 
 import { parsePluginSpecifier, pluginSource } from "./shared"
 
-export namespace PluginMeta {
-  type Source = "file" | "npm"
-
-  export type Theme = {
-    src: string
-    dest: string
-    mtime?: number
-    size?: number
-  }
+type Source = "file" | "npm"
 
-  export type Entry = {
-    id: string
-    source: Source
-    spec: string
-    target: string
-    requested?: string
-    version?: string
-    modified?: number
-    first_time: number
-    last_time: number
-    time_changed: number
-    load_count: number
-    fingerprint: string
-    themes?: Record<string, Theme>
-  }
+export type Theme = {
+  src: string
+  dest: string
+  mtime?: number
+  size?: number
+}
 
-  export type State = "first" | "updated" | "same"
+export type Entry = {
+  id: string
+  source: Source
+  spec: string
+  target: string
+  requested?: string
+  version?: string
+  modified?: number
+  first_time: number
+  last_time: number
+  time_changed: number
+  load_count: number
+  fingerprint: string
+  themes?: Record<string, Theme>
+}
 
-  export type Touch = {
-    spec: string
-    target: string
-    id: string
-  }
+export type State = "first" | "updated" | "same"
 
-  type Store = Record<string, Entry>
-  type Core = Omit<Entry, "first_time" | "last_time" | "time_changed" | "load_count" | "fingerprint" | "themes">
-  type Row = Touch & { core: Core }
+export type Touch = {
+  spec: string
+  target: string
+  id: string
+}
 
-  function storePath() {
-    return Flag.OPENCODE_PLUGIN_META_FILE ?? path.join(Global.Path.state, "plugin-meta.json")
-  }
+type Store = Record<string, Entry>
+type Core = Omit<Entry, "first_time" | "last_time" | "time_changed" | "load_count" | "fingerprint" | "themes">
+type Row = Touch & { core: Core }
 
-  function lock(file: string) {
-    return `plugin-meta:${file}`
-  }
+function storePath() {
+  return Flag.OPENCODE_PLUGIN_META_FILE ?? path.join(Global.Path.state, "plugin-meta.json")
+}
 
-  function fileTarget(spec: string, target: string) {
-    if (spec.startsWith("file://")) return fileURLToPath(spec)
-    if (target.startsWith("file://")) return fileURLToPath(target)
-    return
-  }
+function lock(file: string) {
+  return `plugin-meta:${file}`
+}
 
-  async function modifiedAt(file: string) {
-    const stat = await Filesystem.statAsync(file)
-    if (!stat) return
-    const mtime = stat.mtimeMs
-    return Math.floor(typeof mtime === "bigint" ? Number(mtime) : mtime)
-  }
+function fileTarget(spec: string, target: string) {
+  if (spec.startsWith("file://")) return fileURLToPath(spec)
+  if (target.startsWith("file://")) return fileURLToPath(target)
+  return
+}
 
-  function resolvedTarget(target: string) {
-    if (target.startsWith("file://")) return fileURLToPath(target)
-    return target
-  }
+async function modifiedAt(file: string) {
+  const stat = await Filesystem.statAsync(file)
+  if (!stat) return
+  const mtime = stat.mtimeMs
+  return Math.floor(typeof mtime === "bigint" ? Number(mtime) : mtime)
+}
 
-  async function npmVersion(target: string) {
-    const resolved = resolvedTarget(target)
-    const stat = await Filesystem.statAsync(resolved)
-    const dir = stat?.isDirectory() ? resolved : path.dirname(resolved)
-    return Filesystem.readJson<{ version?: string }>(path.join(dir, "package.json"))
-      .then((item) => item.version)
-      .catch(() => undefined)
-  }
+function resolvedTarget(target: string) {
+  if (target.startsWith("file://")) return fileURLToPath(target)
+  return target
+}
 
-  async function entryCore(item: Touch): Promise<Core> {
-    const spec = item.spec
-    const target = item.target
-    const source = pluginSource(spec)
-    if (source === "file") {
-      const file = fileTarget(spec, target)
-      return {
-        id: item.id,
-        source,
-        spec,
-        target,
-        modified: file ? await modifiedAt(file) : undefined,
-      }
-    }
+async function npmVersion(target: string) {
+  const resolved = resolvedTarget(target)
+  const stat = await Filesystem.statAsync(resolved)
+  const dir = stat?.isDirectory() ? resolved : path.dirname(resolved)
+  return Filesystem.readJson<{ version?: string }>(path.join(dir, "package.json"))
+    .then((item) => item.version)
+    .catch(() => undefined)
+}
 
+async function entryCore(item: Touch): Promise<Core> {
+  const spec = item.spec
+  const target = item.target
+  const source = pluginSource(spec)
+  if (source === "file") {
+    const file = fileTarget(spec, target)
     return {
       id: item.id,
       source,
       spec,
       target,
-      requested: parsePluginSpecifier(spec).version,
-      version: await npmVersion(target),
+      modified: file ? await modifiedAt(file) : undefined,
     }
   }
 
-  function fingerprint(value: Core) {
-    if (value.source === "file") return [value.target, value.modified ?? ""].join("|")
-    return [value.target, value.requested ?? "", value.version ?? ""].join("|")
+  return {
+    id: item.id,
+    source,
+    spec,
+    target,
+    requested: parsePluginSpecifier(spec).version,
+    version: await npmVersion(target),
   }
+}
 
-  async function read(file: string): Promise<Store> {
-    return Filesystem.readJson<Store>(file).catch(() => ({}) as Store)
-  }
+function fingerprint(value: Core) {
+  if (value.source === "file") return [value.target, value.modified ?? ""].join("|")
+  return [value.target, value.requested ?? "", value.version ?? ""].join("|")
+}
 
-  async function row(item: Touch): Promise<Row> {
-    return {
-      ...item,
-      core: await entryCore(item),
-    }
-  }
+async function read(file: string): Promise<Store> {
+  return Filesystem.readJson<Store>(file).catch(() => ({}) as Store)
+}
 
-  function next(prev: Entry | undefined, core: Core, now: number): { state: State; entry: Entry } {
-    const entry: Entry = {
-      ...core,
-      first_time: prev?.first_time ?? now,
-      last_time: now,
-      time_changed: prev?.time_changed ?? now,
-      load_count: (prev?.load_count ?? 0) + 1,
-      fingerprint: fingerprint(core),
-      themes: prev?.themes,
-    }
-    const state: State = !prev ? "first" : prev.fingerprint === entry.fingerprint ? "same" : "updated"
-    if (state === "updated") entry.time_changed = now
-    return {
-      state,
-      entry,
-    }
+async function row(item: Touch): Promise<Row> {
+  return {
+    ...item,
+    core: await entryCore(item),
   }
+}
 
-  export async function touchMany(items: Touch[]): Promise<Array<{ state: State; entry: Entry }>> {
-    if (!items.length) return []
-    const file = storePath()
-    const rows = await Promise.all(items.map((item) => row(item)))
-
-    return Flock.withLock(lock(file), async () => {
-      const store = await read(file)
-      const now = Date.now()
-      const out: Array<{ state: State; entry: Entry }> = []
-      for (const item of rows) {
-        const hit = next(store[item.id], item.core, now)
-        store[item.id] = hit.entry
-        out.push(hit)
-      }
-      await Filesystem.writeJson(file, store)
-      return out
-    })
+function next(prev: Entry | undefined, core: Core, now: number): { state: State; entry: Entry } {
+  const entry: Entry = {
+    ...core,
+    first_time: prev?.first_time ?? now,
+    last_time: now,
+    time_changed: prev?.time_changed ?? now,
+    load_count: (prev?.load_count ?? 0) + 1,
+    fingerprint: fingerprint(core),
+    themes: prev?.themes,
+  }
+  const state: State = !prev ? "first" : prev.fingerprint === entry.fingerprint ? "same" : "updated"
+  if (state === "updated") entry.time_changed = now
+  return {
+    state,
+    entry,
   }
+}
 
-  export async function touch(spec: string, target: string, id: string): Promise<{ state: State; entry: Entry }> {
-    return touchMany([{ spec, target, id }]).then((item) => {
-      const hit = item[0]
-      if (hit) return hit
-      throw new Error("Failed to touch plugin metadata.")
-    })
-  }
+export async function touchMany(items: Touch[]): Promise<Array<{ state: State; entry: Entry }>> {
+  if (!items.length) return []
+  const file = storePath()
+  const rows = await Promise.all(items.map((item) => row(item)))
+
+  return Flock.withLock(lock(file), async () => {
+    const store = await read(file)
+    const now = Date.now()
+    const out: Array<{ state: State; entry: Entry }> = []
+    for (const item of rows) {
+      const hit = next(store[item.id], item.core, now)
+      store[item.id] = hit.entry
+      out.push(hit)
+    }
+    await Filesystem.writeJson(file, store)
+    return out
+  })
+}
 
-  export async function setTheme(id: string, name: string, theme: Theme): Promise<void> {
-    const file = storePath()
-    await Flock.withLock(lock(file), async () => {
-      const store = await read(file)
-      const entry = store[id]
-      if (!entry) return
-      entry.themes = {
-        ...entry.themes,
-        [name]: theme,
-      }
-      await Filesystem.writeJson(file, store)
-    })
-  }
+export async function touch(spec: string, target: string, id: string): Promise<{ state: State; entry: Entry }> {
+  return touchMany([{ spec, target, id }]).then((item) => {
+    const hit = item[0]
+    if (hit) return hit
+    throw new Error("Failed to touch plugin metadata.")
+  })
+}
 
-  export async function list(): Promise<Store> {
-    const file = storePath()
-    return Flock.withLock(lock(file), async () => read(file))
-  }
+export async function setTheme(id: string, name: string, theme: Theme): Promise<void> {
+  const file = storePath()
+  await Flock.withLock(lock(file), async () => {
+    const store = await read(file)
+    const entry = store[id]
+    if (!entry) return
+    entry.themes = {
+      ...entry.themes,
+      [name]: theme,
+    }
+    await Filesystem.writeJson(file, store)
+  })
 }
+
+export async function list(): Promise<Store> {
+  const file = storePath()
+  return Flock.withLock(lock(file), async () => read(file))
+}
+
+export * as PluginMeta from "./meta"