/** * This module provides helper functions for working with Confluent Schema Registry. * It handles schema registration, serialization, and deserialization of messages * using various schema formats (AVRO, JSON, PROTOBUF). */ import { MutableRegistry } from "@bufbuild/protobuf"; import { IHeaders } from "@confluentinc/kafka-javascript/types/kafkajs.js"; import { Deserializer, SchemaRegistryClient, SerdeType, Serializer, SerializerConfig } from "@confluentinc/schemaregistry"; /** * Where the Schema Registry schema ID rides on the wire. "payload" embeds it as * magic bytes at the front of the serialized payload (the default Confluent * wire format); "header" writes the schema GUID to the __value_schema_id / * __key_schema_id Kafka record header and leaves the payload as bare bytes. */ export type SchemaIdLocation = "payload" | "header"; /** * Supported schema types for Confluent Schema Registry. * AVRO: Apache Avro binary format with schema evolution support * JSON: JSON Schema format with validation * PROTOBUF: Protocol Buffers format with backward compatibility */ export type SchemaType = "AVRO" | "JSON" | "PROTOBUF"; /** * Common options for schema registry operations. * These options control how schemas are registered and used for serialization. */ export interface SchemaRegistryOptions { useSchemaRegistry?: boolean; schemaType?: SchemaType; schema?: string; subject?: string; normalize?: boolean; /** * Fully-qualified Protobuf message type to encode the payload as * (e.g. `com.example.User`). Required when `schemaType` is `PROTOBUF`, * ignored otherwise. */ messageName?: string; schemaIdLocation?: SchemaIdLocation; } /** * Options for message serialization/deserialization. * Includes the message payload and schema registry configuration. */ export type MessageOptions = { message: Buffer | object | string | number | boolean; useSchemaRegistry?: boolean; schemaType?: SchemaType; schema?: string; subject?: string; normalize?: boolean; /** * Fully-qualified Protobuf message type to encode the payload as * (e.g. `com.example.User`). Required when `schemaType` is `PROTOBUF`, * ignored otherwise. */ messageName?: string; schemaIdLocation?: SchemaIdLocation; }; /** * Result of checking if a schema is needed for a message. * Returned only when schema registry is in use, the caller did not supply a * schema, and no schema is registered for the subject yet — that's the one * case the caller must resolve before serialization can proceed. Otherwise * null: schema registry is disabled, or the caller supplied a schema * (register-and-use path), or one is already registered (use-latest path). */ export type SchemaCheckResult = { type: "no-schema"; subject: string; } | null; /** * Creates and returns the appropriate serializer instance based on schema type. * * This is a pure factory: it maps a {@link SchemaType} to its serializer * constructor and forwards the caller-built {@link SerializerConfig}. The * format-specific *decisions* — schema-id vs. use-latest for AVRO/JSON, plus the descriptor registry for PROTOBUF — live * with the callers ({@link serializeMessage}, {@link serializeProtobufMessage}), * which is why the config arrives ready-made. For PROTOBUF the descriptor * registry rides inside the config as its optional `registry` field * (`ProtobufSerializerConfig = SerializerConfig & { registry?: MutableRegistry }`). * * @param schemaType - The type of schema (AVRO, JSON, PROTOBUF) * @param registry - The schema registry client instance * @param serdeType - Whether this is for key or value serialization * @param serializerConfig - The serializer configuration to forward (use-latest, * use-schema-id, the optional `schemaIdLocation` header serializer, and/or the * PROTOBUF descriptor registry) * @returns The appropriate Serializer instance * @throws Error if the schema type is unknown or unsupported */ export declare function getSerializer(schemaType: SchemaType | undefined, registry: SchemaRegistryClient, serdeType: SerdeType, serializerConfig: SerializerConfig): Serializer; /** * Creates and returns the appropriate deserializer instance based on schema type. * The deserializer is configured to handle schema evolution and compatibility. * * @param schemaType - The type of schema (AVRO, JSON, PROTOBUF) * @param registry - The schema registry client instance * @param serdeType - Whether this is for key or value deserialization * @returns The appropriate Deserializer instance * @throws Error if the schema type is unknown or unsupported */ export declare function getDeserializer(schemaType: SchemaType | undefined, registry: SchemaRegistryClient, serdeType: SerdeType): Deserializer; /** * Checks if a schema is needed for the given message options. * This function determines if: * 1. A schema is already registered and should be used * 2. No schema exists and needs to be provided * 3. No schema action is needed * * @param topicName - The Kafka topic name * @param options - The message options including schema, type, and payload * @param serdeType - Whether this is for key or value serialization * @param registry - The schema registry client instance (if used) * @returns An object describing the schema state, or null if no schema action is needed */ export declare function checkSchemaNeeded(topicName: string, options: MessageOptions, serdeType: SerdeType, registry: SchemaRegistryClient | undefined): Promise; /** * Fetches the latest schema string and schema type for a given subject from the schema registry. * Handles 404 errors gracefully by returning null when no schema exists. * * @param registry - The schema registry client instance * @param subject - The subject to look up in the registry * @returns An object with the latest schema string and schema type, or null if not found * @throws Error if there's an unexpected error from the registry */ export declare function getLatestSchemaIfExists(registry: SchemaRegistryClient, subject: string): Promise<{ schema: string; schemaType: SchemaType; } | null>; /** * Fetches the latest registered schema for a subject and asserts it matches the * requested schema type. Without this guard a use-latest produce against a * subject registered with a different format fails deep inside the serializer * with an opaque parse/decode error (e.g. an AvroSerializer trying to parse a * JSON schema string, or the Protobuf path base64-decoding an Avro schema); * surfacing the mismatch here gives the caller an actionable message instead. * * @param registry - The schema registry client instance * @param subject - The resolved Schema Registry subject * @param expected - The schema type the caller asked to produce with * @returns The latest schema string and (matching) schema type * @throws Error if no schema is registered for the subject, or the registered * schema type differs from `expected` */ export declare function getLatestSchemaOfTypeOrThrow(registry: SchemaRegistryClient, subject: string, expected: SchemaType): Promise<{ schema: string; schemaType: SchemaType; }>; /** * Builds a `@bufbuild/protobuf` descriptor registry from raw `.proto` schema text. * * The `@confluentinc/schemaregistry` ProtobufSerializer encodes locally against * a descriptor registry, so we parse the `.proto` text with protobufjs, export * it to a canonical `FileDescriptorSet` (the standard `google.protobuf` wire * format), and read that into a registry. This is the path used when the caller * supplies the schema on a produce. * * @param protoText - The `.proto` schema definition (proto3) * @returns A mutable descriptor registry the serializer can consume * @throws Error if the `.proto` text cannot be parsed */ export declare function protobufRegistryFromProto(protoText: string): MutableRegistry; /** * Builds a descriptor registry from a Protobuf schema as stored in Schema * Registry — a base64-encoded `FileDescriptorProto` (the "serialized" format * this SDK reads/writes). Used on the use-latest produce path, where the schema * was previously registered by the serializer rather than supplied as text. * * @param serializedSchema - base64-encoded `FileDescriptorProto` * @returns A mutable descriptor registry the serializer can consume * @throws Error if the stored schema cannot be decoded */ export declare function protobufRegistryFromSerialized(serializedSchema: string): MutableRegistry; /** * Converts a plain JS payload into a typed `@bufbuild/protobuf` message (carrying * the `$typeName` the ProtobufSerializer requires) using a descriptor registry. * * @param registry - Descriptor registry containing the target message type * @param messageName - Fully-qualified message type name (e.g. `com.example.User`) * @param payload - The payload to encode. Keys may use either the proto field * name (`user_id`) or its auto-generated camelCase JSON name (`userId`): * `fromJson` accepts both and maps them onto the same field. Keys that match * neither are rejected as unknown fields. * @returns The typed protobuf message * @throws Error if `messageName` does not match a message in the registry (the * error lists the available names) */ export declare function protobufMessageFrom(registry: MutableRegistry, messageName: string, payload: object): object; /** * Serializes a message using the provided options and schema registry configuration. * This function: * 1. Registers the schema if provided * 2. Validates the message type * 3. Creates the appropriate serializer * 4. Serializes the message * * @param topicName - The Kafka topic name * @param options - The message options including schema, type, and payload * @param serdeType - Whether this is for key or value serialization * @param registry - The schema registry client instance (if used) * @param recordHeaders - Mutable record-header accumulator. Required for * `schemaIdLocation: "header"`, where the serializer writes the schema-id * header into it; ignored by the payload format and the raw (non-registry) path. * @returns The serialized message as a Buffer or string * @throws Error if serialization fails, schema registration fails, or message type is invalid */ export declare function serializeMessage(topicName: string, options: MessageOptions, serdeType: SerdeType, registry: SchemaRegistryClient | undefined, recordHeaders?: IHeaders): Promise; /** * Deserializes a message using Schema Registry. * This function: * 1. Creates the appropriate deserializer * 2. Deserializes the message using the schema from the registry * * @param topic - The Kafka topic name * @param message - The message buffer to deserialize * @param schemaType - The schema type (AVRO, JSON, PROTOBUF) * @param registry - The schema registry client * @param serdeType - Whether this is key or value * @param headers - Raw record headers. When present, the default dual * deserializer reads a header-located schema ID (__value_schema_id / * __key_schema_id) before falling back to the magic-byte prefix. * @returns The deserialized object * @throws Error if deserialization fails */ export declare function deserializeMessage(topic: string, message: Buffer, schemaType: SchemaType, registry: SchemaRegistryClient, serdeType: SerdeType, headers?: IHeaders): Promise; /** * Decode a header-located schema-id record-header value into its canonical * schema GUID string. The header wire format (written by the serde library's * HeaderSchemaIdSerializer) is MAGIC_BYTE_V1 followed by the 16-byte GUID; the * schema type only governs the Protobuf message-index tail that the GUID read * ignores, so a fixed type is safe here. Returns null when the bytes aren't a * recognizable GUID header (e.g. a payload-format magic-byte-0 buffer, or * garbage), letting the caller fall back to echoing the raw value. */ export declare function decodeSchemaGuidHeader(headerValue: Buffer): string | null; //# sourceMappingURL=schema-registry-helper.d.ts.map