Integrating Svelte Kit and Prisma without wrapper class to workaround
Tags: svelte, prisma
Published: 2022-04-21 10:14:22

---
title: Integrating Svelte Kit and Prisma without wrapper class to workaround
published: true
description: 
tags: #svelte #prisma
//cover_image: https://direct_url_to_image.jpg
---

[Svelte Kit](https://kit.svelte.dev/) and [Prisma](https://www.prisma.io/ ) is a go-to stack for me these days. I like its great ergonomics in frontend and less cost of cognitive load from context switches between server sides.

Users of Svelte Kit, Nuxt or other Vite based frameworks haven't been able to import PrismaClient or other exports in the way the documentation suggests[^1].

![doc says...](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b3rhl24qwg2pa2aoxmo1.png)

which leads you to see:

```

import Prisma, { PrismaClient } from "@prisma/client";
                 ^^^^^^^^^^^^
SyntaxError: Named export 'PrismaClient' not found. The requested module '@prisma/client' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from '@prisma/client';
const { PrismaClient } = pkg;
```

While there's [several](https://github.com/prisma/prisma/discussions/9027#discussion-3548083) [workarounds](https://github.com/prisma/prisma/issues/5030#issuecomment-970157451) [known](https://www.mikenikles.com/blog/svelte-kit-prisma-a-match-made-in-digital-heaven#commento-comment-name-c13f447ec60eb97a32ae2cb8fe7aaabd760208be22be65d1345f533c5a51f251) in the community, they still have some shortcomings like inability to import Enum values or `Prisma` object for SQL templates nicely.

For the context, when you use Prisma, what you use is not something in `@prisma/client`, but a code locally generated prisma generate command, which in turn `@prisma/client` would import inside. Since Prisma need to provide you a custom made API that reflects your schema, it wouldn't able to come as like an ordinary package.

As a result, `@prisma/client` contains just a line of code or two, to import the custom-made client supposedly generated at the time of deployment. It's really small piece of code: 

```js
const prisma = require('.prisma/client/index')

module.exports = prisma
```

Since this glues the application code and generated code, I would call this as Prisma's glue code.

This works fine for CJS code to require. Similarly, the code that would be transpiled by TypeScript or other bundlers can work with this, since those tools take care at compile time.

The problem is ES modules, who cannot recognize any exports other than default exports.

Svelte Kit (as far as I know also Nuxt or other Vite based frameworks, depending on configs) emits ES modules as their build artifacts, unlike Next that emits CJS bundles, and encounters this problem.

But why?

When an ES module tries to `import` named exports from other CJS modules, Node recognizes only the exports that explicitly defiend in specific syntax. They would be detected before they get executed with static analysis [^2]

> For better compatibility with existing usage in the JS ecosystem, Node.js in addition attempts to determine the CommonJS named exports of every imported CommonJS module to provide them as separate ES module exports using a static analysis process.
> 
> The detection of named exports is based on common syntax patterns but does not always correctly detect named exports.

Because of this, Prisma's glue code effectively reexports just default export from perspective of Node, while TS compiler somehow recognized the named exports. This causes a weird situation where they would work fine in dev server, but fails with the error message like this once they have been bundled for production, as ES modules with static `import` s.

Fortunately, Node doesn't detect only `export.name = value`. It seems to support more involved syntax, like [^3]:

```js
module.exports = {
  ...require('.prisma/client/index'),
}
```

Which I sent as [a pull request to Prisma](https://github.com/prisma/prisma/pull/12907). I'm not sure when or even if it would be accepted, I assume you would be able to use this hook in `package.json` for the time being. Assuming above glue code replacement (JS snippet) saved as `patches/prisma-fixed-glue.js`, add this:

```json
  "build": "cp patches/prisma-fixed-glue.js node_modules/@prisma/client/index.js && svelte-kit build",
```

(I use pnpm which [no longer supports lifecycle scripts](https://github.com/pnpm/pnpm/issues/2891) in default, but you can put `prebuild` as long as you enabled it or use npm)

[^1]: https://www.prisma.io/docs/concepts/components/prisma-client/working-with-prismaclient/instantiate-prisma-client
[^2]: https://nodejs.org/api/esm.html#commonjs-namespaces
[^3]: https://github.com/nodejs/cjs-module-lexer/tree/1.2.2