fix(config): preserve permission order with Effect decode (#24308)
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
export * as ConfigPermission from "./permission"
|
||||
import { Schema, SchemaGetter } from "effect"
|
||||
import z from "zod"
|
||||
import { ZodOverride, zod } from "@/util/effect-zod"
|
||||
import { zod } from "@/util/effect-zod"
|
||||
import { withStatics } from "@/util/schema"
|
||||
|
||||
export const Action = Schema.Literals(["ask", "allow", "deny"])
|
||||
@@ -20,8 +19,8 @@ export const Rule = Schema.Union([Action, Object])
|
||||
export type Rule = Schema.Schema.Type<typeof Rule>
|
||||
|
||||
// Known permission keys get explicit types in the Effect schema for generated
|
||||
// docs/types. Runtime config parsing uses `InfoZod` below so user key order is
|
||||
// preserved for permission precedence.
|
||||
// docs/types. Runtime config parsing uses Effect's `propertyOrder: "original"`
|
||||
// parse option so user key order is preserved for permission precedence.
|
||||
const InputObject = Schema.StructWithRest(
|
||||
Schema.Struct({
|
||||
read: Schema.optional(Rule),
|
||||
@@ -53,35 +52,6 @@ const InputSchema = Schema.Union([Action, InputObject])
|
||||
const normalizeInput = (input: Schema.Schema.Type<typeof InputSchema>): Schema.Schema.Type<typeof InputObject> =>
|
||||
typeof input === "string" ? { "*": input } : input
|
||||
|
||||
const InfoZod = z
|
||||
.union([
|
||||
zod(Action),
|
||||
z.intersection(
|
||||
z.record(z.string(), zod(Rule)),
|
||||
z
|
||||
.object({
|
||||
read: zod(Rule).optional(),
|
||||
edit: zod(Rule).optional(),
|
||||
glob: zod(Rule).optional(),
|
||||
grep: zod(Rule).optional(),
|
||||
list: zod(Rule).optional(),
|
||||
bash: zod(Rule).optional(),
|
||||
task: zod(Rule).optional(),
|
||||
external_directory: zod(Rule).optional(),
|
||||
todowrite: zod(Action).optional(),
|
||||
question: zod(Action).optional(),
|
||||
webfetch: zod(Action).optional(),
|
||||
websearch: zod(Action).optional(),
|
||||
codesearch: zod(Action).optional(),
|
||||
lsp: zod(Rule).optional(),
|
||||
doom_loop: zod(Action).optional(),
|
||||
skill: zod(Rule).optional(),
|
||||
})
|
||||
.catchall(zod(Rule)),
|
||||
),
|
||||
])
|
||||
.transform(normalizeInput)
|
||||
|
||||
export const Info = InputSchema.pipe(
|
||||
Schema.decodeTo(InputObject, {
|
||||
decode: SchemaGetter.transform(normalizeInput),
|
||||
@@ -92,7 +62,6 @@ export const Info = InputSchema.pipe(
|
||||
}),
|
||||
)
|
||||
.annotate({ identifier: "PermissionConfig" })
|
||||
.annotate({ [ZodOverride]: InfoZod })
|
||||
.pipe(
|
||||
// Walker already emits the decodeTo transform into the derived zod (see
|
||||
// `encoded()` in effect-zod.ts), so just expose that directly.
|
||||
|
||||
Reference in New Issue
Block a user