Closed griiettner closed 4 months ago
Thanks for the kind words! You have multiple options here:
import { supabaseDataProvider } from 'ra-supabase';
import { supabaseClient } from './supabase';
const baseDataProvider = supabaseDataProvider({
instanceUrl: 'YOUR_SUPABASE_URL',
apiKey: 'YOUR_SUPABASE_ANON_KEY',
supabaseClient
});
export const dataProvider = {
...baseDataProvider,
myCustomMethod: async () => {
}
}
useMutation
from react-query
)Ok, thanks for the response, by looking to the documentation, I came up with another solution, so can still use the Guesser
layouts.
Here is a sample implementation
import { supabaseDataProvider } from "ra-supabase";
import { supabase } from "./supabase";
import {
GetListParams,
GetListResult,
PaginationPayload,
SortPayload,
DataProvider,
} from "react-admin";
import { PostgrestSingleResponse } from "@supabase/supabase-js";
const baseDataProvider = supabaseDataProvider({
instanceUrl: import.meta.env.VITE_SUPABASE_URL as string,
apiKey: import.meta.env.VITE_SUPABASE_ANON_KEY as string,
supabaseClient: supabase,
});
export const dataProvider: DataProvider = {
...baseDataProvider,
getList: async (
resource: string,
params: GetListParams
): Promise<GetListResult> => {
if (!resource.startsWith("@")) {
return baseDataProvider.getList(resource, params);
} else {
const cleanedResource = resource.slice(1);
const { page, perPage }: PaginationPayload = params.pagination || {
page: 1,
perPage: 10,
};
const { field, order }: SortPayload = params.sort || {
field: "id",
order: "ASC",
};
const rangeFrom = (page - 1) * perPage;
const funcName = `getlist${cleanedResource.toLowerCase()}`;
try {
// Call the RPC function
const response: PostgrestSingleResponse<any[]> = await supabase
.rpc(funcName, params.filter)
.order(field, { ascending: order === "ASC" })
.range(rangeFrom, rangeFrom + perPage - 1);
if (response.error) {
throw new Error(response.error.message);
}
if (!response.data) {
throw new Error("Received null data from Supabase");
}
const data: any[] = response.data;
return {
data,
total: response.count ?? data.length, // Adjust based on actual total count logic
};
} catch (error) {
console.error("Error calling Supabase RPC function:", error);
throw error; // Re-throw the error to propagate it
}
}
},
};
In the case above, when calling the Resource
component, I just add the @
symbol at the beginning of the name
field. You notice that I remove the @
symbol on my dataProvider implementation.
Everything should be named accordingly, for example, if the resource name is products
, I have to do this
<Resource
name="@products"
list={ListGuesser}
edit={EditGuesser}
show={ShowGuesser}
/>
The name of my RPC function need to follow the convention as well and it should be getlistproducts
.
In my case, I created RPC functions to getList
, getOne
, getMany
, create
, update
, updateMany
, delete
, deleteMany
.
I made sure my RPC function takes care of all the scenarios listed on the documentation as well.
interface GetListParams {
pagination: { page: number, perPage: number };
sort: { field: string, order: 'ASC' | 'DESC' };
filter: any;
meta?: any;
signal?: AbortSignal;
}
Ah I see, I thought you wanted RPC functions for custom calls not following the usual CRUD conventions. :+1:
I'm trying to find if is possible to call Supabase RPC functions. For example, when creating a data in one of tables, it need to update data on another table at the same time, so I created a RPC function that perform all the tasks that need to be done and I'm not looking to rewrite the logic in JavaScript, since it is very complicated. My hope is that I can call the this RPC function every time I create a new data row on my database.
In reality, I have several RPC functions, I use it heavily, for filtering data, generating reports, applying changes to existing data and so on.
I the documentation I could not find anything that pointed to RPC on the dataProvider, only on the filter part.
Thanks for the amazing framework.