backfill: clearer logs + token check endpoint

This commit is contained in:
MOHAN 2026-07-02 23:59:35 +05:30
parent ef1a963c7f
commit 96dfd467df

View File

@ -36,13 +36,13 @@ app.get('/free-access/:shop', (req, res) => {
// ── BACKFILL: Re-run fulfillment service + locationId for shops that have null ─
// Hit: GET /admin/fix-location → runs all shops with null locationId
// Hit: GET /admin/fix-location/:shop → runs one specific shop
async function runFixLocation(req, res) {
async function runFixLocation(req, res) {
const stores = listTokens();
const targetShop = req.params.shop ? decodeURIComponent(req.params.shop).toLowerCase().trim() : null;
const toFix = Object.entries(stores).filter(([shop, record]) => {
if (targetShop) return shop === targetShop;
return !record.locationId;
return !record.locationId;
});
if (toFix.length === 0) {
@ -56,22 +56,48 @@ async function runFixLocation(req, res) {
continue;
}
try {
log(shop, `🔧 [BACKFILL] Re-running fulfillment setup for ${shop}`);
log(shop, `🔧 [BACKFILL] Starting fulfillment setup — token: ${record.accessToken?.slice(0,10)}...`);
const { fulfillmentService, locationId } = await createFulfillmentService(shop, record.accessToken);
log(shop, `🔧 [BACKFILL] createFulfillmentService returned → fulfillmentService=${JSON.stringify(fulfillmentService?.id || null)}, locationId=${locationId}`);
if (!locationId) {
log(shop, `❌ [BACKFILL] locationId is STILL null after createFulfillmentService — token is likely expired/revoked for this shop`);
results.push({ shop, status: 'failed', reason: 'locationId still null — token likely revoked, shop must reinstall', locationId: null });
continue;
}
saveToken(shop, record.accessToken, record.scope, fulfillmentService, locationId);
results.push({ shop, status: 'fixed', locationId, fulfillmentServiceId: fulfillmentService?.id || null });
log(shop, `✅ [BACKFILL] locationId=${locationId}`);
log(shop, `✅ [BACKFILL] SUCCESS — locationId=${locationId}`);
} catch (err) {
results.push({ shop, status: 'error', error: err.message });
log(shop, `❌ [BACKFILL] Error: ${err.message}`);
log(shop, `❌ [BACKFILL] Exception: ${err.message}`);
}
}
res.json({ fixed: results.filter(r => r.status === 'fixed').length, total: toFix.length, results });
}
app.get('/admin/fix-location', runFixLocation);
app.get('/admin/fix-location/:shop', runFixLocation);
}
app.get('/admin/fix-location', runFixLocation);
app.get('/admin/fix-location/:shop', runFixLocation);
// Debug: test if a shop's stored token is still valid
app.get('/admin/check-token/:shop', async (req, res) => {
const shop = decodeURIComponent(req.params.shop).toLowerCase().trim();
const record = getToken(shop);
if (!record) return res.json({ shop, status: 'not_found' });
if (!record.accessToken) return res.json({ shop, status: 'no_token' });
try {
const axios = require('axios');
const resp = await axios.get(`https://${shop}/admin/api/2025-10/shop.json`, {
headers: { 'X-Shopify-Access-Token': record.accessToken },
});
res.json({ shop, status: 'token_valid', shopName: resp.data?.shop?.name, locationId: record.locationId });
} catch (err) {
const statusCode = err.response?.status;
res.json({ shop, status: 'token_invalid', httpStatus: statusCode, error: err.response?.data || err.message, locationId: record.locationId });
}
});
// ── PUBLIC CHAT ENDPOINTS (for customer widget) ──────────────────────────────
// widget.js MUST be before /chat/:shop — otherwise Express treats "widget.js" as the :shop param