Queries with Next.js API Routes

Hi folks. Fairly new to Thin.dev and Next.js. I’m trying to build API routes in a Next.js app powered by Thin.dev that I’m hosting on Vercel. For now, there’s no UI in this app, just API for a desktop app I’m building.

I can’t figure out how to query for records from this API route. Here’s is an example of code I have at api/widgets:

import { NextApiRequest, NextApiResponse } from 'next'
import { query, initThinBackend } from 'thin-backend'

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
	initThinBackend({ host: process.env.NEXT_PUBLIC_BACKEND_URL })

	if (req.method === 'GET') {
		// Look for query param systemIdHash
		const systemIdHash: string = req.query.systemIdHash as string
		if (systemIdHash) {
            try {
				const widget = await query('widgets').where('systemIdHash', systemIdHash).fetchOne()
				res.send({ result: widget })
			} catch (err) {
				console.log(err)
				res.status(500).send({ error: err })
			}
        }
    }
}

However when I hit this endpoint locally in Postman, and pass the expected systemIdHash, the app goes into this strange mode where I see output:

Retrying in 1s
Retrying in 2s
Retrying in 4s
Retrying in 8s...

And on it goes. No response, nothing in the catch block. Does anyone know what’s happening here, and how I can query from a Next.js API route handler without the ability to use any hooks? Thanks.

EDIT: Is it because I’m not authenciated as the User who is related to these records? How can I query outside the context of a user?

Quick note: I created a pages/widgets component and was able to use useQuery(query('widgets').orderByDesc('createdAt')) without problem. Got data back, from same app, in localhost. So that tells me it’s probably not a localhost-related issue.

Thanks for reporting this. I can reproduce the issue. It looks like that node is missing a WebSocket implementation by default. I’ve tried adding a third-party WebSocket library (npm i websocket), which now causes a different error. I’ll try to fix this soon.

So for now using Thin from the handlers is unsupported. Likely using useQuery is a good workaround for now.

1 Like

This has just been fixed with thin-backend version 0.11.0. After you’ve updated the npm package, try this:

// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next'
import { initThinBackend, query } from 'thin-backend'
import { DataSyncController } from 'thin-backend';

type Data = {
  name: string
}

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse<Data>
) {
  initThinBackend({ host: process.env.NEXT_PUBLIC_BACKEND_URL });
  
  const task = await query('tasks').fetchOne();

  res.status(200).json({ task })
}

This will have the same permissions as calling Thin as a logged out user. If you want to access the Thin api as a logged in user, you need to pass the JWT from the client to the next.js app.

On the client side you can retrieve the JWT like this:

import { DataSyncController } from 'thin-backend';

const jwt = DataSyncController.getJWT();

fetch("/api/my-nextjs-endpoint", { headers: { Authentication: jwt } })

On the serverside you need to override the getJWT function of thin:

// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next'
import { initThinBackend, query } from 'thin-backend'
import { DataSyncController } from 'thin-backend';

type Data = {
  name: string
}

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse<Data>
) {
  initThinBackend({ host: process.env.NEXT_PUBLIC_BACKEND_URL });

  DataSyncController.getJWT = () => req.headers.Authentication;
  
  const task = await query('tasks').fetchOne();

  res.status(200).json({ task })
}

Let me know if this solves the issue :slight_smile:

I copied your solution for, but I get the following error:

unhandledRejection: SyntaxError: Unexpected token < in JSON at position 0

What might cause this issue?