Hyperlinkv0.8.0-beta.28

Schema

Schema.Redactedfunctioneffect/Schema.ts:8930
Redacted<S>

Schema for values that hide sensitive information from error output and inspection.

Details

If the wrapped schema fails, the issue will be redacted to prevent both the actual value and the schema details from being exposed.

Options:

  • label: When provided, the schema will behave as follows:
    • Values will be validated against the label in addition to the wrapped schema
    • The default JSON serializer will deserialize into a Redacted instance with the label
    • The arbitrary generator will produce a Redacted instance with the label
    • The formatter will return the label
  • disallowJsonEncode: When set to true, when attempting to encode a Redacted instance into JSON, it will fail with an error. This is useful when the wrapped schema is sensitive and should not be exposed in JSON.
Source effect/Schema.ts:8930105 lines
export interface Redacted<S extends Constraint> extends
  declareConstructor<
    Redacted_.Redacted<S["Type"]>,
    Redacted_.Redacted<S["Encoded"]>,
    readonly [S]
  >
{
  readonly "Rebuild": Redacted<S>
  readonly value: S
}

/**
 * Schema for values that hide sensitive information from error output and
 * inspection.
 *
 * **Details**
 *
 * If the wrapped schema fails, the issue will be redacted to prevent both
 * the actual value and the schema details from being exposed.
 *
 * Options:
 *
 * - `label`: When provided, the schema will behave as follows:
 *   - Values will be validated against the label in addition to the wrapped schema
 *   - The default JSON serializer will deserialize into a `Redacted` instance with the label
 *   - The arbitrary generator will produce a `Redacted` instance with the label
 *   - The formatter will return the label
 * - `disallowJsonEncode`: When set to `true`, when attempting to encode a `Redacted` instance
 *   into JSON, it will fail with an error. This is useful when the wrapped schema is
 *   sensitive and should not be exposed in JSON.
 *
 * @see {@link RedactedFromValue} for decoding raw values and wrapping them in `Redacted`.
 * @category Redacted
 * @since 3.10.0
 */
export function Redacted<S extends Constraint>(value: S, options?: {
  readonly label?: string | undefined
  readonly disallowJsonEncode?: boolean | undefined
}): Redacted<S> {
  const decodeLabel = typeof options?.label === "string"
    ? SchemaParser.decodeUnknownEffect(Literal(options.label))
    : undefined
  const schema = declareConstructor<Redacted_.Redacted<S["Type"]>, Redacted_.Redacted<S["Encoded"]>>()(
    [value],
    ([value]) => (input, ast, poptions) => {
      if (Redacted_.isRedacted(input)) {
        const label: Effect.Effect<void, SchemaIssue.Issue, never> = decodeLabel !== undefined
          ? Effect.mapErrorEager(
            decodeLabel(input.label, poptions),
            (issue) => new SchemaIssue.Pointer(["label"], issue)
          )
          : Effect.void
        return Effect.flatMapEager(
          label,
          () =>
            Effect.mapBothEager(
              SchemaParser.decodeUnknownEffect(value)(Redacted_.value(input), poptions),
              {
                onSuccess: () => input,
                onFailure: (/** ignore the actual issue because of security reasons */) => {
                  const oinput = Option_.some(input)
                  return new SchemaIssue.Composite(ast, oinput, [
                    new SchemaIssue.Pointer(["value"], new SchemaIssue.InvalidValue(oinput))
                  ])
                }
              }
            )
        )
      }
      return Effect.fail(new SchemaIssue.InvalidType(ast, Option_.some(input)))
    },
    {
      typeConstructor: {
        _tag: "effect/Redacted",
        options
      },
      generation: {
        runtime: options !== undefined ? `Schema.Redacted(?, ${format(options)})` : `Schema.Redacted(?)`,
        Type: `Redacted.Redacted<?>`,
        importDeclaration: `import * as Redacted from "effect/Redacted"`
      },
      expected: "Redacted",
      toCodecJson: ([value]) =>
        link<Redacted_.Redacted<S["Encoded"]>>()(
          redact(value),
          {
            decode: SchemaGetter.transform((e) => Redacted_.make(e, { label: options?.label })),
            encode: options?.disallowJsonEncode ?
              SchemaGetter.forbidden((oe) =>
                "Cannot serialize Redacted" +
                (Option_.isSome(oe) && typeof oe.value.label === "string" ? ` with label: "${oe.value.label}"` : "")
              ) :
              SchemaGetter.transform(Redacted_.value)
          }
        ),
      toArbitrary: ([value]) => () => ({
        arbitrary: value.arbitrary.map((a) => Redacted_.make(a, { label: options?.label })),
        terminal: value.terminal?.map((a) => Redacted_.make(a, { label: options?.label }))
      }),
      toFormatter: () => globalThis.String,
      toEquivalence: ([value]) => Redacted_.makeEquivalence(value)
    }
  )
  return make(schema.ast, { value })
}
Referenced by 3 symbols