Skip to content

Commit 4fb26f6

Browse files
Apply PR #22327: refactor(file): clean up ripgrep schema decoding
2 parents 64ef77a + c9261db commit 4fb26f6

File tree

2 files changed

+71
-86
lines changed

2 files changed

+71
-86
lines changed

packages/opencode/src/file/ripgrep.ts

Lines changed: 70 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import path from "path"
33
import { Global } from "../global"
44
import fs from "fs/promises"
55
import z from "zod"
6-
import { Effect, Layer, Context, Schema } from "effect"
6+
import { Array as Arr, Effect, Layer, Context, Schema } from "effect"
77
import * as Stream from "effect/Stream"
88
import { ChildProcess } from "effect/unstable/process"
99
import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner"
@@ -20,117 +20,99 @@ import { text } from "node:stream/consumers"
2020

2121
import { ZipReader, BlobReader, BlobWriter } from "@zip.js/zip.js"
2222
import { Log } from "@/util/log"
23+
import { zod } from "@/util/effect-zod"
2324

2425
export namespace Ripgrep {
2526
const log = Log.create({ service: "ripgrep" })
26-
const Stats = z.object({
27-
elapsed: z.object({
28-
secs: z.number(),
29-
nanos: z.number(),
30-
human: z.string(),
27+
const stats = Schema.Struct({
28+
elapsed: Schema.Struct({
29+
secs: Schema.Number,
30+
nanos: Schema.Number,
31+
human: Schema.String,
3132
}),
32-
searches: z.number(),
33-
searches_with_match: z.number(),
34-
bytes_searched: z.number(),
35-
bytes_printed: z.number(),
36-
matched_lines: z.number(),
37-
matches: z.number(),
33+
searches: Schema.Number,
34+
searches_with_match: Schema.Number,
35+
bytes_searched: Schema.Number,
36+
bytes_printed: Schema.Number,
37+
matched_lines: Schema.Number,
38+
matches: Schema.Number,
3839
})
3940

40-
const Begin = z.object({
41-
type: z.literal("begin"),
42-
data: z.object({
43-
path: z.object({
44-
text: z.string(),
41+
const begin = Schema.Struct({
42+
type: Schema.Literal("begin"),
43+
data: Schema.Struct({
44+
path: Schema.Struct({
45+
text: Schema.String,
4546
}),
4647
}),
4748
})
4849

49-
export const Match = z.object({
50-
type: z.literal("match"),
51-
data: z.object({
52-
path: z.object({
53-
text: z.string(),
54-
}),
55-
lines: z.object({
56-
text: z.string(),
57-
}),
58-
line_number: z.number(),
59-
absolute_offset: z.number(),
60-
submatches: z.array(
61-
z.object({
62-
match: z.object({
63-
text: z.string(),
50+
const item = Schema.Struct({
51+
path: Schema.Struct({
52+
text: Schema.String,
53+
}),
54+
lines: Schema.Struct({
55+
text: Schema.String,
56+
}),
57+
line_number: Schema.Number,
58+
absolute_offset: Schema.Number,
59+
submatches: Schema.mutable(
60+
Schema.Array(
61+
Schema.Struct({
62+
match: Schema.Struct({
63+
text: Schema.String,
6464
}),
65-
start: z.number(),
66-
end: z.number(),
65+
start: Schema.Number,
66+
end: Schema.Number,
6767
}),
6868
),
69-
}),
69+
),
7070
})
7171

72-
const End = z.object({
73-
type: z.literal("end"),
74-
data: z.object({
75-
path: z.object({
76-
text: z.string(),
77-
}),
78-
binary_offset: z.number().nullable(),
79-
stats: Stats,
80-
}),
72+
const match = Schema.Struct({
73+
type: Schema.Literal("match"),
74+
data: item,
8175
})
8276

83-
const Summary = z.object({
84-
type: z.literal("summary"),
85-
data: z.object({
86-
elapsed_total: z.object({
87-
human: z.string(),
88-
nanos: z.number(),
89-
secs: z.number(),
77+
const end = Schema.Struct({
78+
type: Schema.Literal("end"),
79+
data: Schema.Struct({
80+
path: Schema.Struct({
81+
text: Schema.String,
9082
}),
91-
stats: Stats,
83+
binary_offset: Schema.NullOr(Schema.Number),
84+
stats,
9285
}),
9386
})
9487

95-
const Result = z.union([Begin, Match, End, Summary])
96-
97-
const Hit = Schema.Struct({
98-
type: Schema.Literal("match"),
88+
const summary = Schema.Struct({
89+
type: Schema.Literal("summary"),
9990
data: Schema.Struct({
100-
path: Schema.Struct({
101-
text: Schema.String,
91+
elapsed_total: Schema.Struct({
92+
human: Schema.String,
93+
nanos: Schema.Number,
94+
secs: Schema.Number,
10295
}),
103-
lines: Schema.Struct({
104-
text: Schema.String,
105-
}),
106-
line_number: Schema.Number,
107-
absolute_offset: Schema.Number,
108-
submatches: Schema.mutable(
109-
Schema.Array(
110-
Schema.Struct({
111-
match: Schema.Struct({
112-
text: Schema.String,
113-
}),
114-
start: Schema.Number,
115-
end: Schema.Number,
116-
}),
117-
),
118-
),
96+
stats,
11997
}),
12098
})
12199

122-
const Row = Schema.Union([
123-
Schema.Struct({ type: Schema.Literal("begin"), data: Schema.Unknown }),
124-
Hit,
125-
Schema.Struct({ type: Schema.Literal("end"), data: Schema.Unknown }),
126-
Schema.Struct({ type: Schema.Literal("summary"), data: Schema.Unknown }),
127-
])
100+
const row = Schema.Union([begin, match, end, summary])
101+
102+
const decode = Schema.decodeUnknownSync(Schema.fromJsonString(row))
128103

129-
const decode = Schema.decodeUnknownEffect(Schema.fromJsonString(Row))
104+
export const Stats = zod(stats)
105+
export const Begin = zod(begin)
106+
export const Item = zod(item)
107+
export const Match = zod(match)
108+
export const End = zod(end)
109+
export const Summary = zod(summary)
110+
export const Result = zod(row)
130111

112+
export type Stats = z.infer<typeof Stats>
131113
export type Result = z.infer<typeof Result>
132114
export type Match = z.infer<typeof Match>
133-
export type Item = Match["data"]
115+
export type Item = z.infer<typeof Item>
134116
export type Begin = z.infer<typeof Begin>
135117
export type End = z.infer<typeof End>
136118
export type Summary = z.infer<typeof Summary>
@@ -428,10 +410,13 @@ export namespace Ripgrep {
428410
Stream.decodeText(handle.stdout).pipe(
429411
Stream.splitLines,
430412
Stream.filter((line) => line.length > 0),
431-
Stream.mapEffect((line) =>
432-
decode(line).pipe(Effect.mapError((cause) => new Error("invalid ripgrep output", { cause }))),
413+
Stream.mapArrayEffect((lines) =>
414+
Effect.try({
415+
try: () => Arr.map(lines, (line) => decode(line)),
416+
catch: (cause) => new Error("invalid ripgrep output", { cause }),
417+
}),
433418
),
434-
Stream.filter((row): row is Schema.Schema.Type<typeof Hit> => row.type === "match"),
419+
Stream.filter((row): row is Schema.Schema.Type<typeof match> => row.type === "match"),
435420
Stream.map((row): Item => row.data),
436421
Stream.runCollect,
437422
Effect.map((chunk) => [...chunk]),

packages/opencode/src/server/instance/file.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const FileRoutes = lazy(() =>
2222
description: "Matches",
2323
content: {
2424
"application/json": {
25-
schema: resolver(Ripgrep.Match.shape.data.array()),
25+
schema: resolver(Ripgrep.Item.array()),
2626
},
2727
},
2828
},

0 commit comments

Comments
 (0)