#!/usr/bin/env node import { randomBytes } from 'node:crypto'; const APP_ID = process.env.XIAOSHU_PARSE_APP_ID || '7pIbDBJmKx_main'; const MASTER_KEY = process.env.XIAOSHU_MASTER_KEY || ''; const PARSE_URL = (process.env.XIAOSHU_PARSE_URL || 'https://server.xiaoshu.pro/parse').replace(/\/$/, ''); const FUNCTION_URL = PARSE_URL.replace(/\/parse$/, '/api/functions/xiaoshu/app/gateway'); const SAMPLE_USER_ID = Number(process.env.XIAOSHU_SMOKE_USER_ID || 1845); if (!MASTER_KEY) throw new Error('缺少 XIAOSHU_MASTER_KEY'); const appHeaders = { 'X-Parse-Application-Id': APP_ID, 'Content-Type': 'application/json' }; const masterHeaders = { ...appHeaders, 'X-Parse-Master-Key': MASTER_KEY }; let userId = ''; async function json(url, init = {}) { const response = await fetch(url, init); const payload = await response.json().catch(() => ({})); if (!response.ok || payload.error || payload.retcode === -1) throw new Error(payload.error || payload.retmsg || `HTTP ${response.status}`); return payload; } async function master(path, init = {}) { return json(`${PARSE_URL}${path}`, { ...init, headers: { ...masterHeaders, ...(init.headers || {}) } }); } async function timedCloud(token, action, params) { const startedAt = performance.now(); const payload = await json(FUNCTION_URL, { method: 'POST', headers: appHeaders, body: JSON.stringify({ token, params: { action, uid: SAMPLE_USER_ID, ...params } }), signal: AbortSignal.timeout(30_000), }); const result = payload.result; const summary = { action, durationMs: Math.round(performance.now() - startedAt), rows: Array.isArray(result) ? result.length : Array.isArray(result?.records) ? result.records.length : Array.isArray(result?.schedules) ? result.schedules.length : undefined, }; console.log(JSON.stringify(summary)); return summary; } try { const company = (await master('/classes/Company?limit=1&keys=objectId')).results?.[0]; if (!company?.objectId) throw new Error('生产 Parse 未找到 Company'); const suffix = `${Date.now()}_${randomBytes(4).toString('hex')}`; const username = `app_read_smoke_${suffix}`; const password = `${randomBytes(24).toString('base64url')}Aa9!`; const created = await master('/users', { method: 'POST', body: JSON.stringify({ username, password, isAdmin: true, role: 'admin', roles: ['admin', 'super-admin'], adminRoleKey: 'super-admin', legacyGroupId: 1, legacyUserId: 990000000 + Math.floor(Date.now() / 1000) % 9000000, company: { __type: 'Pointer', className: 'Company', objectId: company.objectId }, testCreatedBy: 'smoke-app-performance-read', }), }); userId = created.objectId; const login = await json(`${PARSE_URL}/login`, { method: 'POST', headers: appHeaders, body: JSON.stringify({ username, password }) }); const token = login.sessionToken; const results = []; results.push(await timedCloud(token, 'app_companion_overview', { mode: 'student', rangeStart: '2026-08-01', rangeEnd: '2026-09-11', limit: 200 })); results.push(await timedCloud(token, 'app_learning_overview', { studentId: SAMPLE_USER_ID, calendarStart: '2026-08-01', calendarEnd: '2026-09-11' })); results.push(await timedCloud(token, 'e_ck_list', { nids: '40', cpage: 1, psize: 100 })); results.push(await timedCloud(token, 'app_account_overview', {})); console.log(JSON.stringify({ sampleUserId: SAMPLE_USER_ID, results }, null, 2)); } finally { if (userId) { const where = encodeURIComponent(JSON.stringify({ user: { __type: 'Pointer', className: '_User', objectId: userId } })); const sessions = await master(`/classes/_Session?where=${where}&limit=100&keys=objectId`).catch(() => ({ results: [] })); for (const session of sessions.results || []) await master(`/classes/_Session/${session.objectId}`, { method: 'DELETE' }).catch(() => undefined); await master(`/users/${userId}`, { method: 'DELETE' }).catch(() => undefined); } }