import * as _alepha_core2 from "alepha";
import * as _alepha_core1 from "alepha";
import * as _alepha_core0 from "alepha";
import { Alepha, Descriptor, KIND, Logger } from "alepha";
import * as _alepha_server0 from "alepha/server";
import { ActionDescriptor, ApiLink, ApiLinksResponse, ClientRequestEntry, ClientRequestOptions, ClientRequestResponse, FetchResponse, HttpClient, RequestConfigSchema, ServerHandler, ServerRequestConfigEntry } from "alepha/server";
import * as _alepha_retry0 from "alepha/retry";
import { ProxyDescriptorOptions, ServerProxyProvider } from "alepha/server/proxy";
import { ServiceAccountDescriptor, UserAccountToken } from "alepha/security";
import * as _sinclair_typebox0 from "@sinclair/typebox";

//#region src/providers/LinkProvider.d.ts
declare class LinkProvider {
  readonly URL_LINKS = "/api/_links";
  protected readonly log: Logger;
  protected readonly alepha: Alepha;
  protected readonly httpClient: HttpClient;
  links?: Array<HttpClientLink>;
  pushLink(link: HttpClientLink): void;
  getLinks(force?: boolean): Promise<HttpClientLink[]>;
  client<T extends object>(scope?: ClientScope): HttpVirtualClient<T>;
  protected createVirtualAction<T extends RequestConfigSchema>(name: string, scope?: ClientScope): VirtualAction<T>;
  /**
   * Resolve a link by its name and call it.
   * - If link is local, it will call the local handler.
   * - If link is remote, it will make a fetch request to the remote server.
   */
  follow(name: string, config?: Partial<ServerRequestConfigEntry>, options?: ClientRequestOptions & ClientScope): Promise<any>;
  protected followRemote(link: HttpClientLink, config?: Partial<ServerRequestConfigEntry>, options?: ClientRequestOptions): Promise<FetchResponse>;
  can(name: string): boolean;
  protected getLinkByName(name: string, options?: ClientScope): Promise<HttpClientLink>;
}
interface HttpClientLink extends ApiLink {
  secured?: boolean;
  prefix?: string;
  host?: string;
  service?: string;
  schema?: RequestConfigSchema;
  handler?: ServerHandler;
}
interface ClientScope {
  group?: string;
  service?: string;
}
type HttpVirtualClient<T> = { [K in keyof T as T[K] extends ActionDescriptor<RequestConfigSchema> ? K : never]: T[K] extends ActionDescriptor<infer Schema> ? VirtualAction<Schema> : never };
interface VirtualAction<T extends RequestConfigSchema> extends Pick<ActionDescriptor<T>, "name" | "run" | "fetch"> {
  (config?: ClientRequestEntry<T>, opts?: ClientRequestOptions): Promise<ClientRequestResponse<T>>;
  can: () => boolean;
}
//# sourceMappingURL=LinkProvider.d.ts.map
//#endregion
//#region src/descriptors/$client.d.ts
/**
 * Create a new client.
 */
declare const $client: {
  <T extends object>(scope?: ClientScope): HttpVirtualClient<T>;
  [KIND]: string;
};
//# sourceMappingURL=$client.d.ts.map

//#endregion
//#region src/descriptors/$remote.d.ts
/**
 * $remote is a descriptor that allows you to define remote service access.
 *
 * Use it only when you have 2 or more services that need to communicate with each other.
 *
 * All remote services can be exposed as actions, ... or not.
 *
 * You can add a service account if you want to use a security layer.
 */
