-
Notifications
You must be signed in to change notification settings - Fork 1k
/
lambdaLoader.ts
114 lines (98 loc) · 3.26 KB
/
lambdaLoader.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
110
111
112
113
114
import path from 'path'
import c from 'ansi-colors'
import type { Handler } from 'aws-lambda'
import fg from 'fast-glob'
import type {
FastifyReply,
FastifyRequest,
RequestGenericInterface,
} from 'fastify'
import { escape } from 'lodash'
import { getPaths } from '@redwoodjs/project-config'
import { requestHandler } from '../requestHandlers/awsLambdaFastify'
export type Lambdas = Record<string, Handler>
export const LAMBDA_FUNCTIONS: Lambdas = {}
// Import the API functions and add them to the LAMBDA_FUNCTIONS object
export const setLambdaFunctions = async (foundFunctions: string[]) => {
const tsImport = Date.now()
console.log(c.italic(c.dim('Importing Server Functions... ')))
const imports = foundFunctions.map((fnPath) => {
return new Promise((resolve) => {
const ts = Date.now()
const routeName = path.basename(fnPath).replace('.js', '')
const { handler } = require(fnPath)
LAMBDA_FUNCTIONS[routeName] = handler
if (!handler) {
console.warn(
routeName,
'at',
fnPath,
'does not have a function called handler defined.'
)
}
// TODO: Use terminal link.
console.log(
c.magenta('/' + routeName),
c.italic(c.dim(Date.now() - ts + ' ms'))
)
return resolve(true)
})
})
Promise.all(imports).then((_results) => {
console.log(
c.italic(c.dim('...Done importing in ' + (Date.now() - tsImport) + ' ms'))
)
})
}
// TODO: Use v8 caching to load these crazy fast.
export const loadFunctionsFromDist = async () => {
const serverFunctions = findApiDistFunctions()
// Place `GraphQL` serverless function at the start.
const i = serverFunctions.findIndex((x) => x.indexOf('graphql') !== -1)
if (i >= 0) {
const graphQLFn = serverFunctions.splice(i, 1)[0]
serverFunctions.unshift(graphQLFn)
}
await setLambdaFunctions(serverFunctions)
}
// NOTE: Copied from @redwoodjs/internal/dist/files to avoid depending on @redwoodjs/internal.
// import { findApiDistFunctions } from '@redwoodjs/internal/dist/files'
function findApiDistFunctions(cwd: string = getPaths().api.base) {
return fg.sync('dist/functions/**/*.{ts,js}', {
cwd,
deep: 2, // We don't support deeply nested api functions, to maximise compatibility with deployment providers
absolute: true,
})
}
interface LambdaHandlerRequest extends RequestGenericInterface {
Params: {
routeName: string
}
}
/**
This will take a fastify request
Then convert it to a lambdaEvent, and pass it to the the appropriate handler for the routeName
The LAMBDA_FUNCTIONS lookup has been populated already by this point
**/
export const lambdaRequestHandler = async (
req: FastifyRequest<LambdaHandlerRequest>,
reply: FastifyReply
) => {
const { routeName } = req.params
if (!LAMBDA_FUNCTIONS[routeName]) {
const errorMessage = `Function "${routeName}" was not found.`
req.log.error(errorMessage)
reply.status(404)
if (process.env.NODE_ENV === 'development') {
const devError = {
error: errorMessage,
availableFunctions: Object.keys(LAMBDA_FUNCTIONS),
}
reply.send(devError)
} else {
reply.send(escape(errorMessage))
}
return
}
return requestHandler(req, reply, LAMBDA_FUNCTIONS[routeName])
}