@effortless-aws/cli 0.1.1 → 0.2.1
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 +502 -290
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -6,15 +6,15 @@ var __export = (target, all) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// src/cli/index.ts
|
|
9
|
-
import { Command as Command7 } from "@effect/cli";
|
|
9
|
+
import { CliConfig, Command as Command7 } from "@effect/cli";
|
|
10
10
|
import { NodeContext, NodeRuntime } from "@effect/platform-node";
|
|
11
|
-
import { Effect as
|
|
11
|
+
import { Effect as Effect45 } from "effect";
|
|
12
12
|
import { createRequire as createRequire2 } from "module";
|
|
13
13
|
|
|
14
14
|
// src/cli/commands/deploy.ts
|
|
15
15
|
import { Args, Command } from "@effect/cli";
|
|
16
|
-
import { Effect as
|
|
17
|
-
import * as
|
|
16
|
+
import { Effect as Effect38, Console as Console3, Logger, LogLevel, Option } from "effect";
|
|
17
|
+
import * as path9 from "path";
|
|
18
18
|
|
|
19
19
|
// src/deploy/deploy.ts
|
|
20
20
|
import { Effect as Effect35, Console as Console2 } from "effect";
|
|
@@ -2628,6 +2628,92 @@ var readProductionDependencies = (projectDir) => Effect18.gen(function* () {
|
|
|
2628
2628
|
const pkg = JSON.parse(content);
|
|
2629
2629
|
return Object.keys(pkg.dependencies ?? {});
|
|
2630
2630
|
});
|
|
2631
|
+
var DEV_ONLY_PACKAGES = /* @__PURE__ */ new Set([
|
|
2632
|
+
"typescript",
|
|
2633
|
+
"ts-node",
|
|
2634
|
+
"tsx",
|
|
2635
|
+
"vitest",
|
|
2636
|
+
"jest",
|
|
2637
|
+
"mocha",
|
|
2638
|
+
"eslint",
|
|
2639
|
+
"prettier",
|
|
2640
|
+
"tsup",
|
|
2641
|
+
"esbuild",
|
|
2642
|
+
"webpack",
|
|
2643
|
+
"rollup",
|
|
2644
|
+
"vite",
|
|
2645
|
+
"turbo",
|
|
2646
|
+
"husky",
|
|
2647
|
+
"lint-staged",
|
|
2648
|
+
"commitlint",
|
|
2649
|
+
"nodemon",
|
|
2650
|
+
"ts-jest",
|
|
2651
|
+
"concurrently",
|
|
2652
|
+
"rimraf"
|
|
2653
|
+
]);
|
|
2654
|
+
var DEV_ONLY_PREFIXES = [
|
|
2655
|
+
"@types/",
|
|
2656
|
+
"@typescript-eslint/",
|
|
2657
|
+
"@eslint/",
|
|
2658
|
+
"eslint-plugin-",
|
|
2659
|
+
"eslint-config-",
|
|
2660
|
+
"@vitest/",
|
|
2661
|
+
"@jest/"
|
|
2662
|
+
];
|
|
2663
|
+
var extractExportPaths = (value) => {
|
|
2664
|
+
if (typeof value === "string") return [value];
|
|
2665
|
+
if (typeof value === "object" && value !== null) {
|
|
2666
|
+
return Object.values(value).flatMap(extractExportPaths);
|
|
2667
|
+
}
|
|
2668
|
+
return [];
|
|
2669
|
+
};
|
|
2670
|
+
var isRawTypeScript = (p) => /\.(?:ts|tsx|mts|cts)$/.test(p) && !p.endsWith(".d.ts") && !p.endsWith(".d.mts") && !p.endsWith(".d.cts");
|
|
2671
|
+
var checkDependencyWarnings = (projectDir) => Effect18.gen(function* () {
|
|
2672
|
+
const pkgPath = path.join(projectDir, "package.json");
|
|
2673
|
+
const content = yield* Effect18.tryPromise({
|
|
2674
|
+
try: () => fs.readFile(pkgPath, "utf-8"),
|
|
2675
|
+
catch: () => Effect18.succeed(null)
|
|
2676
|
+
});
|
|
2677
|
+
if (!content) return [];
|
|
2678
|
+
const pkg = JSON.parse(content);
|
|
2679
|
+
const deps = Object.keys(pkg.dependencies ?? {});
|
|
2680
|
+
const devDeps = Object.keys(pkg.devDependencies ?? {});
|
|
2681
|
+
const warnings = [];
|
|
2682
|
+
const devInProd = deps.filter(
|
|
2683
|
+
(d) => DEV_ONLY_PACKAGES.has(d) || DEV_ONLY_PREFIXES.some((p) => d.startsWith(p))
|
|
2684
|
+
);
|
|
2685
|
+
if (devInProd.length > 0) {
|
|
2686
|
+
warnings.push(
|
|
2687
|
+
`These packages are in "dependencies" but look like dev tools (they will bloat the Lambda layer): ${devInProd.join(", ")}. Consider moving them to "devDependencies".`
|
|
2688
|
+
);
|
|
2689
|
+
}
|
|
2690
|
+
if (deps.length === 0 && devDeps.length > 0) {
|
|
2691
|
+
warnings.push(
|
|
2692
|
+
`"dependencies" is empty but "devDependencies" has ${devDeps.length} package(s). Runtime packages must be in "dependencies" to be included in the Lambda layer.`
|
|
2693
|
+
);
|
|
2694
|
+
}
|
|
2695
|
+
for (const dep of deps) {
|
|
2696
|
+
const depPath = getPackageRealPath(projectDir, dep);
|
|
2697
|
+
if (!depPath) continue;
|
|
2698
|
+
const depPkgPath = path.join(depPath, "package.json");
|
|
2699
|
+
if (!fsSync.existsSync(depPkgPath)) continue;
|
|
2700
|
+
try {
|
|
2701
|
+
const depPkg = JSON.parse(fsSync.readFileSync(depPkgPath, "utf-8"));
|
|
2702
|
+
const entryPoints = [];
|
|
2703
|
+
if (typeof depPkg.main === "string") entryPoints.push(depPkg.main);
|
|
2704
|
+
if (typeof depPkg.module === "string") entryPoints.push(depPkg.module);
|
|
2705
|
+
entryPoints.push(...extractExportPaths(depPkg.exports));
|
|
2706
|
+
const tsEntries = [...new Set(entryPoints.filter(isRawTypeScript))];
|
|
2707
|
+
if (tsEntries.length > 0) {
|
|
2708
|
+
warnings.push(
|
|
2709
|
+
`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.`
|
|
2710
|
+
);
|
|
2711
|
+
}
|
|
2712
|
+
} catch {
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
return warnings;
|
|
2716
|
+
});
|
|
2631
2717
|
var getPackageRealPath = (projectDir, pkgName) => {
|
|
2632
2718
|
const pkgPath = path.join(projectDir, "node_modules", pkgName);
|
|
2633
2719
|
if (!fsSync.existsSync(pkgPath)) return null;
|
|
@@ -2816,6 +2902,12 @@ var getExistingLayerByHash = (layerName, expectedHash) => Effect18.gen(function*
|
|
|
2816
2902
|
};
|
|
2817
2903
|
});
|
|
2818
2904
|
var ensureLayer = (config) => Effect18.gen(function* () {
|
|
2905
|
+
const depWarnings = yield* checkDependencyWarnings(config.projectDir).pipe(
|
|
2906
|
+
Effect18.catchAll(() => Effect18.succeed([]))
|
|
2907
|
+
);
|
|
2908
|
+
for (const w of depWarnings) {
|
|
2909
|
+
yield* Effect18.logWarning(`[layer] ${w}`);
|
|
2910
|
+
}
|
|
2819
2911
|
const dependencies = yield* readProductionDependencies(config.projectDir).pipe(
|
|
2820
2912
|
Effect18.catchAll(() => Effect18.succeed([]))
|
|
2821
2913
|
);
|
|
@@ -3194,6 +3286,16 @@ var CACHING_OPTIMIZED_POLICY_ID = "658327ea-f89d-4fab-a63d-7e88639e58f6";
|
|
|
3194
3286
|
var CACHING_DISABLED_POLICY_ID = "4135ea2d-6df8-44a3-9df3-4b5a84be39ad";
|
|
3195
3287
|
var ALL_VIEWER_EXCEPT_HOST_HEADER_POLICY_ID = "b689b0a8-53d0-40ab-baf2-68738e2966ac";
|
|
3196
3288
|
var SECURITY_HEADERS_POLICY_ID = "67f7725c-6f97-4210-82d7-5512b31e9d03";
|
|
3289
|
+
var expandRoutePatterns = (patterns) => {
|
|
3290
|
+
const expanded = /* @__PURE__ */ new Set();
|
|
3291
|
+
for (const p of patterns) {
|
|
3292
|
+
expanded.add(p);
|
|
3293
|
+
if (p.endsWith("/*")) {
|
|
3294
|
+
expanded.add(p.slice(0, -2));
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
return [...expanded];
|
|
3298
|
+
};
|
|
3197
3299
|
var ensureOAC = (input) => Effect21.gen(function* () {
|
|
3198
3300
|
const { name, originType = "s3" } = input;
|
|
3199
3301
|
const result = yield* cloudfront_exports.make("list_origin_access_controls", {});
|
|
@@ -3304,7 +3406,8 @@ var ensureDistribution = (input) => Effect21.gen(function* () {
|
|
|
3304
3406
|
const comment = makeDistComment(project, stage, handlerName);
|
|
3305
3407
|
const s3OriginId = `S3-${bucketName}`;
|
|
3306
3408
|
const s3OriginDomain = `${bucketName}.s3.${bucketRegion}.amazonaws.com`;
|
|
3307
|
-
const
|
|
3409
|
+
const expandedRoutePatterns = routePatterns ? expandRoutePatterns(routePatterns) : void 0;
|
|
3410
|
+
const hasApiRoutes = apiOriginDomain && expandedRoutePatterns && expandedRoutePatterns.length > 0;
|
|
3308
3411
|
const apiOriginId = hasApiRoutes ? `API-${project}-${stage}` : void 0;
|
|
3309
3412
|
const originsItems = [
|
|
3310
3413
|
{
|
|
@@ -3335,8 +3438,8 @@ var ensureDistribution = (input) => Effect21.gen(function* () {
|
|
|
3335
3438
|
const API_METHODS = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"];
|
|
3336
3439
|
const CACHED_METHODS = ["GET", "HEAD"];
|
|
3337
3440
|
const cacheBehaviors = hasApiRoutes ? {
|
|
3338
|
-
Quantity:
|
|
3339
|
-
Items:
|
|
3441
|
+
Quantity: expandedRoutePatterns.length,
|
|
3442
|
+
Items: expandedRoutePatterns.map((pattern) => ({
|
|
3340
3443
|
PathPattern: pattern,
|
|
3341
3444
|
TargetOriginId: apiOriginId,
|
|
3342
3445
|
ViewerProtocolPolicy: "redirect-to-https",
|
|
@@ -3404,7 +3507,7 @@ var ensureDistribution = (input) => Effect21.gen(function* () {
|
|
|
3404
3507
|
const currentLambdaEdgeArn = currentConfig.DefaultCacheBehavior?.LambdaFunctionAssociations?.Items?.[0]?.LambdaFunctionARN;
|
|
3405
3508
|
const originsMatch = (currentConfig.Origins?.Quantity ?? 0) === originsItems.length;
|
|
3406
3509
|
const currentBehaviorPatterns = (currentConfig.CacheBehaviors?.Items ?? []).map((b) => b.PathPattern).sort();
|
|
3407
|
-
const desiredBehaviorPatterns = (
|
|
3510
|
+
const desiredBehaviorPatterns = (expandedRoutePatterns ?? []).slice().sort();
|
|
3408
3511
|
const behaviorsMatch = currentBehaviorPatterns.length === desiredBehaviorPatterns.length && desiredBehaviorPatterns.every((p, i) => currentBehaviorPatterns[i] === p);
|
|
3409
3512
|
const apiOriginMatch = !hasApiRoutes || currentConfig.Origins?.Items?.some((o) => o.DomainName === apiOriginDomain);
|
|
3410
3513
|
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;
|
|
@@ -3524,7 +3627,7 @@ var ensureDistribution = (input) => Effect21.gen(function* () {
|
|
|
3524
3627
|
};
|
|
3525
3628
|
});
|
|
3526
3629
|
var ensureSsrDistribution = (input) => Effect21.gen(function* () {
|
|
3527
|
-
const { project, stage, handlerName, bucketName, bucketRegion, s3OacId, lambdaOriginDomain, lambdaOacId, assetPatterns, tags, aliases, acmCertificateArn } = input;
|
|
3630
|
+
const { project, stage, handlerName, bucketName, bucketRegion, s3OacId, lambdaOriginDomain, lambdaOacId, assetPatterns, tags, aliases, acmCertificateArn, apiOriginDomain, routePatterns } = input;
|
|
3528
3631
|
const comment = makeDistComment(project, stage, handlerName);
|
|
3529
3632
|
const lambdaOriginId = `Lambda-${project}-${stage}-${handlerName}`;
|
|
3530
3633
|
const s3OriginId = `S3-${bucketName}`;
|
|
@@ -3537,6 +3640,9 @@ var ensureSsrDistribution = (input) => Effect21.gen(function* () {
|
|
|
3537
3640
|
} : void 0;
|
|
3538
3641
|
const ALL_METHODS = ["GET", "HEAD", "OPTIONS", "PUT", "POST", "PATCH", "DELETE"];
|
|
3539
3642
|
const CACHED_METHODS = ["GET", "HEAD"];
|
|
3643
|
+
const expandedRoutePatterns = routePatterns ? expandRoutePatterns(routePatterns) : void 0;
|
|
3644
|
+
const hasApiRoutes = apiOriginDomain && expandedRoutePatterns && expandedRoutePatterns.length > 0;
|
|
3645
|
+
const apiOriginId = hasApiRoutes ? `API-${project}-${stage}` : void 0;
|
|
3540
3646
|
const originsItems = [
|
|
3541
3647
|
{
|
|
3542
3648
|
Id: lambdaOriginId,
|
|
@@ -3560,7 +3666,23 @@ var ensureSsrDistribution = (input) => Effect21.gen(function* () {
|
|
|
3560
3666
|
OriginAccessControlId: s3OacId,
|
|
3561
3667
|
S3OriginConfig: { OriginAccessIdentity: "" },
|
|
3562
3668
|
CustomHeaders: { Quantity: 0, Items: [] }
|
|
3563
|
-
}
|
|
3669
|
+
},
|
|
3670
|
+
...hasApiRoutes ? [{
|
|
3671
|
+
Id: apiOriginId,
|
|
3672
|
+
DomainName: apiOriginDomain,
|
|
3673
|
+
OriginPath: "",
|
|
3674
|
+
ConnectionAttempts: 3,
|
|
3675
|
+
ConnectionTimeout: 10,
|
|
3676
|
+
CustomOriginConfig: {
|
|
3677
|
+
HTTPPort: 80,
|
|
3678
|
+
HTTPSPort: 443,
|
|
3679
|
+
OriginProtocolPolicy: "https-only",
|
|
3680
|
+
OriginSslProtocols: { Quantity: 1, Items: ["TLSv1.2"] },
|
|
3681
|
+
OriginReadTimeout: 30,
|
|
3682
|
+
OriginKeepaliveTimeout: 5
|
|
3683
|
+
},
|
|
3684
|
+
CustomHeaders: { Quantity: 0, Items: [] }
|
|
3685
|
+
}] : []
|
|
3564
3686
|
];
|
|
3565
3687
|
const defaultCacheBehavior = {
|
|
3566
3688
|
TargetOriginId: lambdaOriginId,
|
|
@@ -3579,26 +3701,42 @@ var ensureSsrDistribution = (input) => Effect21.gen(function* () {
|
|
|
3579
3701
|
LambdaFunctionAssociations: { Quantity: 0, Items: [] },
|
|
3580
3702
|
FieldLevelEncryptionId: ""
|
|
3581
3703
|
};
|
|
3582
|
-
const
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3704
|
+
const apiRouteBehaviors = hasApiRoutes ? expandedRoutePatterns.map((pattern) => ({
|
|
3705
|
+
PathPattern: pattern,
|
|
3706
|
+
TargetOriginId: apiOriginId,
|
|
3707
|
+
ViewerProtocolPolicy: "redirect-to-https",
|
|
3708
|
+
AllowedMethods: {
|
|
3709
|
+
Quantity: 7,
|
|
3710
|
+
Items: [...ALL_METHODS],
|
|
3711
|
+
CachedMethods: { Quantity: 2, Items: [...CACHED_METHODS] }
|
|
3712
|
+
},
|
|
3713
|
+
Compress: true,
|
|
3714
|
+
SmoothStreaming: false,
|
|
3715
|
+
CachePolicyId: CACHING_DISABLED_POLICY_ID,
|
|
3716
|
+
OriginRequestPolicyId: ALL_VIEWER_EXCEPT_HOST_HEADER_POLICY_ID,
|
|
3717
|
+
FunctionAssociations: { Quantity: 0, Items: [] },
|
|
3718
|
+
LambdaFunctionAssociations: { Quantity: 0, Items: [] },
|
|
3719
|
+
FieldLevelEncryptionId: ""
|
|
3720
|
+
})) : [];
|
|
3721
|
+
const assetBehaviors = assetPatterns.map((pattern) => ({
|
|
3722
|
+
PathPattern: pattern,
|
|
3723
|
+
TargetOriginId: s3OriginId,
|
|
3724
|
+
ViewerProtocolPolicy: "redirect-to-https",
|
|
3725
|
+
AllowedMethods: {
|
|
3726
|
+
Quantity: 2,
|
|
3727
|
+
Items: [...CACHED_METHODS],
|
|
3728
|
+
CachedMethods: { Quantity: 2, Items: [...CACHED_METHODS] }
|
|
3729
|
+
},
|
|
3730
|
+
Compress: true,
|
|
3731
|
+
SmoothStreaming: false,
|
|
3732
|
+
CachePolicyId: CACHING_OPTIMIZED_POLICY_ID,
|
|
3733
|
+
ResponseHeadersPolicyId: SECURITY_HEADERS_POLICY_ID,
|
|
3734
|
+
FunctionAssociations: { Quantity: 0, Items: [] },
|
|
3735
|
+
LambdaFunctionAssociations: { Quantity: 0, Items: [] },
|
|
3736
|
+
FieldLevelEncryptionId: ""
|
|
3737
|
+
}));
|
|
3738
|
+
const allBehaviors = [...apiRouteBehaviors, ...assetBehaviors];
|
|
3739
|
+
const cacheBehaviors = allBehaviors.length > 0 ? { Quantity: allBehaviors.length, Items: allBehaviors } : { Quantity: 0, Items: [] };
|
|
3602
3740
|
const existing = yield* findDistributionByTags(project, stage, handlerName);
|
|
3603
3741
|
if (existing) {
|
|
3604
3742
|
const configResult = yield* cloudfront_exports.make("get_distribution_config", {
|
|
@@ -4375,6 +4513,19 @@ var discoverHandlers = (files) => {
|
|
|
4375
4513
|
}
|
|
4376
4514
|
return { httpHandlers, tableHandlers, appHandlers, staticSiteHandlers, fifoQueueHandlers, bucketHandlers, mailerHandlers, apiHandlers };
|
|
4377
4515
|
};
|
|
4516
|
+
var flattenHandlers = (discovered) => {
|
|
4517
|
+
const entries = (type, handlers) => handlers.flatMap((h) => h.exports.map((e) => ({ exportName: e.exportName, file: h.file, type })));
|
|
4518
|
+
return [
|
|
4519
|
+
...entries("http", discovered.httpHandlers),
|
|
4520
|
+
...entries("table", discovered.tableHandlers),
|
|
4521
|
+
...entries("app", discovered.appHandlers),
|
|
4522
|
+
...entries("site", discovered.staticSiteHandlers),
|
|
4523
|
+
...entries("queue", discovered.fifoQueueHandlers),
|
|
4524
|
+
...entries("bucket", discovered.bucketHandlers),
|
|
4525
|
+
...entries("mailer", discovered.mailerHandlers),
|
|
4526
|
+
...entries("api", discovered.apiHandlers)
|
|
4527
|
+
];
|
|
4528
|
+
};
|
|
4378
4529
|
|
|
4379
4530
|
// src/deploy/resolve-config.ts
|
|
4380
4531
|
import { Effect as Effect25 } from "effect";
|
|
@@ -4448,10 +4599,10 @@ var ensureLayerAndExternal = (input) => Effect26.gen(function* () {
|
|
|
4448
4599
|
project: input.project,
|
|
4449
4600
|
stage: input.stage,
|
|
4450
4601
|
region: input.region,
|
|
4451
|
-
projectDir: input.
|
|
4602
|
+
projectDir: input.packageDir
|
|
4452
4603
|
});
|
|
4453
|
-
const prodDeps = layerResult ? yield* readProductionDependencies(input.
|
|
4454
|
-
const { packages: external, warnings: layerWarnings } = prodDeps.length > 0 ? yield* Effect26.sync(() => collectLayerPackages(input.
|
|
4604
|
+
const prodDeps = layerResult ? yield* readProductionDependencies(input.packageDir) : [];
|
|
4605
|
+
const { packages: external, warnings: layerWarnings } = prodDeps.length > 0 ? yield* Effect26.sync(() => collectLayerPackages(input.packageDir, prodDeps)) : { packages: [], warnings: [] };
|
|
4455
4606
|
for (const warning of layerWarnings) {
|
|
4456
4607
|
yield* Effect26.logWarning(`[layer] ${warning}`);
|
|
4457
4608
|
}
|
|
@@ -4566,7 +4717,7 @@ var deploy = (input) => Effect27.gen(function* () {
|
|
|
4566
4717
|
project: input.project,
|
|
4567
4718
|
stage: tagCtx.stage,
|
|
4568
4719
|
region: input.region,
|
|
4569
|
-
|
|
4720
|
+
packageDir: input.packageDir ?? input.projectDir
|
|
4570
4721
|
});
|
|
4571
4722
|
const { functionArn } = yield* deployLambda({
|
|
4572
4723
|
input,
|
|
@@ -4619,7 +4770,7 @@ var deployAll = (input) => Effect27.gen(function* () {
|
|
|
4619
4770
|
project: input.project,
|
|
4620
4771
|
stage: tagCtx.stage,
|
|
4621
4772
|
region: input.region,
|
|
4622
|
-
|
|
4773
|
+
packageDir: input.packageDir ?? input.projectDir
|
|
4623
4774
|
});
|
|
4624
4775
|
yield* Effect27.logDebug("Setting up API Gateway...");
|
|
4625
4776
|
const { apiId } = yield* ensureProjectApi({
|
|
@@ -4731,7 +4882,7 @@ var deployTable = (input) => Effect28.gen(function* () {
|
|
|
4731
4882
|
project: input.project,
|
|
4732
4883
|
stage: resolveStage(input.stage),
|
|
4733
4884
|
region: input.region,
|
|
4734
|
-
|
|
4885
|
+
packageDir: input.packageDir ?? input.projectDir
|
|
4735
4886
|
});
|
|
4736
4887
|
const result = yield* deployTableFunction({
|
|
4737
4888
|
input,
|
|
@@ -4760,7 +4911,7 @@ var deployAllTables = (input) => Effect28.gen(function* () {
|
|
|
4760
4911
|
project: input.project,
|
|
4761
4912
|
stage: resolveStage(input.stage),
|
|
4762
4913
|
region: input.region,
|
|
4763
|
-
|
|
4914
|
+
packageDir: input.packageDir ?? input.projectDir
|
|
4764
4915
|
});
|
|
4765
4916
|
const results = yield* Effect28.forEach(
|
|
4766
4917
|
functions,
|
|
@@ -4793,12 +4944,31 @@ var deployApp = (input) => Effect29.gen(function* () {
|
|
|
4793
4944
|
const stage = resolveStage(input.stage);
|
|
4794
4945
|
const handlerName = exportName;
|
|
4795
4946
|
const tagCtx = { project, stage, handler: handlerName };
|
|
4947
|
+
const routePatterns = fn13.routePatterns;
|
|
4948
|
+
if (routePatterns.length > 0 && !input.apiOriginDomain) {
|
|
4949
|
+
return yield* Effect29.fail(
|
|
4950
|
+
new Error(
|
|
4951
|
+
`App "${exportName}" has routes but no API Gateway exists. Ensure defineHttp() or defineApi() handlers are included in the discovery patterns.`
|
|
4952
|
+
)
|
|
4953
|
+
);
|
|
4954
|
+
}
|
|
4796
4955
|
if (config.build) {
|
|
4797
4956
|
yield* Effect29.logDebug(`Building app: ${config.build}`);
|
|
4957
|
+
const buildStart = Date.now();
|
|
4798
4958
|
yield* Effect29.try({
|
|
4799
|
-
try: () => execSync(config.build, {
|
|
4800
|
-
|
|
4959
|
+
try: () => execSync(config.build, {
|
|
4960
|
+
cwd: projectDir,
|
|
4961
|
+
stdio: input.verbose ? "inherit" : "pipe"
|
|
4962
|
+
}),
|
|
4963
|
+
catch: (error) => {
|
|
4964
|
+
if (!input.verbose && error && typeof error === "object" && "stderr" in error) {
|
|
4965
|
+
const stderr = String(error.stderr);
|
|
4966
|
+
if (stderr) process.stderr.write(stderr);
|
|
4967
|
+
}
|
|
4968
|
+
return new Error(`App build failed: ${config.build}`);
|
|
4969
|
+
}
|
|
4801
4970
|
});
|
|
4971
|
+
yield* Effect29.logDebug(`App built in ${((Date.now() - buildStart) / 1e3).toFixed(1)}s`);
|
|
4802
4972
|
}
|
|
4803
4973
|
const serverDir = path5.resolve(projectDir, config.server);
|
|
4804
4974
|
yield* Effect29.logDebug(`Zipping server directory: ${serverDir}`);
|
|
@@ -4864,7 +5034,8 @@ var deployApp = (input) => Effect29.gen(function* () {
|
|
|
4864
5034
|
assetPatterns,
|
|
4865
5035
|
tags: makeTags(tagCtx, "cloudfront-distribution"),
|
|
4866
5036
|
aliases,
|
|
4867
|
-
acmCertificateArn
|
|
5037
|
+
acmCertificateArn,
|
|
5038
|
+
...input.apiOriginDomain && routePatterns.length > 0 ? { apiOriginDomain: input.apiOriginDomain, routePatterns } : {}
|
|
4868
5039
|
});
|
|
4869
5040
|
yield* addCloudFrontPermission(lambdaName, distributionArn);
|
|
4870
5041
|
yield* putBucketPolicyForOAC(bucketName, distributionArn);
|
|
@@ -4978,10 +5149,21 @@ var deployStaticSite = (input) => Effect30.gen(function* () {
|
|
|
4978
5149
|
}
|
|
4979
5150
|
if (config.build) {
|
|
4980
5151
|
yield* Effect30.logDebug(`Building site: ${config.build}`);
|
|
5152
|
+
const buildStart = Date.now();
|
|
4981
5153
|
yield* Effect30.try({
|
|
4982
|
-
try: () => execSync2(config.build, {
|
|
4983
|
-
|
|
5154
|
+
try: () => execSync2(config.build, {
|
|
5155
|
+
cwd: projectDir,
|
|
5156
|
+
stdio: input.verbose ? "inherit" : "pipe"
|
|
5157
|
+
}),
|
|
5158
|
+
catch: (error) => {
|
|
5159
|
+
if (!input.verbose && error && typeof error === "object" && "stderr" in error) {
|
|
5160
|
+
const stderr = String(error.stderr);
|
|
5161
|
+
if (stderr) process.stderr.write(stderr);
|
|
5162
|
+
}
|
|
5163
|
+
return new Error(`Site build failed: ${config.build}`);
|
|
5164
|
+
}
|
|
4984
5165
|
});
|
|
5166
|
+
yield* Effect30.logDebug(`Site built in ${((Date.now() - buildStart) / 1e3).toFixed(1)}s`);
|
|
4985
5167
|
}
|
|
4986
5168
|
const bucketName = `${project}-${stage}-${handlerName}-site`.toLowerCase();
|
|
4987
5169
|
yield* ensureBucket({
|
|
@@ -5325,7 +5507,7 @@ var prepareLayer = (input) => Effect35.gen(function* () {
|
|
|
5325
5507
|
project: input.project,
|
|
5326
5508
|
stage: input.stage,
|
|
5327
5509
|
region: input.region,
|
|
5328
|
-
projectDir: input.
|
|
5510
|
+
projectDir: input.packageDir
|
|
5329
5511
|
}).pipe(
|
|
5330
5512
|
Effect35.provide(
|
|
5331
5513
|
clients_exports.makeClients({
|
|
@@ -5333,8 +5515,8 @@ var prepareLayer = (input) => Effect35.gen(function* () {
|
|
|
5333
5515
|
})
|
|
5334
5516
|
)
|
|
5335
5517
|
);
|
|
5336
|
-
const prodDeps = layerResult ? yield* readProductionDependencies(input.
|
|
5337
|
-
const { packages: external, warnings: layerWarnings } = prodDeps.length > 0 ? yield* Effect35.sync(() => collectLayerPackages(input.
|
|
5518
|
+
const prodDeps = layerResult ? yield* readProductionDependencies(input.packageDir) : [];
|
|
5519
|
+
const { packages: external, warnings: layerWarnings } = prodDeps.length > 0 ? yield* Effect35.sync(() => collectLayerPackages(input.packageDir, prodDeps)) : { packages: [], warnings: [] };
|
|
5338
5520
|
for (const warning of layerWarnings) {
|
|
5339
5521
|
yield* Effect35.logWarning(`[layer] ${warning}`);
|
|
5340
5522
|
}
|
|
@@ -5398,6 +5580,31 @@ var buildBucketNameMap = (bucketHandlers, project, stage) => {
|
|
|
5398
5580
|
}
|
|
5399
5581
|
return map;
|
|
5400
5582
|
};
|
|
5583
|
+
var validateDeps = (discovered, tableNameMap, bucketNameMap, mailerDomainMap) => {
|
|
5584
|
+
const errors = [];
|
|
5585
|
+
const allGroups = [
|
|
5586
|
+
...discovered.httpHandlers,
|
|
5587
|
+
...discovered.apiHandlers,
|
|
5588
|
+
...discovered.tableHandlers,
|
|
5589
|
+
...discovered.fifoQueueHandlers,
|
|
5590
|
+
...discovered.bucketHandlers,
|
|
5591
|
+
...discovered.staticSiteHandlers,
|
|
5592
|
+
...discovered.appHandlers,
|
|
5593
|
+
...discovered.mailerHandlers
|
|
5594
|
+
];
|
|
5595
|
+
for (const { exports } of allGroups) {
|
|
5596
|
+
for (const fn13 of exports) {
|
|
5597
|
+
for (const key of fn13.depsKeys) {
|
|
5598
|
+
if (!tableNameMap.has(key) && !bucketNameMap.has(key) && !mailerDomainMap.has(key)) {
|
|
5599
|
+
errors.push(
|
|
5600
|
+
`Handler "${fn13.exportName}" depends on "${key}", but no matching table, bucket, or mailer handler was found. Make sure it is exported.`
|
|
5601
|
+
);
|
|
5602
|
+
}
|
|
5603
|
+
}
|
|
5604
|
+
}
|
|
5605
|
+
}
|
|
5606
|
+
return errors;
|
|
5607
|
+
};
|
|
5401
5608
|
var resolveDeps = (depsKeys, tableNameMap, bucketNameMap, mailerDomainMap) => {
|
|
5402
5609
|
if (depsKeys.length === 0) return void 0;
|
|
5403
5610
|
const depsEnv = {};
|
|
@@ -5523,9 +5730,10 @@ var buildTableTasks = (ctx, handlers, results) => {
|
|
|
5523
5730
|
}
|
|
5524
5731
|
return tasks;
|
|
5525
5732
|
};
|
|
5526
|
-
var buildAppTasks = (ctx, handlers, results) => {
|
|
5733
|
+
var buildAppTasks = (ctx, handlers, results, apiId) => {
|
|
5527
5734
|
const tasks = [];
|
|
5528
5735
|
const { region } = ctx.input;
|
|
5736
|
+
const apiOriginDomain = apiId ? `${apiId}.execute-api.${region}.amazonaws.com` : void 0;
|
|
5529
5737
|
for (const { exports } of handlers) {
|
|
5530
5738
|
for (const fn13 of exports) {
|
|
5531
5739
|
tasks.push(
|
|
@@ -5535,7 +5743,9 @@ var buildAppTasks = (ctx, handlers, results) => {
|
|
|
5535
5743
|
project: ctx.input.project,
|
|
5536
5744
|
stage: ctx.input.stage,
|
|
5537
5745
|
region,
|
|
5538
|
-
fn: fn13
|
|
5746
|
+
fn: fn13,
|
|
5747
|
+
verbose: ctx.input.verbose,
|
|
5748
|
+
...apiOriginDomain ? { apiOriginDomain } : {}
|
|
5539
5749
|
}).pipe(Effect35.provide(clients_exports.makeClients({
|
|
5540
5750
|
lambda: { region },
|
|
5541
5751
|
iam: { region },
|
|
@@ -5566,6 +5776,7 @@ var buildStaticSiteTasks = (ctx, handlers, results, apiId) => {
|
|
|
5566
5776
|
stage: ctx.input.stage,
|
|
5567
5777
|
region,
|
|
5568
5778
|
fn: fn13,
|
|
5779
|
+
verbose: ctx.input.verbose,
|
|
5569
5780
|
...fn13.hasHandler ? { file } : {},
|
|
5570
5781
|
...apiOriginDomain ? { apiOriginDomain } : {}
|
|
5571
5782
|
}).pipe(Effect35.provide(clients_exports.makeClients({
|
|
@@ -5744,11 +5955,19 @@ var deployProject = (input) => Effect35.gen(function* () {
|
|
|
5744
5955
|
const tableNameMap = buildTableNameMap(tableHandlers, input.project, stage);
|
|
5745
5956
|
const bucketNameMap = buildBucketNameMap(bucketHandlers, input.project, stage);
|
|
5746
5957
|
const mailerDomainMap = buildMailerDomainMap(mailerHandlers);
|
|
5958
|
+
const depsErrors = validateDeps(discovered, tableNameMap, bucketNameMap, mailerDomainMap);
|
|
5959
|
+
if (depsErrors.length > 0) {
|
|
5960
|
+
yield* Console2.log("");
|
|
5961
|
+
for (const err of depsErrors) {
|
|
5962
|
+
yield* Console2.log(` ${c.red("\u2717")} ${err}`);
|
|
5963
|
+
}
|
|
5964
|
+
return yield* Effect35.fail(new Error("Unresolved deps \u2014 aborting deploy"));
|
|
5965
|
+
}
|
|
5747
5966
|
const { layerArn, layerVersion, layerStatus, external } = yield* prepareLayer({
|
|
5748
5967
|
project: input.project,
|
|
5749
5968
|
stage,
|
|
5750
5969
|
region: input.region,
|
|
5751
|
-
|
|
5970
|
+
packageDir: input.packageDir ?? input.projectDir
|
|
5752
5971
|
});
|
|
5753
5972
|
if (layerArn && layerStatus) {
|
|
5754
5973
|
const status = layerStatus === "cached" ? c.dim("cached") : c.green("created");
|
|
@@ -5759,7 +5978,10 @@ var deployProject = (input) => Effect35.gen(function* () {
|
|
|
5759
5978
|
const staticSitesNeedApi = !input.noSites && staticSiteHandlers.some(
|
|
5760
5979
|
({ exports }) => exports.some((fn13) => fn13.routePatterns.length > 0)
|
|
5761
5980
|
);
|
|
5762
|
-
|
|
5981
|
+
const appsNeedApi = appHandlers.some(
|
|
5982
|
+
({ exports }) => exports.some((fn13) => fn13.routePatterns.length > 0)
|
|
5983
|
+
);
|
|
5984
|
+
if (totalHttpHandlers > 0 || totalApiHandlers > 0 || staticSitesNeedApi || appsNeedApi) {
|
|
5763
5985
|
const tagCtx = {
|
|
5764
5986
|
project: input.project,
|
|
5765
5987
|
stage,
|
|
@@ -5824,7 +6046,7 @@ var deployProject = (input) => Effect35.gen(function* () {
|
|
|
5824
6046
|
const tasks = [
|
|
5825
6047
|
...apiId ? buildHttpTasks(ctx, httpHandlers, apiId, httpResults) : [],
|
|
5826
6048
|
...buildTableTasks(ctx, tableHandlers, tableResults),
|
|
5827
|
-
...buildAppTasks(ctx, appHandlers, appResults),
|
|
6049
|
+
...buildAppTasks(ctx, appHandlers, appResults, apiId),
|
|
5828
6050
|
...input.noSites ? [] : buildStaticSiteTasks(ctx, staticSiteHandlers, staticSiteResults, apiId),
|
|
5829
6051
|
...buildFifoQueueTasks(ctx, fifoQueueHandlers, fifoQueueResults),
|
|
5830
6052
|
...buildBucketTasks(ctx, bucketHandlers, bucketResults),
|
|
@@ -5876,18 +6098,22 @@ import * as path7 from "path";
|
|
|
5876
6098
|
import * as fs4 from "fs";
|
|
5877
6099
|
import { pathToFileURL } from "url";
|
|
5878
6100
|
import * as esbuild2 from "esbuild";
|
|
5879
|
-
|
|
6101
|
+
import { Effect as Effect36 } from "effect";
|
|
6102
|
+
var loadConfig = Effect36.fn("loadConfig")(function* () {
|
|
5880
6103
|
const configPath = path7.resolve(process.cwd(), "effortless.config.ts");
|
|
5881
6104
|
if (!fs4.existsSync(configPath)) {
|
|
5882
6105
|
return null;
|
|
5883
6106
|
}
|
|
5884
|
-
const result =
|
|
5885
|
-
|
|
5886
|
-
|
|
5887
|
-
|
|
5888
|
-
|
|
5889
|
-
|
|
5890
|
-
|
|
6107
|
+
const result = yield* Effect36.tryPromise({
|
|
6108
|
+
try: () => esbuild2.build({
|
|
6109
|
+
entryPoints: [configPath],
|
|
6110
|
+
bundle: true,
|
|
6111
|
+
write: false,
|
|
6112
|
+
format: "esm",
|
|
6113
|
+
platform: "node",
|
|
6114
|
+
external: ["effortless-aws"]
|
|
6115
|
+
}),
|
|
6116
|
+
catch: (error) => new Error(`Failed to compile config: ${error}`)
|
|
5891
6117
|
});
|
|
5892
6118
|
const output = result.outputFiles?.[0];
|
|
5893
6119
|
if (!output) {
|
|
@@ -5896,13 +6122,12 @@ var loadConfig = async () => {
|
|
|
5896
6122
|
const code = output.text;
|
|
5897
6123
|
const tempFile = path7.join(process.cwd(), ".effortless-config.mjs");
|
|
5898
6124
|
fs4.writeFileSync(tempFile, code);
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
}
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
};
|
|
6125
|
+
const mod = yield* Effect36.tryPromise({
|
|
6126
|
+
try: () => import(pathToFileURL(tempFile).href),
|
|
6127
|
+
catch: (error) => new Error(`Failed to load config: ${error}`)
|
|
6128
|
+
}).pipe(Effect36.ensuring(Effect36.sync(() => fs4.unlinkSync(tempFile))));
|
|
6129
|
+
return mod.default;
|
|
6130
|
+
});
|
|
5906
6131
|
var projectOption = Options.text("project").pipe(
|
|
5907
6132
|
Options.withAlias("p"),
|
|
5908
6133
|
Options.withDescription("Project name (or 'name' in effortless.config.ts)"),
|
|
@@ -5910,12 +6135,12 @@ var projectOption = Options.text("project").pipe(
|
|
|
5910
6135
|
);
|
|
5911
6136
|
var stageOption = Options.text("stage").pipe(
|
|
5912
6137
|
Options.withAlias("s"),
|
|
5913
|
-
Options.withDescription("
|
|
6138
|
+
Options.withDescription("Deployment stage (default: dev)"),
|
|
5914
6139
|
Options.withDefault("dev")
|
|
5915
6140
|
);
|
|
5916
6141
|
var regionOption = Options.text("region").pipe(
|
|
5917
6142
|
Options.withAlias("r"),
|
|
5918
|
-
Options.withDescription("AWS region"),
|
|
6143
|
+
Options.withDescription("AWS region (default: eu-central-1)"),
|
|
5919
6144
|
Options.withDefault("eu-central-1")
|
|
5920
6145
|
);
|
|
5921
6146
|
var verboseOption = Options.boolean("verbose").pipe(
|
|
@@ -5948,6 +6173,23 @@ var getPatternsFromConfig = (config) => {
|
|
|
5948
6173
|
});
|
|
5949
6174
|
};
|
|
5950
6175
|
|
|
6176
|
+
// src/cli/project-config.ts
|
|
6177
|
+
import * as Context13 from "effect/Context";
|
|
6178
|
+
import * as Layer14 from "effect/Layer";
|
|
6179
|
+
import * as Effect37 from "effect/Effect";
|
|
6180
|
+
import * as path8 from "path";
|
|
6181
|
+
var ProjectConfig = class _ProjectConfig extends Context13.Tag("ProjectConfig")() {
|
|
6182
|
+
static Live = Layer14.effect(
|
|
6183
|
+
_ProjectConfig,
|
|
6184
|
+
Effect37.gen(function* () {
|
|
6185
|
+
const config = yield* loadConfig();
|
|
6186
|
+
const cwd = process.cwd();
|
|
6187
|
+
const projectDir = config?.root ? path8.resolve(cwd, config.root) : cwd;
|
|
6188
|
+
return { config, cwd, projectDir };
|
|
6189
|
+
})
|
|
6190
|
+
);
|
|
6191
|
+
};
|
|
6192
|
+
|
|
5951
6193
|
// src/cli/commands/deploy.ts
|
|
5952
6194
|
var deployTargetArg = Args.text({ name: "target" }).pipe(
|
|
5953
6195
|
Args.withDescription("Handler name or file path to deploy (optional - uses config patterns if not specified)"),
|
|
@@ -5959,8 +6201,8 @@ var isFilePath = (target) => {
|
|
|
5959
6201
|
var deployCommand = Command.make(
|
|
5960
6202
|
"deploy",
|
|
5961
6203
|
{ target: deployTargetArg, project: projectOption, stage: stageOption, region: regionOption, verbose: verboseOption, noSites: noSitesOption },
|
|
5962
|
-
({ target, project: projectOpt, stage, region, verbose, noSites }) =>
|
|
5963
|
-
const config = yield*
|
|
6204
|
+
({ target, project: projectOpt, stage, region, verbose, noSites }) => Effect38.gen(function* () {
|
|
6205
|
+
const { config, cwd, projectDir } = yield* ProjectConfig;
|
|
5964
6206
|
const project = Option.getOrElse(projectOpt, () => config?.name ?? "");
|
|
5965
6207
|
const finalStage = config?.stage ?? stage;
|
|
5966
6208
|
const finalRegion = config?.region ?? region;
|
|
@@ -5979,9 +6221,8 @@ var deployCommand = Command.make(
|
|
|
5979
6221
|
acm: { region: "us-east-1" }
|
|
5980
6222
|
});
|
|
5981
6223
|
const logLevel = verbose ? LogLevel.Debug : LogLevel.Warning;
|
|
5982
|
-
const projectDir = process.cwd();
|
|
5983
6224
|
yield* Option.match(target, {
|
|
5984
|
-
onNone: () =>
|
|
6225
|
+
onNone: () => Effect38.gen(function* () {
|
|
5985
6226
|
const patterns = getPatternsFromConfig(config);
|
|
5986
6227
|
if (!patterns) {
|
|
5987
6228
|
yield* Console3.error("Error: No target specified and no 'handlers' patterns in config");
|
|
@@ -5989,13 +6230,15 @@ var deployCommand = Command.make(
|
|
|
5989
6230
|
}
|
|
5990
6231
|
const results = yield* deployProject({
|
|
5991
6232
|
projectDir,
|
|
6233
|
+
packageDir: cwd,
|
|
5992
6234
|
patterns,
|
|
5993
6235
|
project,
|
|
5994
6236
|
stage: finalStage,
|
|
5995
6237
|
region: finalRegion,
|
|
5996
|
-
noSites
|
|
6238
|
+
noSites,
|
|
6239
|
+
verbose
|
|
5997
6240
|
});
|
|
5998
|
-
const total = results.httpResults.length + results.tableResults.length + results.appResults.length + results.staticSiteResults.length;
|
|
6241
|
+
const total = results.httpResults.length + results.tableResults.length + results.appResults.length + results.staticSiteResults.length + results.apiResults.length;
|
|
5999
6242
|
yield* Console3.log(`
|
|
6000
6243
|
${c.green(`Deployed ${total} handler(s):`)}`);
|
|
6001
6244
|
if (results.apiUrl) {
|
|
@@ -6014,6 +6257,10 @@ ${c.green(`Deployed ${total} handler(s):`)}`);
|
|
|
6014
6257
|
for (const r of results.tableResults) {
|
|
6015
6258
|
summaryLines.push({ name: r.exportName, line: ` ${c.cyan("[table]")} ${c.bold(r.exportName)}` });
|
|
6016
6259
|
}
|
|
6260
|
+
for (const r of results.apiResults) {
|
|
6261
|
+
const pathPart = results.apiUrl ? r.url.replace(results.apiUrl, "") : r.url;
|
|
6262
|
+
summaryLines.push({ name: r.exportName, line: ` ${c.cyan("[api]")} ${c.bold(r.exportName)} ${c.dim(pathPart)}` });
|
|
6263
|
+
}
|
|
6017
6264
|
for (const r of results.staticSiteResults) {
|
|
6018
6265
|
summaryLines.push({ name: r.exportName, line: ` ${c.cyan("[site]")} ${c.bold(r.exportName)}: ${c.cyan(r.url)}` });
|
|
6019
6266
|
}
|
|
@@ -6022,26 +6269,27 @@ ${c.green(`Deployed ${total} handler(s):`)}`);
|
|
|
6022
6269
|
yield* Console3.log(line);
|
|
6023
6270
|
}
|
|
6024
6271
|
}),
|
|
6025
|
-
onSome: (targetValue) =>
|
|
6272
|
+
onSome: (targetValue) => Effect38.gen(function* () {
|
|
6026
6273
|
if (isFilePath(targetValue)) {
|
|
6027
|
-
const fullPath =
|
|
6274
|
+
const fullPath = path9.isAbsolute(targetValue) ? targetValue : path9.resolve(projectDir, targetValue);
|
|
6028
6275
|
const input = {
|
|
6029
6276
|
projectDir,
|
|
6277
|
+
packageDir: cwd,
|
|
6030
6278
|
file: fullPath,
|
|
6031
6279
|
project,
|
|
6032
6280
|
stage: finalStage,
|
|
6033
6281
|
region: finalRegion
|
|
6034
6282
|
};
|
|
6035
6283
|
const httpResult = yield* deployAll(input).pipe(
|
|
6036
|
-
|
|
6284
|
+
Effect38.catchIf(
|
|
6037
6285
|
(e) => e instanceof Error && e.message.includes("No defineHttp"),
|
|
6038
|
-
() =>
|
|
6286
|
+
() => Effect38.succeed(null)
|
|
6039
6287
|
)
|
|
6040
6288
|
);
|
|
6041
6289
|
const tableResults = yield* deployAllTables(input).pipe(
|
|
6042
|
-
|
|
6290
|
+
Effect38.catchIf(
|
|
6043
6291
|
(e) => e instanceof Error && e.message.includes("No defineTable"),
|
|
6044
|
-
() =>
|
|
6292
|
+
() => Effect38.succeed([])
|
|
6045
6293
|
)
|
|
6046
6294
|
);
|
|
6047
6295
|
if (!httpResult && tableResults.length === 0) {
|
|
@@ -6071,68 +6319,23 @@ Deployed ${tableResults.length} table handler(s):`));
|
|
|
6071
6319
|
}
|
|
6072
6320
|
const files = findHandlerFiles(patterns, projectDir);
|
|
6073
6321
|
const discovered = discoverHandlers(files);
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
for (const { file, exports } of discovered.httpHandlers) {
|
|
6078
|
-
for (const { exportName } of exports) {
|
|
6079
|
-
if (exportName === targetValue) {
|
|
6080
|
-
foundFile = file;
|
|
6081
|
-
foundExport = exportName;
|
|
6082
|
-
break;
|
|
6083
|
-
}
|
|
6084
|
-
}
|
|
6085
|
-
if (foundFile) break;
|
|
6086
|
-
}
|
|
6087
|
-
if (!foundFile) {
|
|
6088
|
-
for (const { file, exports } of discovered.tableHandlers) {
|
|
6089
|
-
for (const { exportName } of exports) {
|
|
6090
|
-
if (exportName === targetValue) {
|
|
6091
|
-
foundFile = file;
|
|
6092
|
-
foundExport = exportName;
|
|
6093
|
-
handlerType = "table";
|
|
6094
|
-
break;
|
|
6095
|
-
}
|
|
6096
|
-
}
|
|
6097
|
-
if (foundFile) break;
|
|
6098
|
-
}
|
|
6099
|
-
}
|
|
6100
|
-
if (!foundFile) {
|
|
6101
|
-
for (const { file, exports } of discovered.appHandlers) {
|
|
6102
|
-
for (const { exportName } of exports) {
|
|
6103
|
-
if (exportName === targetValue) {
|
|
6104
|
-
foundFile = file;
|
|
6105
|
-
foundExport = exportName;
|
|
6106
|
-
handlerType = "app";
|
|
6107
|
-
break;
|
|
6108
|
-
}
|
|
6109
|
-
}
|
|
6110
|
-
if (foundFile) break;
|
|
6111
|
-
}
|
|
6112
|
-
}
|
|
6113
|
-
if (!foundFile || !foundExport) {
|
|
6322
|
+
const allHandlers = flattenHandlers(discovered);
|
|
6323
|
+
const found = allHandlers.find((h) => h.exportName === targetValue);
|
|
6324
|
+
if (!found) {
|
|
6114
6325
|
yield* Console3.error(`Error: Handler "${targetValue}" not found`);
|
|
6115
6326
|
yield* Console3.log("\nAvailable handlers:");
|
|
6116
|
-
for (const
|
|
6117
|
-
|
|
6118
|
-
yield* Console3.log(` ${c.cyan("[http]")} ${exportName}`);
|
|
6119
|
-
}
|
|
6120
|
-
}
|
|
6121
|
-
for (const { exports } of discovered.tableHandlers) {
|
|
6122
|
-
for (const { exportName } of exports) {
|
|
6123
|
-
yield* Console3.log(` ${c.cyan("[table]")} ${exportName}`);
|
|
6124
|
-
}
|
|
6125
|
-
}
|
|
6126
|
-
for (const { exports } of discovered.appHandlers) {
|
|
6127
|
-
for (const { exportName } of exports) {
|
|
6128
|
-
yield* Console3.log(` ${c.cyan("[app]")} ${exportName}`);
|
|
6129
|
-
}
|
|
6327
|
+
for (const h of allHandlers) {
|
|
6328
|
+
yield* Console3.log(` ${c.cyan(`[${h.type}]`.padEnd(9))} ${h.exportName}`);
|
|
6130
6329
|
}
|
|
6131
6330
|
return;
|
|
6132
6331
|
}
|
|
6133
|
-
|
|
6332
|
+
const foundFile = found.file;
|
|
6333
|
+
const foundExport = found.exportName;
|
|
6334
|
+
const handlerType = found.type;
|
|
6335
|
+
yield* Console3.log(`Found handler ${c.bold(targetValue)} in ${c.dim(path9.relative(projectDir, foundFile))}`);
|
|
6134
6336
|
const input = {
|
|
6135
6337
|
projectDir,
|
|
6338
|
+
packageDir: cwd,
|
|
6136
6339
|
file: foundFile,
|
|
6137
6340
|
project,
|
|
6138
6341
|
stage: finalStage,
|
|
@@ -6151,15 +6354,15 @@ ${c.green("Deployed:")} ${c.cyan(result.url)}`);
|
|
|
6151
6354
|
}
|
|
6152
6355
|
})
|
|
6153
6356
|
}).pipe(
|
|
6154
|
-
|
|
6357
|
+
Effect38.provide(clientsLayer),
|
|
6155
6358
|
Logger.withMinimumLogLevel(logLevel)
|
|
6156
6359
|
);
|
|
6157
|
-
})
|
|
6158
|
-
).pipe(Command.withDescription("Deploy handlers
|
|
6360
|
+
}).pipe(Effect38.provide(ProjectConfig.Live))
|
|
6361
|
+
).pipe(Command.withDescription("Deploy handlers to AWS Lambda. Accepts a handler name, file path, or deploys all from config"));
|
|
6159
6362
|
|
|
6160
6363
|
// src/cli/commands/status.ts
|
|
6161
6364
|
import { Command as Command2 } from "@effect/cli";
|
|
6162
|
-
import { Effect as
|
|
6365
|
+
import { Effect as Effect39, Console as Console4, Logger as Logger2, LogLevel as LogLevel2, Option as Option2 } from "effect";
|
|
6163
6366
|
var { lambda, apigatewayv2: apigateway } = clients_exports;
|
|
6164
6367
|
var INTERNAL_HANDLERS = /* @__PURE__ */ new Set(["api", "platform"]);
|
|
6165
6368
|
var extractFunctionName = (arn) => {
|
|
@@ -6184,7 +6387,7 @@ var formatDate = (date) => {
|
|
|
6184
6387
|
if (days < 7) return `${days}d ago`;
|
|
6185
6388
|
return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
6186
6389
|
};
|
|
6187
|
-
var getLambdaDetails = (functionName) =>
|
|
6390
|
+
var getLambdaDetails = (functionName) => Effect39.gen(function* () {
|
|
6188
6391
|
const config = yield* lambda.make("get_function_configuration", {
|
|
6189
6392
|
FunctionName: functionName
|
|
6190
6393
|
});
|
|
@@ -6194,62 +6397,21 @@ var getLambdaDetails = (functionName) => Effect37.gen(function* () {
|
|
|
6194
6397
|
timeout: config.Timeout
|
|
6195
6398
|
};
|
|
6196
6399
|
}).pipe(
|
|
6197
|
-
|
|
6400
|
+
Effect39.catchAll(() => Effect39.succeed({}))
|
|
6198
6401
|
);
|
|
6199
|
-
var getApiUrl = (apiId) =>
|
|
6402
|
+
var getApiUrl = (apiId) => Effect39.gen(function* () {
|
|
6200
6403
|
const api = yield* apigateway.make("get_api", { ApiId: apiId });
|
|
6201
6404
|
return api.ApiEndpoint;
|
|
6202
6405
|
}).pipe(
|
|
6203
|
-
|
|
6406
|
+
Effect39.catchAll(() => Effect39.succeed(void 0))
|
|
6204
6407
|
);
|
|
6205
6408
|
var discoverCodeHandlers = (projectDir, patterns) => {
|
|
6206
6409
|
const files = findHandlerFiles(patterns, projectDir);
|
|
6207
6410
|
const discovered = discoverHandlers(files);
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
name: fn13.exportName,
|
|
6213
|
-
type: "http",
|
|
6214
|
-
method: fn13.config.method,
|
|
6215
|
-
path: fn13.config.path
|
|
6216
|
-
});
|
|
6217
|
-
}
|
|
6218
|
-
}
|
|
6219
|
-
for (const { exports } of discovered.tableHandlers) {
|
|
6220
|
-
for (const fn13 of exports) {
|
|
6221
|
-
handlers.push({
|
|
6222
|
-
name: fn13.exportName,
|
|
6223
|
-
type: "table"
|
|
6224
|
-
});
|
|
6225
|
-
}
|
|
6226
|
-
}
|
|
6227
|
-
for (const { exports } of discovered.appHandlers) {
|
|
6228
|
-
for (const fn13 of exports) {
|
|
6229
|
-
handlers.push({
|
|
6230
|
-
name: fn13.exportName,
|
|
6231
|
-
type: "app",
|
|
6232
|
-
path: fn13.config.path
|
|
6233
|
-
});
|
|
6234
|
-
}
|
|
6235
|
-
}
|
|
6236
|
-
for (const { exports } of discovered.staticSiteHandlers) {
|
|
6237
|
-
for (const fn13 of exports) {
|
|
6238
|
-
handlers.push({
|
|
6239
|
-
name: fn13.exportName,
|
|
6240
|
-
type: "site"
|
|
6241
|
-
});
|
|
6242
|
-
}
|
|
6243
|
-
}
|
|
6244
|
-
for (const { exports } of discovered.fifoQueueHandlers) {
|
|
6245
|
-
for (const fn13 of exports) {
|
|
6246
|
-
handlers.push({
|
|
6247
|
-
name: fn13.exportName,
|
|
6248
|
-
type: "queue"
|
|
6249
|
-
});
|
|
6250
|
-
}
|
|
6251
|
-
}
|
|
6252
|
-
return handlers;
|
|
6411
|
+
return flattenHandlers(discovered).map((h) => ({
|
|
6412
|
+
name: h.exportName,
|
|
6413
|
+
type: h.type
|
|
6414
|
+
}));
|
|
6253
6415
|
};
|
|
6254
6416
|
var discoverAwsHandlers = (resources) => {
|
|
6255
6417
|
const byHandler = groupResourcesByHandler(resources);
|
|
@@ -6277,6 +6439,7 @@ var TYPE_LABELS = {
|
|
|
6277
6439
|
http: "http",
|
|
6278
6440
|
table: "table",
|
|
6279
6441
|
app: "app",
|
|
6442
|
+
api: "api",
|
|
6280
6443
|
site: "site",
|
|
6281
6444
|
queue: "queue",
|
|
6282
6445
|
lambda: "lambda",
|
|
@@ -6297,9 +6460,9 @@ var STATUS_COLORS = {
|
|
|
6297
6460
|
var formatStatus = (status) => {
|
|
6298
6461
|
return STATUS_COLORS[status](status.padEnd(10));
|
|
6299
6462
|
};
|
|
6300
|
-
var formatRoute = (method,
|
|
6301
|
-
if (method &&
|
|
6302
|
-
if (
|
|
6463
|
+
var formatRoute = (method, path11) => {
|
|
6464
|
+
if (method && path11) return `${method.padEnd(5)} ${path11}`;
|
|
6465
|
+
if (path11) return path11;
|
|
6303
6466
|
return "";
|
|
6304
6467
|
};
|
|
6305
6468
|
var formatEntry = (entry) => {
|
|
@@ -6321,8 +6484,8 @@ var formatEntry = (entry) => {
|
|
|
6321
6484
|
var statusCommand = Command2.make(
|
|
6322
6485
|
"status",
|
|
6323
6486
|
{ project: projectOption, stage: stageOption, region: regionOption, verbose: verboseOption },
|
|
6324
|
-
({ project: projectOpt, stage, region, verbose }) =>
|
|
6325
|
-
const config = yield*
|
|
6487
|
+
({ project: projectOpt, stage, region, verbose }) => Effect39.gen(function* () {
|
|
6488
|
+
const { config, projectDir } = yield* ProjectConfig;
|
|
6326
6489
|
const project = Option2.getOrElse(projectOpt, () => config?.name ?? "");
|
|
6327
6490
|
const finalStage = config?.stage ?? stage;
|
|
6328
6491
|
const finalRegion = config?.region ?? region;
|
|
@@ -6336,11 +6499,10 @@ var statusCommand = Command2.make(
|
|
|
6336
6499
|
resource_groups_tagging_api: { region: finalRegion }
|
|
6337
6500
|
});
|
|
6338
6501
|
const logLevel = verbose ? LogLevel2.Debug : LogLevel2.Info;
|
|
6339
|
-
const projectDir = process.cwd();
|
|
6340
6502
|
const patterns = getPatternsFromConfig(config);
|
|
6341
6503
|
const codeHandlers = patterns ? discoverCodeHandlers(projectDir, patterns) : [];
|
|
6342
6504
|
const codeHandlerNames = new Set(codeHandlers.map((h) => h.name));
|
|
6343
|
-
yield*
|
|
6505
|
+
yield* Effect39.gen(function* () {
|
|
6344
6506
|
yield* Console4.log(`
|
|
6345
6507
|
Status for ${c.bold(project + "/" + finalStage)}:
|
|
6346
6508
|
`);
|
|
@@ -6436,19 +6598,28 @@ API: ${c.cyan(apiUrl)}`);
|
|
|
6436
6598
|
if (counts.orphaned > 0) parts.push(c.red(`${counts.orphaned} orphaned`));
|
|
6437
6599
|
yield* Console4.log(`
|
|
6438
6600
|
Total: ${parts.join(", ")}`);
|
|
6601
|
+
const depWarnings = yield* checkDependencyWarnings(projectDir).pipe(
|
|
6602
|
+
Effect39.catchAll(() => Effect39.succeed([]))
|
|
6603
|
+
);
|
|
6604
|
+
if (depWarnings.length > 0) {
|
|
6605
|
+
yield* Console4.log("");
|
|
6606
|
+
for (const w of depWarnings) {
|
|
6607
|
+
yield* Console4.log(c.yellow(` \u26A0 ${w}`));
|
|
6608
|
+
}
|
|
6609
|
+
}
|
|
6439
6610
|
}).pipe(
|
|
6440
|
-
|
|
6611
|
+
Effect39.provide(clientsLayer),
|
|
6441
6612
|
Logger2.withMinimumLogLevel(logLevel)
|
|
6442
6613
|
);
|
|
6443
|
-
})
|
|
6444
|
-
).pipe(Command2.withDescription("
|
|
6614
|
+
}).pipe(Effect39.provide(ProjectConfig.Live))
|
|
6615
|
+
).pipe(Command2.withDescription("Compare local handlers with deployed AWS resources. Shows new, deployed, and orphaned handlers"));
|
|
6445
6616
|
|
|
6446
6617
|
// src/cli/commands/cleanup.ts
|
|
6447
6618
|
import { Command as Command3, Options as Options2 } from "@effect/cli";
|
|
6448
|
-
import { Effect as
|
|
6619
|
+
import { Effect as Effect41, Console as Console5, Logger as Logger3, LogLevel as LogLevel3, Option as Option3 } from "effect";
|
|
6449
6620
|
|
|
6450
6621
|
// src/deploy/cleanup.ts
|
|
6451
|
-
import { Effect as
|
|
6622
|
+
import { Effect as Effect40 } from "effect";
|
|
6452
6623
|
var extractResourceName = (arn, type) => {
|
|
6453
6624
|
switch (type) {
|
|
6454
6625
|
case "lambda": {
|
|
@@ -6491,7 +6662,7 @@ var extractLayerInfo = (arn) => {
|
|
|
6491
6662
|
version: parseInt(parts[parts.length - 1] ?? "0", 10)
|
|
6492
6663
|
};
|
|
6493
6664
|
};
|
|
6494
|
-
var deleteResource = (resource) =>
|
|
6665
|
+
var deleteResource = (resource) => Effect40.gen(function* () {
|
|
6495
6666
|
const name = extractResourceName(resource.arn, resource.type);
|
|
6496
6667
|
switch (resource.type) {
|
|
6497
6668
|
case "lambda":
|
|
@@ -6524,18 +6695,18 @@ var deleteResource = (resource) => Effect38.gen(function* () {
|
|
|
6524
6695
|
yield* deleteSesIdentity(name);
|
|
6525
6696
|
break;
|
|
6526
6697
|
default:
|
|
6527
|
-
yield*
|
|
6698
|
+
yield* Effect40.logWarning(`Unknown resource type: ${resource.type}, skipping ${resource.arn}`);
|
|
6528
6699
|
}
|
|
6529
6700
|
});
|
|
6530
|
-
var deleteResources = (resources) =>
|
|
6701
|
+
var deleteResources = (resources) => Effect40.gen(function* () {
|
|
6531
6702
|
const orderedTypes = ["lambda", "api-gateway", "cloudfront-distribution", "sqs", "ses", "dynamodb", "s3-bucket", "lambda-layer", "iam-role"];
|
|
6532
6703
|
const iamRolesToDelete = /* @__PURE__ */ new Set();
|
|
6533
6704
|
for (const type of orderedTypes) {
|
|
6534
6705
|
const resourcesOfType = resources.filter((r) => r.type === type);
|
|
6535
6706
|
for (const resource of resourcesOfType) {
|
|
6536
6707
|
yield* deleteResource(resource).pipe(
|
|
6537
|
-
|
|
6538
|
-
(error) =>
|
|
6708
|
+
Effect40.catchAll(
|
|
6709
|
+
(error) => Effect40.logError(`Failed to delete ${resource.type} ${resource.arn}: ${error}`)
|
|
6539
6710
|
)
|
|
6540
6711
|
);
|
|
6541
6712
|
if (resource.type === "lambda") {
|
|
@@ -6547,8 +6718,8 @@ var deleteResources = (resources) => Effect38.gen(function* () {
|
|
|
6547
6718
|
}
|
|
6548
6719
|
for (const roleName of iamRolesToDelete) {
|
|
6549
6720
|
yield* deleteRole(roleName).pipe(
|
|
6550
|
-
|
|
6551
|
-
(error) =>
|
|
6721
|
+
Effect40.catchAll(
|
|
6722
|
+
(error) => Effect40.logError(`Failed to delete IAM role ${roleName}: ${error}`)
|
|
6552
6723
|
)
|
|
6553
6724
|
);
|
|
6554
6725
|
}
|
|
@@ -6569,11 +6740,14 @@ var layerOption = Options2.boolean("layer").pipe(
|
|
|
6569
6740
|
var rolesOption = Options2.boolean("roles").pipe(
|
|
6570
6741
|
Options2.withDescription("Clean up orphaned IAM roles instead of handler resources")
|
|
6571
6742
|
);
|
|
6743
|
+
var orphanedOption = Options2.boolean("orphaned").pipe(
|
|
6744
|
+
Options2.withDescription("Delete only handlers that exist in AWS but not in code")
|
|
6745
|
+
);
|
|
6572
6746
|
var cleanupCommand = Command3.make(
|
|
6573
6747
|
"cleanup",
|
|
6574
|
-
{ project: projectOption, stage: stageOption, region: regionOption, handler: handlerOption, layer: layerOption, roles: rolesOption, all: cleanupAllOption, dryRun: dryRunOption, verbose: verboseOption },
|
|
6575
|
-
({ project: projectOpt, stage, region, handler: handlerOpt, layer: cleanupLayer, roles: cleanupRoles, all: deleteAll, dryRun, verbose }) =>
|
|
6576
|
-
const config = yield*
|
|
6748
|
+
{ project: projectOption, stage: stageOption, region: regionOption, handler: handlerOption, layer: layerOption, roles: rolesOption, orphaned: orphanedOption, all: cleanupAllOption, dryRun: dryRunOption, verbose: verboseOption },
|
|
6749
|
+
({ project: projectOpt, stage, region, handler: handlerOpt, layer: cleanupLayer, roles: cleanupRoles, orphaned: cleanupOrphaned, all: deleteAll, dryRun, verbose }) => Effect41.gen(function* () {
|
|
6750
|
+
const { config, projectDir } = yield* ProjectConfig;
|
|
6577
6751
|
const project = Option3.getOrElse(projectOpt, () => config?.name ?? "");
|
|
6578
6752
|
const finalStage = config?.stage ?? stage;
|
|
6579
6753
|
const finalRegion = config?.region ?? region;
|
|
@@ -6584,14 +6758,14 @@ var cleanupCommand = Command3.make(
|
|
|
6584
6758
|
const logLevel = verbose ? LogLevel3.Debug : LogLevel3.Info;
|
|
6585
6759
|
if (cleanupLayer) {
|
|
6586
6760
|
yield* cleanupLayerVersions({ project, region: finalRegion, deleteAll, dryRun }).pipe(
|
|
6587
|
-
|
|
6761
|
+
Effect41.provide(clients_exports.makeClients({ lambda: { region: finalRegion } })),
|
|
6588
6762
|
Logger3.withMinimumLogLevel(logLevel)
|
|
6589
6763
|
);
|
|
6590
6764
|
return;
|
|
6591
6765
|
}
|
|
6592
6766
|
if (cleanupRoles) {
|
|
6593
6767
|
yield* cleanupIamRoles({ project, stage: finalStage, region: finalRegion, deleteAll, dryRun }).pipe(
|
|
6594
|
-
|
|
6768
|
+
Effect41.provide(clients_exports.makeClients({ iam: { region: finalRegion } })),
|
|
6595
6769
|
Logger3.withMinimumLogLevel(logLevel)
|
|
6596
6770
|
);
|
|
6597
6771
|
return;
|
|
@@ -6606,7 +6780,7 @@ var cleanupCommand = Command3.make(
|
|
|
6606
6780
|
s3: { region: finalRegion },
|
|
6607
6781
|
cloudfront: { region: "us-east-1" }
|
|
6608
6782
|
});
|
|
6609
|
-
yield*
|
|
6783
|
+
yield* Effect41.gen(function* () {
|
|
6610
6784
|
yield* Console5.log(`
|
|
6611
6785
|
Looking for resources in ${c.bold(project + "/" + finalStage)}...
|
|
6612
6786
|
`);
|
|
@@ -6616,14 +6790,34 @@ Looking for resources in ${c.bold(project + "/" + finalStage)}...
|
|
|
6616
6790
|
return;
|
|
6617
6791
|
}
|
|
6618
6792
|
const byHandler = groupResourcesByHandler(resources);
|
|
6619
|
-
|
|
6620
|
-
if (
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6793
|
+
let handlersToDelete;
|
|
6794
|
+
if (cleanupOrphaned) {
|
|
6795
|
+
const patterns = getPatternsFromConfig(config);
|
|
6796
|
+
if (!patterns) {
|
|
6797
|
+
yield* Console5.error("Error: No 'handlers' patterns in config \u2014 cannot determine orphaned handlers");
|
|
6798
|
+
return;
|
|
6625
6799
|
}
|
|
6626
|
-
|
|
6800
|
+
const files = findHandlerFiles(patterns, projectDir);
|
|
6801
|
+
const discovered = discoverHandlers(files);
|
|
6802
|
+
const codeNames = new Set(flattenHandlers(discovered).map((h) => h.exportName));
|
|
6803
|
+
const INTERNAL_HANDLERS2 = /* @__PURE__ */ new Set(["api", "platform"]);
|
|
6804
|
+
handlersToDelete = Array.from(byHandler.entries()).filter(([name]) => !codeNames.has(name) && !INTERNAL_HANDLERS2.has(name));
|
|
6805
|
+
if (handlersToDelete.length === 0) {
|
|
6806
|
+
yield* Console5.log("No orphaned handlers found.");
|
|
6807
|
+
return;
|
|
6808
|
+
}
|
|
6809
|
+
} else if (handlerFilter) {
|
|
6810
|
+
if (!byHandler.has(handlerFilter)) {
|
|
6811
|
+
yield* Console5.error(`Handler "${handlerFilter}" not found.`);
|
|
6812
|
+
yield* Console5.log("\nAvailable handlers:");
|
|
6813
|
+
for (const [h] of byHandler) {
|
|
6814
|
+
yield* Console5.log(` - ${h}`);
|
|
6815
|
+
}
|
|
6816
|
+
return;
|
|
6817
|
+
}
|
|
6818
|
+
handlersToDelete = [[handlerFilter, byHandler.get(handlerFilter) ?? []]];
|
|
6819
|
+
} else {
|
|
6820
|
+
handlersToDelete = Array.from(byHandler.entries());
|
|
6627
6821
|
}
|
|
6628
6822
|
const resourcesToDelete = [];
|
|
6629
6823
|
const derivedRoles = [];
|
|
@@ -6654,9 +6848,10 @@ Total: ${totalResources} resource(s) (${derivedRoles.length} derived)`);
|
|
|
6654
6848
|
${c.yellow("[DRY RUN]")} No resources were deleted.`);
|
|
6655
6849
|
return;
|
|
6656
6850
|
}
|
|
6657
|
-
if (!handlerFilter && !deleteAll) {
|
|
6851
|
+
if (!handlerFilter && !cleanupOrphaned && !deleteAll) {
|
|
6658
6852
|
yield* Console5.log("\nTo delete these resources, use one of:");
|
|
6659
6853
|
yield* Console5.log(` ${c.dim("eff cleanup --all")} # Delete all resources`);
|
|
6854
|
+
yield* Console5.log(` ${c.dim("eff cleanup --orphaned")} # Delete orphaned handlers only`);
|
|
6660
6855
|
yield* Console5.log(` ${c.dim("eff cleanup --handler <name>")} # Delete specific handler`);
|
|
6661
6856
|
yield* Console5.log(` ${c.dim("eff cleanup --dry-run")} # Preview without deleting`);
|
|
6662
6857
|
return;
|
|
@@ -6665,12 +6860,12 @@ ${c.yellow("[DRY RUN]")} No resources were deleted.`);
|
|
|
6665
6860
|
yield* deleteResources(resourcesToDelete);
|
|
6666
6861
|
yield* Console5.log(c.green("\nDone!"));
|
|
6667
6862
|
}).pipe(
|
|
6668
|
-
|
|
6863
|
+
Effect41.provide(clientsLayer),
|
|
6669
6864
|
Logger3.withMinimumLogLevel(logLevel)
|
|
6670
6865
|
);
|
|
6671
|
-
})
|
|
6672
|
-
).pipe(Command3.withDescription("Delete deployed resources"));
|
|
6673
|
-
var cleanupLayerVersions = (input) =>
|
|
6866
|
+
}).pipe(Effect41.provide(ProjectConfig.Live))
|
|
6867
|
+
).pipe(Command3.withDescription("Delete deployed resources (Lambda, API Gateway, DynamoDB, IAM roles, layers)"));
|
|
6868
|
+
var cleanupLayerVersions = (input) => Effect41.gen(function* () {
|
|
6674
6869
|
const layerName = `${input.project}-deps`;
|
|
6675
6870
|
yield* Console5.log(`
|
|
6676
6871
|
Searching for layer versions: ${layerName}
|
|
@@ -6702,7 +6897,7 @@ ${c.yellow("[DRY RUN]")} No layers were deleted.`);
|
|
|
6702
6897
|
yield* Console5.log(c.green(`
|
|
6703
6898
|
Deleted ${deleted} layer version(s).`));
|
|
6704
6899
|
});
|
|
6705
|
-
var cleanupIamRoles = (input) =>
|
|
6900
|
+
var cleanupIamRoles = (input) => Effect41.gen(function* () {
|
|
6706
6901
|
yield* Console5.log("\nSearching for effortless IAM roles...\n");
|
|
6707
6902
|
const allRoles = yield* listEffortlessRoles();
|
|
6708
6903
|
if (allRoles.length === 0) {
|
|
@@ -6751,8 +6946,8 @@ ${c.yellow("[DRY RUN]")} No roles were deleted.`);
|
|
|
6751
6946
|
yield* Console5.log(c.red("\nDeleting roles..."));
|
|
6752
6947
|
for (const role of roles) {
|
|
6753
6948
|
yield* deleteRole(role.name).pipe(
|
|
6754
|
-
|
|
6755
|
-
(error) =>
|
|
6949
|
+
Effect41.catchAll(
|
|
6950
|
+
(error) => Effect41.logError(`Failed to delete ${role.name}: ${error}`)
|
|
6756
6951
|
)
|
|
6757
6952
|
);
|
|
6758
6953
|
}
|
|
@@ -6761,7 +6956,7 @@ ${c.yellow("[DRY RUN]")} No roles were deleted.`);
|
|
|
6761
6956
|
|
|
6762
6957
|
// src/cli/commands/logs.ts
|
|
6763
6958
|
import { Args as Args2, Command as Command4, Options as Options3 } from "@effect/cli";
|
|
6764
|
-
import { Effect as
|
|
6959
|
+
import { Effect as Effect42, Console as Console6, Logger as Logger4, LogLevel as LogLevel4, Option as Option4, Schedule as Schedule4 } from "effect";
|
|
6765
6960
|
var { cloudwatch_logs } = clients_exports;
|
|
6766
6961
|
var handlerArg = Args2.text({ name: "handler" }).pipe(
|
|
6767
6962
|
Args2.withDescription("Handler name to show logs for")
|
|
@@ -6832,8 +7027,8 @@ var fetchLogs = (logGroupName, startTime, nextToken) => cloudwatch_logs.make("fi
|
|
|
6832
7027
|
var logsCommand = Command4.make(
|
|
6833
7028
|
"logs",
|
|
6834
7029
|
{ handler: handlerArg, project: projectOption, stage: stageOption, region: regionOption, tail: tailOption, since: sinceOption, verbose: verboseOption },
|
|
6835
|
-
({ handler: handlerName, project: projectOpt, stage, region, tail, since, verbose }) =>
|
|
6836
|
-
const config = yield*
|
|
7030
|
+
({ handler: handlerName, project: projectOpt, stage, region, tail, since, verbose }) => Effect42.gen(function* () {
|
|
7031
|
+
const { config, projectDir } = yield* ProjectConfig;
|
|
6837
7032
|
const project = Option4.getOrElse(projectOpt, () => config?.name ?? "");
|
|
6838
7033
|
const finalStage = config?.stage ?? stage;
|
|
6839
7034
|
const finalRegion = config?.region ?? region;
|
|
@@ -6841,17 +7036,11 @@ var logsCommand = Command4.make(
|
|
|
6841
7036
|
yield* Console6.error("Error: --project is required (or set 'name' in effortless.config.ts)");
|
|
6842
7037
|
return;
|
|
6843
7038
|
}
|
|
6844
|
-
const projectDir = process.cwd();
|
|
6845
7039
|
const patterns = getPatternsFromConfig(config);
|
|
6846
7040
|
if (patterns) {
|
|
6847
7041
|
const files = findHandlerFiles(patterns, projectDir);
|
|
6848
7042
|
const discovered = discoverHandlers(files);
|
|
6849
|
-
const allHandlerNames =
|
|
6850
|
-
...discovered.httpHandlers.flatMap((h) => h.exports.map((e) => e.exportName)),
|
|
6851
|
-
...discovered.tableHandlers.flatMap((h) => h.exports.map((e) => e.exportName)),
|
|
6852
|
-
...discovered.appHandlers.flatMap((h) => h.exports.map((e) => e.exportName)),
|
|
6853
|
-
...discovered.fifoQueueHandlers.flatMap((h) => h.exports.map((e) => e.exportName))
|
|
6854
|
-
];
|
|
7043
|
+
const allHandlerNames = flattenHandlers(discovered).map((h) => h.exportName);
|
|
6855
7044
|
if (!allHandlerNames.includes(handlerName)) {
|
|
6856
7045
|
yield* Console6.error(`Handler "${handlerName}" not found in code.`);
|
|
6857
7046
|
if (allHandlerNames.length > 0) {
|
|
@@ -6869,18 +7058,18 @@ var logsCommand = Command4.make(
|
|
|
6869
7058
|
cloudwatch_logs: { region: finalRegion }
|
|
6870
7059
|
});
|
|
6871
7060
|
const logLevel = verbose ? LogLevel4.Debug : LogLevel4.Info;
|
|
6872
|
-
yield*
|
|
7061
|
+
yield* Effect42.gen(function* () {
|
|
6873
7062
|
const durationMs = parseDuration(since);
|
|
6874
7063
|
let startTime = Date.now() - durationMs;
|
|
6875
7064
|
yield* Console6.log(`Logs for ${c.bold(handlerName)} ${c.dim(`(${logGroupName})`)}:
|
|
6876
7065
|
`);
|
|
6877
7066
|
let hasLogs = false;
|
|
6878
7067
|
const result = yield* fetchLogs(logGroupName, startTime).pipe(
|
|
6879
|
-
|
|
7068
|
+
Effect42.catchAll((error) => {
|
|
6880
7069
|
if (error instanceof clients_exports.cloudwatch_logs.CloudWatchLogsError && error.cause.name === "ResourceNotFoundException") {
|
|
6881
|
-
return
|
|
7070
|
+
return Effect42.succeed({ events: void 0, nextToken: void 0 });
|
|
6882
7071
|
}
|
|
6883
|
-
return
|
|
7072
|
+
return Effect42.fail(error);
|
|
6884
7073
|
})
|
|
6885
7074
|
);
|
|
6886
7075
|
if (result.events && result.events.length > 0) {
|
|
@@ -6904,10 +7093,10 @@ var logsCommand = Command4.make(
|
|
|
6904
7093
|
if (!hasLogs) {
|
|
6905
7094
|
yield* Console6.log("Waiting for logs... (Ctrl+C to stop)\n");
|
|
6906
7095
|
}
|
|
6907
|
-
yield*
|
|
6908
|
-
|
|
7096
|
+
yield* Effect42.repeat(
|
|
7097
|
+
Effect42.gen(function* () {
|
|
6909
7098
|
const result2 = yield* fetchLogs(logGroupName, startTime).pipe(
|
|
6910
|
-
|
|
7099
|
+
Effect42.catchAll(() => Effect42.succeed({ events: void 0, nextToken: void 0 }))
|
|
6911
7100
|
);
|
|
6912
7101
|
if (result2.events && result2.events.length > 0) {
|
|
6913
7102
|
for (const event of result2.events) {
|
|
@@ -6925,16 +7114,16 @@ var logsCommand = Command4.make(
|
|
|
6925
7114
|
Schedule4.spaced("2 seconds")
|
|
6926
7115
|
);
|
|
6927
7116
|
}).pipe(
|
|
6928
|
-
|
|
7117
|
+
Effect42.provide(clientsLayer),
|
|
6929
7118
|
Logger4.withMinimumLogLevel(logLevel)
|
|
6930
7119
|
);
|
|
6931
|
-
})
|
|
6932
|
-
).pipe(Command4.withDescription("
|
|
7120
|
+
}).pipe(Effect42.provide(ProjectConfig.Live))
|
|
7121
|
+
).pipe(Command4.withDescription("Stream CloudWatch logs for a handler. Supports --tail for live tailing and --since for time range"));
|
|
6933
7122
|
|
|
6934
7123
|
// src/cli/commands/layer.ts
|
|
6935
7124
|
import { Command as Command5, Options as Options4 } from "@effect/cli";
|
|
6936
|
-
import { Effect as
|
|
6937
|
-
import * as
|
|
7125
|
+
import { Effect as Effect43, Console as Console7 } from "effect";
|
|
7126
|
+
import * as path10 from "path";
|
|
6938
7127
|
import * as fs5 from "fs";
|
|
6939
7128
|
var buildOption = Options4.boolean("build").pipe(
|
|
6940
7129
|
Options4.withDescription("Build layer directory locally (for debugging)")
|
|
@@ -6942,22 +7131,28 @@ var buildOption = Options4.boolean("build").pipe(
|
|
|
6942
7131
|
var layerCommand = Command5.make(
|
|
6943
7132
|
"layer",
|
|
6944
7133
|
{ build: buildOption, output: outputOption, verbose: verboseOption },
|
|
6945
|
-
({ build: build3, output, verbose }) =>
|
|
6946
|
-
const config = yield*
|
|
6947
|
-
const projectDir = process.cwd();
|
|
7134
|
+
({ build: build3, output, verbose }) => Effect43.gen(function* () {
|
|
7135
|
+
const { config, cwd } = yield* ProjectConfig;
|
|
6948
7136
|
if (build3) {
|
|
6949
|
-
yield* buildLayer(
|
|
7137
|
+
yield* buildLayer(cwd, output, verbose);
|
|
6950
7138
|
} else {
|
|
6951
|
-
yield* showLayerInfo(
|
|
7139
|
+
yield* showLayerInfo(cwd, config?.name, verbose);
|
|
6952
7140
|
}
|
|
6953
|
-
})
|
|
6954
|
-
).pipe(Command5.withDescription("
|
|
6955
|
-
var showLayerInfo = (projectDir, projectName, verbose) =>
|
|
7141
|
+
}).pipe(Effect43.provide(ProjectConfig.Live))
|
|
7142
|
+
).pipe(Command5.withDescription("Inspect or locally build the shared Lambda dependency layer from package.json"));
|
|
7143
|
+
var showLayerInfo = (projectDir, projectName, verbose) => Effect43.gen(function* () {
|
|
6956
7144
|
yield* Console7.log(`
|
|
6957
7145
|
${c.bold("=== Layer Packages Preview ===")}
|
|
6958
7146
|
`);
|
|
7147
|
+
const depWarnings = yield* checkDependencyWarnings(projectDir).pipe(
|
|
7148
|
+
Effect43.catchAll(() => Effect43.succeed([]))
|
|
7149
|
+
);
|
|
7150
|
+
for (const w of depWarnings) {
|
|
7151
|
+
yield* Console7.log(c.yellow(` \u26A0 ${w}`));
|
|
7152
|
+
}
|
|
7153
|
+
if (depWarnings.length > 0) yield* Console7.log("");
|
|
6959
7154
|
const prodDeps = yield* readProductionDependencies(projectDir).pipe(
|
|
6960
|
-
|
|
7155
|
+
Effect43.catchAll(() => Effect43.succeed([]))
|
|
6961
7156
|
);
|
|
6962
7157
|
if (prodDeps.length === 0) {
|
|
6963
7158
|
yield* Console7.log("No production dependencies found in package.json");
|
|
@@ -6969,7 +7164,7 @@ ${c.bold("=== Layer Packages Preview ===")}
|
|
|
6969
7164
|
yield* Console7.log(` ${dep}`);
|
|
6970
7165
|
}
|
|
6971
7166
|
const hash = yield* computeLockfileHash(projectDir).pipe(
|
|
6972
|
-
|
|
7167
|
+
Effect43.catchAll(() => Effect43.succeed(null))
|
|
6973
7168
|
);
|
|
6974
7169
|
if (hash) {
|
|
6975
7170
|
yield* Console7.log(`
|
|
@@ -6977,7 +7172,7 @@ Lockfile hash: ${hash}`);
|
|
|
6977
7172
|
} else {
|
|
6978
7173
|
yield* Console7.log("\nNo lockfile found (package-lock.json, pnpm-lock.yaml, or yarn.lock)");
|
|
6979
7174
|
}
|
|
6980
|
-
const { packages: allPackages, warnings: layerWarnings } = yield*
|
|
7175
|
+
const { packages: allPackages, warnings: layerWarnings } = yield* Effect43.sync(() => collectLayerPackages(projectDir, prodDeps));
|
|
6981
7176
|
if (layerWarnings.length > 0) {
|
|
6982
7177
|
yield* Console7.log(c.yellow(`
|
|
6983
7178
|
Warnings (${layerWarnings.length}):`));
|
|
@@ -7006,10 +7201,10 @@ Total packages for layer ${c.dim(`(${allPackages.length})`)}:`);
|
|
|
7006
7201
|
Layer name: ${projectName}-deps`);
|
|
7007
7202
|
}
|
|
7008
7203
|
});
|
|
7009
|
-
var buildLayer = (projectDir, output, verbose) =>
|
|
7010
|
-
const outputDir =
|
|
7011
|
-
const layerDir =
|
|
7012
|
-
const layerRoot =
|
|
7204
|
+
var buildLayer = (projectDir, output, verbose) => Effect43.gen(function* () {
|
|
7205
|
+
const outputDir = path10.isAbsolute(output) ? output : path10.resolve(projectDir, output);
|
|
7206
|
+
const layerDir = path10.join(outputDir, "nodejs", "node_modules");
|
|
7207
|
+
const layerRoot = path10.join(outputDir, "nodejs");
|
|
7013
7208
|
if (fs5.existsSync(layerRoot)) {
|
|
7014
7209
|
fs5.rmSync(layerRoot, { recursive: true });
|
|
7015
7210
|
}
|
|
@@ -7017,8 +7212,15 @@ var buildLayer = (projectDir, output, verbose) => Effect41.gen(function* () {
|
|
|
7017
7212
|
yield* Console7.log(`
|
|
7018
7213
|
${c.bold("=== Building Layer Locally ===")}
|
|
7019
7214
|
`);
|
|
7215
|
+
const depWarnings = yield* checkDependencyWarnings(projectDir).pipe(
|
|
7216
|
+
Effect43.catchAll(() => Effect43.succeed([]))
|
|
7217
|
+
);
|
|
7218
|
+
for (const w of depWarnings) {
|
|
7219
|
+
yield* Console7.log(c.yellow(` \u26A0 ${w}`));
|
|
7220
|
+
}
|
|
7221
|
+
if (depWarnings.length > 0) yield* Console7.log("");
|
|
7020
7222
|
const prodDeps = yield* readProductionDependencies(projectDir).pipe(
|
|
7021
|
-
|
|
7223
|
+
Effect43.catchAll(() => Effect43.succeed([]))
|
|
7022
7224
|
);
|
|
7023
7225
|
if (prodDeps.length === 0) {
|
|
7024
7226
|
yield* Console7.log("No production dependencies found in package.json");
|
|
@@ -7030,11 +7232,11 @@ ${c.bold("=== Building Layer Locally ===")}
|
|
|
7030
7232
|
yield* Console7.log(` ${dep}`);
|
|
7031
7233
|
}
|
|
7032
7234
|
const hash = yield* computeLockfileHash(projectDir).pipe(
|
|
7033
|
-
|
|
7235
|
+
Effect43.catchAll(() => Effect43.succeed("unknown"))
|
|
7034
7236
|
);
|
|
7035
7237
|
yield* Console7.log(`
|
|
7036
7238
|
Lockfile hash: ${hash}`);
|
|
7037
|
-
const { packages: allPackages, resolvedPaths, warnings: layerWarnings } = yield*
|
|
7239
|
+
const { packages: allPackages, resolvedPaths, warnings: layerWarnings } = yield* Effect43.sync(() => collectLayerPackages(projectDir, prodDeps));
|
|
7038
7240
|
if (layerWarnings.length > 0) {
|
|
7039
7241
|
yield* Console7.log(`
|
|
7040
7242
|
Warnings (${layerWarnings.length}):`);
|
|
@@ -7061,9 +7263,9 @@ Collected ${allPackages.length} packages for layer`);
|
|
|
7061
7263
|
}
|
|
7062
7264
|
continue;
|
|
7063
7265
|
}
|
|
7064
|
-
const destPath =
|
|
7266
|
+
const destPath = path10.join(layerDir, pkgName);
|
|
7065
7267
|
if (pkgName.startsWith("@")) {
|
|
7066
|
-
const scopeDir =
|
|
7268
|
+
const scopeDir = path10.join(layerDir, pkgName.split("/")[0] ?? pkgName);
|
|
7067
7269
|
if (!fs5.existsSync(scopeDir)) {
|
|
7068
7270
|
fs5.mkdirSync(scopeDir, { recursive: true });
|
|
7069
7271
|
}
|
|
@@ -7084,20 +7286,20 @@ To inspect: ls ${layerDir}`);
|
|
|
7084
7286
|
// src/cli/commands/config.ts
|
|
7085
7287
|
import { Args as Args3, Command as Command6 } from "@effect/cli";
|
|
7086
7288
|
import { Prompt } from "@effect/cli";
|
|
7087
|
-
import { Effect as
|
|
7088
|
-
var loadRequiredParams = (projectOpt, stage, region) =>
|
|
7089
|
-
const config = yield*
|
|
7289
|
+
import { Effect as Effect44, Console as Console8, Logger as Logger5, LogLevel as LogLevel5, Option as Option5 } from "effect";
|
|
7290
|
+
var loadRequiredParams = (projectOpt, stage, region) => Effect44.gen(function* () {
|
|
7291
|
+
const { config, projectDir } = yield* ProjectConfig;
|
|
7090
7292
|
const project = Option5.getOrElse(projectOpt, () => config?.name ?? "");
|
|
7091
7293
|
if (!project) {
|
|
7092
7294
|
yield* Console8.error("Error: --project is required (or set 'name' in effortless.config.ts)");
|
|
7093
|
-
return yield*
|
|
7295
|
+
return yield* Effect44.fail(new Error("Missing project name"));
|
|
7094
7296
|
}
|
|
7095
7297
|
const patterns = getPatternsFromConfig(config);
|
|
7096
7298
|
if (!patterns) {
|
|
7097
7299
|
yield* Console8.error("Error: No 'handlers' patterns in config");
|
|
7098
|
-
return yield*
|
|
7300
|
+
return yield* Effect44.fail(new Error("Missing handler patterns"));
|
|
7099
7301
|
}
|
|
7100
|
-
const files = findHandlerFiles(patterns,
|
|
7302
|
+
const files = findHandlerFiles(patterns, projectDir);
|
|
7101
7303
|
const handlers = discoverHandlers(files);
|
|
7102
7304
|
const finalStage = config?.stage ?? stage;
|
|
7103
7305
|
const finalRegion = config?.region ?? region;
|
|
@@ -7107,7 +7309,7 @@ var loadRequiredParams = (projectOpt, stage, region) => Effect42.gen(function* (
|
|
|
7107
7309
|
var listCommand = Command6.make(
|
|
7108
7310
|
"list",
|
|
7109
7311
|
{ project: projectOption, stage: stageOption, region: regionOption, verbose: verboseOption },
|
|
7110
|
-
({ project: projectOpt, stage, region, verbose }) =>
|
|
7312
|
+
({ project: projectOpt, stage, region, verbose }) => Effect44.gen(function* () {
|
|
7111
7313
|
const ctx = yield* loadRequiredParams(projectOpt, stage, region);
|
|
7112
7314
|
const { params } = ctx;
|
|
7113
7315
|
if (params.length === 0) {
|
|
@@ -7115,7 +7317,7 @@ var listCommand = Command6.make(
|
|
|
7115
7317
|
return;
|
|
7116
7318
|
}
|
|
7117
7319
|
const { existing, missing } = yield* checkMissingParams(params).pipe(
|
|
7118
|
-
|
|
7320
|
+
Effect44.provide(clients_exports.makeClients({ ssm: { region: ctx.region } }))
|
|
7119
7321
|
);
|
|
7120
7322
|
yield* Console8.log(`
|
|
7121
7323
|
${c.bold("Config parameters")} ${c.dim(`(${ctx.project} / ${ctx.stage})`)}
|
|
@@ -7138,16 +7340,19 @@ ${c.bold("Config parameters")} ${c.dim(`(${ctx.project} / ${ctx.stage})`)}
|
|
|
7138
7340
|
${c.green("All parameters are set.")}`);
|
|
7139
7341
|
}
|
|
7140
7342
|
yield* Console8.log("");
|
|
7141
|
-
}).pipe(
|
|
7142
|
-
|
|
7343
|
+
}).pipe(
|
|
7344
|
+
Effect44.provide(ProjectConfig.Live),
|
|
7345
|
+
Logger5.withMinimumLogLevel(LogLevel5.Warning)
|
|
7346
|
+
)
|
|
7347
|
+
).pipe(Command6.withDescription("List all declared config parameters and show which are set vs missing"));
|
|
7143
7348
|
var setKeyArg = Args3.text({ name: "key" }).pipe(
|
|
7144
7349
|
Args3.withDescription("SSM parameter key (e.g. stripe/secret-key)")
|
|
7145
7350
|
);
|
|
7146
7351
|
var setCommand = Command6.make(
|
|
7147
7352
|
"set",
|
|
7148
7353
|
{ key: setKeyArg, project: projectOption, stage: stageOption, region: regionOption, verbose: verboseOption },
|
|
7149
|
-
({ key, project: projectOpt, stage, region, verbose }) =>
|
|
7150
|
-
const config = yield*
|
|
7354
|
+
({ key, project: projectOpt, stage, region, verbose }) => Effect44.gen(function* () {
|
|
7355
|
+
const { config } = yield* ProjectConfig;
|
|
7151
7356
|
const project = Option5.getOrElse(projectOpt, () => config?.name ?? "");
|
|
7152
7357
|
if (!project) {
|
|
7153
7358
|
yield* Console8.error("Error: --project is required (or set 'name' in effortless.config.ts)");
|
|
@@ -7164,15 +7369,18 @@ var setCommand = Command6.make(
|
|
|
7164
7369
|
Value: value,
|
|
7165
7370
|
Type: "SecureString",
|
|
7166
7371
|
Overwrite: true
|
|
7167
|
-
}).pipe(
|
|
7372
|
+
}).pipe(Effect44.provide(clients_exports.makeClients({ ssm: { region: finalRegion } })));
|
|
7168
7373
|
yield* Console8.log(`
|
|
7169
7374
|
${c.green("\u2713")} ${c.cyan(ssmPath)} ${c.dim("(SecureString)")}`);
|
|
7170
|
-
}).pipe(
|
|
7171
|
-
|
|
7375
|
+
}).pipe(
|
|
7376
|
+
Effect44.provide(ProjectConfig.Live),
|
|
7377
|
+
Logger5.withMinimumLogLevel(LogLevel5.Warning)
|
|
7378
|
+
)
|
|
7379
|
+
).pipe(Command6.withDescription("Set a config parameter value (stored encrypted in AWS)"));
|
|
7172
7380
|
var configRootCommand = Command6.make(
|
|
7173
7381
|
"config",
|
|
7174
7382
|
{ project: projectOption, stage: stageOption, region: regionOption, verbose: verboseOption },
|
|
7175
|
-
({ project: projectOpt, stage, region, verbose }) =>
|
|
7383
|
+
({ project: projectOpt, stage, region, verbose }) => Effect44.gen(function* () {
|
|
7176
7384
|
const ctx = yield* loadRequiredParams(projectOpt, stage, region);
|
|
7177
7385
|
const { params } = ctx;
|
|
7178
7386
|
if (params.length === 0) {
|
|
@@ -7180,7 +7388,7 @@ var configRootCommand = Command6.make(
|
|
|
7180
7388
|
return;
|
|
7181
7389
|
}
|
|
7182
7390
|
const { missing } = yield* checkMissingParams(params).pipe(
|
|
7183
|
-
|
|
7391
|
+
Effect44.provide(clients_exports.makeClients({ ssm: { region: ctx.region } }))
|
|
7184
7392
|
);
|
|
7185
7393
|
if (missing.length === 0) {
|
|
7186
7394
|
yield* Console8.log(`
|
|
@@ -7205,7 +7413,7 @@ ${c.bold("Missing parameters")} ${c.dim(`(${ctx.project} / ${ctx.stage})`)}
|
|
|
7205
7413
|
Value: value,
|
|
7206
7414
|
Type: "SecureString",
|
|
7207
7415
|
Overwrite: false
|
|
7208
|
-
}).pipe(
|
|
7416
|
+
}).pipe(Effect44.provide(clients_exports.makeClients({ ssm: { region: ctx.region } })));
|
|
7209
7417
|
yield* Console8.log(` ${c.green("\u2713")} created`);
|
|
7210
7418
|
created++;
|
|
7211
7419
|
}
|
|
@@ -7218,9 +7426,12 @@ ${c.bold("Missing parameters")} ${c.dim(`(${ctx.project} / ${ctx.stage})`)}
|
|
|
7218
7426
|
No parameters created.
|
|
7219
7427
|
`);
|
|
7220
7428
|
}
|
|
7221
|
-
}).pipe(
|
|
7429
|
+
}).pipe(
|
|
7430
|
+
Effect44.provide(ProjectConfig.Live),
|
|
7431
|
+
Logger5.withMinimumLogLevel(LogLevel5.Warning)
|
|
7432
|
+
)
|
|
7222
7433
|
).pipe(
|
|
7223
|
-
Command6.withDescription("Manage
|
|
7434
|
+
Command6.withDescription("Manage config values declared via param() in handlers. Run without subcommand to interactively set missing values"),
|
|
7224
7435
|
Command6.withSubcommands([listCommand, setCommand])
|
|
7225
7436
|
);
|
|
7226
7437
|
var configCommand = configRootCommand;
|
|
@@ -7237,6 +7448,7 @@ var cli = Command7.run(mainCommand, {
|
|
|
7237
7448
|
version
|
|
7238
7449
|
});
|
|
7239
7450
|
cli(process.argv).pipe(
|
|
7240
|
-
|
|
7451
|
+
Effect45.provide(NodeContext.layer),
|
|
7452
|
+
Effect45.provide(CliConfig.layer({ showBuiltIns: false, showTypes: false })),
|
|
7241
7453
|
NodeRuntime.runMain
|
|
7242
7454
|
);
|