@certik/serverless-api 1.0.12 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/README.md +0 -1
- package/dist/deploy.d.ts +20 -0
- package/dist/deploy.d.ts.map +1 -0
- package/dist/deploy.js +17 -0
- package/dist/dev.d.ts +8 -0
- package/dist/dev.d.ts.map +1 -0
- package/dist/dev.js +8 -0
- package/dist/entrypoint.d.ts +26 -0
- package/dist/entrypoint.d.ts.map +1 -0
- package/dist/entrypoint.js +78 -0
- package/dist/handler.d.ts +2 -0
- package/dist/handler.d.ts.map +1 -0
- package/{index.js → dist/handler.js} +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/lib/app.d.ts +39 -0
- package/dist/lib/app.d.ts.map +1 -0
- package/dist/lib/app.js +139 -0
- package/dist/lib/const.d.ts +12 -0
- package/dist/lib/const.d.ts.map +1 -0
- package/dist/lib/const.js +12 -0
- package/dist/lib/cors.d.ts +19 -0
- package/dist/lib/cors.d.ts.map +1 -0
- package/dist/lib/cors.js +38 -0
- package/dist/lib/dev.d.ts +38 -0
- package/dist/lib/dev.d.ts.map +1 -0
- package/dist/lib/dev.js +78 -0
- package/dist/lib/domain.d.ts +16 -0
- package/dist/lib/domain.d.ts.map +1 -0
- package/dist/lib/domain.js +19 -0
- package/dist/lib/env.d.ts +14 -0
- package/dist/lib/env.d.ts.map +1 -0
- package/dist/lib/env.js +37 -0
- package/dist/lib/pack.d.ts +29 -0
- package/dist/lib/pack.d.ts.map +1 -0
- package/dist/lib/pack.js +93 -0
- package/dist/lib/path.d.ts +22 -0
- package/dist/lib/path.d.ts.map +1 -0
- package/dist/lib/path.js +26 -0
- package/dist/lib/routes.d.ts +32 -0
- package/dist/lib/routes.d.ts.map +1 -0
- package/dist/lib/routes.js +76 -0
- package/dist/lib/types.d.ts +125 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +7 -0
- package/package.json +36 -44
- package/dev.js +0 -4
- package/entrypoint.js +0 -68
- package/lib/app.js +0 -162
- package/lib/const.js +0 -4
- package/lib/cors.js +0 -21
- package/lib/dev.js +0 -54
- package/lib/env.js +0 -24
- package/lib/pack.js +0 -83
- package/lib/path.js +0 -6
- package/lib/routes.js +0 -39
package/entrypoint.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* All handlers will share this same entrypoint
|
|
3
|
-
* the entrypoint will be responsible for routing the request to the correct handler
|
|
4
|
-
* and also for applying middlewares
|
|
5
|
-
* */
|
|
6
|
-
import pathModule from "node:path";
|
|
7
|
-
import { getRoutes } from "./lib/routes.js";
|
|
8
|
-
|
|
9
|
-
export const handler = async (event, context) => {
|
|
10
|
-
const routes = await getRoutes(pathModule.resolve("routes"));
|
|
11
|
-
|
|
12
|
-
const currentRoute = routes.find((route) => {
|
|
13
|
-
return (
|
|
14
|
-
route.path === event.path &&
|
|
15
|
-
route.method.toLowerCase() === event.httpMethod.toLowerCase()
|
|
16
|
-
);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
if (!currentRoute) {
|
|
20
|
-
return {
|
|
21
|
-
statusCode: 404,
|
|
22
|
-
body: "Not Found",
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const extraHeaders = {};
|
|
27
|
-
|
|
28
|
-
if (currentRoute.corsOrigin) {
|
|
29
|
-
extraHeaders["Access-Control-Allow-Origin"] = currentRoute.corsOrigin;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const response = await Promise.race([
|
|
33
|
-
(async () => {
|
|
34
|
-
let body = event.body ? event.body : null;
|
|
35
|
-
|
|
36
|
-
if (event.isBase64Encoded && body) {
|
|
37
|
-
body = Buffer.from(body, "base64").toString("utf-8");
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const rp = await currentRoute.handler(
|
|
41
|
-
{
|
|
42
|
-
...event,
|
|
43
|
-
body,
|
|
44
|
-
isBase64Encoded: false,
|
|
45
|
-
},
|
|
46
|
-
context,
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
return rp;
|
|
50
|
-
})(),
|
|
51
|
-
new Promise(function timeoutResponse(resolve) {
|
|
52
|
-
setTimeout(() => {
|
|
53
|
-
resolve({
|
|
54
|
-
statusCode: 408,
|
|
55
|
-
body: `Request Timeout after ${currentRoute.timeout} seconds`,
|
|
56
|
-
});
|
|
57
|
-
}, currentRoute.timeout * 1000);
|
|
58
|
-
}),
|
|
59
|
-
]);
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
...response,
|
|
63
|
-
headers: {
|
|
64
|
-
...response.headers,
|
|
65
|
-
...extraHeaders,
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
};
|
package/lib/app.js
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import * as pulumi from "@pulumi/pulumi";
|
|
2
|
-
import * as aws from "@pulumi/aws";
|
|
3
|
-
import * as apigateway from "@pulumi/aws-apigateway";
|
|
4
|
-
import { readFile } from "node:fs/promises";
|
|
5
|
-
import { isReservedEnvName } from "./env.js";
|
|
6
|
-
import { packAndZip } from "./pack.js";
|
|
7
|
-
|
|
8
|
-
export function getWildcardCertificateName(domainName) {
|
|
9
|
-
const parts = domainName.split(".");
|
|
10
|
-
return ["*", ...parts.slice(1)].join(".");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export async function createPulumiAPIApp({
|
|
14
|
-
routes,
|
|
15
|
-
bundleDevDependencies = false,
|
|
16
|
-
}) {
|
|
17
|
-
const { zipFileName, zipFileHash } = await packAndZip({
|
|
18
|
-
bundleDevDependencies,
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
const projectName = pulumi.getProject();
|
|
22
|
-
const stackName = pulumi.getStack();
|
|
23
|
-
|
|
24
|
-
const namespace = `wf-${stackName}-${projectName}-${stackName}`;
|
|
25
|
-
|
|
26
|
-
const config = new pulumi.Config();
|
|
27
|
-
const sourceBucketName = config.require("sourceBucket");
|
|
28
|
-
const hostedZone = config.require("hostedZone");
|
|
29
|
-
const runtime = config.require("runtime");
|
|
30
|
-
// we can use subdomain config option to specify a custom name
|
|
31
|
-
let subdomain = config.get("subdomain");
|
|
32
|
-
if (!subdomain) {
|
|
33
|
-
// default subdomain will be generated from pulumi project name
|
|
34
|
-
subdomain = projectName.startsWith("api-")
|
|
35
|
-
? projectName.slice(4)
|
|
36
|
-
: projectName;
|
|
37
|
-
}
|
|
38
|
-
const domainName = `${subdomain}.${hostedZone}`;
|
|
39
|
-
// this bases on a naming convention
|
|
40
|
-
const wildcardCertificateName = getWildcardCertificateName(domainName);
|
|
41
|
-
const lambdaRoleName = config.get("lambdaRole");
|
|
42
|
-
|
|
43
|
-
const role = aws.iam.getRole({ name: lambdaRoleName });
|
|
44
|
-
|
|
45
|
-
const sourceBucket = aws.s3.getBucket({ bucket: sourceBucketName });
|
|
46
|
-
const sourceKey = `${namespace}/sourcecode.zip`;
|
|
47
|
-
|
|
48
|
-
// write to s3 bucket
|
|
49
|
-
// eslint-disable-next-line no-new
|
|
50
|
-
const sourceS3File = new aws.s3.BucketObject(`${namespace}-s3-sourcecode`, {
|
|
51
|
-
bucket: sourceBucket.then((b) => b.id),
|
|
52
|
-
key: sourceKey,
|
|
53
|
-
source: new pulumi.asset.FileArchive(zipFileName),
|
|
54
|
-
sourceHash: zipFileHash,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// Create an API endpoint
|
|
58
|
-
const site = new apigateway.RestAPI(namespace, {
|
|
59
|
-
routes: routes.map(
|
|
60
|
-
({ name, path, method, timeout, memorySize, environmentVariables }) => {
|
|
61
|
-
const variables = environmentVariables
|
|
62
|
-
? environmentVariables.reduce((acc, envName) => {
|
|
63
|
-
if (isReservedEnvName(envName)) {
|
|
64
|
-
// for reserved env names, we don't need to set them
|
|
65
|
-
return acc;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (process.env[envName]) {
|
|
69
|
-
acc[envName] = process.env[envName];
|
|
70
|
-
} else {
|
|
71
|
-
console.warn(
|
|
72
|
-
`Environment variable not set: process.env.${envName}`,
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return acc;
|
|
77
|
-
}, {})
|
|
78
|
-
: {};
|
|
79
|
-
|
|
80
|
-
return {
|
|
81
|
-
path,
|
|
82
|
-
method,
|
|
83
|
-
eventHandler: new aws.lambda.Function(
|
|
84
|
-
// maximum length of lambda function name is 64, pulumi will append 8 random characters to the name
|
|
85
|
-
`${namespace}-${name}`.slice(0, 56),
|
|
86
|
-
{
|
|
87
|
-
name: `${namespace}-${name}`.slice(0, 56),
|
|
88
|
-
role: role.then((r) => r.arn),
|
|
89
|
-
runtime,
|
|
90
|
-
s3Bucket: sourceBucketName,
|
|
91
|
-
s3Key: sourceS3File.key, // wait until the source code is uploaded
|
|
92
|
-
handler: "entrypoint.handler",
|
|
93
|
-
sourceCodeHash: zipFileHash,
|
|
94
|
-
timeout: timeout + 10, // add a few more second for buffer so entrypoint can handle 408 case
|
|
95
|
-
memorySize,
|
|
96
|
-
environment: { variables },
|
|
97
|
-
},
|
|
98
|
-
),
|
|
99
|
-
};
|
|
100
|
-
},
|
|
101
|
-
),
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// Get certificate for desired endpoint
|
|
105
|
-
const certificate = await aws.acm.getCertificate({
|
|
106
|
-
domain: wildcardCertificateName,
|
|
107
|
-
statuses: ["ISSUED"],
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
// Get the zone we're going to use
|
|
111
|
-
const zone = await aws.route53.getZone({ name: hostedZone }, { async: true });
|
|
112
|
-
|
|
113
|
-
// API Gateway requires register the domain with it first
|
|
114
|
-
const domain = new aws.apigateway.DomainName(namespace, {
|
|
115
|
-
certificateArn: certificate.arn,
|
|
116
|
-
domainName,
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// eslint-disable-next-line no-new
|
|
120
|
-
new aws.apigateway.BasePathMapping(namespace, {
|
|
121
|
-
restApi: site.api,
|
|
122
|
-
stageName: site.stage.stageName,
|
|
123
|
-
domainName: domain.domainName,
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// a DNS record to point at the API Gateway
|
|
127
|
-
// eslint-disable-next-line no-new
|
|
128
|
-
new aws.route53.Record(namespace, {
|
|
129
|
-
type: "A",
|
|
130
|
-
zoneId: zone.zoneId,
|
|
131
|
-
name: domainName,
|
|
132
|
-
aliases: [
|
|
133
|
-
{
|
|
134
|
-
// APIGateway provides it's own CloudFront distribution we can point at...
|
|
135
|
-
name: domain.cloudfrontDomainName,
|
|
136
|
-
zoneId: domain.cloudfrontZoneId,
|
|
137
|
-
evaluateTargetHealth: false,
|
|
138
|
-
},
|
|
139
|
-
],
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
const routesInfo = routes.reduce((acc, { name, method, timeout, path }) => {
|
|
143
|
-
acc[name] = {
|
|
144
|
-
method,
|
|
145
|
-
timeout,
|
|
146
|
-
url: `https://${domainName}${path}`,
|
|
147
|
-
};
|
|
148
|
-
return acc;
|
|
149
|
-
}, {});
|
|
150
|
-
|
|
151
|
-
const readme = (await readFile("./README.md")).toString();
|
|
152
|
-
|
|
153
|
-
return {
|
|
154
|
-
zipFileName,
|
|
155
|
-
zipFileHash,
|
|
156
|
-
routes: routesInfo,
|
|
157
|
-
runtime,
|
|
158
|
-
hostedZone,
|
|
159
|
-
domainName,
|
|
160
|
-
readme,
|
|
161
|
-
};
|
|
162
|
-
}
|
package/lib/const.js
DELETED
package/lib/cors.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export function corsPreflight(name, path) {
|
|
2
|
-
return {
|
|
3
|
-
name,
|
|
4
|
-
path,
|
|
5
|
-
method: "OPTIONS",
|
|
6
|
-
timeout: 30,
|
|
7
|
-
memorySize: 128,
|
|
8
|
-
handler: async () => {
|
|
9
|
-
return {
|
|
10
|
-
body: "",
|
|
11
|
-
statusCode: 200,
|
|
12
|
-
headers: {
|
|
13
|
-
"Access-Control-Allow-Origin": "*",
|
|
14
|
-
"Access-Control-Allow-Methods":
|
|
15
|
-
"GET, POST, OPTIONS, PUT, PATCH, DELETE",
|
|
16
|
-
"Access-Control-Allow-Headers": "*",
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
}
|
package/lib/dev.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import express from "express";
|
|
2
|
-
|
|
3
|
-
export function mapRequestToEvent(req) {
|
|
4
|
-
// a custom simulator
|
|
5
|
-
return {
|
|
6
|
-
resource: req.path,
|
|
7
|
-
path: req.path,
|
|
8
|
-
httpMethod: req.method,
|
|
9
|
-
requestContext: {
|
|
10
|
-
resourcePath: req.path,
|
|
11
|
-
httpMethod: req.method,
|
|
12
|
-
path: req.path,
|
|
13
|
-
},
|
|
14
|
-
headers: req.headers,
|
|
15
|
-
multiValueHeaders: {},
|
|
16
|
-
queryStringParameters: req.query,
|
|
17
|
-
body: Buffer.isBuffer(req.body) ? req.body.toString("base64") : "",
|
|
18
|
-
isBase64Encoded: true,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export async function startLocalApp({ routes, handler }) {
|
|
23
|
-
const app = express();
|
|
24
|
-
|
|
25
|
-
app.use(
|
|
26
|
-
express.raw({
|
|
27
|
-
inflate: true,
|
|
28
|
-
limit: "10mb",
|
|
29
|
-
type: () => true, // this matches all content types
|
|
30
|
-
}),
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
routes.forEach(({ path, method }) => {
|
|
34
|
-
const m = method || "GET";
|
|
35
|
-
console.log(`registering ${m} ${path}`);
|
|
36
|
-
const callback = async (req, res) => {
|
|
37
|
-
const context = {};
|
|
38
|
-
const result = await handler(mapRequestToEvent(req), context);
|
|
39
|
-
|
|
40
|
-
for (const [key, value] of Object.entries(result.headers || {})) {
|
|
41
|
-
res.set(key, value);
|
|
42
|
-
}
|
|
43
|
-
res.status(result.statusCode);
|
|
44
|
-
res.send(result.body);
|
|
45
|
-
};
|
|
46
|
-
app[m.toLowerCase()](path, callback);
|
|
47
|
-
// keep compatibility with serverless-offline
|
|
48
|
-
app[m.toLowerCase()](`/dev${path}`, callback);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
console.log("listening on http://localhost:4000");
|
|
52
|
-
|
|
53
|
-
app.listen(4000);
|
|
54
|
-
}
|
package/lib/env.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
const RESERVED_ENV_NAMES = [
|
|
2
|
-
"_HANDLER",
|
|
3
|
-
"_X_AMZN_TRACE_ID",
|
|
4
|
-
"AWS_DEFAULT_REGION",
|
|
5
|
-
"AWS_REGION",
|
|
6
|
-
"AWS_EXECUTION_ENV",
|
|
7
|
-
"AWS_LAMBDA_FUNCTION_NAME",
|
|
8
|
-
"AWS_LAMBDA_FUNCTION_MEMORY_SIZE",
|
|
9
|
-
"AWS_LAMBDA_FUNCTION_VERSION",
|
|
10
|
-
"AWS_LAMBDA_INITIALIZATION_TYPE",
|
|
11
|
-
"AWS_LAMBDA_LOG_GROUP_NAME",
|
|
12
|
-
"AWS_LAMBDA_LOG_STREAM_NAME",
|
|
13
|
-
"AWS_ACCESS_KEY",
|
|
14
|
-
"AWS_ACCESS_KEY_ID",
|
|
15
|
-
"AWS_SECRET_ACCESS_KEY",
|
|
16
|
-
"AWS_SESSION_TOKEN",
|
|
17
|
-
"AWS_LAMBDA_RUNTIME_API",
|
|
18
|
-
"LAMBDA_TASK_ROOT",
|
|
19
|
-
"LAMBDA_RUNTIME_DIR",
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
export function isReservedEnvName(name) {
|
|
23
|
-
return RESERVED_ENV_NAMES.includes(name);
|
|
24
|
-
}
|
package/lib/pack.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import fsModule from "node:fs";
|
|
2
|
-
import pathModule from "node:path";
|
|
3
|
-
import cryptoModule from "node:crypto";
|
|
4
|
-
import { promisify } from "node:util";
|
|
5
|
-
import { exec } from "node:child_process";
|
|
6
|
-
import archiver from "archiver";
|
|
7
|
-
|
|
8
|
-
const execPromise = promisify(exec);
|
|
9
|
-
const rmPromise = promisify(fsModule.rm);
|
|
10
|
-
const mkdirPromise = promisify(fsModule.mkdir);
|
|
11
|
-
const readdirPromise = promisify(fsModule.readdir);
|
|
12
|
-
const cpPromise = promisify(fsModule.cp);
|
|
13
|
-
|
|
14
|
-
const PACK_DIR = ".serverless-pack";
|
|
15
|
-
const ZIP_FILE = "all-code.zip";
|
|
16
|
-
const EXCLUDED_FILES = [
|
|
17
|
-
"node_modules",
|
|
18
|
-
"test",
|
|
19
|
-
"bun.lockb",
|
|
20
|
-
ZIP_FILE,
|
|
21
|
-
PACK_DIR,
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
function zipDirectory(sourceDir, outPath) {
|
|
25
|
-
const archive = archiver("zip", { zlib: { level: 9 } });
|
|
26
|
-
const stream = fsModule.createWriteStream(outPath);
|
|
27
|
-
|
|
28
|
-
return new Promise((resolve, reject) => {
|
|
29
|
-
archive
|
|
30
|
-
.directory(sourceDir, false)
|
|
31
|
-
.on("error", (err) => reject(err))
|
|
32
|
-
.pipe(stream);
|
|
33
|
-
|
|
34
|
-
stream.on("close", () => resolve());
|
|
35
|
-
archive.finalize();
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async function getHash(path) {
|
|
40
|
-
return new Promise((resolve, reject) => {
|
|
41
|
-
const hash = cryptoModule.createHash("sha256");
|
|
42
|
-
const rs = fsModule.createReadStream(path);
|
|
43
|
-
rs.on("error", reject);
|
|
44
|
-
rs.on("data", (chunk) => hash.update(chunk));
|
|
45
|
-
rs.on("end", () => resolve(hash.digest("hex")));
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export async function packAndZip({ bundleDevDependencies } = {}) {
|
|
50
|
-
const packDirAbsolute = pathModule.resolve(PACK_DIR);
|
|
51
|
-
|
|
52
|
-
// remove directory for packing
|
|
53
|
-
await rmPromise(packDirAbsolute, { recursive: true, force: true });
|
|
54
|
-
// make new directory for packing
|
|
55
|
-
await mkdirPromise(packDirAbsolute);
|
|
56
|
-
// copy files to new directory, ignore node_modules, test and all-code.zip
|
|
57
|
-
const rootLevelFiles = await readdirPromise(".");
|
|
58
|
-
|
|
59
|
-
for (const file of rootLevelFiles) {
|
|
60
|
-
if (!EXCLUDED_FILES.includes(file)) {
|
|
61
|
-
await cpPromise(file, pathModule.join(packDirAbsolute, file), {
|
|
62
|
-
recursive: true,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// assume bun exist
|
|
68
|
-
// run bun install --production
|
|
69
|
-
if (bundleDevDependencies) {
|
|
70
|
-
await execPromise("bun install", { cwd: packDirAbsolute });
|
|
71
|
-
} else {
|
|
72
|
-
// install only production dependencies
|
|
73
|
-
await execPromise("bun install --production", { cwd: packDirAbsolute });
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// zip all files in directory
|
|
77
|
-
// create a file to stream archive data to.
|
|
78
|
-
await zipDirectory(packDirAbsolute, pathModule.resolve(ZIP_FILE));
|
|
79
|
-
|
|
80
|
-
const zipFileHash = await getHash(pathModule.resolve(ZIP_FILE));
|
|
81
|
-
|
|
82
|
-
return { zipFileName: ZIP_FILE, zipFileHash };
|
|
83
|
-
}
|
package/lib/path.js
DELETED
package/lib/routes.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import pathModule from "node:path";
|
|
2
|
-
import { readdir } from "node:fs/promises";
|
|
3
|
-
import { corsPreflight } from "./cors.js";
|
|
4
|
-
import { DEFAULT_TIMEOUT, MAX_TIMEOUT, DEFAULT_MEMORY_SIZE } from "./const.js";
|
|
5
|
-
|
|
6
|
-
export async function getRoutes(routeDirectory) {
|
|
7
|
-
const routeFiles = await readdir(routeDirectory);
|
|
8
|
-
|
|
9
|
-
const routesFromFiles = await Promise.all(
|
|
10
|
-
routeFiles.map(async (routeFile) => {
|
|
11
|
-
const routeFilePath = pathModule.join(routeDirectory, routeFile);
|
|
12
|
-
const route = await import(`file://${routeFilePath}`);
|
|
13
|
-
const routeName = pathModule.basename(routeFile, ".js");
|
|
14
|
-
const methods = route.methods || ["GET"];
|
|
15
|
-
const environmentVariables = route.environmentVariables || [];
|
|
16
|
-
|
|
17
|
-
const methodRoutes = methods.map((method) => ({
|
|
18
|
-
name: `${routeName}-${method}`,
|
|
19
|
-
path: `/${routeName}`,
|
|
20
|
-
method,
|
|
21
|
-
corsOrigin: route.corsOrigin,
|
|
22
|
-
timeout: Math.min(route.timeout || DEFAULT_TIMEOUT, MAX_TIMEOUT),
|
|
23
|
-
handler: route.default,
|
|
24
|
-
memorySize: route.memorySize || DEFAULT_MEMORY_SIZE,
|
|
25
|
-
environmentVariables,
|
|
26
|
-
}));
|
|
27
|
-
|
|
28
|
-
if (route.corsOrigin) {
|
|
29
|
-
methodRoutes.push(
|
|
30
|
-
corsPreflight(`${routeName}-OPTIONS`, `/${routeName}`),
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return methodRoutes;
|
|
35
|
-
}),
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
return routesFromFiles.reduce((acc, rs) => acc.concat(rs), []);
|
|
39
|
-
}
|