131 lines
3.4 KiB
TypeScript
131 lines
3.4 KiB
TypeScript
import type { TRegistryProtocol } from './interfaces.core.js';
|
|
|
|
/**
|
|
* Actor information from request context
|
|
*/
|
|
export interface IStorageActor {
|
|
userId?: string;
|
|
tokenId?: string;
|
|
ip?: string;
|
|
userAgent?: string;
|
|
orgId?: string;
|
|
sessionId?: string;
|
|
}
|
|
|
|
/**
|
|
* Metadata about the storage operation
|
|
*/
|
|
export interface IStorageMetadata {
|
|
/** Content type of the object */
|
|
contentType?: string;
|
|
/** Size in bytes */
|
|
size?: number;
|
|
/** Content digest (e.g., sha256:abc123) */
|
|
digest?: string;
|
|
/** Package/artifact name */
|
|
packageName?: string;
|
|
/** Version */
|
|
version?: string;
|
|
}
|
|
|
|
/**
|
|
* Context passed to storage hooks
|
|
*/
|
|
export interface IStorageHookContext {
|
|
/** Type of operation */
|
|
operation: 'put' | 'delete' | 'get';
|
|
/** Storage key/path */
|
|
key: string;
|
|
/** Protocol that triggered this operation */
|
|
protocol: TRegistryProtocol;
|
|
/** Actor who performed the operation (if known) */
|
|
actor?: IStorageActor;
|
|
/** Metadata about the object */
|
|
metadata?: IStorageMetadata;
|
|
/** Timestamp of the operation */
|
|
timestamp: Date;
|
|
}
|
|
|
|
/**
|
|
* Result from a beforePut hook that can modify the operation
|
|
*/
|
|
export interface IBeforePutResult {
|
|
/** Whether to allow the operation */
|
|
allowed: boolean;
|
|
/** Optional reason for rejection */
|
|
reason?: string;
|
|
/** Optional modified metadata */
|
|
metadata?: IStorageMetadata;
|
|
}
|
|
|
|
/**
|
|
* Result from a beforeDelete hook
|
|
*/
|
|
export interface IBeforeDeleteResult {
|
|
/** Whether to allow the operation */
|
|
allowed: boolean;
|
|
/** Optional reason for rejection */
|
|
reason?: string;
|
|
}
|
|
|
|
/**
|
|
* Storage event hooks for quota tracking, audit logging, cache invalidation, etc.
|
|
*
|
|
* @example
|
|
* ```typescript
|
|
* const quotaHooks: IStorageHooks = {
|
|
* async beforePut(context) {
|
|
* const quota = await getQuota(context.actor?.orgId);
|
|
* const currentUsage = await getUsage(context.actor?.orgId);
|
|
* if (currentUsage + (context.metadata?.size || 0) > quota) {
|
|
* return { allowed: false, reason: 'Quota exceeded' };
|
|
* }
|
|
* return { allowed: true };
|
|
* },
|
|
*
|
|
* async afterPut(context) {
|
|
* await updateUsage(context.actor?.orgId, context.metadata?.size || 0);
|
|
* await auditLog('storage.put', context);
|
|
* },
|
|
*
|
|
* async afterDelete(context) {
|
|
* await invalidateCache(context.key);
|
|
* }
|
|
* };
|
|
* ```
|
|
*/
|
|
export interface IStorageHooks {
|
|
/**
|
|
* Called before storing an object.
|
|
* Return { allowed: false } to reject the operation.
|
|
* Use for quota checks, virus scanning, validation, etc.
|
|
*/
|
|
beforePut?(context: IStorageHookContext): Promise<IBeforePutResult>;
|
|
|
|
/**
|
|
* Called after successfully storing an object.
|
|
* Use for quota tracking, audit logging, notifications, etc.
|
|
*/
|
|
afterPut?(context: IStorageHookContext): Promise<void>;
|
|
|
|
/**
|
|
* Called before deleting an object.
|
|
* Return { allowed: false } to reject the operation.
|
|
* Use for preventing deletion of protected resources.
|
|
*/
|
|
beforeDelete?(context: IStorageHookContext): Promise<IBeforeDeleteResult>;
|
|
|
|
/**
|
|
* Called after successfully deleting an object.
|
|
* Use for quota updates, audit logging, cache invalidation, etc.
|
|
*/
|
|
afterDelete?(context: IStorageHookContext): Promise<void>;
|
|
|
|
/**
|
|
* Called after reading an object.
|
|
* Use for access logging, analytics, etc.
|
|
* Note: This is called even for cache hits.
|
|
*/
|
|
afterGet?(context: IStorageHookContext): Promise<void>;
|
|
}
|