summaryrefslogtreecommitdiffhomepage
path: root/packages/shared/src
diff options
context:
space:
mode:
authorDax <[email protected]>2026-04-16 02:03:03 -0400
committerGitHub <[email protected]>2026-04-16 02:03:03 -0400
commit675a46e23e679c294355435584ae662a7c0903c7 (patch)
treefb5162a7e3565f153db26055a0857d4ac3d6448f /packages/shared/src
parent150ab07a833f0b10f4af17b3dd713cfedb16a6ff (diff)
downloadopencode-675a46e23e679c294355435584ae662a7c0903c7.tar.gz
opencode-675a46e23e679c294355435584ae662a7c0903c7.zip
CLI perf: reduce deps (#22652)
Diffstat (limited to 'packages/shared/src')
-rw-r--r--packages/shared/src/npm.ts25
-rw-r--r--packages/shared/src/util/error.ts6
-rw-r--r--packages/shared/src/util/flock.ts10
3 files changed, 33 insertions, 8 deletions
diff --git a/packages/shared/src/npm.ts b/packages/shared/src/npm.ts
index 8bd0cc468..955cafa19 100644
--- a/packages/shared/src/npm.ts
+++ b/packages/shared/src/npm.ts
@@ -1,6 +1,5 @@
import path from "path"
import semver from "semver"
-import { Arborist } from "@npmcli/arborist"
import { Effect, Schema, Context, Layer, Option, FileSystem } from "effect"
import { NodeFileSystem } from "@effect/platform-node"
import { AppFileSystem } from "./filesystem"
@@ -19,8 +18,8 @@ export namespace Npm {
}
export interface Interface {
- readonly add: (pkg: string) => Effect.Effect<EntryPoint, InstallFailedError>
- readonly install: (dir: string) => Effect.Effect<void>
+ readonly add: (pkg: string) => Effect.Effect<EntryPoint, InstallFailedError | EffectFlock.LockError>
+ readonly install: (dir: string, input?: { add: string[] }) => Effect.Effect<void, EffectFlock.LockError>
readonly outdated: (pkg: string, cachedVersion: string) => Effect.Effect<boolean>
readonly which: (pkg: string) => Effect.Effect<Option.Option<string>>
}
@@ -92,6 +91,7 @@ export namespace Npm {
})
const add = Effect.fn("Npm.add")(function* (pkg: string) {
+ const { Arborist } = yield* Effect.promise(() => import("@npmcli/arborist"))
const dir = directory(pkg)
yield* flock.acquire(`npm-install:${dir}`)
@@ -133,10 +133,17 @@ export namespace Npm {
return resolveEntryPoint(first.name, first.path)
}, Effect.scoped)
- const install = Effect.fn("Npm.install")(function* (dir: string) {
+ const install = Effect.fn("Npm.install")(function* (dir: string, input?: { add: string[] }) {
+ const canWrite = yield* afs.access(dir, { writable: true }).pipe(
+ Effect.as(true),
+ Effect.orElseSucceed(() => false),
+ )
+ if (!canWrite) return
+
yield* flock.acquire(`npm-install:${dir}`)
const reify = Effect.fnUntraced(function* () {
+ const { Arborist } = yield* Effect.promise(() => import("@npmcli/arborist"))
const arb = new Arborist({
path: dir,
binLinks: true,
@@ -145,7 +152,14 @@ export namespace Npm {
ignoreScripts: true,
})
yield* Effect.tryPromise({
- try: () => arb.reify().catch(() => {}),
+ try: () =>
+ arb
+ .reify({
+ add: input?.add || [],
+ save: true,
+ saveType: "prod",
+ })
+ .catch(() => {}),
catch: () => {},
}).pipe(Effect.orElseSucceed(() => {}))
})
@@ -167,6 +181,7 @@ export namespace Npm {
...Object.keys(pkgAny?.devDependencies || {}),
...Object.keys(pkgAny?.peerDependencies || {}),
...Object.keys(pkgAny?.optionalDependencies || {}),
+ ...(input?.add || []),
])
const root = lockAny?.packages?.[""] || {}
diff --git a/packages/shared/src/util/error.ts b/packages/shared/src/util/error.ts
index 12c27a0a7..9d3b7c661 100644
--- a/packages/shared/src/util/error.ts
+++ b/packages/shared/src/util/error.ts
@@ -4,6 +4,12 @@ export abstract class NamedError extends Error {
abstract schema(): z.core.$ZodType
abstract toObject(): { name: string; data: any }
+ static hasName(error: unknown, name: string): boolean {
+ return (
+ typeof error === "object" && error !== null && "name" in error && (error as Record<string, unknown>).name === name
+ )
+ }
+
static create<Name extends string, Data extends z.core.$ZodType>(name: Name, data: Data) {
const schema = z
.object({
diff --git a/packages/shared/src/util/flock.ts b/packages/shared/src/util/flock.ts
index 4a1df1dee..958bd9fd1 100644
--- a/packages/shared/src/util/flock.ts
+++ b/packages/shared/src/util/flock.ts
@@ -345,10 +345,14 @@ export namespace Flock {
return await fn()
}
- export const effect = Effect.fn("Flock.effect")(function* (key: string) {
+ export const effect = Effect.fn("Flock.effect")(function* (key: string, input: Options = {}) {
return yield* Effect.acquireRelease(
- Effect.promise((signal) => Flock.acquire(key, { signal })),
- (foo) => Effect.promise(() => foo.release()),
+ Effect.promise((signal) => Flock.acquire(key, { ...input, signal })).pipe(
+ Effect.withSpan("Flock.acquire", {
+ attributes: { key },
+ }),
+ ),
+ (lock) => Effect.promise(() => lock.release()).pipe(Effect.withSpan("Flock.release")),
).pipe(Effect.asVoid)
})
}