effortless-aws 0.9.0 → 0.10.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/dist/{chunk-B4P7ZKNM.js → chunk-HINWSFWC.js} +105 -20
- package/dist/cli/index.js +193 -63
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +191 -77
- package/dist/index.js.map +1 -1
- package/dist/runtime/wrap-app.js +1 -1
- package/dist/runtime/wrap-fifo-queue.js +1 -1
- package/dist/runtime/wrap-http.js +1 -1
- package/dist/runtime/wrap-middleware.js +83 -0
- package/dist/runtime/wrap-table-stream.js +19 -7
- package/package.json +1 -1
|
@@ -1,28 +1,67 @@
|
|
|
1
1
|
// src/runtime/table-client.ts
|
|
2
2
|
import { DynamoDB } from "@aws-sdk/client-dynamodb";
|
|
3
3
|
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";
|
|
4
|
-
var
|
|
4
|
+
var GSI_TAG_PK = "tag-pk-index";
|
|
5
|
+
var marshallKey = (key) => marshall(key, { removeUndefinedValues: true });
|
|
6
|
+
var buildSkCondition = (sk) => {
|
|
7
|
+
const names = { "#sk": "sk" };
|
|
8
|
+
if (typeof sk === "string") {
|
|
9
|
+
return { expression: "AND #sk = :sk", names, values: { ":sk": sk } };
|
|
10
|
+
}
|
|
11
|
+
if ("begins_with" in sk) {
|
|
12
|
+
return { expression: "AND begins_with(#sk, :sk)", names, values: { ":sk": sk.begins_with } };
|
|
13
|
+
}
|
|
14
|
+
if ("gt" in sk) {
|
|
15
|
+
return { expression: "AND #sk > :sk", names, values: { ":sk": sk.gt } };
|
|
16
|
+
}
|
|
17
|
+
if ("gte" in sk) {
|
|
18
|
+
return { expression: "AND #sk >= :sk", names, values: { ":sk": sk.gte } };
|
|
19
|
+
}
|
|
20
|
+
if ("lt" in sk) {
|
|
21
|
+
return { expression: "AND #sk < :sk", names, values: { ":sk": sk.lt } };
|
|
22
|
+
}
|
|
23
|
+
if ("lte" in sk) {
|
|
24
|
+
return { expression: "AND #sk <= :sk", names, values: { ":sk": sk.lte } };
|
|
25
|
+
}
|
|
26
|
+
if ("between" in sk) {
|
|
27
|
+
return { expression: "AND #sk BETWEEN :sk1 AND :sk2", names, values: { ":sk1": sk.between[0], ":sk2": sk.between[1] } };
|
|
28
|
+
}
|
|
29
|
+
return { expression: "", names: {}, values: {} };
|
|
30
|
+
};
|
|
31
|
+
var createTableClient = (tableName, options) => {
|
|
5
32
|
let client2 = null;
|
|
6
33
|
const getClient2 = () => client2 ??= new DynamoDB({});
|
|
34
|
+
const tagField = options?.tagField ?? "tag";
|
|
7
35
|
return {
|
|
8
36
|
tableName,
|
|
9
|
-
async put(item) {
|
|
37
|
+
async put(item, putOptions) {
|
|
38
|
+
const dataObj = item.data;
|
|
39
|
+
const tag = dataObj?.[tagField] || "";
|
|
40
|
+
if (!tag) throw new Error(`tag is required: data must include a "${tagField}" field`);
|
|
41
|
+
const dynamoItem = {
|
|
42
|
+
pk: item.pk,
|
|
43
|
+
sk: item.sk,
|
|
44
|
+
tag,
|
|
45
|
+
data: item.data
|
|
46
|
+
};
|
|
47
|
+
if (item.ttl !== void 0) dynamoItem.ttl = item.ttl;
|
|
10
48
|
await getClient2().putItem({
|
|
11
49
|
TableName: tableName,
|
|
12
|
-
Item: marshall(
|
|
50
|
+
Item: marshall(dynamoItem, { removeUndefinedValues: true }),
|
|
51
|
+
...putOptions?.ifNotExists ? { ConditionExpression: "attribute_not_exists(pk)" } : {}
|
|
13
52
|
});
|
|
14
53
|
},
|
|
15
54
|
async get(key) {
|
|
16
55
|
const result = await getClient2().getItem({
|
|
17
56
|
TableName: tableName,
|
|
18
|
-
Key:
|
|
57
|
+
Key: marshallKey(key)
|
|
19
58
|
});
|
|
20
59
|
return result.Item ? unmarshall(result.Item) : void 0;
|
|
21
60
|
},
|
|
22
61
|
async delete(key) {
|
|
23
62
|
await getClient2().deleteItem({
|
|
24
63
|
TableName: tableName,
|
|
25
|
-
Key:
|
|
64
|
+
Key: marshallKey(key)
|
|
26
65
|
});
|
|
27
66
|
},
|
|
28
67
|
async update(key, actions) {
|
|
@@ -31,63 +70,108 @@ var createTableClient = (tableName) => {
|
|
|
31
70
|
const setClauses = [];
|
|
32
71
|
const removeClauses = [];
|
|
33
72
|
let counter = 0;
|
|
73
|
+
const DATA_ALIAS = "#data";
|
|
74
|
+
let needsDataAlias = false;
|
|
34
75
|
if (actions.set) {
|
|
35
76
|
for (const [attr, val] of Object.entries(actions.set)) {
|
|
77
|
+
needsDataAlias = true;
|
|
36
78
|
const alias = `#a${counter}`;
|
|
37
79
|
const valAlias = `:v${counter}`;
|
|
38
80
|
names[alias] = attr;
|
|
39
81
|
values[valAlias] = val;
|
|
40
|
-
setClauses.push(`${alias} = ${valAlias}`);
|
|
82
|
+
setClauses.push(`${DATA_ALIAS}.${alias} = ${valAlias}`);
|
|
41
83
|
counter++;
|
|
42
84
|
}
|
|
43
85
|
}
|
|
44
86
|
if (actions.append) {
|
|
45
87
|
for (const [attr, val] of Object.entries(actions.append)) {
|
|
88
|
+
needsDataAlias = true;
|
|
46
89
|
const alias = `#a${counter}`;
|
|
47
90
|
const valAlias = `:v${counter}`;
|
|
48
91
|
const emptyAlias = `:empty${counter}`;
|
|
49
92
|
names[alias] = attr;
|
|
50
93
|
values[valAlias] = val;
|
|
51
94
|
values[emptyAlias] = [];
|
|
52
|
-
setClauses.push(`${alias} = list_append(if_not_exists(${alias}, ${emptyAlias}), ${valAlias})`);
|
|
95
|
+
setClauses.push(`${DATA_ALIAS}.${alias} = list_append(if_not_exists(${DATA_ALIAS}.${alias}, ${emptyAlias}), ${valAlias})`);
|
|
53
96
|
counter++;
|
|
54
97
|
}
|
|
55
98
|
}
|
|
56
99
|
if (actions.remove) {
|
|
57
100
|
for (const attr of actions.remove) {
|
|
101
|
+
needsDataAlias = true;
|
|
58
102
|
const alias = `#a${counter}`;
|
|
59
103
|
names[alias] = attr;
|
|
60
|
-
removeClauses.push(alias);
|
|
104
|
+
removeClauses.push(`${DATA_ALIAS}.${alias}`);
|
|
61
105
|
counter++;
|
|
62
106
|
}
|
|
63
107
|
}
|
|
108
|
+
if (needsDataAlias) {
|
|
109
|
+
names[DATA_ALIAS] = "data";
|
|
110
|
+
}
|
|
111
|
+
if (actions.tag !== void 0) {
|
|
112
|
+
names["#tag"] = "tag";
|
|
113
|
+
values[":tagVal"] = actions.tag;
|
|
114
|
+
setClauses.push("#tag = :tagVal");
|
|
115
|
+
}
|
|
116
|
+
if (actions.ttl !== void 0) {
|
|
117
|
+
names["#ttl"] = "ttl";
|
|
118
|
+
if (actions.ttl === null) {
|
|
119
|
+
removeClauses.push("#ttl");
|
|
120
|
+
} else {
|
|
121
|
+
values[":ttlVal"] = actions.ttl;
|
|
122
|
+
setClauses.push("#ttl = :ttlVal");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
64
125
|
const parts = [];
|
|
65
126
|
if (setClauses.length) parts.push(`SET ${setClauses.join(", ")}`);
|
|
66
127
|
if (removeClauses.length) parts.push(`REMOVE ${removeClauses.join(", ")}`);
|
|
67
128
|
if (!parts.length) return;
|
|
68
129
|
await getClient2().updateItem({
|
|
69
130
|
TableName: tableName,
|
|
70
|
-
Key:
|
|
131
|
+
Key: marshallKey(key),
|
|
71
132
|
UpdateExpression: parts.join(" "),
|
|
72
133
|
ExpressionAttributeNames: names,
|
|
73
134
|
...Object.keys(values).length ? { ExpressionAttributeValues: marshall(values, { removeUndefinedValues: true }) } : {}
|
|
74
135
|
});
|
|
75
136
|
},
|
|
76
137
|
async query(params) {
|
|
77
|
-
const names = { "#pk":
|
|
78
|
-
const values = { ":pk": params.pk
|
|
138
|
+
const names = { "#pk": "pk" };
|
|
139
|
+
const values = { ":pk": params.pk };
|
|
79
140
|
let keyCondition = "#pk = :pk";
|
|
80
|
-
if (params.sk) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
141
|
+
if (params.sk !== void 0) {
|
|
142
|
+
const skCond = buildSkCondition(params.sk);
|
|
143
|
+
keyCondition += ` ${skCond.expression}`;
|
|
144
|
+
Object.assign(names, skCond.names);
|
|
145
|
+
Object.assign(values, skCond.values);
|
|
146
|
+
}
|
|
147
|
+
const result = await getClient2().query({
|
|
148
|
+
TableName: tableName,
|
|
149
|
+
KeyConditionExpression: keyCondition,
|
|
150
|
+
ExpressionAttributeNames: names,
|
|
151
|
+
ExpressionAttributeValues: marshall(values, { removeUndefinedValues: true }),
|
|
152
|
+
...params.limit ? { Limit: params.limit } : {},
|
|
153
|
+
...params.scanIndexForward !== void 0 ? { ScanIndexForward: params.scanIndexForward } : {}
|
|
154
|
+
});
|
|
155
|
+
return (result.Items ?? []).map((item) => unmarshall(item));
|
|
156
|
+
},
|
|
157
|
+
async queryByTag(params) {
|
|
158
|
+
const names = { "#tag": "tag" };
|
|
159
|
+
const values = { ":tag": params.tag };
|
|
160
|
+
let keyCondition = "#tag = :tag";
|
|
161
|
+
if (params.pk !== void 0) {
|
|
162
|
+
const pkCond = buildSkCondition(params.pk);
|
|
163
|
+
const remapped = pkCond.expression.replace(/#sk/g, "#pk").replace(/:sk/g, ":pk");
|
|
164
|
+
keyCondition += ` ${remapped}`;
|
|
165
|
+
for (const [k, v] of Object.entries(pkCond.names)) {
|
|
166
|
+
names[k === "#sk" ? "#pk" : k] = v === "sk" ? "pk" : v;
|
|
167
|
+
}
|
|
168
|
+
for (const [k, v] of Object.entries(pkCond.values)) {
|
|
169
|
+
values[k.replace(":sk", ":pk")] = v;
|
|
87
170
|
}
|
|
88
171
|
}
|
|
89
172
|
const result = await getClient2().query({
|
|
90
173
|
TableName: tableName,
|
|
174
|
+
IndexName: GSI_TAG_PK,
|
|
91
175
|
KeyConditionExpression: keyCondition,
|
|
92
176
|
ExpressionAttributeNames: names,
|
|
93
177
|
ExpressionAttributeValues: marshall(values, { removeUndefinedValues: true }),
|
|
@@ -167,7 +251,7 @@ var buildParams = async (params) => {
|
|
|
167
251
|
return result;
|
|
168
252
|
};
|
|
169
253
|
var readStatic = (filePath) => readFileSync(join(process.cwd(), filePath), "utf-8");
|
|
170
|
-
var createHandlerRuntime = (handler, handlerType, logLevel = "info") => {
|
|
254
|
+
var createHandlerRuntime = (handler, handlerType, logLevel = "info", extraSetupArgs) => {
|
|
171
255
|
const handlerName = process.env.EFF_HANDLER ?? "unknown";
|
|
172
256
|
const rank = LOG_RANK[logLevel];
|
|
173
257
|
let ctx = null;
|
|
@@ -187,7 +271,8 @@ var createHandlerRuntime = (handler, handlerType, logLevel = "info") => {
|
|
|
187
271
|
const args = {};
|
|
188
272
|
if (params) args.config = params;
|
|
189
273
|
if (deps) args.deps = deps;
|
|
190
|
-
|
|
274
|
+
if (extraSetupArgs) Object.assign(args, extraSetupArgs());
|
|
275
|
+
ctx = Object.keys(args).length > 0 || extraSetupArgs ? await handler.setup(args) : await handler.setup();
|
|
191
276
|
}
|
|
192
277
|
return ctx;
|
|
193
278
|
};
|
package/dist/cli/index.js
CHANGED
|
@@ -70781,6 +70781,7 @@ var ensureLambda = (config2) => Effect_exports.gen(function* () {
|
|
|
70781
70781
|
const runtime5 = config2.runtime ?? Runtime2.nodejs24x;
|
|
70782
70782
|
const layers = config2.layers ?? [];
|
|
70783
70783
|
const environment2 = config2.environment ?? {};
|
|
70784
|
+
const arch = config2.architecture ?? Architecture.arm64;
|
|
70784
70785
|
const existingFunction = yield* lambda_exports.make("get_function", {
|
|
70785
70786
|
FunctionName: functionName
|
|
70786
70787
|
}).pipe(
|
|
@@ -70800,7 +70801,7 @@ var ensureLambda = (config2) => Effect_exports.gen(function* () {
|
|
|
70800
70801
|
const envKeys = [.../* @__PURE__ */ new Set([...Object.keys(existingEnv), ...Object.keys(environment2)])].sort();
|
|
70801
70802
|
const envChanged = envKeys.some((k) => existingEnv[k] !== environment2[k]);
|
|
70802
70803
|
const existingArch = existingFunction.Architectures?.[0] ?? Architecture.x86_64;
|
|
70803
|
-
const archChanged = existingArch !==
|
|
70804
|
+
const archChanged = existingArch !== arch;
|
|
70804
70805
|
const configChanged = existingFunction.MemorySize !== memory || existingFunction.Timeout !== timeout4 || existingFunction.Handler !== handler || existingFunction.Runtime !== runtime5 || layersChanged || envChanged;
|
|
70805
70806
|
if (!codeChanged && !archChanged && !configChanged) {
|
|
70806
70807
|
yield* Effect_exports.logDebug(`Function ${functionName} unchanged, skipping update`);
|
|
@@ -70811,7 +70812,7 @@ var ensureLambda = (config2) => Effect_exports.gen(function* () {
|
|
|
70811
70812
|
yield* lambda_exports.make("update_function_code", {
|
|
70812
70813
|
FunctionName: functionName,
|
|
70813
70814
|
ZipFile: config2.code,
|
|
70814
|
-
Architectures: [
|
|
70815
|
+
Architectures: [arch]
|
|
70815
70816
|
});
|
|
70816
70817
|
yield* waitForFunctionActive(functionName);
|
|
70817
70818
|
} else {
|
|
@@ -70853,7 +70854,7 @@ var ensureLambda = (config2) => Effect_exports.gen(function* () {
|
|
|
70853
70854
|
},
|
|
70854
70855
|
Handler: handler,
|
|
70855
70856
|
Runtime: runtime5,
|
|
70856
|
-
Architectures: [
|
|
70857
|
+
Architectures: [arch],
|
|
70857
70858
|
MemorySize: memory,
|
|
70858
70859
|
Timeout: timeout4,
|
|
70859
70860
|
Tags: config2.tags,
|
|
@@ -70883,6 +70884,16 @@ var waitForFunctionActive = (functionName) => Effect_exports.gen(function* () {
|
|
|
70883
70884
|
);
|
|
70884
70885
|
yield* Effect_exports.logDebug(`Function ${functionName} is active`);
|
|
70885
70886
|
});
|
|
70887
|
+
var publishVersion = (functionName) => Effect_exports.gen(function* () {
|
|
70888
|
+
yield* Effect_exports.logDebug(`Publishing version for: ${functionName}`);
|
|
70889
|
+
const result = yield* lambda_exports.make("publish_version", {
|
|
70890
|
+
FunctionName: functionName
|
|
70891
|
+
});
|
|
70892
|
+
return {
|
|
70893
|
+
versionArn: result.FunctionArn,
|
|
70894
|
+
version: result.Version
|
|
70895
|
+
};
|
|
70896
|
+
});
|
|
70886
70897
|
var deleteLambda = (functionName) => Effect_exports.gen(function* () {
|
|
70887
70898
|
yield* Effect_exports.logDebug(`Deleting Lambda function: ${functionName}`);
|
|
70888
70899
|
yield* lambda_exports.make("delete_function", {
|
|
@@ -70956,6 +70967,18 @@ var LAMBDA_ASSUME_ROLE_POLICY = JSON.stringify({
|
|
|
70956
70967
|
}
|
|
70957
70968
|
]
|
|
70958
70969
|
});
|
|
70970
|
+
var EDGE_LAMBDA_ASSUME_ROLE_POLICY = JSON.stringify({
|
|
70971
|
+
Version: "2012-10-17",
|
|
70972
|
+
Statement: [
|
|
70973
|
+
{
|
|
70974
|
+
Effect: "Allow",
|
|
70975
|
+
Principal: {
|
|
70976
|
+
Service: ["lambda.amazonaws.com", "edgelambda.amazonaws.com"]
|
|
70977
|
+
},
|
|
70978
|
+
Action: "sts:AssumeRole"
|
|
70979
|
+
}
|
|
70980
|
+
]
|
|
70981
|
+
});
|
|
70959
70982
|
var BASIC_EXECUTION_POLICY_ARN = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole";
|
|
70960
70983
|
var ensureRole = (project2, stage, name, additionalActions, tags2) => Effect_exports.gen(function* () {
|
|
70961
70984
|
const roleName = `${project2}-${stage}-${name}-role`;
|
|
@@ -70996,6 +71019,39 @@ var ensureRole = (project2, stage, name, additionalActions, tags2) => Effect_exp
|
|
|
70996
71019
|
yield* Effect_exports.sleep("10 seconds");
|
|
70997
71020
|
return createResult.Role.Arn;
|
|
70998
71021
|
});
|
|
71022
|
+
var ensureEdgeRole = (project2, stage, name, tags2) => Effect_exports.gen(function* () {
|
|
71023
|
+
const roleName = `${project2}-${stage}-${name}-role`;
|
|
71024
|
+
const existingRole = yield* iam_exports.make("get_role", { RoleName: roleName }).pipe(
|
|
71025
|
+
Effect_exports.map((r) => r.Role),
|
|
71026
|
+
Effect_exports.catchIf(
|
|
71027
|
+
(e) => e._tag === "IAMError" && e.is("NoSuchEntityException"),
|
|
71028
|
+
() => Effect_exports.succeed(void 0)
|
|
71029
|
+
)
|
|
71030
|
+
);
|
|
71031
|
+
if (existingRole) {
|
|
71032
|
+
yield* Effect_exports.logDebug(`Using existing edge role: ${roleName}`);
|
|
71033
|
+
if (tags2) {
|
|
71034
|
+
yield* iam_exports.make("tag_role", {
|
|
71035
|
+
RoleName: roleName,
|
|
71036
|
+
Tags: toAwsTagList(tags2)
|
|
71037
|
+
});
|
|
71038
|
+
}
|
|
71039
|
+
return existingRole.Arn;
|
|
71040
|
+
}
|
|
71041
|
+
yield* Effect_exports.logDebug(`Creating edge role: ${roleName}`);
|
|
71042
|
+
const createResult = yield* iam_exports.make("create_role", {
|
|
71043
|
+
RoleName: roleName,
|
|
71044
|
+
AssumeRolePolicyDocument: EDGE_LAMBDA_ASSUME_ROLE_POLICY,
|
|
71045
|
+
Description: `Execution role for Lambda@Edge function ${name}`,
|
|
71046
|
+
Tags: tags2 ? toAwsTagList(tags2) : void 0
|
|
71047
|
+
});
|
|
71048
|
+
yield* iam_exports.make("attach_role_policy", {
|
|
71049
|
+
RoleName: roleName,
|
|
71050
|
+
PolicyArn: BASIC_EXECUTION_POLICY_ARN
|
|
71051
|
+
});
|
|
71052
|
+
yield* Effect_exports.sleep("10 seconds");
|
|
71053
|
+
return createResult.Role.Arn;
|
|
71054
|
+
});
|
|
70999
71055
|
var ensureInlinePolicy = (roleName, functionName, actions) => Effect_exports.gen(function* () {
|
|
71000
71056
|
const policyName = `${functionName}-inline-policy`;
|
|
71001
71057
|
const policyDocument = JSON.stringify({
|
|
@@ -71085,18 +71141,7 @@ var listEffortlessRoles = () => Effect_exports.gen(function* () {
|
|
|
71085
71141
|
});
|
|
71086
71142
|
|
|
71087
71143
|
// src/aws/dynamodb.ts
|
|
71088
|
-
var
|
|
71089
|
-
switch (type2) {
|
|
71090
|
-
case "string":
|
|
71091
|
-
return "S";
|
|
71092
|
-
case "number":
|
|
71093
|
-
return "N";
|
|
71094
|
-
case "binary":
|
|
71095
|
-
return "B";
|
|
71096
|
-
default:
|
|
71097
|
-
return type2;
|
|
71098
|
-
}
|
|
71099
|
-
};
|
|
71144
|
+
var GSI_TAG_PK = "tag-pk-index";
|
|
71100
71145
|
var streamViewToSpec = (view) => ({
|
|
71101
71146
|
StreamEnabled: true,
|
|
71102
71147
|
StreamViewType: view
|
|
@@ -71141,7 +71186,7 @@ var ensureTimeToLive = (tableName, attributeName) => Effect_exports.gen(function
|
|
|
71141
71186
|
});
|
|
71142
71187
|
});
|
|
71143
71188
|
var ensureTable = (input) => Effect_exports.gen(function* () {
|
|
71144
|
-
const { name,
|
|
71189
|
+
const { name, billingMode = "PAY_PER_REQUEST", streamView = "NEW_AND_OLD_IMAGES", tags: tags2 } = input;
|
|
71145
71190
|
const existingTable = yield* dynamodb_exports.make("describe_table", { TableName: name }).pipe(
|
|
71146
71191
|
Effect_exports.map((result2) => result2.Table),
|
|
71147
71192
|
Effect_exports.catchIf(
|
|
@@ -71152,20 +71197,25 @@ var ensureTable = (input) => Effect_exports.gen(function* () {
|
|
|
71152
71197
|
let result;
|
|
71153
71198
|
if (!existingTable) {
|
|
71154
71199
|
yield* Effect_exports.logInfo(`Creating table ${name}...`);
|
|
71155
|
-
const keySchema = [
|
|
71156
|
-
{ AttributeName: pk.name, KeyType: "HASH" }
|
|
71157
|
-
];
|
|
71158
|
-
const attributeDefinitions = [
|
|
71159
|
-
{ AttributeName: pk.name, AttributeType: keyTypeToDynamoDB(pk.type) }
|
|
71160
|
-
];
|
|
71161
|
-
if (sk) {
|
|
71162
|
-
keySchema.push({ AttributeName: sk.name, KeyType: "RANGE" });
|
|
71163
|
-
attributeDefinitions.push({ AttributeName: sk.name, AttributeType: keyTypeToDynamoDB(sk.type) });
|
|
71164
|
-
}
|
|
71165
71200
|
yield* dynamodb_exports.make("create_table", {
|
|
71166
71201
|
TableName: name,
|
|
71167
|
-
KeySchema:
|
|
71168
|
-
|
|
71202
|
+
KeySchema: [
|
|
71203
|
+
{ AttributeName: "pk", KeyType: "HASH" },
|
|
71204
|
+
{ AttributeName: "sk", KeyType: "RANGE" }
|
|
71205
|
+
],
|
|
71206
|
+
AttributeDefinitions: [
|
|
71207
|
+
{ AttributeName: "pk", AttributeType: "S" },
|
|
71208
|
+
{ AttributeName: "sk", AttributeType: "S" },
|
|
71209
|
+
{ AttributeName: "tag", AttributeType: "S" }
|
|
71210
|
+
],
|
|
71211
|
+
GlobalSecondaryIndexes: [{
|
|
71212
|
+
IndexName: GSI_TAG_PK,
|
|
71213
|
+
KeySchema: [
|
|
71214
|
+
{ AttributeName: "tag", KeyType: "HASH" },
|
|
71215
|
+
{ AttributeName: "pk", KeyType: "RANGE" }
|
|
71216
|
+
],
|
|
71217
|
+
Projection: { ProjectionType: "ALL" }
|
|
71218
|
+
}],
|
|
71169
71219
|
BillingMode: billingMode,
|
|
71170
71220
|
StreamSpecification: streamViewToSpec(streamView),
|
|
71171
71221
|
Tags: tags2 ? toAwsTagList(tags2) : void 0
|
|
@@ -71189,21 +71239,40 @@ var ensureTable = (input) => Effect_exports.gen(function* () {
|
|
|
71189
71239
|
TableName: name,
|
|
71190
71240
|
StreamSpecification: streamViewToSpec(streamView)
|
|
71191
71241
|
});
|
|
71192
|
-
|
|
71193
|
-
result = {
|
|
71194
|
-
tableArn: table3.TableArn,
|
|
71195
|
-
streamArn: table3.LatestStreamArn
|
|
71196
|
-
};
|
|
71197
|
-
} else {
|
|
71198
|
-
result = {
|
|
71199
|
-
tableArn: existingTable.TableArn,
|
|
71200
|
-
streamArn: existingTable.LatestStreamArn
|
|
71201
|
-
};
|
|
71242
|
+
yield* waitForTableActive(name);
|
|
71202
71243
|
}
|
|
71244
|
+
const hasGsi = existingTable.GlobalSecondaryIndexes?.some(
|
|
71245
|
+
(gsi) => gsi.IndexName === GSI_TAG_PK
|
|
71246
|
+
);
|
|
71247
|
+
if (!hasGsi) {
|
|
71248
|
+
yield* Effect_exports.logInfo(`Adding GSI ${GSI_TAG_PK} to table ${name}...`);
|
|
71249
|
+
yield* dynamodb_exports.make("update_table", {
|
|
71250
|
+
TableName: name,
|
|
71251
|
+
AttributeDefinitions: [
|
|
71252
|
+
{ AttributeName: "pk", AttributeType: "S" },
|
|
71253
|
+
{ AttributeName: "sk", AttributeType: "S" },
|
|
71254
|
+
{ AttributeName: "tag", AttributeType: "S" }
|
|
71255
|
+
],
|
|
71256
|
+
GlobalSecondaryIndexUpdates: [{
|
|
71257
|
+
Create: {
|
|
71258
|
+
IndexName: GSI_TAG_PK,
|
|
71259
|
+
KeySchema: [
|
|
71260
|
+
{ AttributeName: "tag", KeyType: "HASH" },
|
|
71261
|
+
{ AttributeName: "pk", KeyType: "RANGE" }
|
|
71262
|
+
],
|
|
71263
|
+
Projection: { ProjectionType: "ALL" }
|
|
71264
|
+
}
|
|
71265
|
+
}]
|
|
71266
|
+
});
|
|
71267
|
+
yield* waitForTableActive(name);
|
|
71268
|
+
}
|
|
71269
|
+
const updated = yield* dynamodb_exports.make("describe_table", { TableName: name });
|
|
71270
|
+
result = {
|
|
71271
|
+
tableArn: updated.Table.TableArn,
|
|
71272
|
+
streamArn: updated.Table.LatestStreamArn
|
|
71273
|
+
};
|
|
71203
71274
|
}
|
|
71204
|
-
|
|
71205
|
-
yield* ensureTimeToLive(name, ttlAttribute);
|
|
71206
|
-
}
|
|
71275
|
+
yield* ensureTimeToLive(name, "ttl");
|
|
71207
71276
|
return result;
|
|
71208
71277
|
});
|
|
71209
71278
|
var ensureEventSourceMapping = (input) => Effect_exports.gen(function* () {
|
|
@@ -72046,14 +72115,15 @@ var ensureViewerRequestFunction = (name, config2) => Effect_exports.gen(function
|
|
|
72046
72115
|
});
|
|
72047
72116
|
var makeDistComment = (project2, stage, handlerName) => `effortless: ${project2}/${stage}/${handlerName}`;
|
|
72048
72117
|
var ensureDistribution = (input) => Effect_exports.gen(function* () {
|
|
72049
|
-
const { project: project2, stage, handlerName, bucketName, bucketRegion, oacId, spa, index, tags: tags2, urlRewriteFunctionArn, aliases, acmCertificateArn } = input;
|
|
72118
|
+
const { project: project2, stage, handlerName, bucketName, bucketRegion, oacId, spa, index, tags: tags2, urlRewriteFunctionArn, lambdaEdgeArn, aliases, acmCertificateArn } = input;
|
|
72050
72119
|
const aliasesConfig = aliases && aliases.length > 0 ? { Quantity: aliases.length, Items: aliases } : { Quantity: 0, Items: [] };
|
|
72051
72120
|
const viewerCertificate = acmCertificateArn ? {
|
|
72052
72121
|
ACMCertificateArn: acmCertificateArn,
|
|
72053
72122
|
SSLSupportMethod: "sni-only",
|
|
72054
72123
|
MinimumProtocolVersion: "TLSv1.2_2021"
|
|
72055
72124
|
} : void 0;
|
|
72056
|
-
const functionAssociations = urlRewriteFunctionArn ? { Quantity: 1, Items: [{ FunctionARN: urlRewriteFunctionArn, EventType: "viewer-request" }] } : { Quantity: 0, Items: [] };
|
|
72125
|
+
const functionAssociations = !lambdaEdgeArn && urlRewriteFunctionArn ? { Quantity: 1, Items: [{ FunctionARN: urlRewriteFunctionArn, EventType: "viewer-request" }] } : { Quantity: 0, Items: [] };
|
|
72126
|
+
const lambdaFunctionAssociations = lambdaEdgeArn ? { Quantity: 1, Items: [{ EventType: "viewer-request", LambdaFunctionARN: lambdaEdgeArn, IncludeBody: false }] } : { Quantity: 0, Items: [] };
|
|
72057
72127
|
const comment = makeDistComment(project2, stage, handlerName);
|
|
72058
72128
|
const originId = `S3-${bucketName}`;
|
|
72059
72129
|
const originDomain = `${bucketName}.s3.${bucketRegion}.amazonaws.com`;
|
|
@@ -72087,7 +72157,8 @@ var ensureDistribution = (input) => Effect_exports.gen(function* () {
|
|
|
72087
72157
|
const desiredAliases = aliases ?? [];
|
|
72088
72158
|
const aliasesMatch = currentAliases.length === desiredAliases.length && desiredAliases.every((a) => currentAliases.includes(a));
|
|
72089
72159
|
const certMatch = currentConfig.ViewerCertificate?.ACMCertificateArn === (acmCertificateArn ?? void 0);
|
|
72090
|
-
const
|
|
72160
|
+
const currentLambdaEdgeArn = currentConfig.DefaultCacheBehavior?.LambdaFunctionAssociations?.Items?.[0]?.LambdaFunctionARN;
|
|
72161
|
+
const needsUpdate = currentOrigin?.DomainName !== originDomain || currentOrigin?.OriginAccessControlId !== oacId || currentConfig.DefaultRootObject !== index || currentConfig.DefaultCacheBehavior?.CachePolicyId !== CACHING_OPTIMIZED_POLICY_ID || (currentConfig.CustomErrorResponses?.Quantity ?? 0) !== customErrorResponses.Quantity || (currentConfig.DefaultCacheBehavior?.FunctionAssociations?.Quantity ?? 0) !== functionAssociations.Quantity || currentConfig.DefaultCacheBehavior?.FunctionAssociations?.Items?.[0]?.FunctionARN !== (urlRewriteFunctionArn ?? void 0) || (currentConfig.DefaultCacheBehavior?.LambdaFunctionAssociations?.Quantity ?? 0) !== lambdaFunctionAssociations.Quantity || currentLambdaEdgeArn !== (lambdaEdgeArn ?? void 0) || !aliasesMatch || !certMatch;
|
|
72091
72162
|
if (needsUpdate) {
|
|
72092
72163
|
yield* Effect_exports.logDebug(`CloudFront distribution ${existing.Id} config changed, updating...`);
|
|
72093
72164
|
const etag = configResult.ETag;
|
|
@@ -72122,6 +72193,7 @@ var ensureDistribution = (input) => Effect_exports.gen(function* () {
|
|
|
72122
72193
|
Compress: true,
|
|
72123
72194
|
CachePolicyId: CACHING_OPTIMIZED_POLICY_ID,
|
|
72124
72195
|
FunctionAssociations: functionAssociations,
|
|
72196
|
+
LambdaFunctionAssociations: lambdaFunctionAssociations,
|
|
72125
72197
|
ForwardedValues: void 0
|
|
72126
72198
|
},
|
|
72127
72199
|
Aliases: aliasesConfig,
|
|
@@ -72171,7 +72243,8 @@ var ensureDistribution = (input) => Effect_exports.gen(function* () {
|
|
|
72171
72243
|
},
|
|
72172
72244
|
Compress: true,
|
|
72173
72245
|
CachePolicyId: CACHING_OPTIMIZED_POLICY_ID,
|
|
72174
|
-
FunctionAssociations: functionAssociations
|
|
72246
|
+
FunctionAssociations: functionAssociations,
|
|
72247
|
+
LambdaFunctionAssociations: lambdaFunctionAssociations
|
|
72175
72248
|
},
|
|
72176
72249
|
Aliases: aliasesConfig,
|
|
72177
72250
|
...viewerCertificate ? { ViewerCertificate: viewerCertificate } : {},
|
|
@@ -72443,7 +72516,7 @@ var parseSource = (source) => {
|
|
|
72443
72516
|
const project2 = new Project({ useInMemoryFileSystem: true });
|
|
72444
72517
|
return project2.createSourceFile("input.ts", source);
|
|
72445
72518
|
};
|
|
72446
|
-
var RUNTIME_PROPS = ["onRequest", "onRecord", "onBatchComplete", "onBatch", "onMessage", "setup", "schema", "onError", "deps", "config", "static"];
|
|
72519
|
+
var RUNTIME_PROPS = ["onRequest", "onRecord", "onBatchComplete", "onBatch", "onMessage", "setup", "schema", "onError", "deps", "config", "static", "middleware"];
|
|
72447
72520
|
var buildConfigWithoutRuntime = (obj) => {
|
|
72448
72521
|
const props = obj.getProperties().filter((p3) => {
|
|
72449
72522
|
if (p3.getKind() === SyntaxKind.PropertyAssignment) {
|
|
@@ -72557,9 +72630,9 @@ var handlerRegistry = {
|
|
|
72557
72630
|
},
|
|
72558
72631
|
staticSite: {
|
|
72559
72632
|
defineFn: "defineStaticSite",
|
|
72560
|
-
handlerProps: [],
|
|
72561
|
-
wrapperFn: "",
|
|
72562
|
-
wrapperPath: ""
|
|
72633
|
+
handlerProps: ["middleware"],
|
|
72634
|
+
wrapperFn: "wrapMiddleware",
|
|
72635
|
+
wrapperPath: "~/runtime/wrap-middleware"
|
|
72563
72636
|
},
|
|
72564
72637
|
fifoQueue: {
|
|
72565
72638
|
defineFn: "defineFifoQueue",
|
|
@@ -73024,8 +73097,6 @@ var deployTableFunction = ({ input, fn: fn2, layerArn, external, depsEnv, depsPe
|
|
|
73024
73097
|
const tableName = `${input.project}-${tagCtx.stage}-${handlerName}`;
|
|
73025
73098
|
const { tableArn, streamArn } = yield* ensureTable({
|
|
73026
73099
|
name: tableName,
|
|
73027
|
-
pk: config2.pk,
|
|
73028
|
-
sk: config2.sk,
|
|
73029
73100
|
billingMode: config2.billingMode ?? "PAY_PER_REQUEST",
|
|
73030
73101
|
streamView: config2.streamView ?? "NEW_AND_OLD_IMAGES",
|
|
73031
73102
|
tags: makeTags(tagCtx, "dynamodb")
|
|
@@ -73157,13 +73228,54 @@ var deployAppLambda = ({ input, fn: fn2, layerArn, external, depsEnv, depsPermis
|
|
|
73157
73228
|
});
|
|
73158
73229
|
|
|
73159
73230
|
// src/deploy/deploy-static-site.ts
|
|
73231
|
+
import { Architecture as Architecture3 } from "@aws-sdk/client-lambda";
|
|
73160
73232
|
import { execSync as execSync2 } from "child_process";
|
|
73161
73233
|
import * as path8 from "path";
|
|
73234
|
+
var deployMiddlewareLambda = (input) => Effect_exports.gen(function* () {
|
|
73235
|
+
const { projectDir, project: project2, stage, handlerName, file: file7, exportName, tagCtx } = input;
|
|
73236
|
+
const middlewareName = `${handlerName}-middleware`;
|
|
73237
|
+
yield* Effect_exports.logDebug(`Deploying middleware Lambda@Edge: ${middlewareName}`);
|
|
73238
|
+
const roleArn = yield* ensureEdgeRole(
|
|
73239
|
+
project2,
|
|
73240
|
+
stage,
|
|
73241
|
+
middlewareName,
|
|
73242
|
+
makeTags(tagCtx, "iam-role")
|
|
73243
|
+
);
|
|
73244
|
+
const bundled = yield* bundle({
|
|
73245
|
+
projectDir,
|
|
73246
|
+
file: file7,
|
|
73247
|
+
exportName,
|
|
73248
|
+
type: "staticSite"
|
|
73249
|
+
});
|
|
73250
|
+
const code2 = yield* zip12({ content: bundled });
|
|
73251
|
+
const { functionArn } = yield* ensureLambda({
|
|
73252
|
+
project: project2,
|
|
73253
|
+
stage,
|
|
73254
|
+
name: middlewareName,
|
|
73255
|
+
region: "us-east-1",
|
|
73256
|
+
roleArn,
|
|
73257
|
+
code: code2,
|
|
73258
|
+
memory: 128,
|
|
73259
|
+
timeout: 5,
|
|
73260
|
+
architecture: Architecture3.x86_64,
|
|
73261
|
+
tags: makeTags(tagCtx, "lambda")
|
|
73262
|
+
}).pipe(
|
|
73263
|
+
Effect_exports.provide(clients_exports.makeClients({ lambda: { region: "us-east-1" } }))
|
|
73264
|
+
);
|
|
73265
|
+
const { versionArn } = yield* publishVersion(
|
|
73266
|
+
`${project2}-${stage}-${middlewareName}`
|
|
73267
|
+
).pipe(
|
|
73268
|
+
Effect_exports.provide(clients_exports.makeClients({ lambda: { region: "us-east-1" } }))
|
|
73269
|
+
);
|
|
73270
|
+
yield* Effect_exports.logDebug(`Middleware deployed: ${versionArn}`);
|
|
73271
|
+
return { versionArn };
|
|
73272
|
+
});
|
|
73162
73273
|
var deployStaticSite = (input) => Effect_exports.gen(function* () {
|
|
73163
73274
|
const { projectDir, project: project2, region, fn: fn2 } = input;
|
|
73164
73275
|
const { exportName, config: config2 } = fn2;
|
|
73165
73276
|
const stage = resolveStage(input.stage);
|
|
73166
73277
|
const handlerName = config2.name ?? exportName;
|
|
73278
|
+
const hasMiddleware = fn2.hasHandler;
|
|
73167
73279
|
const tagCtx = { project: project2, stage, handler: handlerName };
|
|
73168
73280
|
if (config2.build) {
|
|
73169
73281
|
yield* Effect_exports.logDebug(`Building site: ${config2.build}`);
|
|
@@ -73173,7 +73285,7 @@ var deployStaticSite = (input) => Effect_exports.gen(function* () {
|
|
|
73173
73285
|
});
|
|
73174
73286
|
}
|
|
73175
73287
|
const bucketName = `${project2}-${stage}-${handlerName}-site`.toLowerCase();
|
|
73176
|
-
|
|
73288
|
+
yield* ensureBucket({
|
|
73177
73289
|
name: bucketName,
|
|
73178
73290
|
region,
|
|
73179
73291
|
tags: makeTags(tagCtx, "s3-bucket")
|
|
@@ -73201,16 +73313,32 @@ var deployStaticSite = (input) => Effect_exports.gen(function* () {
|
|
|
73201
73313
|
}
|
|
73202
73314
|
}
|
|
73203
73315
|
const isSpa = config2.spa ?? false;
|
|
73204
|
-
const needsUrlRewrite = !isSpa;
|
|
73205
|
-
const needsWwwRedirect = !!wwwDomain;
|
|
73206
73316
|
let urlRewriteFunctionArn;
|
|
73207
|
-
|
|
73208
|
-
|
|
73209
|
-
const result = yield*
|
|
73210
|
-
|
|
73211
|
-
|
|
73212
|
-
|
|
73213
|
-
|
|
73317
|
+
let lambdaEdgeArn;
|
|
73318
|
+
if (hasMiddleware && input.file) {
|
|
73319
|
+
const result = yield* deployMiddlewareLambda({
|
|
73320
|
+
projectDir,
|
|
73321
|
+
project: project2,
|
|
73322
|
+
stage,
|
|
73323
|
+
handlerName,
|
|
73324
|
+
file: input.file,
|
|
73325
|
+
exportName,
|
|
73326
|
+
tagCtx
|
|
73327
|
+
}).pipe(
|
|
73328
|
+
Effect_exports.provide(clients_exports.makeClients({ iam: { region: "us-east-1" } }))
|
|
73329
|
+
);
|
|
73330
|
+
lambdaEdgeArn = result.versionArn;
|
|
73331
|
+
} else {
|
|
73332
|
+
const needsUrlRewrite = !isSpa;
|
|
73333
|
+
const needsWwwRedirect = !!wwwDomain;
|
|
73334
|
+
if (needsUrlRewrite || needsWwwRedirect) {
|
|
73335
|
+
const fnName = needsWwwRedirect ? `${project2}-${stage}-${handlerName}-viewer-req` : `${project2}-${stage}-url-rewrite`;
|
|
73336
|
+
const result = yield* ensureViewerRequestFunction(fnName, {
|
|
73337
|
+
rewriteUrls: needsUrlRewrite,
|
|
73338
|
+
redirectWwwDomain: wwwDomain
|
|
73339
|
+
});
|
|
73340
|
+
urlRewriteFunctionArn = result.functionArn;
|
|
73341
|
+
}
|
|
73214
73342
|
}
|
|
73215
73343
|
const index = config2.index ?? "index.html";
|
|
73216
73344
|
const { distributionId, distributionArn, domainName } = yield* ensureDistribution({
|
|
@@ -73224,6 +73352,7 @@ var deployStaticSite = (input) => Effect_exports.gen(function* () {
|
|
|
73224
73352
|
index,
|
|
73225
73353
|
tags: makeTags(tagCtx, "cloudfront-distribution"),
|
|
73226
73354
|
urlRewriteFunctionArn,
|
|
73355
|
+
lambdaEdgeArn,
|
|
73227
73356
|
aliases,
|
|
73228
73357
|
acmCertificateArn
|
|
73229
73358
|
});
|
|
@@ -73555,7 +73684,7 @@ var buildAppTasks = (ctx, handlers, apiId, results) => {
|
|
|
73555
73684
|
var buildStaticSiteTasks = (ctx, handlers, results) => {
|
|
73556
73685
|
const tasks = [];
|
|
73557
73686
|
const { region } = ctx.input;
|
|
73558
|
-
for (const { exports } of handlers) {
|
|
73687
|
+
for (const { file: file7, exports } of handlers) {
|
|
73559
73688
|
for (const fn2 of exports) {
|
|
73560
73689
|
tasks.push(
|
|
73561
73690
|
Effect_exports.gen(function* () {
|
|
@@ -73564,7 +73693,8 @@ var buildStaticSiteTasks = (ctx, handlers, results) => {
|
|
|
73564
73693
|
project: ctx.input.project,
|
|
73565
73694
|
stage: ctx.input.stage,
|
|
73566
73695
|
region,
|
|
73567
|
-
fn: fn2
|
|
73696
|
+
fn: fn2,
|
|
73697
|
+
...fn2.hasHandler ? { file: file7 } : {}
|
|
73568
73698
|
}).pipe(Effect_exports.provide(clients_exports.makeClients({
|
|
73569
73699
|
s3: { region },
|
|
73570
73700
|
cloudfront: { region: "us-east-1" },
|