import { TerminalError } from "./errors.js";
import { HooksProvider } from "../hooks.js";
import { Context, InvocationHandle, InvocationPromise, ObjectContext, ObjectSharedContext, TypedState, UntypedState, WorkflowContext, WorkflowSharedContext } from "../context.js";
import { Duration, ObjectHandler, Serde, ServiceDefinition, ServiceHandler, VirtualObjectDefinition, WorkflowDefinition, WorkflowHandler, WorkflowSharedHandler } from "@restatedev/restate-sdk-core";

//#region src/types/rpc.d.ts
type ClientCallOptions<I, O$1> = {
  input?: Serde<I>;
  output?: Serde<O$1>;
  headers?: Record<string, string>;
  idempotencyKey?: string;
  /**
   * Observability name, recorded in the Restate journal.
   */
  name?: string;
};
declare class Opts<I, O$1> {
  private readonly opts;
  /**
   * Create a call configuration from the provided options.
   *
   * @param opts the call configuration
   */
  static from<I, O$1>(opts: ClientCallOptions<I, O$1>): Opts<I, O$1>;
  private constructor();
  getOpts(): ClientCallOptions<I, O$1>;
}
type ClientSendOptions<I> = {
  input?: Serde<I>;
  /**
   * Makes a type-safe one-way RPC to the specified target service, after a delay specified by the
   * milliseconds' argument.
   * This method is like setting up a fault-tolerant cron job that enqueues the message in a
   * message queue.
   * The handler calling this function does not have to stay active for the delay time.
   *
   * Both the delay timer and the message are durably stored in Restate and guaranteed to be reliably
   * delivered. The delivery happens no earlier than specified through the delay, but may happen
   * later, if the target service is down, or backpressuring the system.
   *
   * The delay message is journaled for durable execution and will thus not be duplicated when the
   * handler is re-invoked for retries or after suspending.
   *
   * This call will return immediately; the message sending happens asynchronously in the background.
   * Despite that, the message is guaranteed to be sent, because the completion of the invocation that
   * triggers the send (calls this function) happens logically after the sending. That means that any
   * failure where the message does not reach Restate also cannot complete this invocation, and will
   * hence recover this handler and (through the durable execution) recover the message to be sent.
   *
   * @example
   * ```ts
   * ctx.serviceSendClient(Service).anotherAction(1337, { delay: { seconds: 60 } });
   * ```
   */
  delay?: Duration | number;
  headers?: Record<string, string>;
  idempotencyKey?: string;
  /**
   * Observability name, recorded in the Restate journal.
   */
  name?: string;
};
declare class SendOpts<I> {
  private readonly opts;
  static from<I>(opts: ClientSendOptions<I>): SendOpts<I>;
  getOpts(): ClientSendOptions<I>;
  private constructor();
}
declare namespace rpc {
  const opts: <I, O$1>(opts: ClientCallOptions<I, O$1>) => Opts<I, O$1>;
  const sendOpts: <I>(opts: ClientSendOptions<I>) => SendOpts<I>;
}
type InferArg<P$1> = P$1 extends [infer A, ...any[]] ? A : unknown;
type Client<M> = { [K in keyof M as M[K] extends never ? never : K]: M[K] extends ((arg: any, ...args: infer P) => PromiseLike<infer O>) ? (...args: [...P, ...[opts?: Opts<InferArg<P>, O>]]) => InvocationPromise<O> : never };
type SendClient<M> = { [K in keyof M as M[K] extends never ? never : K]: M[K] extends ((arg: any, ...args: infer P) => void) ? (...args: [...P, ...[opts?: SendOpts<InferArg<P>>]]) => InvocationHandle : never };
type ServiceHandlerOpts<I, O$1> = {
  /**
   * Defines which Content-Type values are accepted when this handler is invoked via the ingress.
   * Wildcards are supported, for example `application/*` or `* / *`.
   *
   * If unset, `input.contentType` will be used as the default.
   *
   * This setting does not affect deserialization. To customize how the input is deserialized,
   * provide an `input` Serde.
   */
  accept?: string;
  /**
   * Serde used to deserialize the input parameter.
   * Defaults to `restate.serde.json`.
   *
   * Provide a custom Serde if the input is not JSON, or use
   * `restate.serde.binary` to skip serialization/deserialization altogether;
   * in that case the input parameter is a `Uint8Array`.
   */
  input?: Serde<I>;
  /**
   * Serde used to serialize the output value.
   * Defaults to `restate.serde.json`.
   *
   * Provide a custom Serde if the output is not JSON, or use
   * `restate.serde.binary` to skip serialization/deserialization altogether;
   * in that case the output value is a `Uint8Array`.
   */
  output?: Serde<O$1>;
  /**
   * If `true`, the output `Content-Type` declared by the output `Serde` is set
   * on the response even when the serialized output is an empty byte array.
   *
   * This is needed for serialization formats where an empty byte array is a
   * valid value (for example Protobuf, where an empty message serializes to
   * zero bytes).
   *
   * Defaults to `false`: when the serialized output is empty, no `Content-Type` header is sent.
   */
  setOutputContentTypeIfEmpty?: boolean;
  /**
   * Human-readable description of the handler, shown in documentation/admin tools.
   */
  description?: string;
  /**
   * Arbitrary key/value metadata for the handler. Exposed via the Admin API.
   */
  metadata?: Record<string, string>;
  /**
   * The retention duration of idempotent requests to this handler.
   *
   * Note: Available only when registering this endpoint with restate-server v1.4 or newer; otherwise service discovery will fail.
   */
  idempotencyRetention?: Duration | number;
  /**
   * The journal retention for invocations to this handler.
   *
   * When a request has an idempotency key, `idempotencyRetention` caps the journal retention time.
   *
   * Note: Available only when registering this endpoint with restate-server v1.4 or newer; otherwise service discovery will fail.
   */
  journalRetention?: Duration | number;
  /**
   * Guards against stalled invocations. Once this timeout expires, Restate requests a graceful
   * suspension of the invocation (preserving intermediate progress).
   *
   * If the invocation does not react to the suspension request, `abortTimeout` is used to abort it.
   *
   * Overrides the inactivity timeout set at the service level and the default configured in the Restate server.
   *
   * Note: Available only when registering this endpoint with restate-server v1.4 or newer; otherwise service discovery will fail.
   */
  inactivityTimeout?: Duration | number;
  /**
   * Guards against invocations that fail to terminate after inactivity.
   * The abort timeout starts after `inactivityTimeout` expires and a graceful termination was requested.
   * When this timer expires, the invocation is aborted.
   *
   * This timer may interrupt user code. If more time is needed for graceful termination, increase this value.
   *
   * Overrides the abort timeout set at the service level and the default configured in the Restate server.
   *
   * Note: Available only when registering this endpoint with restate-server v1.4 or newer; otherwise service discovery will fail.
   */
  abortTimeout?: Duration | number;
  /**
   * When set to `true`, this handler cannot be invoked via the Restate server HTTP or Kafka ingress;
   * it can only be called from other services.
   *
   * Note: Available only when registering this endpoint with restate-server v1.4 or newer; otherwise service discovery will fail.
   */
  ingressPrivate?: boolean;
  /**
   * Retry policy to apply to all requests to this handler. For each unspecified field, the default value configured in the service or, if absent, in the restate-server configuration file, will be applied instead.
   */
  retryPolicy?: RetryPolicy;
  /**
   * By default, Restate treats errors as terminal (non-retryable) only when they are instances of `TerminalError`.
   *
   * Use this hook to map domain-specific errors to `TerminalError` (or return `undefined` to keep them retryable).
   * When mapped to `TerminalError`, the error will not be retried.
   *
   * Note: This applies to errors thrown inside `ctx.run` closures as well as errors thrown by Restate handlers.
   *
   * Example:
   *
   * ```ts
   * class MyValidationError extends Error {}
   *
   * const greeter = restate.service({
   *   name: "greeter",
   *   handlers: {
   *     greet: async (ctx: restate.Context, name: string) => {
   *       if (name.length === 0) {
   *         throw new MyValidationError("Length too short");
   *       }
   *       return `Hello ${name}`;
   *     }
   *   },
   *   options: {
   *     asTerminalError: (err) => {
   *       if (err instanceof MyValidationError) {
   *         // My validation error is terminal
   *         return new restate.TerminalError(err.message, { errorCode: 400 });
   *       }
   *
   *       // Any other error is retryable
   *     }
   *   }
   * });
   * ```
   */
  asTerminalError?: (error: any) => TerminalError | undefined;
  /**
   * Default serde to use for requests, responses, state, side effects, awakeables, promises. Used when no other serde is specified.
   *
   * If not provided, defaults to `serde.json`.
   *
   * The input or output of this handler can be overridden using the `input`/`output` fields
   */
  serde?: Serde<any>;
  /**
   * Hooks providers for this handler. Handler-level hooks wrap innermost —
   * they run after service-level hooks. Both levels are merged: service
   * hooks first, then handler hooks. Within each level, hooks execute in
   * array order: for `[A, B]`: A before → B before → handler → B after → A after.
   *
   * The `handler` interceptor fires on every attempt. The `run` interceptor
   * fires only when the `ctx.run()` closure actually executes — replayed
   * runs (already in the journal) are skipped.
   *
   * Errors thrown at any point (before or after `next()`) affect the invocation:
   * {@link TerminalError} fails immediately, any other error triggers a retry.
   * On suspension or pause, `next()` also rejects — do any cleanup and rethrow.
   *
   * @example
   * ```ts
   * const myService = restate.service({
   *   name: "MyService",
   *   handlers: {
   *     greet: restate.createServiceHandler(
   *       {
   *         hooks: [
   *           (ctx) => ({
   *             interceptor: {
   *               handler: async (next) => {
   *                 console.log(`before ${ctx.request.target}`);
   *                 try {
   *                   await next();
   *                   console.log(`after ${ctx.request.target}`);
   *                 } catch (e) {
   *                   console.log(`error ${ctx.request.target}: ${e}`);
   *                   // Always rethrow — swallowing the error changes the
   *                   // invocation outcome. You can also throw a different
   *                   // error (e.g. TerminalError to fail immediately).
   *                   throw e;
   *                 }
   *               },
   *               run: async (name, next) => {
   *                 console.log(`  before run "${name}"`);
   *                 try {
   *                   await next();
   *                   console.log(`  after run "${name}"`);
   *                 } catch (e) {
   *                   console.log(`  error run "${name}": ${e}`);
   *                   throw e;
   *                 }
   *               },
   *             },
   *           }),
   *         ],
   *       },
   *       async (ctx, name) => `Hello, ${name}!`
   *     ),
   *   },
   * });
   * ```
   */
  hooks?: HooksProvider[];
  /**
   * When set to `true`, the SDK will stop automatically propagating cancellations when awaiting {@link RestatePromise}s.
   *
   * Instead, the user code must explicitly listen to cancellations using the `ctx.cancellation()` API in {@link ContextInternal}.
   *
   * @experimental
   */
  explicitCancellation?: boolean;
};
type ObjectHandlerOpts<I, O$1> = ServiceHandlerOpts<I, O$1> & {
  /**
   * When set to `true`, lazy state will be enabled for all invocations to this handler.
   *
   * *NOTE:* You can set this field only if you register this endpoint against restate-server >= 1.4,
   * otherwise the service discovery will fail.
   */
  enableLazyState?: boolean;
};
type WorkflowHandlerOpts<I, O$1> = ServiceHandlerOpts<I, O$1> & {
  /**
   * When set to `true`, lazy state will be enabled for all invocations to this handler.
   *
   * *NOTE:* You can set this field only if you register this endpoint against restate-server >= 1.4,
   * otherwise the service discovery will fail.
   */
  enableLazyState?: boolean;
};
type RemoveVoidArgument<F> = F extends ((ctx: infer C, arg: infer A) => infer R) ? A extends void ? (ctx: C) => R : F : F;
declare namespace handlers {
  /**
   * Create a service handler.
   *
   * @param opts additional configuration
   * @param fn the actual handler code to execute
   */
  function handler<O$1, I = void>(opts: ServiceHandlerOpts<I, O$1>, fn: (ctx: Context, input: I) => Promise<O$1>): RemoveVoidArgument<typeof fn>;
  namespace workflow {
    function workflow<O$1, I = void, TState extends TypedState = UntypedState>(opts: WorkflowHandlerOpts<I, O$1>, fn: (ctx: WorkflowContext<TState>, input: I) => Promise<O$1>): RemoveVoidArgument<typeof fn>;
    function workflow<O$1, I = void, TState extends TypedState = UntypedState>(fn: (ctx: WorkflowContext<TState>, input: I) => Promise<O$1>): RemoveVoidArgument<typeof fn>;
    /**
     * Creates a shared handler for a workflow.
     *
     * A shared handler allows a read-only concurrent execution
     * for a given key.
     *
     * @param opts additional configurations
     * @param fn the handler to execute
     */
    function shared<O$1, I = void, TState extends TypedState = UntypedState>(opts: WorkflowHandlerOpts<I, O$1>, fn: (ctx: WorkflowSharedContext<TState>, input: I) => Promise<O$1>): RemoveVoidArgument<typeof fn>;
    /**
     * Creates a shared handler for a workflow.
     *
     * A shared handler allows a read-only concurrent execution
     * for a given key.
     *
     * @param opts additional configurations
     * @param fn the handler to execute
     */
    function shared<O$1, I = void, TState extends TypedState = UntypedState>(fn: (ctx: WorkflowSharedContext<TState>, input: I) => Promise<O$1>): RemoveVoidArgument<typeof fn>;
  }
  namespace object {
    /**
     * Creates an exclusive handler for a virtual Object.
     *
     * note : This applies only to a virtual object.
     *
     * @param opts additional configurations
     * @param fn the handler to execute
     */
    function exclusive<O$1, I = void, TState extends TypedState = UntypedState>(opts: ObjectHandlerOpts<I, O$1>, fn: (ctx: ObjectContext<TState>, input: I) => Promise<O$1>): RemoveVoidArgument<typeof fn>;
    /**
     * Creates an exclusive handler for a virtual Object.
     *
     *
     * note 1: This applies only to a virtual object.
     * note 2: This is the default for virtual objects, so if no
     *         additional reconfiguration is needed, you can simply
     *         use the handler directly (no need to use exclusive).
     *         This variant here is only for symmetry/convenance.
     *
     * @param fn the handler to execute
     */
    function exclusive<O$1, I = void, TState extends TypedState = UntypedState>(fn: (ctx: ObjectContext<TState>, input: I) => Promise<O$1>): RemoveVoidArgument<typeof fn>;
    /**
     * Creates a shared handler for a virtual Object.
     *
     * A shared handler allows a read-only concurrent execution
     * for a given key.
     *
     * note: This applies only to a virtual object.
     *
     * @param opts additional configurations
     * @param fn the handler to execute
     */
    function shared<O$1, I = void, TState extends TypedState = UntypedState>(opts: ObjectHandlerOpts<I, O$1>, fn: (ctx: ObjectSharedContext<TState>, input: I) => Promise<O$1>): RemoveVoidArgument<typeof fn>;
    /**
     * Creates a shared handler for a virtual Object.
     *
     * A shared handler allows a read-only concurrent execution
     * for a given key.
     *
     * note: This applies only to a virtual object.
     *
     * @param opts additional configurations
     * @param fn the handler to execute
     */
    function shared<O$1, I = void, TState extends TypedState = UntypedState>(fn: (ctx: ObjectSharedContext<TState>, input: I) => Promise<O$1>): RemoveVoidArgument<typeof fn>;
  }
}
type ServiceOpts<U> = { [K in keyof U]: U[K] extends ServiceHandler<U[K], Context> ? U[K] : ServiceHandler<U[K], Context> };
type RetryPolicy = {
  /**
   * Max number of retry attempts (including the initial).
   * When reached, the behavior specified in {@link onMaxAttempts} will be applied.
   */
  maxAttempts?: number;
  /**
   * What to do when max attempts are reached.
   *
   * If `pause`, the invocation will enter the paused state and can be manually resumed from the CLI/UI.
   *
   * If `kill`, the invocation will get automatically killed.
   */
  onMaxAttempts?: "pause" | "kill";
  /**
   * Initial interval for the first retry attempt.
   * Retry interval will grow by a factor specified in `exponentiationFactor`.
   *
   * If a number is provided, it will be interpreted as milliseconds.
   */
  initialInterval?: Duration | number;
  /**
   * Max interval between retries.
   * Retry interval will grow by a factor specified in `exponentiationFactor`.
   *
   * If a number is provided, it will be interpreted as milliseconds.
   */
  maxInterval?: Duration | number;
  /**
   * Exponentiation factor to use when computing the next retry delay.
   */
  exponentiationFactor?: number;
};
type ServiceOptions = {
  /**
   * The retention duration of idempotent requests to this service.
   *
   * Note: Available only when registering this endpoint with restate-server v1.4 or newer; otherwise service discovery will fail.
   */
  idempotencyRetention?: Duration | number;
  /**
   * Journal retention applied to all requests to all handlers of this service.
   *
   * When a request includes an idempotency key, `idempotencyRetention` caps the journal retention time.
   *
   * Note: Available only when registering this endpoint with restate-server v1.4 or newer; otherwise service discovery will fail.
   */
  journalRetention?: Duration | number;
  /**
   * Guards against stalled invocations. Once this timeout expires, Restate requests a graceful
   * suspension of the invocation (preserving intermediate progress).
   *
   * If the invocation does not react to the suspension request, `abortTimeout` is used to abort it.
   *
   * Overrides the default inactivity timeout configured in the Restate server for all invocations to this service.
   *
   * Note: Available only when registering this endpoint with restate-server v1.4 or newer; otherwise service discovery will fail.
   */
  inactivityTimeout?: Duration | number;
  /**
   * Guards against invocations that fail to terminate after inactivity.
   * The abort timeout starts after `inactivityTimeout` expires and a graceful termination was requested.
   * When this timer expires, the invocation is aborted.
   *
   * This timer may interrupt user code. If more time is needed for graceful termination, increase this value.
   *
   * Overrides the default abort timeout configured in the Restate server for invocations to this service.
   *
   * Note: Available only when registering this endpoint with restate-server v1.4 or newer; otherwise service discovery will fail.
   */
  abortTimeout?: Duration | number;
  /**
   * When set to `true`, this service (and all its handlers) cannot be invoked via the Restate server
   * HTTP or Kafka ingress; it can only be called from other services.
   *
   * Note: Available only when registering this endpoint with restate-server v1.4 or newer; otherwise service discovery will fail.
   */
  ingressPrivate?: boolean;
  /**
   * Retry policy to apply to all requests to this service. For each unspecified field, the default value configured in the restate-server configuration file will be applied instead.
   */
  retryPolicy?: RetryPolicy;
  /**
   * By default, Restate treats errors as terminal (non-retryable) only when they are instances of `TerminalError`.
   *
   * Use this hook to map domain-specific errors to `TerminalError` (or return `undefined` to keep them retryable).
   * When mapped to `TerminalError`, the error will not be retried.
   *
   * Note: This applies to errors thrown inside `ctx.run` closures as well as errors thrown by Restate handlers.
   *
   * Example:
   *
   * ```ts
   * class MyValidationError extends Error {}
   *
   * const greeter = restate.service({
   *   name: "greeter",
   *   handlers: {
   *     greet: async (ctx: restate.Context, name: string) => {
   *       if (name.length === 0) {
   *         throw new MyValidationError("Length too short");
   *       }
   *       return `Hello ${name}`;
   *     }
   *   },
   *   options: {
   *     asTerminalError: (err) => {
   *       if (err instanceof MyValidationError) {
   *         // My validation error is terminal
   *         return new restate.TerminalError(err.message, { errorCode: 400 });
   *       }
   *
   *       // Any other error is retryable
   *     }
   *   }
   * });
   * ```
   */
  asTerminalError?: (error: any) => TerminalError | undefined;
  /**
   * Default serde to use for requests, responses, state, side effects, awakeables, promises. Used when no other serde is specified.
   *
   * If not provided, defaults to `serde.json`.
   */
  serde?: Serde<any>;
  /**
   * Hooks providers for this service. Service-level hooks wrap outermost —
   * they run before handler-level hooks. Both levels are merged: service
   * hooks first, then handler hooks. Within each level, hooks execute in
   * array order: for `[A, B]`: A before → B before → handler → B after → A after.
   *
   * The `handler` interceptor fires on every attempt. The `run` interceptor
   * fires only when the `ctx.run()` closure actually executes — replayed
   * runs (already in the journal) are skipped.
   *
   * Errors thrown at any point (before or after `next()`) affect the invocation:
   * {@link TerminalError} fails immediately, any other error triggers a retry.
   * On suspension or pause, `next()` also rejects — do any cleanup and rethrow.
   *
   * @example
   * ```ts
   * const myService = restate.service({
   *   name: "MyService",
   *   handlers: { greet: async (ctx, name) => `Hello, ${name}!` },
   *   options: {
   *     hooks: [
   *       (ctx) => ({
   *         interceptor: {
   *           handler: async (next) => {
   *             console.log(`before ${ctx.request.target}`);
   *             try {
   *               await next();
   *               console.log(`after ${ctx.request.target}`);
   *             } catch (e) {
   *               console.log(`error ${ctx.request.target}: ${e}`);
   *               // Always rethrow — swallowing the error changes the
   *               // invocation outcome. You can also throw a different
   *               // error (e.g. TerminalError to fail immediately).
   *               throw e;
   *             }
   *           },
   *           run: async (name, next) => {
   *             console.log(`  before run "${name}"`);
   *             try {
   *               await next();
   *               console.log(`  after run "${name}"`);
   *             } catch (e) {
   *               console.log(`  error run "${name}": ${e}`);
   *               throw e;
   *             }
   *           },
   *         },
   *       }),
   *     ],
   *   },
   * });
   * ```
   */
  hooks?: HooksProvider[];
  /**
   * When set to `true`, the SDK will stop automatically propagating cancellations when awaiting {@link RestatePromise}s.
   *
   * Instead, the user code must explicitly listen to cancellations using the `ctx.cancellation()` API in {@link ContextInternal}.
   *
   * @experimental
   */
  explicitCancellation?: boolean;
};
/**
 * Define a Restate service.
 *
 * @example Here is an example of how to define a service:
 *
 * ```ts
 * const greeter = service({
 *   name: "greeter",
 *   handlers: {
 *     greet: async (ctx: Context, name: string) => {
 *       return `Hello ${name}`;
 *     }
 *   }
 * });
 * ```
 *
 * To use the service, you can bind it to an endpoint:
 * ```
 * ...
 * endpoint.bind(greeter)
 * ```
 * @example To use a service, you can export its type to be used in a client:
 * ```
 * export type Greeter = typeof greeter;
 * ...
 * ...
 * import type { Greeter } from "./greeter";
 * const client = ctx.serviceClient<Greeter>({ name : "greeter"});
 * client.greet("World").then(console.log);
 * ```
 *
 * @example Alternatively to avoid repeating the service name, you can:
 * ```
 * import type {Greeter} from "./greeter";
 * const Greeter: Greeter = { name : "greeter"};
 *
 * // now you can reference the service like this:
 * const client = ctx.serviceClient(Greeter);
 * ```
 *
 * @param name the service name
 * @param handlers the handlers for the service
 * @param description an optional description for the service
 * @param metadata an optional metadata for the service
 * @type P the name of the service
 * @type M the handlers for the service
 */
