doba

Context

Migration context and metadata types

Every migration function receives a TransformContext as its second argument. This context allows you to interact with the migration process beyond just returning a value.

TransformContext

type TransformContext<
  Keys extends string = string,
  From extends Keys = Keys,
  To extends Keys = Keys,
> = {
  readonly warn: (message: string) => void
  readonly defaulted: (path: readonly PropertyKey[], message: string) => void
  readonly from: From
  readonly to: To
}

The From and To generics are inferred from the migration key (e.g. 'v1->v2' gives From = 'v1', To = 'v2'), so ctx.from and ctx.to are narrowed to literal string types.

warn()

Emits a warning that gets collected in result.meta.warnings. Also triggers the onWarning hook if configured.

'v1->v2': (data, ctx) => {
  if (!data.email) {
    ctx.warn('User has no email, using empty string')
  }
  return { ...data, email: data.email || '' }
}

defaulted()

Records that a field was filled with a default value. Takes a property path and a message. Also triggers the onWarning hook with a formatted message ("defaulted <path>: <message>").

ctx.defaulted(['settings', 'theme'], 'Theme not found, defaulting to "light"')
ctx.defaulted(['address', 'zip'], 'ZIP code not in source, using 00000')

from / to

The schema keys for the current migration step:

'a->b': (value, ctx) => {
  console.log(ctx.from) // "a"
  console.log(ctx.to)   // "b"
  return { /* ... */ }
}

Result metadata types

Warnings and defaults are collected on the transform result. Both types carry two generic parameters for the from and to schema keys. When accessed through result.meta, these are narrowed via NarrowExclude so that from and to exclude the endpoints of the overall transform.

WarningInfo

type WarningInfo<FromKey extends string = string, ToKey extends string = FromKey> = {
  readonly message: string
  readonly from: FromKey
  readonly to: ToKey
}
FieldTypeDescription
messagestringThe warning text passed to ctx.warn().
fromFromKeySchema key the warning was emitted from.
toToKeySchema key the warning was emitted to.

DefaultedInfo

type DefaultedInfo<FromKey extends string = string, ToKey extends string = FromKey> = {
  readonly path: readonly PropertyKey[]
  readonly message: string
  readonly from: FromKey
  readonly to: ToKey
}
FieldTypeDescription
pathreadonly PropertyKey[]Property path to the defaulted field, e.g. ['address', 'zip'].
messagestringDescription of what was defaulted.
fromFromKeySchema key the default was recorded from.
toToKeySchema key the default was recorded to.

Accessing metadata

const result = await registry.transform(data, 'legacy', 'current')

if (result.ok) {
  for (const warning of result.meta.warnings) {
    console.log(`[${warning.from}->${warning.to}] ${warning.message}`)
  }

  for (const d of result.meta.defaults) {
    console.log(`Defaulted ${d.path.join('.')}: ${d.message}`)
  }
}

On this page