@effortless-aws/cli 0.2.0 → 0.2.2
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/cli/index.js +101 -43
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1943,56 +1943,36 @@ var ensureFunctionUrl = (functionName) => Effect13.gen(function* () {
|
|
|
1943
1943
|
)
|
|
1944
1944
|
);
|
|
1945
1945
|
if (existing) {
|
|
1946
|
-
yield*
|
|
1946
|
+
yield* lambda_exports.make("update_function_url_config", {
|
|
1947
|
+
FunctionName: functionName,
|
|
1948
|
+
AuthType: "NONE"
|
|
1949
|
+
});
|
|
1947
1950
|
return { functionUrl: existing.FunctionUrl };
|
|
1948
1951
|
}
|
|
1949
1952
|
yield* Effect13.logDebug(`Creating Function URL for: ${functionName}`);
|
|
1950
1953
|
const result = yield* lambda_exports.make("create_function_url_config", {
|
|
1951
1954
|
FunctionName: functionName,
|
|
1952
|
-
AuthType: "
|
|
1955
|
+
AuthType: "NONE",
|
|
1953
1956
|
InvokeMode: "BUFFERED"
|
|
1954
1957
|
});
|
|
1955
1958
|
return { functionUrl: result.FunctionUrl };
|
|
1956
1959
|
});
|
|
1957
|
-
var
|
|
1960
|
+
var addFunctionUrlPublicAccess = (functionName) => Effect13.gen(function* () {
|
|
1958
1961
|
const statements = [
|
|
1959
|
-
{
|
|
1960
|
-
|
|
1961
|
-
action: "lambda:InvokeFunctionUrl",
|
|
1962
|
-
authType: "AWS_IAM"
|
|
1963
|
-
},
|
|
1964
|
-
{
|
|
1965
|
-
statementId: "cloudfront-oac-invoke",
|
|
1966
|
-
action: "lambda:InvokeFunction",
|
|
1967
|
-
authType: void 0
|
|
1968
|
-
}
|
|
1962
|
+
{ statementId: "function-url-public", action: "lambda:InvokeFunctionUrl", urlAuthType: "NONE" },
|
|
1963
|
+
{ statementId: "function-url-invoke", action: "lambda:InvokeFunction", urlAuthType: void 0 }
|
|
1969
1964
|
];
|
|
1970
1965
|
for (const stmt of statements) {
|
|
1971
1966
|
yield* lambda_exports.make("add_permission", {
|
|
1972
1967
|
FunctionName: functionName,
|
|
1973
1968
|
StatementId: stmt.statementId,
|
|
1974
1969
|
Action: stmt.action,
|
|
1975
|
-
Principal: "
|
|
1976
|
-
|
|
1977
|
-
...stmt.authType ? { FunctionUrlAuthType: stmt.authType } : {}
|
|
1970
|
+
Principal: "*",
|
|
1971
|
+
...stmt.urlAuthType ? { FunctionUrlAuthType: stmt.urlAuthType } : {}
|
|
1978
1972
|
}).pipe(
|
|
1979
1973
|
Effect13.catchIf(
|
|
1980
1974
|
(e) => e._tag === "LambdaError" && e.is("ResourceConflictException"),
|
|
1981
|
-
() => Effect13.
|
|
1982
|
-
yield* Effect13.logDebug(`Permission ${stmt.statementId} exists for ${functionName}, replacing...`);
|
|
1983
|
-
yield* lambda_exports.make("remove_permission", {
|
|
1984
|
-
FunctionName: functionName,
|
|
1985
|
-
StatementId: stmt.statementId
|
|
1986
|
-
});
|
|
1987
|
-
yield* lambda_exports.make("add_permission", {
|
|
1988
|
-
FunctionName: functionName,
|
|
1989
|
-
StatementId: stmt.statementId,
|
|
1990
|
-
Action: stmt.action,
|
|
1991
|
-
Principal: "cloudfront.amazonaws.com",
|
|
1992
|
-
SourceArn: distributionArn,
|
|
1993
|
-
...stmt.authType ? { FunctionUrlAuthType: stmt.authType } : {}
|
|
1994
|
-
});
|
|
1995
|
-
})
|
|
1975
|
+
() => Effect13.logDebug(`Permission ${stmt.statementId} already exists for ${functionName}`)
|
|
1996
1976
|
)
|
|
1997
1977
|
);
|
|
1998
1978
|
}
|
|
@@ -2660,6 +2640,14 @@ var DEV_ONLY_PREFIXES = [
|
|
|
2660
2640
|
"@vitest/",
|
|
2661
2641
|
"@jest/"
|
|
2662
2642
|
];
|
|
2643
|
+
var extractExportPaths = (value) => {
|
|
2644
|
+
if (typeof value === "string") return [value];
|
|
2645
|
+
if (typeof value === "object" && value !== null) {
|
|
2646
|
+
return Object.values(value).flatMap(extractExportPaths);
|
|
2647
|
+
}
|
|
2648
|
+
return [];
|
|
2649
|
+
};
|
|
2650
|
+
var isRawTypeScript = (p) => /\.(?:ts|tsx|mts|cts)$/.test(p) && !p.endsWith(".d.ts") && !p.endsWith(".d.mts") && !p.endsWith(".d.cts");
|
|
2663
2651
|
var checkDependencyWarnings = (projectDir) => Effect18.gen(function* () {
|
|
2664
2652
|
const pkgPath = path.join(projectDir, "package.json");
|
|
2665
2653
|
const content = yield* Effect18.tryPromise({
|
|
@@ -2684,6 +2672,26 @@ var checkDependencyWarnings = (projectDir) => Effect18.gen(function* () {
|
|
|
2684
2672
|
`"dependencies" is empty but "devDependencies" has ${devDeps.length} package(s). Runtime packages must be in "dependencies" to be included in the Lambda layer.`
|
|
2685
2673
|
);
|
|
2686
2674
|
}
|
|
2675
|
+
for (const dep of deps) {
|
|
2676
|
+
const depPath = getPackageRealPath(projectDir, dep);
|
|
2677
|
+
if (!depPath) continue;
|
|
2678
|
+
const depPkgPath = path.join(depPath, "package.json");
|
|
2679
|
+
if (!fsSync.existsSync(depPkgPath)) continue;
|
|
2680
|
+
try {
|
|
2681
|
+
const depPkg = JSON.parse(fsSync.readFileSync(depPkgPath, "utf-8"));
|
|
2682
|
+
const entryPoints = [];
|
|
2683
|
+
if (typeof depPkg.main === "string") entryPoints.push(depPkg.main);
|
|
2684
|
+
if (typeof depPkg.module === "string") entryPoints.push(depPkg.module);
|
|
2685
|
+
entryPoints.push(...extractExportPaths(depPkg.exports));
|
|
2686
|
+
const tsEntries = [...new Set(entryPoints.filter(isRawTypeScript))];
|
|
2687
|
+
if (tsEntries.length > 0) {
|
|
2688
|
+
warnings.push(
|
|
2689
|
+
`Package "${dep}" has TypeScript entry points (${tsEntries.join(", ")}) that will fail at runtime in node_modules (ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING). Move it to "devDependencies" so esbuild can bundle and transpile it.`
|
|
2690
|
+
);
|
|
2691
|
+
}
|
|
2692
|
+
} catch {
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2687
2695
|
return warnings;
|
|
2688
2696
|
});
|
|
2689
2697
|
var getPackageRealPath = (projectDir, pkgName) => {
|
|
@@ -3258,6 +3266,16 @@ var CACHING_OPTIMIZED_POLICY_ID = "658327ea-f89d-4fab-a63d-7e88639e58f6";
|
|
|
3258
3266
|
var CACHING_DISABLED_POLICY_ID = "4135ea2d-6df8-44a3-9df3-4b5a84be39ad";
|
|
3259
3267
|
var ALL_VIEWER_EXCEPT_HOST_HEADER_POLICY_ID = "b689b0a8-53d0-40ab-baf2-68738e2966ac";
|
|
3260
3268
|
var SECURITY_HEADERS_POLICY_ID = "67f7725c-6f97-4210-82d7-5512b31e9d03";
|
|
3269
|
+
var expandRoutePatterns = (patterns) => {
|
|
3270
|
+
const expanded = /* @__PURE__ */ new Set();
|
|
3271
|
+
for (const p of patterns) {
|
|
3272
|
+
expanded.add(p);
|
|
3273
|
+
if (p.endsWith("/*")) {
|
|
3274
|
+
expanded.add(p.slice(0, -2));
|
|
3275
|
+
}
|
|
3276
|
+
}
|
|
3277
|
+
return [...expanded];
|
|
3278
|
+
};
|
|
3261
3279
|
var ensureOAC = (input) => Effect21.gen(function* () {
|
|
3262
3280
|
const { name, originType = "s3" } = input;
|
|
3263
3281
|
const result = yield* cloudfront_exports.make("list_origin_access_controls", {});
|
|
@@ -3368,7 +3386,8 @@ var ensureDistribution = (input) => Effect21.gen(function* () {
|
|
|
3368
3386
|
const comment = makeDistComment(project, stage, handlerName);
|
|
3369
3387
|
const s3OriginId = `S3-${bucketName}`;
|
|
3370
3388
|
const s3OriginDomain = `${bucketName}.s3.${bucketRegion}.amazonaws.com`;
|
|
3371
|
-
const
|
|
3389
|
+
const expandedRoutePatterns = routePatterns ? expandRoutePatterns(routePatterns) : void 0;
|
|
3390
|
+
const hasApiRoutes = apiOriginDomain && expandedRoutePatterns && expandedRoutePatterns.length > 0;
|
|
3372
3391
|
const apiOriginId = hasApiRoutes ? `API-${project}-${stage}` : void 0;
|
|
3373
3392
|
const originsItems = [
|
|
3374
3393
|
{
|
|
@@ -3399,8 +3418,8 @@ var ensureDistribution = (input) => Effect21.gen(function* () {
|
|
|
3399
3418
|
const API_METHODS = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"];
|
|
3400
3419
|
const CACHED_METHODS = ["GET", "HEAD"];
|
|
3401
3420
|
const cacheBehaviors = hasApiRoutes ? {
|
|
3402
|
-
Quantity:
|
|
3403
|
-
Items:
|
|
3421
|
+
Quantity: expandedRoutePatterns.length,
|
|
3422
|
+
Items: expandedRoutePatterns.map((pattern) => ({
|
|
3404
3423
|
PathPattern: pattern,
|
|
3405
3424
|
TargetOriginId: apiOriginId,
|
|
3406
3425
|
ViewerProtocolPolicy: "redirect-to-https",
|
|
@@ -3468,7 +3487,7 @@ var ensureDistribution = (input) => Effect21.gen(function* () {
|
|
|
3468
3487
|
const currentLambdaEdgeArn = currentConfig.DefaultCacheBehavior?.LambdaFunctionAssociations?.Items?.[0]?.LambdaFunctionARN;
|
|
3469
3488
|
const originsMatch = (currentConfig.Origins?.Quantity ?? 0) === originsItems.length;
|
|
3470
3489
|
const currentBehaviorPatterns = (currentConfig.CacheBehaviors?.Items ?? []).map((b) => b.PathPattern).sort();
|
|
3471
|
-
const desiredBehaviorPatterns = (
|
|
3490
|
+
const desiredBehaviorPatterns = (expandedRoutePatterns ?? []).slice().sort();
|
|
3472
3491
|
const behaviorsMatch = currentBehaviorPatterns.length === desiredBehaviorPatterns.length && desiredBehaviorPatterns.every((p, i) => currentBehaviorPatterns[i] === p);
|
|
3473
3492
|
const apiOriginMatch = !hasApiRoutes || currentConfig.Origins?.Items?.some((o) => o.DomainName === apiOriginDomain);
|
|
3474
3493
|
const needsUpdate = currentOrigin?.DomainName !== s3OriginDomain || currentOrigin?.OriginAccessControlId !== oacId || currentConfig.DefaultRootObject !== index || currentConfig.DefaultCacheBehavior?.CachePolicyId !== CACHING_OPTIMIZED_POLICY_ID || currentConfig.DefaultCacheBehavior?.ResponseHeadersPolicyId !== SECURITY_HEADERS_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 || !originsMatch || !behaviorsMatch || !apiOriginMatch;
|
|
@@ -3588,7 +3607,7 @@ var ensureDistribution = (input) => Effect21.gen(function* () {
|
|
|
3588
3607
|
};
|
|
3589
3608
|
});
|
|
3590
3609
|
var ensureSsrDistribution = (input) => Effect21.gen(function* () {
|
|
3591
|
-
const { project, stage, handlerName, bucketName, bucketRegion, s3OacId, lambdaOriginDomain,
|
|
3610
|
+
const { project, stage, handlerName, bucketName, bucketRegion, s3OacId, lambdaOriginDomain, assetPatterns, tags, aliases, acmCertificateArn, apiOriginDomain, routePatterns } = input;
|
|
3592
3611
|
const comment = makeDistComment(project, stage, handlerName);
|
|
3593
3612
|
const lambdaOriginId = `Lambda-${project}-${stage}-${handlerName}`;
|
|
3594
3613
|
const s3OriginId = `S3-${bucketName}`;
|
|
@@ -3601,14 +3620,14 @@ var ensureSsrDistribution = (input) => Effect21.gen(function* () {
|
|
|
3601
3620
|
} : void 0;
|
|
3602
3621
|
const ALL_METHODS = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"];
|
|
3603
3622
|
const CACHED_METHODS = ["GET", "HEAD"];
|
|
3604
|
-
const
|
|
3623
|
+
const expandedRoutePatterns = routePatterns ? expandRoutePatterns(routePatterns) : void 0;
|
|
3624
|
+
const hasApiRoutes = apiOriginDomain && expandedRoutePatterns && expandedRoutePatterns.length > 0;
|
|
3605
3625
|
const apiOriginId = hasApiRoutes ? `API-${project}-${stage}` : void 0;
|
|
3606
3626
|
const originsItems = [
|
|
3607
3627
|
{
|
|
3608
3628
|
Id: lambdaOriginId,
|
|
3609
3629
|
DomainName: lambdaOriginDomain,
|
|
3610
3630
|
OriginPath: "",
|
|
3611
|
-
OriginAccessControlId: lambdaOacId,
|
|
3612
3631
|
CustomOriginConfig: {
|
|
3613
3632
|
HTTPPort: 80,
|
|
3614
3633
|
HTTPSPort: 443,
|
|
@@ -3661,7 +3680,7 @@ var ensureSsrDistribution = (input) => Effect21.gen(function* () {
|
|
|
3661
3680
|
LambdaFunctionAssociations: { Quantity: 0, Items: [] },
|
|
3662
3681
|
FieldLevelEncryptionId: ""
|
|
3663
3682
|
};
|
|
3664
|
-
const apiRouteBehaviors = hasApiRoutes ?
|
|
3683
|
+
const apiRouteBehaviors = hasApiRoutes ? expandedRoutePatterns.map((pattern) => ({
|
|
3665
3684
|
PathPattern: pattern,
|
|
3666
3685
|
TargetOriginId: apiOriginId,
|
|
3667
3686
|
ViewerProtocolPolicy: "redirect-to-https",
|
|
@@ -4969,8 +4988,6 @@ var deployApp = (input) => Effect29.gen(function* () {
|
|
|
4969
4988
|
});
|
|
4970
4989
|
const s3OacName = `${project}-${stage}-oac`;
|
|
4971
4990
|
const { oacId: s3OacId } = yield* ensureOAC({ name: s3OacName, originType: "s3" });
|
|
4972
|
-
const lambdaOacName = `${project}-${stage}-lambda-oac`;
|
|
4973
|
-
const { oacId: lambdaOacId } = yield* ensureOAC({ name: lambdaOacName, originType: "lambda" });
|
|
4974
4991
|
const assetsDir = path5.resolve(projectDir, config.assets);
|
|
4975
4992
|
const assetPatterns = detectAssetPatterns(assetsDir);
|
|
4976
4993
|
yield* Effect29.logDebug(`Detected ${assetPatterns.length} asset pattern(s): ${assetPatterns.join(", ")}`);
|
|
@@ -4990,14 +5007,13 @@ var deployApp = (input) => Effect29.gen(function* () {
|
|
|
4990
5007
|
bucketRegion: region,
|
|
4991
5008
|
s3OacId,
|
|
4992
5009
|
lambdaOriginDomain,
|
|
4993
|
-
lambdaOacId,
|
|
4994
5010
|
assetPatterns,
|
|
4995
5011
|
tags: makeTags(tagCtx, "cloudfront-distribution"),
|
|
4996
5012
|
aliases,
|
|
4997
5013
|
acmCertificateArn,
|
|
4998
5014
|
...input.apiOriginDomain && routePatterns.length > 0 ? { apiOriginDomain: input.apiOriginDomain, routePatterns } : {}
|
|
4999
5015
|
});
|
|
5000
|
-
yield*
|
|
5016
|
+
yield* addFunctionUrlPublicAccess(lambdaName);
|
|
5001
5017
|
yield* putBucketPolicyForOAC(bucketName, distributionArn);
|
|
5002
5018
|
yield* syncFiles({ bucketName, sourceDir: assetsDir });
|
|
5003
5019
|
yield* invalidateDistribution(distributionId);
|
|
@@ -5540,6 +5556,31 @@ var buildBucketNameMap = (bucketHandlers, project, stage) => {
|
|
|
5540
5556
|
}
|
|
5541
5557
|
return map;
|
|
5542
5558
|
};
|
|
5559
|
+
var validateDeps = (discovered, tableNameMap, bucketNameMap, mailerDomainMap) => {
|
|
5560
|
+
const errors = [];
|
|
5561
|
+
const allGroups = [
|
|
5562
|
+
...discovered.httpHandlers,
|
|
5563
|
+
...discovered.apiHandlers,
|
|
5564
|
+
...discovered.tableHandlers,
|
|
5565
|
+
...discovered.fifoQueueHandlers,
|
|
5566
|
+
...discovered.bucketHandlers,
|
|
5567
|
+
...discovered.staticSiteHandlers,
|
|
5568
|
+
...discovered.appHandlers,
|
|
5569
|
+
...discovered.mailerHandlers
|
|
5570
|
+
];
|
|
5571
|
+
for (const { exports } of allGroups) {
|
|
5572
|
+
for (const fn13 of exports) {
|
|
5573
|
+
for (const key of fn13.depsKeys) {
|
|
5574
|
+
if (!tableNameMap.has(key) && !bucketNameMap.has(key) && !mailerDomainMap.has(key)) {
|
|
5575
|
+
errors.push(
|
|
5576
|
+
`Handler "${fn13.exportName}" depends on "${key}", but no matching table, bucket, or mailer handler was found. Make sure it is exported.`
|
|
5577
|
+
);
|
|
5578
|
+
}
|
|
5579
|
+
}
|
|
5580
|
+
}
|
|
5581
|
+
}
|
|
5582
|
+
return errors;
|
|
5583
|
+
};
|
|
5543
5584
|
var resolveDeps = (depsKeys, tableNameMap, bucketNameMap, mailerDomainMap) => {
|
|
5544
5585
|
if (depsKeys.length === 0) return void 0;
|
|
5545
5586
|
const depsEnv = {};
|
|
@@ -5890,6 +5931,14 @@ var deployProject = (input) => Effect35.gen(function* () {
|
|
|
5890
5931
|
const tableNameMap = buildTableNameMap(tableHandlers, input.project, stage);
|
|
5891
5932
|
const bucketNameMap = buildBucketNameMap(bucketHandlers, input.project, stage);
|
|
5892
5933
|
const mailerDomainMap = buildMailerDomainMap(mailerHandlers);
|
|
5934
|
+
const depsErrors = validateDeps(discovered, tableNameMap, bucketNameMap, mailerDomainMap);
|
|
5935
|
+
if (depsErrors.length > 0) {
|
|
5936
|
+
yield* Console2.log("");
|
|
5937
|
+
for (const err of depsErrors) {
|
|
5938
|
+
yield* Console2.log(` ${c.red("\u2717")} ${err}`);
|
|
5939
|
+
}
|
|
5940
|
+
return yield* Effect35.fail(new Error("Unresolved deps \u2014 aborting deploy"));
|
|
5941
|
+
}
|
|
5893
5942
|
const { layerArn, layerVersion, layerStatus, external } = yield* prepareLayer({
|
|
5894
5943
|
project: input.project,
|
|
5895
5944
|
stage,
|
|
@@ -6525,6 +6574,15 @@ API: ${c.cyan(apiUrl)}`);
|
|
|
6525
6574
|
if (counts.orphaned > 0) parts.push(c.red(`${counts.orphaned} orphaned`));
|
|
6526
6575
|
yield* Console4.log(`
|
|
6527
6576
|
Total: ${parts.join(", ")}`);
|
|
6577
|
+
const depWarnings = yield* checkDependencyWarnings(projectDir).pipe(
|
|
6578
|
+
Effect39.catchAll(() => Effect39.succeed([]))
|
|
6579
|
+
);
|
|
6580
|
+
if (depWarnings.length > 0) {
|
|
6581
|
+
yield* Console4.log("");
|
|
6582
|
+
for (const w of depWarnings) {
|
|
6583
|
+
yield* Console4.log(c.yellow(` \u26A0 ${w}`));
|
|
6584
|
+
}
|
|
6585
|
+
}
|
|
6528
6586
|
}).pipe(
|
|
6529
6587
|
Effect39.provide(clientsLayer),
|
|
6530
6588
|
Logger2.withMinimumLogLevel(logLevel)
|