`NamedError` class in opencode codebase.
In this article, we review NamedError
class in opencode codebase. We will look at:
-
NamedError class definition
-
NamedError.create example
I study patterns used in an open source project found on Github Trending. For this week, I reviewed some parts of opencode codebase and wrote this article.
NamedError class definition
In opencode/packages/opencode/src/util/error.ts, you will find the below declaration:
import z from "zod/v4"
// import { Log } from "./log"
// const log = Log.create()
export abstract class NamedError extends Error {
abstract schema(): z.core.$ZodType
abstract toObject(): { name: string; data: any }
static create<Name extends string, Data extends z.core.$ZodType>(name: Name, data: Data) {
}
public static readonly Unknown = NamedError.create(
"UnknownError",
z.object({
message: z.string(),
}),
)
}
create
Create is defined as shown below:
static create<Name extends string, Data extends z.core.$ZodType>(name: Name, data: Data) {
const schema = z
.object({
name: z.literal(name),
data,
})
.meta({
ref: name,
})
const result = class extends NamedError {
public static readonly Schema = schema
public readonly name = name as Name
constructor(
public readonly data: z.input<Data>,
options?: ErrorOptions,
) {
super(name, options)
this.name = name
}
static isInstance(input: any): input is InstanceType<typeof result> {
return "name" in input && input.name === name
}
schema() {
return schema
}
toObject() {
return {
name: name,
data: this.data,
}
}
}
Object.defineProperty(result, "name", { value: name })
return result
}
Accepts two parameters:
-
name
-
data
result
is assigned a class as shown below:
const result = class extends NamedError {
Defines readonly variables
public static readonly Schema = schema
public readonly name = name as Name
constructor is initialized:
constructor(
public readonly data: z.input<Data>,
options?: ErrorOptions,
) {
super(name, options)
this.name = name
}
and has the below methods defined within result object
static isInstance(input: any): input is InstanceType<typeof result> {
return "name" in input && input.name === name
}
schema() {
return schema
}
toObject() {
return {
name: name,
data: this.data,
}
}
Finally result is returned by this NamedError.create method:
Object.defineProperty(result, "name", { value: name })
return result
NamedError.create example
In sst/opencode/packages/opencode/src/lsp/client.ts at L20, you will find the below code:
import { NamedError } from "../util/error"
...
export namespace LSPClient {
const log = Log.create({ service: "lsp.client" })
...
export const InitializeError = NamedError.create(
"LSPInitializeError",
z.object({
serverID: z.string(),
}),
)
About me:
Hey, my name is Ramu Narasinga. I study codebase architecture in large open-source projects.
Email: ramu.narasinga@gmail.com
Want to learn from open-source? Solve challenges inspired by open-source projects.
References:
-
https://github.com/sst/opencode/blob/dev/packages/opencode/src/util/error.ts#L6
-
https://github.com/sst/opencode/blob/dev/packages/opencode/src/lsp/client.ts#L20