This repository has been archived by the owner on Aug 2, 2022. It is now read-only.
/
prismaLayer.ts
109 lines (95 loc) · 3.6 KB
/
prismaLayer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import { Code, LayerVersion, LayerVersionProps, Runtime } from "@aws-cdk/aws-lambda"
import { AssetHashType, Construct, IgnoreMode } from "@aws-cdk/core"
import crypto from "crypto"
// deps to npm install to the layer
const PRISMA_DEPS = ["prisma", "@prisma/migrate", "@prisma/sdk", "@prisma/client"]
export interface PrismaLayerProps extends Omit<LayerVersionProps, "code"> {
// e.g. 3.1.1
prismaVersion?: string
// some more modules to add to the layer
nodeModules?: string[]
}
/**
* Construct a lambda layer with Prisma libraries.
* Be sure to omit the prisma layer modules from your function bundles with the `externalModules` option.
* Include `environment` to point prisma at the right library location.
*
* @example
* ```ts
* const prismaLayer = new PrismaLayer(this, "PrismaLayer", {
* layerVersionName: `${id}-prisma`,
* removalPolicy: isProduction ? RemovalPolicy.RETAIN : RemovalPolicy.DESTROY,
* })
*
* // default lambda function options
* const functionOptions: FunctionOptions = {
* layers: [prismaLayer],
* environment: { ...prismaLayer.environment, DEBUG: "*" },
* bundling: {
* externalModules: prismaLayer.externalModules,
* },
* }
*/
export class PrismaLayer extends LayerVersion {
externalModules: string[]
environment: Record<string, string>
constructor(scope: Construct, id: string, props: PrismaLayerProps = {}) {
const { prismaVersion } = props
const nodeModules = props.nodeModules || []
const layerDir = "/asset-output/nodejs"
const nm = `${layerDir}/node_modules`
const engineDir = `${nm}/@prisma/engines`
// what are we asking npm to install?
let modulesToInstall = PRISMA_DEPS.concat(nodeModules)
if (prismaVersion) modulesToInstall = modulesToInstall.map((dep) => `${dep}@${prismaVersion}`)
const modulesToInstallArgs = modulesToInstall.join(" ")
const createBundleCommand = [
// create asset bundle in docker
"bash",
"-c",
[
`mkdir -p ${layerDir}`,
// install PRISMA_DEPS
`cd ${layerDir} && HOME=/tmp npm install ${modulesToInstallArgs}`,
// delete unneeded engines
`rm -f ${engineDir}/introspection-engine* ${engineDir}/prisma-fmt*`,
// get rid of some junk
`rm -rf ${nm}/prisma/build/public`,
`rm -rf ${nm}/prisma/prisma-client/src/__tests__`,
`rm -rf ${nm}/@types`,
].join(" && "),
]
// hash our parameters so we know when we need to rebuild
const bundleCommandHash = crypto.createHash("sha256")
bundleCommandHash.update(JSON.stringify(createBundleCommand))
// bundle
const code = Code.fromAsset(".", {
// don't send all our files to docker (slow)
ignoreMode: IgnoreMode.GLOB,
exclude: ["*"],
// if our bundle commands (basically our "dockerfile") changes then rebuild the image
assetHashType: AssetHashType.CUSTOM,
assetHash: bundleCommandHash.digest("hex"),
bundling: {
image: Runtime.NODEJS_14_X.bundlingImage,
command: createBundleCommand,
},
})
super(scope, id, { ...props, code })
// hint for prisma to find the engine
this.environment = {
// PRISMA_QUERY_ENGINE_LIBRARY: "/opt/nodejs/node_modules/prisma/libquery_engine-rhel-openssl-1.0.x.so.node",
PRISMA_QUERY_ENGINE_LIBRARY:
"/opt/nodejs/node_modules/@prisma/engines/libquery_engine-rhel-openssl-1.0.x.so.node",
}
// modules provided by layer
this.externalModules = [
"aws-sdk",
"@prisma/migrate",
"@prisma/sdk",
"@prisma/engines",
"@prisma/engines-version",
...nodeModules,
]
}
}