{"version":3,"file":"index.mjs","sources":["../src/status.ts","../src/client.ts","../src/rate.ts"],"sourcesContent":["import { type CodecType, MessageCodec, OptionalCodec } from \"./codec\";\nimport { Cursor } from \"./common\";\n\n/** The request to the `status` endpoint. */\nexport const StatusRequest = MessageCodec({});\n\nexport type StatusRequest = CodecType<typeof StatusRequest>;\n\n/** The response from the `status` endpoint. */\nexport const StatusResponse = MessageCodec({\n  currentHead: OptionalCodec(Cursor),\n  lastIngested: OptionalCodec(Cursor),\n  finalized: OptionalCodec(Cursor),\n  starting: OptionalCodec(Cursor),\n});\n\nexport type StatusResponse = CodecType<typeof StatusResponse>;\n","import assert from \"node:assert\";\n\nimport consola from \"consola\";\nimport {\n  type ChannelCredentials,\n  type ChannelOptions,\n  type DefaultCallOptions,\n  Metadata,\n  type NormalizedServiceDefinition,\n  createChannel,\n  createClient as grpcCreateClient,\n} from \"nice-grpc\";\n\nimport * as proto from \"./proto\";\n\nimport type { Codec } from \"./codec\";\nimport type { Cursor } from \"./common\";\nimport type { StreamConfig } from \"./config\";\nimport { StatusRequest, StatusResponse } from \"./status\";\nimport { type StreamDataRequest, StreamDataResponse } from \"./stream\";\n\nexport { ClientError, ServerError, Status, Metadata } from \"nice-grpc\";\n\nconst DEFAULT_TIMEOUT_MS = 45_000;\n\nexport class TimeoutError extends Error {\n  constructor(timeout: number) {\n    super(`No message received in ${timeout}ms`);\n    this.name = \"TimeoutError\";\n  }\n}\n\n/** Client call options. */\nexport interface ClientCallOptions {\n  signal?: AbortSignal;\n}\n\nexport interface StreamDataOptions extends ClientCallOptions {\n  /** Stop at the specified cursor (inclusive). */\n  endingCursor?: Cursor;\n  /** Timeout between messages, in milliseconds. */\n  timeout?: number;\n}\n\n/** DNA client. */\nexport interface Client<TFilter, TBlock> {\n  /** Fetch the DNA stream status. */\n  status(\n    request?: StatusRequest,\n    options?: ClientCallOptions,\n  ): Promise<StatusResponse>;\n\n  /** Start streaming data from the DNA server. */\n  streamData(\n    request: StreamDataRequest<TFilter>,\n    options?: StreamDataOptions,\n  ): AsyncIterable<StreamDataResponse<TBlock>>;\n}\n\nexport type CreateClientOptions = {\n  defaultCallOptions?: DefaultCallOptions<\n    NormalizedServiceDefinition<proto.stream.DnaStreamDefinition>\n  >;\n  credentials?: ChannelCredentials;\n  channelOptions?: ChannelOptions;\n};\n\n/** Create a client connecting to the DNA grpc service. */\nexport function createClient<TFilter, TBlock>(\n  config: StreamConfig<TFilter, TBlock>,\n  streamUrl: string,\n  options: CreateClientOptions = {},\n) {\n  const channel = createChannel(\n    streamUrl,\n    options?.credentials,\n    options?.channelOptions,\n  );\n\n  const client: proto.stream.DnaStreamClient = grpcCreateClient(\n    proto.stream.DnaStreamDefinition,\n    channel,\n    options?.defaultCallOptions,\n  );\n\n  return new GrpcClient(config, client);\n}\n\nexport function createAuthenticatedClient<TFilter, TBlock>(\n  config: StreamConfig<TFilter, TBlock>,\n  streamUrl: string,\n  options?: CreateClientOptions,\n) {\n  const dnaToken = process.env.DNA_TOKEN;\n  if (!dnaToken) {\n    consola.warn(\n      \"DNA_TOKEN environment variable is not set. Trying to connect without authentication.\",\n    );\n  }\n\n  return createClient(config, streamUrl, {\n    ...options,\n    defaultCallOptions: {\n      ...(options?.defaultCallOptions ?? {}),\n      \"*\": {\n        metadata: Metadata({\n          Authorization: `Bearer ${dnaToken}`,\n        }),\n        // metadata cant be overrided with spread as its a class so we override it fully if user provided it.\n        ...(options?.defaultCallOptions?.[\"*\"] ?? {}),\n      },\n    },\n  });\n}\n\nexport class GrpcClient<TFilter, TBlock> implements Client<TFilter, TBlock> {\n  private encodeRequest;\n\n  constructor(\n    private config: StreamConfig<TFilter, TBlock>,\n    private client: proto.stream.DnaStreamClient,\n  ) {\n    this.encodeRequest = config.Request.encode;\n  }\n\n  async status(request?: StatusRequest, options?: ClientCallOptions) {\n    const response = await this.client.status(\n      StatusRequest.encode(request ?? {}),\n      options,\n    );\n    return StatusResponse.decode(response);\n  }\n\n  streamData(request: StreamDataRequest<TFilter>, options?: StreamDataOptions) {\n    const it = this.client.streamData(this.encodeRequest(request), options);\n    return new StreamDataIterable(it, this.config.Block, options);\n  }\n}\n\nexport class StreamDataIterable<TBlock> {\n  constructor(\n    private it: AsyncIterable<proto.stream.StreamDataResponse>,\n    private schema: Codec<TBlock, Uint8Array>,\n    private options?: StreamDataOptions,\n  ) {}\n\n  [Symbol.asyncIterator](): AsyncIterator<StreamDataResponse<TBlock>> {\n    const inner = this.it[Symbol.asyncIterator]();\n    const schema = StreamDataResponse(this.schema);\n    const decoder = schema.decode;\n    const { endingCursor, timeout = DEFAULT_TIMEOUT_MS } = this.options ?? {};\n    let shouldStop = false;\n\n    let clock: string | number | NodeJS.Timeout | undefined;\n\n    return {\n      async next() {\n        if (shouldStop) {\n          return { done: true, value: undefined };\n        }\n\n        // biome-ignore lint/suspicious/noExplicitAny: any is ok\n        const t: Promise<{ done: boolean; value: any }> = new Promise(\n          (_, reject) => {\n            clock = setTimeout(() => {\n              reject(new TimeoutError(timeout));\n            }, timeout);\n          },\n        );\n\n        try {\n          const { done, value } = await Promise.race([inner.next(), t]);\n\n          clearTimeout(clock);\n\n          if (done || value.message === undefined) {\n            return { done: true, value: undefined };\n          }\n\n          const decodedMessage = decoder(value.message);\n\n          if (endingCursor) {\n            assert(value.message.$case === \"data\");\n            assert(decodedMessage._tag === \"data\");\n\n            const { orderKey, uniqueKey } = endingCursor;\n            const endCursor = decodedMessage.data.endCursor;\n\n            // Check if the orderKey matches\n            if (orderKey === endCursor?.orderKey) {\n              // If a uniqueKey is specified, it must also match\n              if (!uniqueKey || uniqueKey === endCursor.uniqueKey) {\n                shouldStop = true;\n                return { done: false, value: decodedMessage };\n              }\n            }\n          }\n\n          return {\n            done: false,\n            value: decodedMessage,\n          };\n        } finally {\n          clearTimeout(clock);\n        }\n      },\n    };\n  }\n}\n","/** Track data rate using high precision timers. */\nexport class RateGauge {\n  private interval: number;\n  private prev?: bigint;\n  private rateMs?: number;\n  private var: number;\n\n  constructor(intervalSeconds: number) {\n    // Convert seconds to milliseconds.\n    this.interval = intervalSeconds * 1_000;\n    this.var = 0;\n  }\n\n  public record(items: number) {\n    // Compute the exponential moving average of the rate.\n    const prev = this.prev;\n    const now = process.hrtime.bigint();\n    this.prev = now;\n\n    if (!prev) {\n      return;\n    }\n\n    const deltaMs = Number(now - prev) / 1_000_000;\n    // rate in items/ms.\n    const rateMs = items / deltaMs;\n\n    if (this.rateMs === undefined) {\n      this.rateMs = rateMs;\n      this.var = 0;\n      return;\n    }\n\n    const alpha = 1 - Math.exp(-deltaMs / this.interval);\n    this.rateMs = alpha * rateMs + (1 - alpha) * this.rateMs;\n\n    const diff = rateMs - this.rateMs;\n    const incr = alpha * diff;\n    this.var = (1 - alpha) * (this.var + incr * diff);\n  }\n\n  /** Returns the average rate per second. */\n  public average() {\n    if (this.rateMs === undefined) {\n      return undefined;\n    }\n    return this.rateMs * 1_000;\n  }\n\n  /** Returns the variance. */\n  public variance() {\n    return this.var;\n  }\n}\n"],"names":["grpcCreateClient","proto.stream.DnaStreamDefinition","__publicField"],"mappings":"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"}