83 lines
2.6 KiB
TypeScript
83 lines
2.6 KiB
TypeScript
import type { IStorageHooks, IStorageHookContext } from '../../ts/core/interfaces.storage.js';
|
|
|
|
/**
|
|
* Create test storage hooks that track all calls.
|
|
* Useful for verifying hook invocation order and parameters.
|
|
*/
|
|
export function createTrackingHooks(options?: {
|
|
beforePutAllowed?: boolean;
|
|
beforeDeleteAllowed?: boolean;
|
|
throwOnAfterPut?: boolean;
|
|
throwOnAfterGet?: boolean;
|
|
}): {
|
|
hooks: IStorageHooks;
|
|
calls: Array<{ method: string; context: IStorageHookContext; timestamp: number }>;
|
|
} {
|
|
const calls: Array<{ method: string; context: IStorageHookContext; timestamp: number }> = [];
|
|
|
|
return {
|
|
calls,
|
|
hooks: {
|
|
beforePut: async (ctx) => {
|
|
calls.push({ method: 'beforePut', context: ctx, timestamp: Date.now() });
|
|
return {
|
|
allowed: options?.beforePutAllowed !== false,
|
|
reason: options?.beforePutAllowed === false ? 'Blocked by test' : undefined,
|
|
};
|
|
},
|
|
afterPut: async (ctx) => {
|
|
calls.push({ method: 'afterPut', context: ctx, timestamp: Date.now() });
|
|
if (options?.throwOnAfterPut) {
|
|
throw new Error('Test error in afterPut');
|
|
}
|
|
},
|
|
beforeDelete: async (ctx) => {
|
|
calls.push({ method: 'beforeDelete', context: ctx, timestamp: Date.now() });
|
|
return {
|
|
allowed: options?.beforeDeleteAllowed !== false,
|
|
reason: options?.beforeDeleteAllowed === false ? 'Blocked by test' : undefined,
|
|
};
|
|
},
|
|
afterDelete: async (ctx) => {
|
|
calls.push({ method: 'afterDelete', context: ctx, timestamp: Date.now() });
|
|
},
|
|
afterGet: async (ctx) => {
|
|
calls.push({ method: 'afterGet', context: ctx, timestamp: Date.now() });
|
|
if (options?.throwOnAfterGet) {
|
|
throw new Error('Test error in afterGet');
|
|
}
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create a blocking storage hooks implementation for quota testing.
|
|
*/
|
|
export function createQuotaHooks(maxSizeBytes: number): {
|
|
hooks: IStorageHooks;
|
|
currentUsage: { bytes: number };
|
|
} {
|
|
const currentUsage = { bytes: 0 };
|
|
|
|
return {
|
|
currentUsage,
|
|
hooks: {
|
|
beforePut: async (ctx) => {
|
|
const size = ctx.metadata?.size || 0;
|
|
if (currentUsage.bytes + size > maxSizeBytes) {
|
|
return { allowed: false, reason: `Quota exceeded: ${currentUsage.bytes + size} > ${maxSizeBytes}` };
|
|
}
|
|
return { allowed: true };
|
|
},
|
|
afterPut: async (ctx) => {
|
|
currentUsage.bytes += ctx.metadata?.size || 0;
|
|
},
|
|
afterDelete: async (ctx) => {
|
|
currentUsage.bytes -= ctx.metadata?.size || 0;
|
|
if (currentUsage.bytes < 0) currentUsage.bytes = 0;
|
|
},
|
|
},
|
|
};
|
|
}
|