CRM માં ૨૦ કોન્ટેક્ટ્સ આર્કાઇવ થવાના હતા, છતાં UI એ લીલા રંગનું સક્સેસ બેજ બતાવ્યું અને ઓપરેશન કંઈ કર્યા વગર શાંતિથી પતી ગયું. Supabase-JS મ્યુટેશનમાં error ફિલ્ડને ફરજિયાત બનાવતું એક TypeScript હેલ્પર હવે ડેવલપર્સને તે નિષ્ફળતાને છુપાવવાને બદલે તેનો સામનો કરવા માટે મજબૂર કરે છે.

Supabase-JS નું રિટર્ન શેપ (return shape) કેમ એક જાળ છે

Supabase નું JavaScript ક્લાયન્ટ (@supabase/supabase-js) જ્યારે ડેટાબેઝ રાઈટ (write) રિજેક્ટ થાય ત્યારે એક્સેપ્શન (exceptions) થ્રો કરતું નથી. તેના બદલે તે { data, error } ઓબ્જેક્ટ સાથે પ્રોમિસ (promise) રિઝોલ્વ કરે છે. જો રો-લેવલ સિક્યુરિટી (RLS) પોલિસી, યુનિક-કી વાયોલેશન અથવા અન્ય કોઈ કન્સ્ટ્રેન્ટ ક્વેરીને બ્લોક કરે, તો data null તરીકે આવે છે અને error માં ડેટાબેઝ મેસેજ હોય છે. ક્લાયન્ટ એવું માની લે છે કે કોલર error ની તપાસ કરશે; તે ક્યારેય કોલને અટકાવતું નથી.

વ્યવહારમાં ઘણા કોડબેઝ આ કોલને 'ફાયર-એન્ડ-ફોરગેટ' (fire-and-forget) ઓપરેશન તરીકે ગણે છે:

await supabase
  .from('contacts')
  .update({ statut: 'ancien', archived_at: now })
  .eq('id', id)

return { ok: true }

જ્યારે update ને RLS રૂલ દ્વારા બ્લોક કરવામાં આવે છે, ત્યારે પણ પ્રોમિસ રિઝોલ્વ થાય છે. કારણ કે ડેવલપર ક્યારેય { error } ને ડિસ્ટ્રક્ચર (destructure) કરતો નથી, તેથી નિષ્ફળતા અદ્રશ્ય રહે છે. ફંક્શન { ok: true } રિટર્ન કરે છે, UI સફળતા બતાવે છે, અને ડેટા યથાવત રહે છે. કોઈ લોગ્સ દેખાતા નથી, કોઈ Sentry એલર્ટ નથી આવતું, અને આ બગ દિવસો સુધી રહી શકે છે.

લિન્ટર (linter) પૂરતું નથી

સ્ટેટિક એનાલિસિસ ટૂલ્સ error પ્રોપર્ટીને અવગણવામાં આવે ત્યારે ચેતવણી આપી શકે છે, પરંતુ તેઓ રનટાઇમ કોન્ટ્રાક્ટ (runtime contract) લાગુ કરી શકતા નથી. ડેવલપર હજુ પણ const _ = await … લખી શકે છે અને ચેતવણીને શાંત કરી શકે છે, અથવા તેઓ રૂલને દબાવવા માટે કોમેન્ટ ઉમેરી શકે છે. મૂળ સમસ્યા એ છે કે ટાઇપ સિસ્ટમ error નો ઉલ્લેખ કર્યા વગર પણ કોલ સફળ થવા દે છે.

mutate() હેલ્પર: એરર હેન્ડલિંગને ફરજિયાત બનાવવું

લેખકે mutate() નામનું એક નાનું રેપર (wrapper) બનાવ્યું છે જે રિટર્ન ટાઇપના શેપને બદલે છે. { data, error } ને બદલે, હેલ્પર એક ટ્યુપલ (tuple) [data, error] રિટર્ન કરે છે જ્યાં error એ ફરજિયાત ફિલ્ડ છે. ત્યારબાદ TypeScript એવા કોઈપણ કોલને કમ્પાઇલ કરવાનો ઇનકાર કરે છે જે બીજા એલિમેન્ટને અવગણે છે.

async function mutate<T>(promise: Promise<{ data: T | null; error: any }>) {
  const { data, error } = await promise
  // Send error to Sentry immediately
  if (error) Sentry.captureException(error)
  return [data, error] as const
}

ઉપયોગ સ્પષ્ટ બને છે:

const [result, err] = await mutate(
  supabase
    .from('contacts')
    .update({ statut: 'ancien', archived_at: now })
    .eq('id', id)
)

if (err) {
  // Handle or rethrow
  return { ok: false, message: err.message }
}
return { ok: true, data: result }

