alepha
Version:
Easy-to-use modern TypeScript framework for building many kind of applications.
453 lines • 21.8 kB
TypeScript
import { Alepha, Static } from "alepha";
import { IssuerResolver, UserInfo } from "alepha/security";
import { DateTimeProvider } from "alepha/datetime";
//#region ../../src/api/keys/entities/apiKeyEntity.d.ts
declare const apiKeyEntity: import("alepha/orm").EntityPrimitive<import("zod").ZodObject<{
id: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_PRIMARY_KEY>, typeof import("alepha/orm").PG_DEFAULT>;
createdAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_CREATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
updatedAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_UPDATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
organizationId: import("alepha/orm").PgAttr<import("zod").ZodOptional<import("zod").ZodString> | import("zod").ZodString, typeof import("alepha/orm").PG_ORGANIZATION>;
userId: import("zod").ZodString;
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
tokenHash: import("zod").ZodString;
tokenPrefix: import("zod").ZodString;
tokenSuffix: import("zod").ZodString;
roles: import("alepha/orm").PgAttr<import("zod").ZodArray<import("zod").ZodString>, typeof import("alepha/orm").PG_DEFAULT>;
lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>;
lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>;
usageCount: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
revokedAt: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>>;
type ApiKeyEntity = Static<typeof apiKeyEntity.schema>;
//#endregion
//#region ../../src/api/keys/services/ApiKeyService.d.ts
declare class ApiKeyService {
protected readonly alepha: Alepha;
protected readonly dateTimeProvider: DateTimeProvider;
protected readonly log: import("alepha/logger").Logger;
protected readonly repo: import("alepha/orm").Repository<import("zod").ZodObject<{
id: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_PRIMARY_KEY>, typeof import("alepha/orm").PG_DEFAULT>;
createdAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_CREATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
updatedAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_UPDATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
organizationId: import("alepha/orm").PgAttr<import("zod").ZodOptional<import("zod").ZodString> | import("zod").ZodString, typeof import("alepha/orm").PG_ORGANIZATION>;
userId: import("zod").ZodString;
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
tokenHash: import("zod").ZodString;
tokenPrefix: import("zod").ZodString;
tokenSuffix: import("zod").ZodString;
roles: import("alepha/orm").PgAttr<import("zod").ZodArray<import("zod").ZodString>, typeof import("alepha/orm").PG_DEFAULT>;
lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>;
lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>;
usageCount: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
revokedAt: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>>;
/**
* Cache validated API keys for 15 minutes.
*
* Pinned to per-isolate memory:
* - The cache replaces a single indexed SELECT on `api_keys`. Routing it
* through a distributed K/V (KV/Redis) buys little — the SELECT is
* already cheap — and pinning to DB would actively trade one SQL read
* for another.
* - Cold-start gives a fresh DB read on every new isolate, which is
* *better* for revocation visibility than a distributed cache that
* keeps serving stale entries until its own TTL.
* - Avoids provisioning KV/Redis just for this one cache. Users who need
* cross-isolate sharing for high-throughput API auth can override
* globally via `alepha.with({ provide: CacheProvider, use: ... })`.
*/
protected readonly validationCache: import("alepha/cache").CacheMiddlewareFn<{
id: string;
createdAt: string;
updatedAt: string;
organizationId: string | undefined;
userId: string;
name: string;
description?: string | undefined;
tokenHash: string;
tokenPrefix: string;
tokenSuffix: string;
roles: string[];
lastUsedAt?: string | undefined;
lastUsedIp?: string | undefined;
usageCount: number;
expiresAt?: string | undefined;
revokedAt?: string | undefined;
} | null>;
/**
* Create an issuer resolver for API key authentication.
* Lower priority means it runs before JWT resolver.
*
* @param options.priority - Priority of this resolver (default: 50, JWT is 100)
* @param options.prefix - API key prefix to match in Bearer header (default: "ak")
*/
createResolver(options?: {
priority?: number;
prefix?: string;
}): IssuerResolver;
/**
* Create a new API key for a user.
* Returns both the API key entity and the plain token (which is only available once).
*/
create(options: {
userId: string;
name: string;
roles: string[];
description?: string;
expiresAt?: Date;
prefix?: string;
}): Promise<{
apiKey: ApiKeyEntity;
token: string;
}>;
/**
* List all non-revoked API keys for a user.
*/
list(userId: string): Promise<ApiKeyEntity[]>;
/**
* Find all API keys with optional filtering (admin only).
*/
findAll(query: {
userId?: string;
includeRevoked?: boolean;
page?: number;
size?: number;
sort?: string;
}): Promise<import("alepha").Page<import("alepha/orm").PgStatic<import("zod").ZodObject<{
id: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_PRIMARY_KEY>, typeof import("alepha/orm").PG_DEFAULT>;
createdAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_CREATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
updatedAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_UPDATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
organizationId: import("alepha/orm").PgAttr<import("zod").ZodOptional<import("zod").ZodString> | import("zod").ZodString, typeof import("alepha/orm").PG_ORGANIZATION>;
userId: import("zod").ZodString;
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
tokenHash: import("zod").ZodString;
tokenPrefix: import("zod").ZodString;
tokenSuffix: import("zod").ZodString;
roles: import("alepha/orm").PgAttr<import("zod").ZodArray<import("zod").ZodString>, typeof import("alepha/orm").PG_DEFAULT>;
lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>;
lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>;
usageCount: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
revokedAt: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>, import("alepha/orm").PgRelationMap<import("zod").ZodObject<{
id: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_PRIMARY_KEY>, typeof import("alepha/orm").PG_DEFAULT>;
createdAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_CREATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
updatedAt: import("alepha/orm").PgAttr<import("alepha/orm").PgAttr<import("zod").ZodString, typeof import("alepha/orm").PG_UPDATED_AT>, typeof import("alepha/orm").PG_DEFAULT>;
organizationId: import("alepha/orm").PgAttr<import("zod").ZodOptional<import("zod").ZodString> | import("zod").ZodString, typeof import("alepha/orm").PG_ORGANIZATION>;
userId: import("zod").ZodString;
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
tokenHash: import("zod").ZodString;
tokenPrefix: import("zod").ZodString;
tokenSuffix: import("zod").ZodString;
roles: import("alepha/orm").PgAttr<import("zod").ZodArray<import("zod").ZodString>, typeof import("alepha/orm").PG_DEFAULT>;
lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>;
lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>;
usageCount: import("alepha/orm").PgAttr<import("zod").ZodInt, typeof import("alepha/orm").PG_DEFAULT>;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
revokedAt: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>>>>>;
/**
* Get an API key by ID (admin only).
*/
getById(id: string): Promise<ApiKeyEntity>;
/**
* Revoke any API key (admin only).
*/
revokeByAdmin(id: string): Promise<void>;
/**
* Revoke many API keys in one repository call (admin only). Already-revoked
* keys are silently skipped. Returns the ids that were actually revoked.
*/
revokeManyByAdmin(ids: string[]): Promise<string[]>;
/**
* Revoke an API key. Only the owner can revoke their own keys.
*/
revoke(id: string, userId: string): Promise<void>;
/**
* Validate an API key token and return user info if valid.
*/
validate(token: string): Promise<UserInfo | null>;
/**
* Update usage statistics for an API key.
*/
protected updateUsage(id: string): Promise<void>;
/**
* Hash a token using SHA-256.
*/
protected hashToken(token: string): string;
}
//#endregion
//#region ../../src/api/keys/controllers/AdminApiKeyController.d.ts
/**
* REST API controller for admin API key management.
* Admins can list, view, and revoke any API key.
*/
declare class AdminApiKeyController {
protected readonly url = "/admin/api-keys";
protected readonly group = "admin:api-keys";
protected readonly apiKeyService: ApiKeyService;
/**
* Find all API keys with optional filtering.
*/
readonly findApiKeys: import("alepha/server").ActionPrimitiveFn<{
query: import("zod").ZodObject<{
page: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodInt>>;
size: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodInt>>;
sort: import("zod").ZodOptional<import("zod").ZodString>;
userId: import("zod").ZodOptional<import("zod").ZodString>;
includeRevoked: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, import("zod/v4/core").$strip>;
response: import("zod").ZodObject<{
content: import("zod").ZodArray<import("zod").ZodObject<{
id: import("zod").ZodString;
userId: import("zod").ZodString;
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
tokenPrefix: import("zod").ZodString;
tokenSuffix: import("zod").ZodString;
roles: import("zod").ZodArray<import("zod").ZodString>;
createdAt: import("zod").ZodString;
lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>;
lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
revokedAt: import("zod").ZodOptional<import("zod").ZodString>;
usageCount: import("zod").ZodInt;
}, import("zod/v4/core").$strip>>;
page: import("zod").ZodObject<{
number: import("zod").ZodInt;
size: import("zod").ZodInt;
offset: import("zod").ZodInt;
numberOfElements: import("zod").ZodInt;
totalElements: import("zod").ZodOptional<import("zod").ZodInt>;
totalPages: import("zod").ZodOptional<import("zod").ZodInt>;
isEmpty: import("zod").ZodBoolean;
isFirst: import("zod").ZodBoolean;
isLast: import("zod").ZodBoolean;
}, import("zod/v4/core").$strip>;
}, import("zod/v4/core").$strip>;
}>;
/**
* Get an API key by ID.
*/
readonly getApiKey: import("alepha/server").ActionPrimitiveFn<{
params: import("zod").ZodObject<{
id: import("zod").ZodString;
}, import("zod/v4/core").$strip>;
response: import("zod").ZodObject<{
id: import("zod").ZodString;
userId: import("zod").ZodString;
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
tokenPrefix: import("zod").ZodString;
tokenSuffix: import("zod").ZodString;
roles: import("zod").ZodArray<import("zod").ZodString>;
createdAt: import("zod").ZodString;
lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>;
lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
revokedAt: import("zod").ZodOptional<import("zod").ZodString>;
usageCount: import("zod").ZodInt;
}, import("zod/v4/core").$strip>;
}>;
/**
* Revoke any API key.
*/
readonly revokeApiKey: import("alepha/server").ActionPrimitiveFn<{
params: import("zod").ZodObject<{
id: import("zod").ZodString;
}, import("zod/v4/core").$strip>;
response: import("zod").ZodObject<{
ok: import("zod").ZodBoolean;
id: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodInt]>>;
count: import("zod").ZodOptional<import("zod").ZodNumber>;
}, import("zod/v4/core").$strip>;
}>;
/**
* Revoke many API keys in one request.
*/
readonly revokeApiKeys: import("alepha/server").ActionPrimitiveFn<{
body: import("zod").ZodObject<{
ids: import("zod").ZodArray<import("zod").ZodString>;
}, import("zod/v4/core").$strip>;
response: import("zod").ZodObject<{
revoked: import("zod").ZodArray<import("zod").ZodString>;
}, import("zod/v4/core").$strip>;
}>;
}
//#endregion
//#region ../../src/api/keys/controllers/ApiKeyController.d.ts
/**
* REST API controller for user's own API key management.
* Users can create, list, and revoke their own API keys.
*/
declare class ApiKeyController {
protected readonly url = "/api-keys";
protected readonly group = "api-keys";
protected readonly apiKeyService: ApiKeyService;
/**
* Create a new API key for the authenticated user.
* The token is only returned once upon creation.
*/
readonly createApiKey: import("alepha/server").ActionPrimitiveFn<{
body: import("zod").ZodObject<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>;
response: import("zod").ZodObject<{
id: import("zod").ZodString;
name: import("zod").ZodString;
token: import("zod").ZodString;
tokenSuffix: import("zod").ZodString;
roles: import("zod").ZodArray<import("zod").ZodString>;
createdAt: import("zod").ZodString;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>;
}>;
/**
* List all active API keys for the authenticated user.
* Does not return the actual tokens.
*/
readonly listApiKeys: import("alepha/server").ActionPrimitiveFn<{
response: import("zod").ZodArray<import("zod").ZodObject<{
id: import("zod").ZodString;
name: import("zod").ZodString;
tokenPrefix: import("zod").ZodString;
tokenSuffix: import("zod").ZodString;
roles: import("zod").ZodArray<import("zod").ZodString>;
createdAt: import("zod").ZodString;
lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>;
lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
usageCount: import("zod").ZodInt;
}, import("zod/v4/core").$strip>>;
}>;
/**
* Revoke an API key. Only the owner can revoke their own keys.
*/
readonly revokeMyApiKey: import("alepha/server").ActionPrimitiveFn<{
params: import("zod").ZodObject<{
id: import("zod").ZodString;
}, import("zod/v4/core").$strip>;
response: import("zod").ZodObject<{
ok: import("zod").ZodBoolean;
}, import("zod/v4/core").$strip>;
}>;
}
//#endregion
//#region ../../src/api/keys/schemas/adminApiKeyQuerySchema.d.ts
declare const adminApiKeyQuerySchema: import("zod").ZodObject<{
page: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodInt>>;
size: import("zod").ZodOptional<import("zod").ZodDefault<import("zod").ZodInt>>;
sort: import("zod").ZodOptional<import("zod").ZodString>;
userId: import("zod").ZodOptional<import("zod").ZodString>;
includeRevoked: import("zod").ZodOptional<import("zod").ZodBoolean>;
}, import("zod/v4/core").$strip>;
//#endregion
//#region ../../src/api/keys/schemas/adminApiKeyResourceSchema.d.ts
declare const adminApiKeyResourceSchema: import("zod").ZodObject<{
id: import("zod").ZodString;
userId: import("zod").ZodString;
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
tokenPrefix: import("zod").ZodString;
tokenSuffix: import("zod").ZodString;
roles: import("zod").ZodArray<import("zod").ZodString>;
createdAt: import("zod").ZodString;
lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>;
lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
revokedAt: import("zod").ZodOptional<import("zod").ZodString>;
usageCount: import("zod").ZodInt;
}, import("zod/v4/core").$strip>;
type AdminApiKeyResource = Static<typeof adminApiKeyResourceSchema>;
//#endregion
//#region ../../src/api/keys/schemas/createApiKeyBodySchema.d.ts
declare const createApiKeyBodySchema: import("zod").ZodObject<{
name: import("zod").ZodString;
description: import("zod").ZodOptional<import("zod").ZodString>;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>;
//#endregion
//#region ../../src/api/keys/schemas/createApiKeyResponseSchema.d.ts
declare const createApiKeyResponseSchema: import("zod").ZodObject<{
id: import("zod").ZodString;
name: import("zod").ZodString;
token: import("zod").ZodString;
tokenSuffix: import("zod").ZodString;
roles: import("zod").ZodArray<import("zod").ZodString>;
createdAt: import("zod").ZodString;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
}, import("zod/v4/core").$strip>;
//#endregion
//#region ../../src/api/keys/schemas/listApiKeyResponseSchema.d.ts
declare const listApiKeyItemSchema: import("zod").ZodObject<{
id: import("zod").ZodString;
name: import("zod").ZodString;
tokenPrefix: import("zod").ZodString;
tokenSuffix: import("zod").ZodString;
roles: import("zod").ZodArray<import("zod").ZodString>;
createdAt: import("zod").ZodString;
lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>;
lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
usageCount: import("zod").ZodInt;
}, import("zod/v4/core").$strip>;
declare const listApiKeyResponseSchema: import("zod").ZodArray<import("zod").ZodObject<{
id: import("zod").ZodString;
name: import("zod").ZodString;
tokenPrefix: import("zod").ZodString;
tokenSuffix: import("zod").ZodString;
roles: import("zod").ZodArray<import("zod").ZodString>;
createdAt: import("zod").ZodString;
lastUsedAt: import("zod").ZodOptional<import("zod").ZodString>;
lastUsedIp: import("zod").ZodOptional<import("zod").ZodString>;
expiresAt: import("zod").ZodOptional<import("zod").ZodString>;
usageCount: import("zod").ZodInt;
}, import("zod/v4/core").$strip>>;
//#endregion
//#region ../../src/api/keys/schemas/revokeApiKeyParamsSchema.d.ts
declare const revokeApiKeyParamsSchema: import("zod").ZodObject<{
id: import("zod").ZodString;
}, import("zod/v4/core").$strip>;
//#endregion
//#region ../../src/api/keys/schemas/revokeApiKeyResponseSchema.d.ts
declare const revokeApiKeyResponseSchema: import("zod").ZodObject<{
ok: import("zod").ZodBoolean;
}, import("zod/v4/core").$strip>;
//#endregion
//#region ../../src/api/keys/index.d.ts
/**
* API key management module for programmatic access.
*
* **Features:**
* - Create API keys with role snapshots
* - List and revoke API keys
* - 15-minute validation caching
* - Query param (?api_key=) and Bearer header support
*
* **Integration:**
* To enable API key authentication for an issuer, register the resolver:
*
* ```ts
* class MyApp {
* apiKeyService = $inject(ApiKeyService);
* issuer = $issuer({
* secret: env.APP_SECRET,
* resolvers: [this.apiKeyService.createResolver()],
* });
* }
* ```
*
* @module alepha.api.keys
*/
declare const AlephaApiKeys: import("alepha").Service<import("alepha").Module>;
//#endregion
export { AdminApiKeyController, AdminApiKeyResource, AlephaApiKeys, ApiKeyController, ApiKeyEntity, ApiKeyService, adminApiKeyQuerySchema, adminApiKeyResourceSchema, apiKeyEntity, createApiKeyBodySchema, createApiKeyResponseSchema, listApiKeyItemSchema, listApiKeyResponseSchema, revokeApiKeyParamsSchema, revokeApiKeyResponseSchema };
//# sourceMappingURL=index.d.ts.map