declare const service: <P$1 extends string, M>(service: {
  name: P$1;
  handlers: ServiceOpts<M> & ThisType<M>;
  description?: string;
  metadata?: Record<string, string>;
  options?: ServiceOptions;
}) => ServiceDefinition<P$1, M>;
type ObjectOpts<U> = { [K in keyof U]: U[K] extends ObjectHandler<U[K], ObjectContext<any>> ? U[K] : U[K] extends ObjectHandler<U[K], ObjectSharedContext<any>> ? U[K] : ObjectHandler<U[K], ObjectContext<any>> | ObjectHandler<U[K], ObjectSharedContext<any>> };
type ObjectOptions = ServiceOptions & {
  /**
   * When set to `true`, lazy state will be enabled for all invocations to this service.
   *
   * *NOTE:* You can set this field only if you register this endpoint against restate-server >= 1.4,
   * otherwise the service discovery will fail.
   */
  enableLazyState?: boolean;
};
/**
 * Define a Restate virtual object.
 *
 * @example Here is an example of how to define a virtual object:
 * ```ts
 *        const counter = object({
 *            name: "counter",
 *            handlers: {
 *                  add: async (ctx: ObjectContext, amount: number) => {},
 *                  get: async (ctx: ObjectContext) => {}
 *            }
 *        })
 *  ```
 *
 * @example To use the object, you can bind it to an endpoint:
 * ```ts
 * ...
 * endpoint.bind(counter)
 * ```
 *
 *  @see to interact with the object, you can use the object client:
 * ```ts
 * ...
 * const client = ctx.objectClient<typeof counter>({ name: "counter"});
 * const res = await client.add(1)
 * ```
 *
 * ### Shared handlers
 *
 * Shared handlers are used to allow concurrent read-only access to the object.
 * This is useful when you want to allow multiple clients to read the object's state at the same time.
 * To define a shared handler, you can use the `shared` decorator as shown below:
 *
 * ```ts
 *      const counter = object({
 *          name: "counter",
 *          handlers: {
 *
 *            add: async (ctx: ObjectContext, amount: number) => { .. },
 *
 *            get: handlers.object.shared(async (ctx: ObjectSharedContext) => {
 *                  return ctx.get<number>("count");
 *            })
 *       }
 *     });
 * ```
 *
 * @param name the name of the object
 * @param handlers the handlers for the object
 * @param description an optional description for the object
 * @param metadata an optional metadata for the object
 * @type P the name of the object
 * @type M the handlers for the object
 */
