#!/usr/bin/env node const configuredBase = String(process.env.JD_TARGET_PARSE_URL || '').replace(/\/+$/, ''); const appId = process.env.JD_TARGET_PARSE_APP_ID; const masterKey = process.env.JD_TARGET_PARSE_MASTER_KEY; if (!configuredBase || !appId || !masterKey) { throw new Error('JD target Parse configuration is incomplete'); } const origin = new URL(configuredBase).origin; const appPathMatch = configuredBase.match(/\/backend\/([^/]+)/); const appPath = appPathMatch?.[1] || ''; const candidates = [ configuredBase, `${configuredBase}/classes/ProductDetail?limit=1`, appPath ? `${origin}/backend/${appPath}/classes/ProductDetail?limit=1` : '', appPath ? `${origin}/backend/${appPath}/data/parse/classes/ProductDetail?limit=1` : '', `${origin}/parse/classes/ProductDetail?limit=1`, ].filter(Boolean); async function fetchWithAuthorizationRetry(url) { for (let attempt = 1; attempt <= 10; attempt += 1) { const response = await fetch(url, { headers: { 'X-Parse-Application-Id': appId, 'X-Parse-Master-Key': masterKey, }, }); const body = await response.json().catch(() => null); if (!(response.status === 403 && body?.error === 'unauthorized') || attempt === 10) { return { response, body, attempt }; } } throw new Error('unreachable'); } for (const url of [...new Set(candidates)]) { const response = await fetch(url, { headers: { 'X-Parse-Application-Id': appId, 'X-Parse-Master-Key': masterKey, }, }); const text = await response.text(); let payload = null; try { payload = text ? JSON.parse(text) : null; } catch {} console.log(JSON.stringify({ url, status: response.status, contentType: response.headers.get('content-type'), parseCode: payload?.code ?? null, error: payload?.error ?? payload?.message ?? null, resultCount: Array.isArray(payload?.results) ? payload.results.length : null, bodyKind: payload ? 'json' : text ? 'non-json' : 'empty', }, null, 2)); } for (const className of ['ProductDetail', 'Product', 'AsinSkuMapping', 'JdStockSnapshot']) { const schemaResponse = await fetch(`${configuredBase}/schemas/${className}`, { headers: { 'X-Parse-Application-Id': appId, 'X-Parse-Master-Key': masterKey, }, }); const schema = await schemaResponse.json().catch(() => null); const countResponse = await fetch(`${configuredBase}/classes/${className}?limit=0&count=1`, { headers: { 'X-Parse-Application-Id': appId, 'X-Parse-Master-Key': masterKey, }, }); const countPayload = await countResponse.json().catch(() => null); console.log(JSON.stringify({ schemaStatus: schemaResponse.status, className: schema?.className ?? className, countStatus: countResponse.status, count: countPayload?.count ?? null, fields: Object.fromEntries( Object.entries(schema?.fields || {}).map(([name, definition]) => [name, definition?.type || null]), ), }, null, 2)); } for (const endpoint of [ `${configuredBase}/classes/ProductDetail?limit=1`, `${origin}/parse/classes/ProductDetail?limit=1`, ]) { const samples = []; for (let attempt = 0; attempt < 10; attempt += 1) { const response = await fetch(endpoint, { headers: { 'X-Parse-Application-Id': appId, 'X-Parse-Master-Key': masterKey, }, }); const body = await response.json().catch(() => null); samples.push({ status: response.status, resultCount: Array.isArray(body?.results) ? body.results.length : null }); } console.log(JSON.stringify({ endpoint, stabilitySamples: samples }, null, 2)); } for (const className of ['ProductDetail', 'Product', 'AsinSkuMapping', 'JdStockSnapshot']) { const { response, body, attempt } = await fetchWithAuthorizationRetry( `${configuredBase}/classes/${className}?limit=100&count=1`, ); console.log(JSON.stringify({ verifiedClass: className, status: response.status, attempts: attempt, count: body?.count ?? null, returnedItems: Array.isArray(body?.results) ? body.results.length : null, }, null, 2)); }