જો ડેવલપર err ને કેપ્ચર કરવાનું ભૂલી જાય, તો TypeScript એરર આપે છે: “Tuple type [T, any] of length 2 has no element at index 1.” જ્યાં સુધી એરરનું નિરાકરણ ન આવે ત્યાં સુધી કોડ કમ્પાઇલ થશે નહીં. આ હેલ્પર Sentry ઇન્સ્ટ્રુમેન્ટેશન (instrumentation) પણ ઇન્જેક્ટ કરે છે, જે ખાતરી કરે છે કે દરેક ડેટાબેઝ રિજેક્શન લોગ થાય છે, ભલે કોલર તેને પછીથી અવગણી નાખે.

શું જોખમમાં છે

  • ડેટા ઇન્ટિગ્રિટી (Data integrity) – સાયલન્ટ ફેઈલ્યોર (Silent failures) પ્રોડક્શનમાં અમાન્ય સ્ટેટ આવવા દે છે. આર્કાઇવ થયેલ કોન્ટેક્ટ જે ક્યારેય એક્ટિવ લિસ્ટમાંથી નીકળ્યો નથી, તેના કારણે આગળના રિપોર્ટ્સ ખોટા પડી શકે છે.
  • યુઝર ટ્રસ્ટ (User trust) – જ્યારે કંઈ બદલાયું નથી છતાં UI સફળતાનો દાવો કરે છે, ત્યારે વિશ્વાસ ઘટે છે. ગ્રાહકો "archived" જુએ છે પરંતુ સર્ચમાં હજુ પણ કોન્ટેક્ટ શોધી શકે છે.
  • ડેવલપરનો સમય – કાલ્પનિક બગ્સ (phantom bugs) શોધવામાં કલાકો બગડે છે. સ્પષ્ટ એરર હેન્ડલિંગ નિષ્ફળતાના સમયે જ સમસ્યાને સામે લાવે છે, જેનાથી ડીબગિંગ લૂપ ટૂંકાવી શકાય છે.
  • ઓપરેશનલ કોસ્ટ (Operational cost) – સાયલન્ટ ડેટા લોસની ઘટનાના ખર્ચની સરખામણીમાં થોડી વધારાની લાઇન અને નાનું રેપર ઉમેરવું નહિવત છે.

ટ્રેડ-ઓફ (The trade-off)

આ હેલ્પરથી કોડમાં થોડી વધારાની લાઇન (verbosity) ઉમેરાય છે: હવે દરેક મ્યુટેશન કોલ એક ટ્યુપલ રિટર્ન કરે છે, અને કોલર્સએ if (err) બ્લોક લખવો પડે છે. કેટલીક ટીમો આને બિનજરૂરી (boilerplate noise) ગણી શકે છે, ખાસ કરીને સાદા CRUD એક્શન માટે જ્યાં તેઓ સફળતાની અપેક્ષા રાખતા હોય. તેનો વિરોધ એ છે કે વધારાનો કોડ એક સુરક્ષા કવચ છે, કોઈ વૈકલ્પિક ફીચર નથી. જે વાતાવરણમાં ડેટાની સચોટતા સર્વોપરી હોય—જેમ કે CRM સિસ્ટમ્સ, ફાઇનાન્સ, હેલ્થ—ત્યાં આ ચેક લગાવવો ફાયદાકારક સાબિત થાય છે.

આગળ શું

લેખકે ત્રીજા ભાગનું વચન આપ્યું છે જે સમજાવશે કે કેવી રીતે RLS પોલિસીઓ કોઈ સમજૂતી વગર શૂન્ય રો (rows) રિટર્ન કરે છે. તે પેટર્ન, સાયલન્ટ-એરર કેસની જેમ જ, દેખીતી રીતે સફળ ક્વેરી પાછળ નિષ્ફળતાઓને છુપાવે છે. આ શ્રેણીનો હેતુ Supabase ના API ના "અફવાવાળા" (rumor) પાસાને ખુલ્લું પાડવાનો અને ડેવલપર્સને તથ્યો માંગવા માટે નક્કર સાધનો આપવાનો છે.

Takeaway: Supabase-JS ની ડિઝાઇન નિષ્ફળ રાઈટને સફળતા જેવું દેખાવા દે છે, સિવાય કે તમે error ફિલ્ડ વાંચવાનું યાદ રાખો. કોલ્સને TypeScript-એન્ફોર્સ્ડ હેલ્પર દ્વારા રેપ કરવામાંથી, જે error ને ફરજિયાત બનાવે છે અને તેને Sentry માં લોગ કરે છે, તમે સાયલન્ટ ફેઈલ્યોરને દૃશ્યમાન અને કાર્યક્ષમ ઇવેન્ટ્સમાં બદલી શકો છો. કોડના કદમાં થોડો વધારો તમને ડેટાની વિશ્વસનીયતા અને યુઝર ટ્રસ્ટ આપે છે—બે એવી વસ્તુઓ જે કોઈ પણ સાયલન્ટ સક્સેસ ક્યારેય આપી શકતું નથી.