codeledge / ra-tools

React Admin Tools, namely the Prisma Data Adapter
66 stars 19 forks source link

Saving JSON data does not work #90

Closed bartoszhernas closed 1 month ago

bartoszhernas commented 1 month ago

Hi,

I've made a JSONInput to be able to edit JSON fields.

What I get from provider to render the fields: (data is json field in postgres)

{
    "data": {
        "id": 78,
        "position": 1,
        "smartLinkVersionId": 110,
        "data": {
            "text": "The Dunes",
            "type": "title"
        },
        "createdAt": "2024-08-16T13:10:11.949Z",
        "updatedAt": "2024-08-16T13:10:11.949Z",
        "type": "info",
        "uuid": "3edbfa3d-70d7-4855-9849-9023b7d88883"
    }
}

what is being sent to server:

{
  "method": "update",
  "resource": "SmartLinkWidgetModel",
  "params": {
    "id": 78,
    "data": {
      "id": 78,
      "position": 1,
      "smartLinkVersionId": 110,
      "data": {
        "text": "The Dunessssssssssssssssssssssss",
        "type": "title"
      },
      "createdAt": "2024-08-16T13:10:11.949Z",
      "updatedAt": "2024-08-16T13:10:11.949Z",
      "type": "info",
      "uuid": "3edbfa3d-70d7-4855-9849-9023b7d88883"
    },
    "previousData": {
      "id": 78,
      "position": 1,
      "smartLinkVersionId": 110,
      "data": {
        "text": "The Dunes",
        "type": "title"
      },
      "createdAt": "2024-08-16T13:10:11.949Z",
      "updatedAt": "2024-08-16T13:10:11.949Z",
      "type": "info",
      "uuid": "3edbfa3d-70d7-4855-9849-9023b7d88883"
    }
  }
}

but the response sadly is just:

{
    "data": {
        "id": 78,
        "position": 1,
        "smartLinkVersionId": 110,
        "data": {
            "text": "The Dunes",
            "type": "title"
        },
        "createdAt": "2024-08-16T13:10:11.949Z",
        "updatedAt": "2024-08-16T13:10:11.949Z",
        "type": "info",
        "uuid": "3edbfa3d-70d7-4855-9849-9023b7d88883"
    }
}

Any ideas what I am doing wrong?

bartoszhernas commented 1 month ago

Ok, I checked the code and it seems like I need to explicitly allow the field to be saved. Options needs something like this:

{
  update: {
    allowJsonUpdate: {
      data: true,
    },
  },
 }

Because I pass other options to the provider, I made a helper function

export const mainPrismaRouteWithOptions = (options: any) => async (req: Request) => {
  const session = await getServerSession(authOptions);
  const body = await req.json();
  try {
    await checkAccess(body);
  } catch (error: any) {
    return NextResponse.json(error, { status: error.status });
  }

  const result = await defaultHandler(body, prisma as any, {
    audit: {
      model: prisma.adminAudit,
      authProvider: authProvider(session),
    },
    ...options,
  });
  return NextResponse.json(result);
};

for api/[resource]/route.ts I just return the helper:

const handler = mainPrismaRouteWithOptions({});

export { handler as GET, handler as POST };

Then for some models (eg. /api/SmartLinkWidgetModel/route.ts I can do

const handler = mainPrismaRouteWithOptions({
  update: {
    allowJsonUpdate: {
      data: true,
    },
  },
});

export { handler as GET, handler as POST };