declare const object: <P$1 extends string, M>(object: {
  name: P$1;
  handlers: ObjectOpts<M> & ThisType<M>;
  description?: string;
  metadata?: Record<string, string>;
  options?: ObjectOptions;
}) => VirtualObjectDefinition<P$1, M>;
/**
 * A workflow handlers is a type that describes the handlers for a workflow.
 * The handlers must contain exactly one handler named 'run', and this handler must accept as a first argument a WorkflowContext.
 * It can contain any number of additional handlers, which must accept as a first argument a WorkflowSharedContext.
 * The handlers can not be named 'workflowSubmit', 'workflowAttach', 'workflowOutput' - as these are reserved.
 * @see {@link workflow} for an example.
 */
type WorkflowOpts<U> = {
  run: (ctx: WorkflowContext<any>, argument: any) => Promise<any>;
} & { [K in keyof U]: K extends "workflowSubmit" | "workflowAttach" | "workflowOutput" ? `${K} is a reserved keyword` : K extends "run" ? U[K] extends WorkflowHandler<U[K], WorkflowContext<any>> ? U[K] : "An handler named 'run' must take as a first argument a WorkflowContext, and must return a Promise" : U[K] extends WorkflowSharedHandler<U[K], WorkflowSharedContext<any>> ? U[K] : "An handler other then 'run' must accept as a first argument a WorkflowSharedContext" };
type WorkflowOptions = ServiceOptions & {
  /**
   * The retention duration for this workflow.
   *
   * *NOTE:* You can set this field only if you register this endpoint against restate-server >= 1.4,
   * otherwise the service discovery will fail.
   */
  workflowRetention?: Duration | number;
  /**
   * When set to `true`, lazy state will be enabled for all invocations to this service.
   *
   * *NOTE:* You can set this field only if you register this endpoint against restate-server >= 1.4,
   * otherwise the service discovery will fail.
   */
  enableLazyState?: boolean;
};
/**
 * Define a Restate workflow.
 *
 *
 * @example Here is an example of how to define a workflow:
 * ```ts
 * const mywf = workflow({
 *   name: "mywf",
 *   handlers: {
 *     run: async (ctx: WorkflowContext, argument: any) => {
 *       return "Hello World";
 *     }
 *   }
 * });
 * ```
 *
 * ### Note:
 * * That a workflow must contain exactly one handler named 'run', and this handler must accept as a first argument a WorkflowContext.
 * * The workflow handlers other than 'run' must accept as a first argument a WorkflowSharedContext.
 * * The workflow handlers can not be named 'workflowSubmit', 'workflowAttach', 'workflowOutput' - as these are reserved keywords.
 *
 * @example To use the workflow, you can bind it to an endpoint:
 * ```ts
 * endpoint.bind(mywf)
 * ```
 *
 * @example To interact with the workflow, you can use the workflow client:
 * ```ts
 * const client = ctx.workflowClient<typeof mywf>({ name: "mywf"});
 * const res = await client.run("Hello");
 * ```
 *
 * To use the workflow client from any other environment (like a browser), please refer to the documentation.
 * https://docs.restate.dev
 *
 *
 *
 * @param name the workflow name
 * @param handlers the handlers for the workflow.
 */
declare const workflow: <P$1 extends string, M>(workflow: {
  name: P$1;
  handlers: WorkflowOpts<M> & ThisType<M>;
  description?: string;
  metadata?: Record<string, string>;
  options?: WorkflowOptions;
}) => WorkflowDefinition<P$1, M>;
//#endregion
export { Client, ClientCallOptions, ClientSendOptions, InferArg, ObjectHandlerOpts, ObjectOptions, ObjectOpts, Opts, RemoveVoidArgument, RetryPolicy, SendClient, SendOpts, ServiceHandlerOpts, ServiceOptions, ServiceOpts, WorkflowHandlerOpts, WorkflowOptions, WorkflowOpts, handlers, object, rpc, service, workflow };
//# sourceMappingURL=rpc.d.ts.map