one-sdk-js icon indicating copy to clipboard operation
one-sdk-js copied to clipboard

[Compat] OneSDK fails to read .supr file with Next.js serverless functions on Vercel

Open jnv opened this issue 3 years ago • 3 comments

This was originally reported on Discord server by Petr.

Expected Behavior

When using OneSDK in Next.js with API routes, I expect for them to work without any problem wherever I deploy the application, especially to Vercel.

Current Behavior

SDK throws an exception during initialization:

File referenced in super.json not found: /var/task/superface/grid/weather/[email protected]

Possible Solution

Next.js on Vercel doesn't allow importing of files per documentation.

Possible workarounds include moving the API route from /pages/api to /api so it is executed in Node.js runtime (and hence not a subject to the bundling), but there may be other solutions as well.

Steps to Reproduce

Here is repro project: https://github.com/jnv/one-sdk-nextjs-vercel-repro It's a vanilla Next.js project with OneSDK and the additional /api/weather route (see here).

The route can be executed here: https://one-sdk-nextjs-vercel-repro.vercel.app/api/weather An error is thrown instead of successful perform.

Your Environment

  • Next.js v12.0.10
  • OneSDK v1.3.0
  • Vercel

jnv avatar Feb 16 '22 22:02 jnv

Next.js supports output file tracing, which does static analysis of the code and includes files that are used.

Next.js uses for it https://github.com/vercel/nft, so we can look if we can refactor code to get data caught, but from dynamism of the configuration, it might be tough task.

This is where profiles and it's ASTs are loaded.

  • https://github.com/superfaceai/one-sdk-js/blob/2afd7d90e282cb3c7ad2f63b629ace4165da9827/src/client/profile-provider.ts#L455
  • https://github.com/superfaceai/one-sdk-js/blob/a948565c000188612d787a71cc2401650273934a/src/internal/parser.ts#L98-L101

freaz avatar Feb 17 '22 10:02 freaz

Update on the current status: OneSDK now works on Vercel with changes in v2.0, because we don't rely on access to local .supr files anymore.

However if you use superface/super.json file, it won't be included in the bundle by default, you must import it manually and pass it to OneSDK constructor:

import { SuperfaceClient } from '@superfaceai/one-sdk';
import superJson from './path/to/superface/super.json';

const sdk = new SuperfaceClient({
  superJson,
});

Furthermore, this only works for profiles published to registry, local .supr and .suma files are still not included (Vercel has no idea how to extract these from super.json). I'm trying a workaround for that.

jnv avatar Nov 14 '22 08:11 jnv

I've tried to trick the underlying @vercel/nft package to include the whole superface/ directory. Good news is, that this can be easily done by putting readdir call into the code – it doesn't even need to be called. So I wrapped SDK into a stand-alone module in the root of my project like this:

import { SuperfaceClient } from '@superfaceai/one-sdk';
import { readdir } from 'fs';
import { resolve } from 'path';
import superJson from './superface/super.json';

const SUPERFACE_PATH = resolve(__dirname, 'superface');

// Trick @vercel/nft to include the whole superface/ dir
function noop() {
  try {
    readdir(SUPERFACE_PATH);
  } catch (e) {}
}

let sdk;

function getSdk() {
  if (sdk) {
    return sdk;
  }
  sdk = new SuperfaceClient({
    superJson,
    superfacePath: resolve(SUPERFACE_PATH, 'super.json'),
  });
  return sdk;
}

export default getSdk;

I've verified that this works by checking nft.json files in the output and also with the standalone option I saw superface directory in the standalone output. However, after deployment to Vercel I'm getting .supr extension found. error. I suspect the superface/ folder isn't included in the deployment in the end, and at this point I ran out of ideas.

Here is my test project if you'd like to play with it.

jnv avatar Nov 14 '22 12:11 jnv