declare const $remote: {
  (options: RemoteDescriptorOptions): RemoteDescriptor;
  [KIND]: typeof RemoteDescriptor;
};
interface RemoteDescriptorOptions {
  /**
   * The URL of the remote service.
   * You can use a function to generate the URL dynamically.
   * You probably should use $env(env) to get the URL from the environment.
   *
   * @example
   * ```ts
   * import { $remote } from "alepha/server";
   * import { $inject, t } from "alepha";
   *
   * class App {
   *   env = $env(t.object({
   *     REMOTE_URL: t.string({default: "http://localhost:3000"}),
   *   }));
   *   remote = $remote({
   *     url: this.env.REMOTE_URL,
   *   });
   * }
   * ```
   */
  url: string | (() => string);
  /**
   * The name of the remote service.
   *
   * @default Member of the class containing the remote service.
   */
  name?: string;
  /**
   * If true, all methods of the remote service will be exposed as actions in this context.
   * > Note: Proxy will never use the service account, it just... proxies the request.
   */
  proxy?: boolean | Partial<ProxyDescriptorOptions & {
    /**
     * If true, the remote service won't be available internally, only through the proxy.
     */
    noInternal: boolean;
  }>;
  /**
   * For communication between the server and the remote service with a security layer.
   * This will be used for internal communication and will not be exposed to the client.
   */
  serviceAccount?: ServiceAccountDescriptor;
}
declare class RemoteDescriptor extends Descriptor<RemoteDescriptorOptions> {
  get name(): string;
}
//# sourceMappingURL=$remote.d.ts.map
//#endregion
//#region src/providers/RemoteDescriptorProvider.d.ts
declare class RemoteDescriptorProvider {
  static path: {
    apiLinks: string;
  };
  protected readonly alepha: Alepha;
  protected readonly client: LinkProvider;
  protected readonly proxyProvider: ServerProxyProvider;
  protected readonly remotes: Array<ServerRemote>;
  protected readonly log: Logger;
  getRemotes(): ServerRemote[];
  readonly configure: _alepha_core2.HookDescriptor<"configure">;
  readonly start: _alepha_core2.HookDescriptor<"start">;
  registerRemote(value: RemoteDescriptor): Promise<void>;
  protected readonly fetchLinks: _alepha_retry0.RetryDescriptorFn<(opts: FetchLinksOptions) => Promise<ApiLinksResponse>>;
}
interface FetchLinksOptions {
  service: string;
  url: string;
  authorization?: string;
}
interface ServerRemote {
  url: string;
  name: string;
  proxy: boolean;
  internal: boolean;
  links: (args: {
    authorization?: string;
  }) => Promise<ApiLinksResponse>;
  schema: (args: {
    name: string;
    authorization?: string;
  }) => Promise<any>;
  serviceAccount?: ServiceAccountDescriptor;
  prefix: string;
}
//# sourceMappingURL=RemoteDescriptorProvider.d.ts.map
//#endregion
//#region src/providers/ServerLinksProvider.d.ts
declare class ServerLinksProvider {
  protected readonly alepha: Alepha;
  protected readonly client: LinkProvider;
  protected readonly remoteProvider: RemoteDescriptorProvider;
  readonly onRoute: _alepha_core1.HookDescriptor<"configure">;
  readonly links: _alepha_server0.RouteDescriptor<{
    response: _sinclair_typebox0.TObject<{
      prefix: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
      links: _sinclair_typebox0.TArray<_sinclair_typebox0.TObject<{
        name: _sinclair_typebox0.TString;
        path: _sinclair_typebox0.TString;
        method: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
        group: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
        requestBodyType: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
        service: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
      }>>;
    }>;
  }>;
  readonly schema: _alepha_server0.RouteDescriptor<{
    params: _sinclair_typebox0.TObject<{
      name: _sinclair_typebox0.TString;
    }>;
    response: _sinclair_typebox0.TRecord<_sinclair_typebox0.TString, _sinclair_typebox0.TAny>;
  }>;
  getLinks(options: GetLinksOptions): Promise<ApiLinksResponse>;
}
interface GetLinksOptions {
  user?: UserAccountToken;
  authorization?: string;
}
//# sourceMappingURL=ServerLinksProvider.d.ts.map
//#endregion
//#region src/index.d.ts
declare const AlephaServerLinks: _alepha_core0.Service<_alepha_core0.Module>;
//# sourceMappingURL=index.d.ts.map

//#endregion
export { $client, $remote, AlephaServerLinks, ClientScope, FetchLinksOptions, GetLinksOptions, HttpClientLink, HttpVirtualClient, LinkProvider, RemoteDescriptor, RemoteDescriptorOptions, RemoteDescriptorProvider, ServerLinksProvider, ServerRemote, VirtualAction };
//# sourceMappingURL=index.d.ts.map