psteinroe / supabase-cache-helpers

A collection of framework specific Cache utilities for working with Supabase.
https://supabase-cache-helpers.vercel.app
MIT License
502 stars 31 forks source link

[Question]: Does this work with a self hosted postgrest server (no supabase account)? #503

Open zacharyhansen opened 1 month ago

zacharyhansen commented 1 month ago

Apologies if this is the incorrect place to ask.

I have a simple example component and DB spun up using a self hosted postgrest server where I am trying to test out the auto cache update functionality for an insert and update mutation however I cannot seem to get it working.

Would it be expected the following example works? Or is it required I have a supabase project and connect to that?

Postgest Client

import { PostgrestClient } from "@supabase/postgrest-js";
import { NewOTask, OTask, OTaskUpdate } from "odigos-types";

interface Database {
  public: {
    Tables: {
      o_task: {
        Row: OTask;
        Insert: NewOTask;
        Update: Partial<OTask>;
      };
      // ... other tables
    };
    Views: {
      // ... any views you have
    };
    Functions: {
      // ... any functions you have
    };
  };
  ["tenant_base_org"]: {
    Tables: {
      o_task: {
        Row: OTask;
        Insert: NewOTask;
        Update: Partial<OTask>;
      };
      // ... other tables
    };
    Views: {
      // ... any views you have
    };
    Functions: {
      // ... any functions you have
    };
  };
  // ... other schemas if you have any
}

const postgrest = new PostgrestClient<Database>(
  process.env.NEXT_PUBLIC_REST_URL!
);

export default postgrest;

Simple component (clicking the button does not update the table or the rendered list of titles)

"use client";

import {
  useInsertMutation,
  useQuery,
  useUpdateMutation,
} from "@supabase-cache-helpers/postgrest-swr";
import {
  ODealId,
  OTaskId,
  TaskPriority,
  TaskStatus,
  UserId,
} from "odigos-types";
import { useSWRConfig } from "swr";
import { Alert } from "ui";

import postgrest from "backend/postgrest";
import { ClientAgGrid } from "modules/ClientAgGrid";

export default function Page() {
  const { cache } = useSWRConfig();
  const { data, error, isLoading } = useQuery(
    postgrest.schema("tenant_base_org").from("o_task").select("*")
  );

  const { trigger: update } = useUpdateMutation(
    postgrest.schema("tenant_base_org").from("o_task"),
    ["id"],
    "title",
    {
      onError: (res) => console.log("onError!", { res }),
      onSuccess: (res) => console.log("Success!", { res }),
    }
  );

  const { trigger: insert } = useInsertMutation(
    postgrest.schema("tenant_base_org").from("o_task"),
    ["id"],
    "title",
    {
      onError: (res) => console.log("onError!", { res }),
      onSuccess: (res) => console.log("Success!", { res }),
    }
  );

  const change = () => {
    insert([
      {
        assignee_id: "28256bc7-0222-4dea-9fa1-2e78929e5671" as UserId,
        deal_id: "74738208-3058-49d6-b55b-9ee448c08923" as ODealId,
        priority: TaskPriority["no priority"],
        status: TaskStatus["todo"],
        title: "test insert",
      },
    ]);
    update(
      {
        id: "95d4577b-0c01-4482-99cc-cb45708b0e08" as OTaskId,
        title: "test6",
      },
      {
        optimisticData: {
          title: "test6",
        },
      }
    );
  };

  console.log({ cache });

  if (error) {
    return <Alert>There was an error showing you task information </Alert>;
  }

  return (
    // wrapping container with theme & size
    <div
      className="ag-theme-quartz" // applying the Data Grid theme
      style={{ height: 700 }} // the Data Grid will fill the size of the parent container
    >
      <button onClick={change}>click</button>
      {JSON.stringify(data?.map((d) => d.title))}
      <ClientAgGrid
        rowData={data}
        columnDefs={[
          { field: "priority" },
          { field: "status" },
          { field: "title" },
          { field: "description" },
          {
            cellDataType: "timeStamp",
            field: "created_at",
            headerName: "Created",
          },
          {
            cellDataType: "timeStamp",
            field: "updated_at",
            headerName: "Updated",
          },
        ]}
      />
    </div>
  );
}
psteinroe commented 1 month ago

hey! Sure, self hosted should work as long as you have the rest api enabled. cache helpers is really just a wrapper around the supabase client.

if the cache updates are not working, could you provide a more focussed report?

zacharyhansen commented 1 month ago

Hi @psteinroe thanks so much for the repsonse!

I ended up switching it over to react query as the debugging tools were more robust - below is as far as I have gotten. Please let me know what specifics I can provide you in addition to the below.

