Skip to content

Commit

Permalink
Fix non functional template for Prisma (#3686)
Browse files Browse the repository at this point in the history
Fixed:
- update Prisma files location (remove the obsolete one - .prisma)
- rmSync and cpSync instead of removeSync and copySync
- add 'recursive' option while copying prisma files to avoid the error 'Path is a directory: cp returned EISDIR'
- remove the local only deployment to make it work with 'sst dev' mode
- load database URL from .env instead of hard coded one
- added the "linux-arm64" architecture if you are using AWS Graviton 2 (source: https://www.prisma.io/docs/orm/prisma-client/deployment/serverless/deploy-to-aws-lambda)
Some of the updates above are based on this repo: https://github.com/geauser/sst-prisma-example
Tested OK with Node 20 LTS.
  • Loading branch information
eguenou committed Mar 2, 2024
1 parent 7d04664 commit 7c2e7d0
Showing 1 changed file with 40 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,56 @@ import fs from "fs";
import * as lambda from "aws-cdk-lib/aws-lambda";
import { Api, StackContext } from "sst/constructs";

export function ExampleStack({ stack, app }: StackContext) {
if (!app.local) {
// Create a layer for production
// This saves shipping Prisma binaries once per function
const layerPath = ".sst/layers/prisma";

// Clear out the layer path
fs.removeSync(layerPath, { force: true, recursive: true });
fs.mkdirSync(layerPath, { recursive: true });

// Copy files to the layer
const toCopy = [
"node_modules/.prisma",
"node_modules/@prisma/client",
"node_modules/prisma/build",
];
for (const file of toCopy) {
fs.copySync(file, path.join(layerPath, "nodejs", file), {
// Do not include binary files that aren't for AWS to save space
filter: (src) => !src.endsWith("so.node") || src.includes("rhel"),
});
}
const prismaLayer = new lambda.LayerVersion(stack, "PrismaLayer", {
code: lambda.Code.fromAsset(path.resolve(layerPath)),
});
const prismaDatabaseLayerPath = "./.sst/layers/prisma";

function preparePrismaLayerFiles() {
// Remove any existing layer path data
fs.rmSync(prismaDatabaseLayerPath, { force: true, recursive: true });

// Add to all functions in this stack
stack.addDefaultFunctionLayers([prismaLayer]);
// Create a fresh new layer path
fs.mkdirSync(prismaDatabaseLayerPath, { recursive: true });

// Prisma folders to retrieve the client and the binaries from
const prismaFiles = [
"node_modules/@prisma/client",
"node_modules/prisma/build",
];

for (const file of prismaFiles) {
fs.cpSync(file, path.join(prismaDatabaseLayerPath, "nodejs", file), {
// Do not include binary files that aren't for AWS to save space
filter: (src) =>
!src.endsWith("so.node") ||
src.includes("rhel") ||
src.includes("linux-arm64"),
recursive: true,
});
}
}

export function ExampleStack({ stack, app }: StackContext) {
preparePrismaLayerFiles();

// Creation of the Prisma layer
const prismaLayer = new lambda.LayerVersion(stack, "PrismaLayer", {
code: lambda.Code.fromAsset(path.resolve(prismaDatabaseLayerPath)),
});

// Add the Prisma layer to all functions in this stack
stack.addDefaultFunctionLayers([prismaLayer]);

const api = new Api(stack, "Api", {
defaults: {
function: {
runtime: "nodejs20.x",
environment: {
DATABASE_URL: app.local
? "mysql://root@localhost:3306/test"
: "mysql://production-url",
// You can also use the Config.DATABASE_URL object here
// or the bind functionality instead of environment props, i.e. bind: [DATABASE_URL],
DATABASE_URL: process.env.DATABASE_URL!,
},
nodejs: {
esbuild: {
// Only reference external modules when deployed
externalModules: app.local ? [] : ["@prisma/client", ".prisma"],
external: ["@prisma/client", ".prisma"],
},
},
},
Expand Down

0 comments on commit 7c2e7d0

Please sign in to comment.