105 lines
4.6 KiB
TypeScript
105 lines
4.6 KiB
TypeScript
#!/usr/bin/env ts-node
|
||
/**
|
||
* Test: Guest API responses vs runtime config (DB).
|
||
* Calls public config and guest-facing endpoints, then compares guest limits
|
||
* and feature flags with the values from GET /api/v1/config (runtime config we configured).
|
||
* Run: npx ts-node scripts/test-guest-config-api.ts
|
||
* API_URL=http://127.0.0.1:4000 npx ts-node scripts/test-guest-config-api.ts
|
||
*/
|
||
|
||
import axios from 'axios';
|
||
|
||
const BASE_URL = process.env.API_URL || 'http://127.0.0.1:4000';
|
||
|
||
type PublicConfig = Record<string, unknown>;
|
||
|
||
interface GuestLimitsResponse {
|
||
tier: string;
|
||
limits: { maxFileSizeMb: number; maxFilesPerBatch: number; maxBatchSizeMb: number };
|
||
opsLimit: number | null;
|
||
opsUsedToday: number | null;
|
||
nextReset: string | null;
|
||
}
|
||
|
||
function assert(condition: boolean, message: string): void {
|
||
if (!condition) {
|
||
throw new Error(message);
|
||
}
|
||
}
|
||
|
||
async function main(): Promise<void> {
|
||
console.log('\n=== Guest API vs Runtime Config (DB) ===\n');
|
||
console.log('Base URL:', BASE_URL);
|
||
|
||
// 1. Fetch public runtime config (from DB - what we configured)
|
||
const configRes = await axios.get<PublicConfig>(`${BASE_URL}/api/v1/config`, {
|
||
validateStatus: () => true,
|
||
timeout: 10000,
|
||
});
|
||
assert(configRes.status === 200, `GET /api/v1/config failed: ${configRes.status}`);
|
||
const config = configRes.data;
|
||
console.log(' GET /api/v1/config: 200 OK');
|
||
|
||
// 2. Fetch guest limits (no auth = guest)
|
||
const limitsRes = await axios.get<GuestLimitsResponse>(`${BASE_URL}/api/v1/user/limits`, {
|
||
validateStatus: () => true,
|
||
timeout: 10000,
|
||
});
|
||
assert(limitsRes.status === 200, `GET /api/v1/user/limits failed: ${limitsRes.status}`);
|
||
const guest = limitsRes.data;
|
||
console.log(' GET /api/v1/user/limits (no auth): 200 OK');
|
||
|
||
// 3. Assert guest tier
|
||
assert(guest.tier === 'GUEST', `Expected tier GUEST, got ${guest.tier}`);
|
||
console.log(' Tier: GUEST');
|
||
|
||
// 4. Compare guest limits with runtime config (DB)
|
||
const maxFileMb = Number(config.max_file_size_mb_guest);
|
||
const maxFilesBatch = Number(config.max_files_per_batch_guest);
|
||
const maxBatchMb = Number(config.max_batch_size_mb_guest);
|
||
const maxOpsDay = Number(config.max_ops_per_day_guest);
|
||
|
||
assert(!Number.isNaN(maxFileMb), 'max_file_size_mb_guest missing or invalid in config');
|
||
assert(guest.limits.maxFileSizeMb === maxFileMb, `maxFileSizeMb: API=${guest.limits.maxFileSizeMb}, config(DB)=${maxFileMb}`);
|
||
console.log(` limits.maxFileSizeMb: ${guest.limits.maxFileSizeMb} (matches config)`);
|
||
|
||
assert(!Number.isNaN(maxFilesBatch), 'max_files_per_batch_guest missing or invalid in config');
|
||
assert(guest.limits.maxFilesPerBatch === maxFilesBatch, `maxFilesPerBatch: API=${guest.limits.maxFilesPerBatch}, config(DB)=${maxFilesBatch}`);
|
||
console.log(` limits.maxFilesPerBatch: ${guest.limits.maxFilesPerBatch} (matches config)`);
|
||
|
||
assert(!Number.isNaN(maxBatchMb), 'max_batch_size_mb_guest missing or invalid in config');
|
||
assert(guest.limits.maxBatchSizeMb === maxBatchMb, `maxBatchSizeMb: API=${guest.limits.maxBatchSizeMb}, config(DB)=${maxBatchMb}`);
|
||
console.log(` limits.maxBatchSizeMb: ${guest.limits.maxBatchSizeMb} (matches config)`);
|
||
|
||
assert(!Number.isNaN(maxOpsDay), 'max_ops_per_day_guest missing or invalid in config');
|
||
assert(guest.opsLimit === maxOpsDay, `opsLimit: API=${guest.opsLimit}, config(DB)=${maxOpsDay}`);
|
||
console.log(` opsLimit: ${guest.opsLimit} (matches config)`);
|
||
|
||
// 5. Guest-relevant feature flags from config (for reference)
|
||
const adsEnabled = config.ads_enabled === true || config.ads_enabled === 'true';
|
||
const registrationOpen = config.registration_open === true || config.registration_open === 'true';
|
||
const maintenanceMode = config.maintenance_mode === true || config.maintenance_mode === 'true';
|
||
console.log('\n Feature flags (from config):');
|
||
console.log(` ads_enabled: ${adsEnabled}`);
|
||
console.log(` registration_open: ${registrationOpen}`);
|
||
console.log(` maintenance_mode: ${maintenanceMode}`);
|
||
|
||
// 6. Optional: GET /api/v1/config/pricing – guest section (still from env in many setups; we just log)
|
||
const pricingRes = await axios.get(`${BASE_URL}/api/v1/config/pricing`, {
|
||
validateStatus: () => true,
|
||
timeout: 10000,
|
||
});
|
||
if (pricingRes.status === 200 && pricingRes.data?.limits?.guest) {
|
||
const pricingGuest = pricingRes.data.limits.guest;
|
||
console.log('\n GET /api/v1/config/pricing guest limits (may be env-driven):');
|
||
console.log(` maxFileSizeMb: ${pricingGuest.maxFileSizeMb}, maxOpsPerDay: ${pricingGuest.maxOpsPerDay}`);
|
||
}
|
||
|
||
console.log('\n=== All guest vs config checks passed ===\n');
|
||
}
|
||
|
||
main().catch((err) => {
|
||
console.error('\nFAIL:', err.message);
|
||
process.exit(1);
|
||
});
|