UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

105 lines • 6.61 kB
import { z, type ZodObject, type ZodRawShape } from 'zod'; import { type FieldNormalizer } from '../utils/normalize.ts'; export { z }; export declare const REDACTED_SECRET: "<REDACTED>"; export declare function secretStr(): SecretSchema<z.ZodString>; export declare function secretSchema<T extends z.ZodType>(schema: T): SecretSchema<T>; /** * The python spellings a config schema takes, registered beside the schema * (`z.object({...}).register(FIELD_NORMALIZERS, { rename: {...} })`) the way * a pydantic field carries its alias, so every caller of * {@link parseConfigWithSchema} renames the same keys. */ export declare const FIELD_NORMALIZERS: z.core.$ZodRegistry<FieldNormalizer, z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>; /** * The one loader a mount config comes through: rename the python-side * spellings, then validate. * * Every registry entry calls this with its backend's schema, so a config * that reaches a VFS has been checked the way pydantic checks the python * twin on construction. It used to be `normalizeFields` alone in 56 of 60 * normalizers, which let `bucket: 123`, `timeout: "abc"` and a Google * config naming no credential at all reach their clients unrefused, and * left every requiredness rule in these schemas unreachable from the mount * path -- `GitHubConfigSchema` required `owner` and nothing ever asked it. * The renames come from the schema's {@link FIELD_NORMALIZERS} entry. * * Unknown keys are refused, as every python config refuses them with * `extra="forbid"`: they used to be stripped, so a typo'd `team_idz` built * a mount that exposed every team, with no error on either side. The check * runs on the input before the renames, so a snake_case spelling of a * declared field is known and an unknown key is named as the block wrote * it. A callable a config carries (a token provider, a refresh hook) must * be declared in the schema through `secretSchema(z.custom(...))` or it is * an unknown key too -- the declaration is also what keeps it out of * snapshot state. */ export declare function parseConfigWithSchema<T extends ZodRawShape>(schema: ZodObject<T>, input: Record<string, unknown>): ConfigOf<ZodObject<T>>; /** * Refuse the keys of a config block that no field takes. * * Each key is looked up under the name the normalizer writes it to, and an * unknown one is reported in the block's own spelling, one * `unrecognized_keys` issue per key: the summary then reads * `<vfs>: team_idz: unrecognized_keys` where python's reads * `<vfs>: team_idz: extra_forbidden`, the same field named the same way. * Exported for the backends that take their options without a schema * (`ram`, `disk`, `redis`, `opfs`), which python builds from constructor * keywords and refuses the same way. */ export declare function refuseUnknownKeys(input: Record<string, unknown>, fields: Iterable<string>, normalizer?: FieldNormalizer): void; /** * Refuse a config block that names one field under two spellings. * * `normalizeFields` writes `key_prefix` and `keyPrefix` to the same key, * so without this the later one would win by object order. Python's * models take only the snake_case spelling and refuse the camelCase one * as an extra field, so each clash is reported the way * `refuseUnknownKeys` reports a key: an `unrecognized_keys` issue naming * the camelCase spelling, whose summary then reads as python's * `keyPrefix: extra_forbidden` does. */ export declare function refuseRepeatedFields(input: Record<string, unknown>): void; /** A string field trimmed, refused when nothing is left. */ export declare function normalizeNonEmpty(value: string, field: string): string; export declare function redactConfigWithSchema<S extends ZodObject>(schema: S, config: unknown): RedactedSchema<S>; export declare function hasRedactedSecret(value: unknown): boolean; /** * Whether restoring this mount needs a live VFS handed in. * * A redaction marker says the saved config is missing a credential. The * explicit `needs_override` says the mount cannot be rebuilt from its * state at all — which in TypeScript is true of every config-backed * backend, because `buildMountArgs` substitutes a `RAMVFS` for any * mount it was not given (`snapshot/state.ts`). Python instead * reconstructs the class from `vfs_state["type"]` via its registry * (`_vfs_class_for`), so the field is inert there and only four of * its VFS classes bother to write it; TypeScript has to read it or a live * database mount comes back as an empty directory. * * The lasting fix is to give `buildMountArgs` a VFS factory, which * core cannot import today (`buildVfs` lives in node/browser). */ export declare function vfsStateRequiresOverride(state: unknown): boolean; declare const SECRET_SCHEMA: unique symbol; /** A schema whose value is secret; this marker changes no input type. */ export type SecretSchema<S extends z.ZodType> = S & { readonly [SECRET_SCHEMA]: true; }; type Unwrapped<S extends z.ZodType> = S extends SecretSchema<z.ZodType> ? S : S extends z.ZodOptional<infer I> | z.ZodNullable<infer I> | z.ZodDefault<infer I> | z.ZodPrefault<infer I> | z.ZodNonOptional<infer I> | z.ZodReadonly<infer I> ? I extends z.ZodType ? Unwrapped<I> : S : S; type SecretValue<S extends z.ZodType> = Unwrapped<S> extends SecretSchema<z.ZodType> ? true : Unwrapped<S> extends z.ZodRecord<z.core.$ZodRecordKey, infer V> ? V extends z.ZodType ? SecretValue<V> : false : false; type RedactedValue<S extends z.ZodType, T> = SecretValue<S> extends true ? typeof REDACTED_SECRET | Extract<T, null | undefined> : Unwrapped<S> extends z.ZodObject<infer Shape> ? RedactedFields<T, Shape> : Unwrapped<S> extends z.ZodArray<infer Item> ? Item extends z.ZodType ? T extends (infer V)[] ? RedactedValue<Item, V>[] : T extends readonly (infer V)[] ? readonly RedactedValue<Item, V>[] : T : T : T; type RedactedFields<T, Shape extends z.ZodRawShape> = { [K in keyof T]: Exclude<K extends keyof Shape ? Shape[K] extends z.ZodType ? RedactedValue<Shape[K], T[K]> : T[K] : T[K], undefined>; }; /** Snapshot fields inferred from the same schema that redacts them at runtime. */ export type RedactedSchema<S extends z.ZodObject, C = ConfigOf<S>> = RedactedFields<C, S['shape']>; /** Schema output with absent optional fields, matching exactOptionalPropertyTypes. */ export type ConfigOf<S extends z.ZodType> = { [K in keyof z.infer<S>]: Exclude<z.infer<S>[K], undefined>; }; export type SchemaType = z.core.SomeType; export interface SchemaDef { innerType?: SchemaType; } //# sourceMappingURL=secrets.d.ts.map