alepha
Version:
Alepha is a convention-driven TypeScript framework for building robust, end-to-end type-safe applications, from serverless APIs to full-stack React apps.
316 lines (315 loc) • 10.9 kB
TypeScript
import { ServerRouteSecure } from "alepha/server/security";
import * as _alepha_core2 from "alepha";
import { Alepha, Descriptor, KIND, Static } from "alepha";
import * as _alepha_server0 from "alepha/server";
import { ActionDescriptor, ClientRequestEntry, ClientRequestOptions, ClientRequestResponse, FetchResponse, HttpClient, RequestConfigSchema, ServerHandler, ServerRequestConfigEntry, ServerTimingProvider } from "alepha/server";
import * as _alepha_logger0 from "alepha/logger";
import * as _alepha_retry0 from "alepha/retry";
import { ProxyDescriptorOptions, ServerProxyProvider } from "alepha/server/proxy";
import { ServiceAccountDescriptor, UserAccountToken } from "alepha/security";
import * as typebox18 from "typebox";
//#region src/schemas/apiLinksResponseSchema.d.ts
declare const apiLinkSchema: typebox18.TObject<{
name: typebox18.TString;
group: typebox18.TOptional<typebox18.TString>;
path: typebox18.TString;
method: typebox18.TOptional<typebox18.TString>;
requestBodyType: typebox18.TOptional<typebox18.TString>;
service: typebox18.TOptional<typebox18.TString>;
}>;
declare const apiLinksResponseSchema: typebox18.TObject<{
prefix: typebox18.TOptional<typebox18.TString>;
links: typebox18.TArray<typebox18.TObject<{
name: typebox18.TString;
group: typebox18.TOptional<typebox18.TString>;
path: typebox18.TString;
method: typebox18.TOptional<typebox18.TString>;
requestBodyType: typebox18.TOptional<typebox18.TString>;
service: typebox18.TOptional<typebox18.TString>;
}>>;
}>;
type ApiLinksResponse = Static<typeof apiLinksResponseSchema>;
type ApiLink = Static<typeof apiLinkSchema>;
//#endregion
//#region src/providers/LinkProvider.d.ts
/**
* Browser, SSR friendly, service to handle links.
*/
declare class LinkProvider {
static path: {
apiLinks: string;
apiSchema: string;
};
protected readonly log: _alepha_logger0.Logger;
protected readonly alepha: Alepha;
protected readonly httpClient: HttpClient;
protected serverLinks: Array<HttpClientLink>;
/**
* Get applicative links registered on the server.
* This does not include lazy-loaded remote links.
*/
getServerLinks(): HttpClientLink[];
/**
* Register a new link for the application.
*/
registerLink(link: HttpClientLink): void;
get links(): HttpClientLink[];
/**
* Force browser to refresh links from the server.
*/
fetchLinks(): Promise<HttpClientLink[]>;
/**
* Create a virtual client that can be used to call actions.
*
* Use js Proxy under the hood.
*/
client<T extends object>(scope?: ClientScope): HttpVirtualClient<T>;
/**
* Check if a link with the given name exists.
* @param name
*/
can(name: string): boolean;
/**
* 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 createVirtualAction<T extends RequestConfigSchema>(name: string, scope?: ClientScope): VirtualAction<T>;
protected followRemote(link: HttpClientLink, config?: Partial<ServerRequestConfigEntry>, options?: ClientRequestOptions): Promise<FetchResponse>;
protected getLinkByName(name: string, options?: ClientScope): Promise<HttpClientLink>;
}
interface HttpClientLink extends ApiLink {
secured?: boolean | ServerRouteSecure;
prefix?: string;
host?: string;
service?: string;
schema?: RequestConfigSchema;
handler?: ServerHandler;
}
interface ClientScope {
group?: string;
service?: string;
hostname?: 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;
}
//#endregion
//#region src/descriptors/$client.d.ts
/**
* Create a new client.
*/
declare const $client: {
<T extends object>(scope?: ClientScope): HttpVirtualClient<T>;
[KIND]: string;
};
//#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.text({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;
}
//#endregion
//#region src/providers/RemoteDescriptorProvider.d.ts
declare class RemoteDescriptorProvider {
protected readonly env: {
SERVER_API_PREFIX: string;
};
protected readonly alepha: Alepha;
protected readonly proxyProvider: ServerProxyProvider;
protected readonly linkProvider: LinkProvider;
protected readonly remotes: Array<ServerRemote>;
protected readonly log: _alepha_logger0.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 {
/**
* Name of the remote service.
*/
service: string;
/**
* URL to fetch links from.
*/
url: string;
/**
* Authorization header containing access token.
*/
authorization?: string;
}
interface ServerRemote {
/**
* URL of the remote service.
*/
url: string;
/**
* Name of the remote service.
*/
name: string;
/**
* Expose links as endpoint. It's not only internal.
*/
proxy: boolean;
/**
* It's only used inside the application.
*/
internal: boolean;
/**
* Links fetcher.
*/
links: (args: {
authorization?: string;
}) => Promise<ApiLinksResponse>;
/**
* Fetches schema for the remote service.
*/
schema: (args: {
name: string;
authorization?: string;
}) => Promise<any>;
/**
* Force a default access token provider when not provided.
*/
serviceAccount?: ServiceAccountDescriptor;
/**
* Prefix for the remote service links.
*/
prefix: string;
}
//#endregion
//#region src/providers/ServerLinksProvider.d.ts
declare class ServerLinksProvider {
protected readonly env: {
SERVER_API_PREFIX: string;
};
protected readonly alepha: Alepha;
protected readonly linkProvider: LinkProvider;
protected readonly remoteProvider: RemoteDescriptorProvider;
protected readonly serverTimingProvider: ServerTimingProvider;
get prefix(): string;
readonly onRoute: _alepha_core2.HookDescriptor<"configure">;
/**
* First API - Get all API links for the user.
*
* This is based on the user's permissions.
*/
readonly links: _alepha_server0.RouteDescriptor<{
response: typebox18.TObject<{
prefix: typebox18.TOptional<typebox18.TString>;
links: typebox18.TArray<typebox18.TObject<{
name: typebox18.TString;
group: typebox18.TOptional<typebox18.TString>;
path: typebox18.TString;
method: typebox18.TOptional<typebox18.TString>;
requestBodyType: typebox18.TOptional<typebox18.TString>;
service: typebox18.TOptional<typebox18.TString>;
}>>;
}>;
}>;
/**
* Second API - Get schema for a specific API link.
*
* Note: Body/Response schema are not included in `links` API because it's TOO BIG.
* I mean for 150+ links, you got 50ms of serialization time.
*/
readonly schema: _alepha_server0.RouteDescriptor<{
params: typebox18.TObject<{
name: typebox18.TString;
}>;
response: typebox18.TRecord<string, typebox18.TAny>;
}>;
getSchemaByName(name: string, options?: GetApiLinksOptions): Promise<RequestConfigSchema>;
/**
* Retrieves API links for the user based on their permissions.
* Will check on local links and remote links.
*/
getUserApiLinks(options: GetApiLinksOptions): Promise<ApiLinksResponse>;
}
interface GetApiLinksOptions {
user?: UserAccountToken;
authorization?: string;
}
//#endregion
//#region src/index.d.ts
declare module "alepha" {
interface State {
api?: ApiLinksResponse;
}
}
/**
* Provides server-side link management and remote capabilities for client-server interactions.
*
* The server-links module enables declarative link definitions using `$remote` and `$client` descriptors,
* facilitating seamless API endpoint management and client-server communication. It integrates with server
* security features to ensure safe and controlled access to resources.
*
* @see {@link $remote}
* @see {@link $client}
* @module alepha.server.links
*/
declare const AlephaServerLinks: _alepha_core2.Service<_alepha_core2.Module<{}>>;
//#endregion
export { $client, $remote, AlephaServerLinks, ApiLink, ApiLinksResponse, ClientScope, FetchLinksOptions, GetApiLinksOptions, HttpClientLink, HttpVirtualClient, LinkProvider, RemoteDescriptor, RemoteDescriptorOptions, RemoteDescriptorProvider, ServerLinksProvider, ServerRemote, VirtualAction, apiLinkSchema, apiLinksResponseSchema };
//# sourceMappingURL=index.d.ts.map