What seems to be happening is that the mutation methods are not correctly receiving a cache key.

In this simple example you can see react query is properly receiving and caching the GET of my tasks.

image

Now once I trigger the insert logic the mutation is registered by react query but without a cache mutationKey.

image

The mutation is set up as the following

"use client";

import "ag-grid-community/styles/ag-grid.css";
import "ag-grid-community/styles/ag-theme-quartz.css";

import { AgGridReact, AgGridReactProps } from "ag-grid-react";
import { DealId } from "odigos-types";

import { useInsertMutation } from "@supabase-cache-helpers/postgrest-react-query";
import postgrest from "backend/postgrest";

import { dataTypeDefinitions } from "./dataTypeDefinitions";

export function ClientAgGrid({
  height = 200,
  ...props
}: AgGridReactProps & { height?: number }) {
  const { mutateAsync: insert } = useInsertMutation(
    postgrest.schema("tenant_base_org").from("task"),
    ["id"],
    "*",
    {
      onError: (res) => {
        console.log("onError!", { res });
      },
      onSuccess: (res) => {
        console.log("Success!", { res });
      },
    }
  );

  return (
    <>
      <button
        onClick={() =>
          insert([
            {
              deal_id: "becb9367-e263-4bd0-948b-46c7db1d4b54" as DealId,
              title: `${Math.random() * 100}`,
            },
          ])
        }
      >
        insert
      </button>
      <div
        className="ag-theme-quartz" // applying the Data Grid theme
        style={{ height }} // the Data Grid will fill the size of the parent container
      >
        <AgGridReact {...props} dataTypeDefinitions={dataTypeDefinitions} />
      </div>
    </>
  );
}

Obviosuly this is not going to merge to the original query data without the proper mutationKey but I am at a loss for why the useInsertMutation is acting any differently from the useQuery wrapper.

Thanks for you help in advance!

Below are my dependency versions

"dependencies": {
    "@apollo/client": "^3.9.11",
    "@clerk/nextjs": "^5.2.3",
    "@stripe/react-stripe-js": "^2.7.3",
    "@stripe/stripe-js": "^4.1.0",
    "@supabase-cache-helpers/postgrest-react-query": "^1.10.1",
    "@supabase-cache-helpers/postgrest-swr": "^1.10.1",
    "@supabase/postgrest-js": "^1.16.0",
    "@supabase/supabase-js": "^2.45.4",
    "@tanstack/react-query": "^5.56.2",
    "@tanstack/react-query-devtools": "^5.56.2",
    "@visx/curve": "^3.3.0",
    "@visx/grid": "^3.5.0",
    "@visx/responsive": "^3.10.2",
    "@visx/scale": "^3.5.0",
    "@visx/shape": "^3.5.0",
    "@visx/vendor": "^3.5.0",
    "ag-grid-react": "^32.1.0",
    "axios": "^1.7.2",
    "change-case": "^5.4.4",
    "clsx": "^2.1.1",
    "framer-motion": "^11.3.21",
    "geist": "^1.3.1",
    "graphql": "^16.8.1",
    "lucide-react": "0.400.0",
    "next": "14.0.4",
    "react": "^18",
    "react-dom": "^18",
    "server-only": "^0.0.1",
    "stripe": "^16.2.0",
    "swr": "^2.2.5",
    "ui": "*",
    "utilities": "*"
  },
  "devDependencies": {
    "@graphql-codegen/cli": "^5.0.2",
    "@graphql-codegen/client-preset-swc-plugin": "^0.2.0",
    "@graphql-codegen/schema-ast": "^4.0.2",
    "@graphql-codegen/typescript": "^4.0.6",
    "@graphql-codegen/typescript-operations": "^4.2.0",
    "@graphql-codegen/typescript-react-apollo": "^4.3.0",
    "@parcel/watcher": "^2.4.1",
    "@types/config": "^3.3.4",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "autoprefixer": "^10.4.14",
    "config": "*",
    "eslint": "^8",
    "eslint-config-next": "14.0.4",
    "eslint-plugin-sort": "^3.0.2",
    "odigos-types": "*",
    "postcss": "^8.4.27",
    "tailwindcss": "^3.3.6",
    "ts-node": "^10.9.2",
    "tsconfig": "*",
    "typescript": "5.5.4"
  }
zacharyhansen commented 1 month ago

What I did notice is that cache helpers requires @supabase/supabase-js while what I am using to create the api client is @supabase/postgrest-js. I was hoping these were interchangeable but assuming this is likely not going to work for me due to differences in the package?