effx
API reference@effx/compilerdiagnostics

lift

API reference for @effx/compiler/diagnostics/lift

lift.ts overview


Exports Grouped by Category


utils

LiftDiagnostics

Typed factories; occurrence locations and related diagnostics remain caller-owned.

Signature

declare const LiftDiagnostics: {
  EFFX3001: Definition<
    {
      readonly code: "EFFX3001"
      readonly owner: "lift"
      readonly title: "Unsupported Effect construct"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "Lift reads only the exact declaration grammar of the spec: literal keys, paths and option objects; registered application wrappers; registered metadata calls with literal arguments; registered annotation keys. A computed key, path or option object, a spread, an unknown endpoint step, an unknown pipe step, an unregistered annotation key, a form-encoded inline payload, a group prefix, group middleware or group addError, and a registered metadata call with a non-literal argument are all reported with the construct named. The endpoint is omitted from every suggestion: lift never guesses and never evaluates source."
      readonly examples: readonly [
        {
          readonly before: 'HttpApiEndpoint.get("list", "/items", { success: ItemsResponse }).setHeaders(CustomHeaders)'
          readonly after: 'HttpApiEndpoint.get("list", "/items", { success: ItemsResponse })'
          readonly explanation: "Remove the unsupported step or move the behavior into a registered wrapper; lift reports the construct instead of dropping it."
        }
      ]
    },
    Schema.TaggedUnion<{
      readonly ComputedKey: Schema.TaggedStruct<
        "ComputedKey",
        { readonly subject: Schema.String; readonly construct: Schema.String }
      >
      readonly Spread: Schema.TaggedStruct<
        "Spread",
        { readonly subject: Schema.String; readonly construct: Schema.String }
      >
      readonly UnknownStep: Schema.TaggedStruct<
        "UnknownStep",
        { readonly subject: Schema.String; readonly step: Schema.String }
      >
      readonly UnknownPipeStep: Schema.TaggedStruct<
        "UnknownPipeStep",
        { readonly subject: Schema.String; readonly construct: Schema.String }
      >
      readonly UnknownAnnotationKey: Schema.TaggedStruct<
        "UnknownAnnotationKey",
        { readonly subject: Schema.String; readonly key: Schema.String }
      >
      readonly FormEncodedPayload: Schema.TaggedStruct<"FormEncodedPayload", { readonly subject: Schema.String }>
      readonly GroupConstruct: Schema.TaggedStruct<
        "GroupConstruct",
        { readonly subject: Schema.String; readonly construct: Schema.String }
      >
      readonly NonLiteralArgument: Schema.TaggedStruct<
        "NonLiteralArgument",
        { readonly subject: Schema.String; readonly callee: Schema.String; readonly argument: Schema.String }
      >
      readonly UnsupportedOption: Schema.TaggedStruct<
        "UnsupportedOption",
        { readonly subject: Schema.String; readonly callee: Schema.String; readonly option: Schema.String }
      >
      readonly UnrecognizedConstruct: Schema.TaggedStruct<
        "UnrecognizedConstruct",
        { readonly subject: Schema.String; readonly construct: Schema.String }
      >
    }>
  >
  EFFX3002: Definition<
    {
      readonly code: "EFFX3002"
      readonly owner: "lift"
      readonly title: "Channel schema must be an exported named schema"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "A request channel or the success of an endpoint is written as inline fields, as the bare fields of another schema, or as an inline Schema expression, so it has no exported name. An effx declaration references schemas by exported name, so lift suggests a wire-preserving refactor that exports a named schema and points the channel at it. The diagnostic carries the source edits; it blocks --check unless the overlay applies it."
      readonly examples: readonly [
        {
          readonly before: "query: ScopeQuery.fields"
          readonly after: "export const ScopeQuerySchema = Schema.Struct(ScopeQuery.fields);\n// query: ScopeQuerySchema"
          readonly explanation: "The bare fields are not the schema itself, because the named schema carries an identifier annotation that would add an OpenAPI component."
        }
      ]
    },
    Schema.Struct<{
      readonly subject: Schema.String
      readonly channel: Schema.Literals<readonly ["params", "query", "headers", "payload", "success"]>
      readonly form: Schema.Literals<readonly ["inline-fields", "fields-access", "schema-call"]>
      readonly planned: Schema.String
    }>
  >
  EFFX3003: Definition<
    {
      readonly code: "EFFX3003"
      readonly owner: "lift"
      readonly title: "Response header schema must be an exported named schema"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "A registered success wrapper builds its response headers inline, so no exported schema names them. Lift suggests exporting the header schema from the wrapper's module and making the wrapper use it, a wire-preserving refactor that the overlay check proves. The diagnostic carries the source edits."
      readonly examples: readonly [
        {
          readonly before: "export const privateRead = (success) => HttpApiSchema.WithHeaders(success, { cache: Cache })"
          readonly after: "export const PrivateReadHeaders = Schema.Struct({ cache: Cache });\nexport const privateRead = (success) => HttpApiSchema.WithHeaders(success, PrivateReadHeaders)"
          readonly explanation: "Export the headers once and reference the export from the wrapper."
        }
      ]
    },
    Schema.Struct<{ readonly subject: Schema.String; readonly wrapper: Schema.String; readonly planned: Schema.String }>
  >
  EFFX3004: Definition<
    {
      readonly code: "EFFX3004"
      readonly owner: "lift"
      readonly title: "Problem codes must be an exported const tuple"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "The code list of a problem union is written inline, so the effx declaration would duplicate it. Lift suggests extracting the list into an exported const tuple that both the union and the declaration reference. A list that is not a literal array of string literals cannot be read without evaluating source and is unliftable until it is named."
      readonly examples: readonly [
        {
          readonly before: 'problemUnion("ReadProblem", ["not-found", "forbidden"])'
          readonly after: 'export const ReadProblemCodes = ["not-found", "forbidden"] as const;\nproblemUnion("ReadProblem", ReadProblemCodes)'
          readonly explanation: "One exported tuple is the single source of truth for the codes."
        }
      ]
    },
    Schema.TaggedUnion<{
      readonly ExportCodes: Schema.TaggedStruct<
        "ExportCodes",
        { readonly subject: Schema.String; readonly union: Schema.String; readonly planned: Schema.String }
      >
      readonly NonLiteralCodes: Schema.TaggedStruct<
        "NonLiteralCodes",
        { readonly subject: Schema.String; readonly union: Schema.String }
      >
    }>
  >
  EFFX3005: Definition<
    {
      readonly code: "EFFX3005"
      readonly owner: "lift"
      readonly title: "Access annotation is not a registered builder call with literal arguments"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "Access is lifted only from a registered access builder called with literal arguments. A local closure, a named constant, a spread or a non-literal builder argument would require partial evaluation, which lift never performs. The endpoint is omitted from every suggestion."
      readonly examples: readonly [
        {
          readonly before: ".pipe((endpoint) => annotateAccessSpec(endpoint, access(true)))"
          readonly after: '.pipe((endpoint) => annotateAccessSpec(endpoint, personNativeAccess({ capability: "profile.read-self", canonicalScopeResolver: "profile.current-person", decisionTime: "SnapshotRead" })))'
          readonly explanation: "Write the access with a registered builder and literal arguments."
        }
      ]
    },
    Schema.Struct<{
      readonly subject: Schema.String
      readonly form: Schema.Literals<readonly ["closure", "constant", "spread", "non-literal-argument"]>
      readonly builder: Schema.optionalKey<Schema.String>
    }>
  >
  EFFX3006: Definition<
    {
      readonly code: "EFFX3006"
      readonly owner: "lift"
      readonly title: "No lifter rule for callee"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "An application helper is used as a success wrapper, metadata, access or problem helper, but no lifter rule registers it. Rules are data supplied through the definition-owned lift hook; lift never guesses a helper's meaning and never unfolds its body as authority."
      readonly examples: readonly [
        {
          readonly before: "success: customResponse(UserResponse)"
          readonly after: "// register customResponse as a SuccessWrapper rule, or write the schema directly\nsuccess: UserResponse"
          readonly explanation: "Register the helper with a lift rule so lift can map it."
        }
      ]
    },
    Schema.Struct<{
      readonly subject: Schema.String
      readonly position: Schema.Literals<readonly ["success", "metadata", "access", "problems"]>
      readonly callee: Schema.String
    }>
  >
  EFFX3007: Definition<
    {
      readonly code: "EFFX3007"
      readonly owner: "lift"
      readonly title: "Success has no schema"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "The success of the endpoint is a document body of a runtime content type, or another construct with no Schema. effx declares a success only by a schema, so the endpoint is not liftable. A body-less success such as HttpApiSchema.NoContent is liftable and does not produce this diagnostic."
      readonly examples: readonly [
        {
          readonly before: 'success: documentMutationResponse("application/pdf")'
          readonly after: "success: ReceiptResponse"
          readonly explanation: "Declare the response with a schema, or keep the endpoint as handwritten Effect."
        }
      ]
    },
    Schema.Struct<{ readonly subject: Schema.String; readonly construct: Schema.String }>
  >
  EFFX3008: Definition<
    {
      readonly code: "EFFX3008"
      readonly owner: "lift"
      readonly title: "Group not found, or not in exactly one root"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "The requested group id matches no HttpApiGroup.make declaration, or the group is not added to exactly one HttpApi root. The root is the unique HttpApi.make value whose .add contains the group; zero or several roots cannot select a unique root identity."
      readonly examples: readonly [
        {
          readonly before: "effx lift --group profile  // the group is added to two roots"
          readonly after: "effx lift --group profile  // the group is added to one root"
          readonly explanation: "Add the group to exactly one root declaration."
        }
      ]
    },
    Schema.TaggedUnion<{
      readonly NotFound: Schema.TaggedStruct<"NotFound", { readonly group: Schema.String }>
      readonly AmbiguousGroup: Schema.TaggedStruct<
        "AmbiguousGroup",
        { readonly group: Schema.String; readonly declarations: Schema.$Array<Schema.String> }
      >
      readonly NoRoot: Schema.TaggedStruct<"NoRoot", { readonly group: Schema.String }>
      readonly AmbiguousRoots: Schema.TaggedStruct<
        "AmbiguousRoots",
        { readonly group: Schema.String; readonly roots: Schema.$Array<Schema.String> }
      >
    }>
  >
  EFFX3009: Definition<
    {
      readonly code: "EFFX3009"
      readonly owner: "lift"
      readonly title: "No request channel to serve as operation input"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "An effx operation requires a fully resolved input. The endpoint declares no params, query, headers or payload schema, and no emptyInput schema is configured, so lift cannot choose an input without inventing one. Configure a real exported emptyInput schema."
      readonly examples: readonly [
        {
          readonly before: 'HttpApiEndpoint.get("health", "/health", { success: Health })'
          readonly after: "// configure emptyInput: an exported Schema for no input"
          readonly explanation: "Name a real exported schema as the lifter's emptyInput."
        }
      ]
    },
    Schema.Struct<{ readonly subject: Schema.String }>
  >
  EFFX3010: Definition<
    {
      readonly code: "EFFX3010"
      readonly owner: "lift"
      readonly title: "Lift decision requires review"
      readonly severity: "warning"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "The effx IR contains facts with no Effect twin: the operation kind, the operation input and the real names of new exports. They cannot be validated by comparing wire contracts, so lift prints them as decisions to review and never reports them as verified."
      readonly examples: readonly [
        {
          readonly before: "POST /search  // lifted as a Command"
          readonly after: "// review: the read-only POST may be a Query with payloadIsQuery"
          readonly explanation: "Review each decision before accepting the suggestion."
        }
      ]
    },
    Schema.Struct<{
      readonly subject: Schema.String
      readonly decision: Schema.Literals<readonly ["kind", "input", "export"]>
      readonly value: Schema.String
    }>
  >
  EFFX3011: Definition<
    {
      readonly code: "EFFX3011"
      readonly owner: "lift"
      readonly title: "Annotation lift could not run"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "A registered annotation definition's compiler lift failed at one `.annotate` site: the definition-owned recognizer rejected the site, threw, returned a non-Result value, produced arguments that do not satisfy the definition's own lowered-args schema, or named a reference the analyzed project does not record. The diagnostic carries a closed reason and, where the recognizer's own schema-defined failure named one, the construct text; it never carries the thrown value, a message, a cause or argument payload. The site is blocked: no annotation, refactor or code plan is produced for it, and no fallback recognition runs after the hook claimed the key."
      readonly examples: readonly [
        {
          readonly before: ".annotate(RateLimit.effect.key, { perMinute: -1 })"
          readonly after: ".annotate(RateLimit.effect.key, { perMinute: 60 })"
          readonly explanation: "The recognizer returned its own Unsupported construct; lift blocks the site with the reason named instead of guessing."
        }
      ]
    },
    Schema.Struct<{
      readonly subject: Schema.String
      readonly reason: Schema.Literals<
        readonly [
          "hook-failed",
          "hook-threw",
          "hook-arity",
          "invalid-return",
          "encode-failed",
          "decode-failed",
          "unresolved-ref"
        ]
      >
      readonly construct: Schema.optionalKey<Schema.String>
      readonly issue: Schema.optionalKey<Schema.String>
    }>
  >
  EFFX3012: Definition<
    {
      readonly code: "EFFX3012"
      readonly owner: "lift"
      readonly title: "Effect key is not statically resolvable"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "An `.annotate` effect key is not a statically resolvable registered definition key: the source names a key-shaped reference (a `.key` or `.effect.key` chain, or a definition whose recorded key id differs from the runtime definition's own key id) and the analyzed source provides no literal key identity for it. Lift never evaluates application code, so such a key cannot become an annotation. It is distinct from EFFX3001 (a registered key that no selected definition claims, reported as today) and does not reuse the two-owners EFFX1304 entry or the check-only EFFX3103."
      readonly examples: readonly [
        {
          readonly before: ".annotate(keyOfSomeService.id, { perMinute: 60 })"
          readonly after: ".annotate(RateLimit.effect.key, { perMinute: 60 })"
          readonly explanation: "Write the Context key of a registered definition's effect clause through its literal key identity; lift never evaluates a key supplier."
        }
      ]
    },
    Schema.Struct<{ readonly subject: Schema.String; readonly construct: Schema.String }>
  >
  EFFX3101: Definition<
    {
      readonly code: "EFFX3101"
      readonly owner: "lift"
      readonly title: "Wire contracts differ"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "The check built the Reflection of the untouched original group and of the generated group and found a difference outside the closed set of tolerated deltas. The difference is the payload of the report."
      readonly examples: readonly [
        {
          readonly before: "original summary: Read own profile"
          readonly after: "generated summary: Read my profile"
          readonly explanation: "Any difference in a wire-visible field fails the check."
        }
      ]
    },
    Schema.Struct<{ readonly group: Schema.String; readonly difference: Schema.String }>
  >
  EFFX3102: Definition<
    {
      readonly code: "EFFX3102"
      readonly owner: "lift"
      readonly title: "Check passed"
      readonly severity: "info"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "The Reflections of the original and the generated group are equal after the closed set of delta normalizers. The applied delta classes are listed."
      readonly examples: readonly [
        {
          readonly before: "effx lift --check --group profile"
          readonly after: "PASS(ref-suffix)"
          readonly explanation: "The only tolerated differences were the named deltas."
        }
      ]
    },
    Schema.Struct<{
      readonly group: Schema.String
      readonly applied: Schema.$Array<
        Schema.Literals<readonly ["ref-suffix", "explicit-default-identifier", "endpoint-order"]>
      >
    }>
  >
  EFFX3103: Definition<
    {
      readonly code: "EFFX3103"
      readonly owner: "lift"
      readonly title: "Check could not run"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "The overlay does not compile, a root cannot be built, or a registered projection hook threw. Lift stays total: a check-time exception becomes this diagnostic and never an exit by exception. It is not a pass. The definition-owned output-recognizer exceptions of the compiler lift are EFFX3011, not this entry: the 0019 check and the recognition paths report through separate closed reasons."
      readonly examples: readonly [
        {
          readonly before: "effx lift --check  // the overlay has a type error"
          readonly after: "effx lift --check  // the overlay compiles"
          readonly explanation: "Fix the overlay or the hook, then run the check again."
        }
      ]
    },
    Schema.Struct<{
      readonly reason: Schema.Literals<readonly ["overlay-compile", "root-build", "projection-hook"]>
      readonly detail: Schema.String
    }>
  >
  EFFX3201: Definition<
    {
      readonly code: "EFFX3201"
      readonly owner: "lift"
      readonly title: "Binding keys differ from the group's endpoint keys"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "The handler keys registered by the application's HttpApiBuilder.group call are not exactly the endpoint keys of the group. The key sets are compared statically without executing source."
      readonly examples: readonly [
        {
          readonly before: 'h.handleRaw("read", fn)  // the group also declares update'
          readonly after: 'h.handleRaw("read", fn).handleRaw("update", fn)'
          readonly explanation: "Register exactly the group's endpoint keys."
        }
      ]
    },
    Schema.Struct<{
      readonly group: Schema.String
      readonly missing: Schema.$Array<Schema.String>
      readonly extra: Schema.$Array<Schema.String>
    }>
  >
  EFFX3202: Definition<
    {
      readonly code: "EFFX3202"
      readonly owner: "lift"
      readonly title: "Binding needs hand adaptation"
      readonly severity: "error"
      readonly severityPolicy: { readonly kind: "fixed" }
      readonly explanation: "A handler calls the application's authorization function directly, decodes the payload itself, or registers with .handle instead of .handleRaw. Moving an authorization call behind the lazy authorize callback cannot be mechanical. Lift lists each site and never invents handler code."
      readonly examples: readonly [
        {
          readonly before: "yield* authorize(request)  // inside the handler"
          readonly after: "(input, authorize) => ... // lazy authorize callback"
          readonly explanation: "Adapt the site by hand; the binding report stays unverified until then."
        }
      ]
    },
    Schema.Struct<{
      readonly subject: Schema.String
      readonly site: Schema.Literals<readonly ["authorize", "payload-decode", "handle"]>
    }>
  >
}

liftEntries

Declaration list retained before indexing so composition can detect duplicates.

Signature

declare const liftEntries: ReadonlyArray<{
  readonly code: string
  readonly owner: string
  readonly title: string
  readonly severity: "error" | "warning" | "info"
  readonly severityPolicy:
    | { readonly kind: "fixed" }
    | {
        readonly kind: "named"
        readonly name: string
        readonly description: string
        readonly allowedSeverities: readonly ["error" | "warning" | "info", ...("error" | "warning" | "info")[]]
      }
  readonly explanation: string
  readonly examples: readonly [
    {
      readonly before: string
      readonly after: string
      readonly explanation: string
      readonly language?: string | undefined
    },
    ...{
      readonly before: string
      readonly after: string
      readonly explanation: string
      readonly language?: string | undefined
    }[]
  ]
}>

On this page