supabase / supabase-js

An isomorphic Javascript client for Supabase. Query your Supabase database, subscribe to realtime events, upload and download files, browse typescript examples, invoke postgres functions via rpc, invoke supabase edge functions, query pgvector.
https://supabase.com
MIT License
2.86k stars 220 forks source link

{"error":"a.replace is not a function"} #888

Closed Yemidatadev closed 7 months ago

Yemidatadev commented 7 months ago

Please everytime i test my api endpoint from the edge functions i created, i get "a.replace is not a function".

This is the Event message

Event message Error: TypeError: a.replace is not a function at b (https://esm.sh/v133/@supabase/supabase-js@2.38.2/deno/supabase-js.mjs:2:1387) at new f (https://esm.sh/v133/@supabase/supabase-js@2.38.2/deno/supabase-js.mjs:2:2429) at ie (https://esm.sh/v133/@supabase/supabase-js@2.38.2/deno/supabase-js.mjs:2:5377) at Server. (file:///C:/Users/Administrator/supabase/functions/transfer-funds/index.ts:14:32) at Server.#respond (https://deno.land/std@0.182.0/http/server.ts:220:43) at Server.#serveHttp (https://deno.land/std@0.182.0/http/server.ts:258:26) at eventLoopTick (ext:core/01_core.js:183:11)

Bug report

Describe the bug

A clear and concise description of what the bug is.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Go to '…'
  2. Click on '…'
  3. Scroll down to '…'
  4. See error

Expected behavior

A clear and concise description of what you expected to happen.

Screenshots

If applicable, add screenshots to help explain your problem.

System information

Additional context

Add any other context about the problem here.

kamilogorek commented 7 months ago

This error is originating from https://github.com/supabase/supabase-js/blob/86fdf6174836f4211c756a8f4780f908e4e2e536/src/SupabaseClient.ts#L91C26-L91C44 and effectively from https://github.com/supabase/supabase-js/blob/86fdf6174836f4211c756a8f4780f908e4e2e536/src/lib/helpers.ts#L12

Which basically means that you are calling createClient or new SupabaseClient with an object as the first argument. It should be url, key, options instead.

Yemidatadev commented 7 months ago

How do i correct this please? Do i need to open up the fie on my pc and correct it?

kamilogorek commented 7 months ago

Yes, it lives inside supabase/functions/transfer-funds/index.ts, just like the stacktrace tells.

Yemidatadev commented 7 months ago

This is the code:

// Create a Supabase client for database interaction const supabaseClient = createClient({ url: Deno.env.get('SUPABASE_URL') ?? '', key: Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '', }, { headers: { Authorization: request.headers.get('Authorization') || '' } });

What do i need to correct here please?

kamilogorek commented 7 months ago
const supabaseClient = createClient(Deno.env.get('SUPABASE_URL'), Deno.env.get('SUPABASE_SERVICE_ROLE_KEY'));

or

const supabaseClient = createClient(
  Deno.env.get('SUPABASE_URL'),
  Deno.env.get('SUPABASE_SERVICE_ROLE_KEY'),
  global: {
    headers: {
      Authorization: request.headers.get('Authorization')
    }
  }
);

I don't know your codebase to answer exactly.

Yemidatadev commented 7 months ago

Here is the whole code:

import { serve } from "https://deno.land/std@0.182.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.38.2";
import { corsHeaders } from "../_shared/cors2.ts";

console.log("Transfer Funds Function");

serve(async (request) => {
  if (request.method === "OPTIONS") {
    // Handle preflight CORS requests
    return new Response("ok", { headers: corsHeaders });
  }

  try {
    // Create a Supabase client for database interaction
    const supabaseClient = createClient({
      url: Deno.env.get("SUPABASE_URL") ?? "",
      key: Deno.env.get("SUPABASE_SERVICE_ROLE_KEY") ?? "",
    }, {
      headers: { Authorization: request.headers.get("Authorization") || "" },
    });

    // Parse the JSON request body to get senderUserId, receiverUserId, and transferAmount
    const requestBody = await request.json();
    const senderUserId = requestBody.senderUserId;
    const receiverUserId = requestBody.receiverUserId;
    const transferAmount = requestBody.transferAmount;

    console.log("Request Body:", requestBody);

    // Check if the sender has enough balance to perform the transfer
    const { data: senderData } = await supabaseClient
      .from("users")
      .select("balance")
      .eq("id", senderUserId)
      .single();

    console.log("Sender User Data:", senderData);

    if (!senderData) {
      throw new Error("Sender not found");
    }

    if (typeof senderData.balance !== "number" || isNaN(senderData.balance)) {
      throw new Error("Invalid balance for the sender");
    }

    if (typeof transferAmount !== "number" || isNaN(transferAmount)) {
      throw new Error("Invalid transfer amount");
    }

    if (senderData.balance < transferAmount) {
      throw new Error("Insufficient balance for the transfer");
    }

    // Retrieve receiver's balance
    const receiverData = await supabaseClient
      .from("users")
      .select("balance")
      .eq("id", receiverUserId)
      .single();

    console.log("Receiver User Data:", receiverData);

    if (!receiverData) {
      throw new Error("Receiver not found");
    }

    if (
      typeof receiverData.balance !== "number" || isNaN(receiverData.balance)
    ) {
      throw new Error("Invalid balance for the receiver");
    }

    // Proceed with the transfer by updating sender and receiver balances
    const senderNewBalance = senderData.balance - transferAmount;
    const receiverNewBalance = receiverData.balance + transferAmount;

    await supabaseClient
      .from("users")
      .update({ balance: senderNewBalance })
      .eq("id", senderUserId);

    await supabaseClient
      .from("users")
      .update({ balance: receiverNewBalance })
      .eq("id", receiverUserId);

    return new Response("Funds transferred successfully", {
      headers: { ...corsHeaders, "Content-Type": "application/json" },
      status: 200,
    });
  } catch (error) {
    // Handle errors and return an appropriate response with an error message
    console.error("Error:", error);
    return new Response(JSON.stringify({ error: error.message }), {
      headers: { ...corsHeaders, "Content-Type": "application/json" },
      status: 400,
    });
  }
});

So whenever i implement the one you sent, Supabase will throw this error whenever i try to deploy it

error: Uncaught (in promise) Error: The module's source code could not be parsed: Expected ',', got ':' at file:///C:/Users/Administrator/supabase/functions/transfer-funds/index.ts:17:13

But when i leave it as is, it will deploy but i will throw the error "error": "a.replace is not a function"

whenever i want to test the endpoint.

kamilogorek commented 7 months ago

I had missing brackets there, it should be:

    // Create a Supabase client with the Auth context of the logged in user.
    const supabaseClient = createClient(
      // Supabase API URL - env var exported by default.
      Deno.env.get('SUPABASE_URL') ?? '',
      // Supabase API ANON KEY - env var exported by default.
      Deno.env.get('SUPABASE_ANON_KEY') ?? '',
      // Create client with Auth context of the user that called the function.
      // This way your row-level-security (RLS) policies are applied.
      { global: { headers: { Authorization: req.headers.get('Authorization')! } } }
    )

Just follow docs here https://supabase.com/docs/guides/functions/auth and you should be good.

Yemidatadev commented 7 months ago

Thanks a lot. The req is not defined but I'll figure it out. Thanks you've helped immensely.

kamilogorek commented 7 months ago

For you it's just request.headers instead :)

Yemidatadev commented 7 months ago

Please kindly do me a favor, everything worked fine but now when i test the endpoint, i get the error "Sender not found" even though i've supply all data needed to run it. What do you think might be the problem?

kamilogorek commented 7 months ago

It literally cannot find a database entry you asked for. It's right there in your code.

    if (!senderData) {
      throw new Error("Sender not found");
    }
Yemidatadev commented 7 months ago

Honesty that's what I've been giving me headache, i supply the data which is right there in the database but keep returning that error. Anyways thanks for your time, you've been so so helpful. I appreciate you.