@wraps.dev/cli 2.12.0 → 2.12.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.js
CHANGED
|
@@ -69,6 +69,7 @@ var init_ci_detection = __esm({
|
|
|
69
69
|
// src/utils/shared/s3-state.ts
|
|
70
70
|
var s3_state_exports = {};
|
|
71
71
|
__export(s3_state_exports, {
|
|
72
|
+
deleteMetadata: () => deleteMetadata,
|
|
72
73
|
downloadMetadata: () => downloadMetadata,
|
|
73
74
|
ensureStateBucket: () => ensureStateBucket,
|
|
74
75
|
getS3BackendUrl: () => getS3BackendUrl,
|
|
@@ -188,6 +189,17 @@ async function uploadMetadata(bucketName, metadata) {
|
|
|
188
189
|
})
|
|
189
190
|
);
|
|
190
191
|
}
|
|
192
|
+
async function deleteMetadata(bucketName, accountId, region) {
|
|
193
|
+
const { S3Client: S3Client2, DeleteObjectCommand } = await import("@aws-sdk/client-s3");
|
|
194
|
+
const client = new S3Client2({ region });
|
|
195
|
+
const key = `metadata/${accountId}-${region}.json`;
|
|
196
|
+
await client.send(
|
|
197
|
+
new DeleteObjectCommand({
|
|
198
|
+
Bucket: bucketName,
|
|
199
|
+
Key: key
|
|
200
|
+
})
|
|
201
|
+
);
|
|
202
|
+
}
|
|
191
203
|
async function downloadMetadata(bucketName, accountId, region) {
|
|
192
204
|
const { S3Client: S3Client2, GetObjectCommand: GetObjectCommand2 } = await import("@aws-sdk/client-s3");
|
|
193
205
|
const client = new S3Client2({ region });
|
|
@@ -4156,6 +4168,17 @@ async function deleteConnectionMetadata(accountId, region) {
|
|
|
4156
4168
|
const { unlink } = await import("fs/promises");
|
|
4157
4169
|
await unlink(metadataPath);
|
|
4158
4170
|
}
|
|
4171
|
+
if (process.env.WRAPS_LOCAL_ONLY !== "1") {
|
|
4172
|
+
try {
|
|
4173
|
+
const { stateBucketExists: stateBucketExists2, deleteMetadata: deleteMetadata2, getStateBucketName: getStateBucketName2 } = await Promise.resolve().then(() => (init_s3_state(), s3_state_exports));
|
|
4174
|
+
const bucketExists = await stateBucketExists2(accountId, region);
|
|
4175
|
+
if (bucketExists) {
|
|
4176
|
+
const bucketName = getStateBucketName2(accountId, region);
|
|
4177
|
+
await deleteMetadata2(bucketName, accountId, region);
|
|
4178
|
+
}
|
|
4179
|
+
} catch {
|
|
4180
|
+
}
|
|
4181
|
+
}
|
|
4159
4182
|
}
|
|
4160
4183
|
async function listConnections() {
|
|
4161
4184
|
const connectionsDir = getConnectionsDir();
|
|
@@ -7631,7 +7654,11 @@ var test_exports = {};
|
|
|
7631
7654
|
__export(test_exports, {
|
|
7632
7655
|
emailTest: () => emailTest
|
|
7633
7656
|
});
|
|
7634
|
-
import {
|
|
7657
|
+
import {
|
|
7658
|
+
GetEmailIdentityCommand as GetEmailIdentityCommand3,
|
|
7659
|
+
SESv2Client as SESv2Client5,
|
|
7660
|
+
SendEmailCommand
|
|
7661
|
+
} from "@aws-sdk/client-sesv2";
|
|
7635
7662
|
import * as clack21 from "@clack/prompts";
|
|
7636
7663
|
import pc22 from "picocolors";
|
|
7637
7664
|
async function emailTest(options) {
|
|
@@ -7736,11 +7763,35 @@ Run ${pc22.cyan("wraps email init")} to set up a domain.
|
|
|
7736
7763
|
}
|
|
7737
7764
|
}
|
|
7738
7765
|
const fromEmail = `test@${domain}`;
|
|
7766
|
+
const sesClient = new SESv2Client5({ region });
|
|
7767
|
+
try {
|
|
7768
|
+
const identityResponse = await sesClient.send(
|
|
7769
|
+
new GetEmailIdentityCommand3({ EmailIdentity: domain })
|
|
7770
|
+
);
|
|
7771
|
+
if (!identityResponse.VerifiedForSendingStatus) {
|
|
7772
|
+
progress.stop();
|
|
7773
|
+
const dkimStatus = identityResponse.DkimAttributes?.Status || "PENDING";
|
|
7774
|
+
clack21.log.error(
|
|
7775
|
+
`Sending domain ${pc22.cyan(domain)} is not yet verified (DKIM: ${dkimStatus})`
|
|
7776
|
+
);
|
|
7777
|
+
console.log(
|
|
7778
|
+
"\nDKIM DNS records need to propagate before you can send emails."
|
|
7779
|
+
);
|
|
7780
|
+
console.log("This typically takes a few minutes after deployment.\n");
|
|
7781
|
+
console.log(
|
|
7782
|
+
`Run ${pc22.cyan(`wraps email domains verify --domain ${domain}`)} to check DNS status.
|
|
7783
|
+
`
|
|
7784
|
+
);
|
|
7785
|
+
process.exit(1);
|
|
7786
|
+
return;
|
|
7787
|
+
}
|
|
7788
|
+
} catch (identityError) {
|
|
7789
|
+
}
|
|
7739
7790
|
try {
|
|
7740
7791
|
const messageId = await progress.execute(
|
|
7741
7792
|
`Sending test email to ${toEmail}`,
|
|
7742
7793
|
async () => {
|
|
7743
|
-
const client =
|
|
7794
|
+
const client = sesClient;
|
|
7744
7795
|
const response = await client.send(
|
|
7745
7796
|
new SendEmailCommand({
|
|
7746
7797
|
FromEmailAddress: fromEmail,
|
|
@@ -7806,12 +7857,33 @@ Run ${pc22.cyan("wraps email init")} to set up a domain.
|
|
|
7806
7857
|
});
|
|
7807
7858
|
if (errorName === "MessageRejected" || errorMessage.includes("MessageRejected")) {
|
|
7808
7859
|
if (errorMessage.includes("not verified")) {
|
|
7809
|
-
|
|
7810
|
-
|
|
7811
|
-
console.log(
|
|
7812
|
-
`Simulator addresses always work: ${pc22.cyan("success@simulator.amazonses.com")}
|
|
7813
|
-
`
|
|
7860
|
+
const failedIdentityMatch = errorMessage.match(
|
|
7861
|
+
/identities failed the check.*?:\s*(.+)/i
|
|
7814
7862
|
);
|
|
7863
|
+
const failedIdentity = failedIdentityMatch?.[1]?.trim();
|
|
7864
|
+
const isFromDomainFailure = failedIdentity && (failedIdentity === fromEmail || failedIdentity.endsWith(`@${domain}`) || failedIdentity === domain);
|
|
7865
|
+
if (isFromDomainFailure) {
|
|
7866
|
+
clack21.log.error(
|
|
7867
|
+
`Sending domain ${pc22.cyan(domain)} is not yet verified`
|
|
7868
|
+
);
|
|
7869
|
+
console.log(
|
|
7870
|
+
"\nDKIM DNS records need to propagate before you can send emails."
|
|
7871
|
+
);
|
|
7872
|
+
console.log("This typically takes a few minutes after deployment.\n");
|
|
7873
|
+
console.log(
|
|
7874
|
+
`Run ${pc22.cyan(`wraps email domains verify --domain ${domain}`)} to check DNS status.
|
|
7875
|
+
`
|
|
7876
|
+
);
|
|
7877
|
+
} else {
|
|
7878
|
+
clack21.log.error("Email address is not verified");
|
|
7879
|
+
console.log(
|
|
7880
|
+
"\nIn sandbox mode, recipient addresses must be verified."
|
|
7881
|
+
);
|
|
7882
|
+
console.log(
|
|
7883
|
+
`Simulator addresses always work: ${pc22.cyan("success@simulator.amazonses.com")}
|
|
7884
|
+
`
|
|
7885
|
+
);
|
|
7886
|
+
}
|
|
7815
7887
|
} else {
|
|
7816
7888
|
clack21.log.error(`Email rejected: ${errorMessage}`);
|
|
7817
7889
|
}
|
|
@@ -8243,7 +8315,7 @@ var init_dynamodb_metrics = __esm({
|
|
|
8243
8315
|
// src/cli.ts
|
|
8244
8316
|
init_esm_shims();
|
|
8245
8317
|
import { readFileSync as readFileSync3 } from "fs";
|
|
8246
|
-
import { dirname as dirname3, join as
|
|
8318
|
+
import { dirname as dirname3, join as join16 } from "path";
|
|
8247
8319
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
8248
8320
|
import * as clack47 from "@clack/prompts";
|
|
8249
8321
|
import args from "args";
|
|
@@ -15765,10 +15837,10 @@ async function eventDestinationExists(configSetName, eventDestName, region) {
|
|
|
15765
15837
|
}
|
|
15766
15838
|
async function emailIdentityExists(emailIdentity, region) {
|
|
15767
15839
|
try {
|
|
15768
|
-
const { SESv2Client: SESv2Client8, GetEmailIdentityCommand:
|
|
15840
|
+
const { SESv2Client: SESv2Client8, GetEmailIdentityCommand: GetEmailIdentityCommand6 } = await import("@aws-sdk/client-sesv2");
|
|
15769
15841
|
const ses = new SESv2Client8({ region });
|
|
15770
15842
|
await ses.send(
|
|
15771
|
-
new
|
|
15843
|
+
new GetEmailIdentityCommand6({ EmailIdentity: emailIdentity })
|
|
15772
15844
|
);
|
|
15773
15845
|
return true;
|
|
15774
15846
|
} catch (error) {
|
|
@@ -15808,9 +15880,8 @@ async function createSESResources(config2) {
|
|
|
15808
15880
|
}
|
|
15809
15881
|
const configSetName = "wraps-email-tracking";
|
|
15810
15882
|
const exists = await configurationSetExists(configSetName, config2.region);
|
|
15811
|
-
const configSet = exists ? new aws8.sesv2.ConfigurationSet(configSetName, configSetOptions, {
|
|
15883
|
+
const configSet = exists && !config2.skipResourceImports ? new aws8.sesv2.ConfigurationSet(configSetName, configSetOptions, {
|
|
15812
15884
|
import: configSetName
|
|
15813
|
-
// Import existing configuration set
|
|
15814
15885
|
}) : new aws8.sesv2.ConfigurationSet(configSetName, configSetOptions);
|
|
15815
15886
|
const defaultEventBus = aws8.cloudwatch.getEventBusOutput({
|
|
15816
15887
|
name: "default"
|
|
@@ -15843,9 +15914,9 @@ async function createSESResources(config2) {
|
|
|
15843
15914
|
}
|
|
15844
15915
|
},
|
|
15845
15916
|
{
|
|
15846
|
-
// Import existing resource if it already exists in AWS
|
|
15847
|
-
//
|
|
15848
|
-
import: config2.importExistingEventDestination ? `wraps-email-tracking|${eventDestName}` : void 0
|
|
15917
|
+
// Import existing resource if it already exists in AWS but not in Pulumi state.
|
|
15918
|
+
// Skip when skipResourceImports is true (resource already tracked in state).
|
|
15919
|
+
import: config2.importExistingEventDestination && !config2.skipResourceImports ? `wraps-email-tracking|${eventDestName}` : void 0
|
|
15849
15920
|
}
|
|
15850
15921
|
);
|
|
15851
15922
|
}
|
|
@@ -15857,12 +15928,11 @@ async function createSESResources(config2) {
|
|
|
15857
15928
|
config2.domain,
|
|
15858
15929
|
config2.region
|
|
15859
15930
|
);
|
|
15860
|
-
domainIdentity = identityExists ? new aws8.sesv2.EmailIdentity(
|
|
15931
|
+
domainIdentity = identityExists && !config2.skipResourceImports ? new aws8.sesv2.EmailIdentity(
|
|
15861
15932
|
"wraps-email-domain",
|
|
15862
15933
|
{
|
|
15863
15934
|
emailIdentity: config2.domain,
|
|
15864
15935
|
configurationSetName: configSet.configurationSetName,
|
|
15865
|
-
// Link configuration set to domain
|
|
15866
15936
|
dkimSigningAttributes: {
|
|
15867
15937
|
nextSigningKeyLength: "RSA_2048_BIT"
|
|
15868
15938
|
},
|
|
@@ -15872,7 +15942,6 @@ async function createSESResources(config2) {
|
|
|
15872
15942
|
},
|
|
15873
15943
|
{
|
|
15874
15944
|
import: config2.domain
|
|
15875
|
-
// Import existing identity
|
|
15876
15945
|
}
|
|
15877
15946
|
) : new aws8.sesv2.EmailIdentity("wraps-email-domain", {
|
|
15878
15947
|
emailIdentity: config2.domain,
|
|
@@ -16106,7 +16175,7 @@ async function deployEmailStack(config2) {
|
|
|
16106
16175
|
}
|
|
16107
16176
|
let sesResources;
|
|
16108
16177
|
if (emailConfig.tracking?.enabled || emailConfig.eventTracking?.enabled) {
|
|
16109
|
-
const shouldImportEventDest = emailConfig.eventTracking?.enabled && await eventDestinationExists(
|
|
16178
|
+
const shouldImportEventDest = !config2.skipResourceImports && emailConfig.eventTracking?.enabled && await eventDestinationExists(
|
|
16110
16179
|
"wraps-email-tracking",
|
|
16111
16180
|
"wraps-email-eventbridge",
|
|
16112
16181
|
config2.region
|
|
@@ -16133,8 +16202,10 @@ async function deployEmailStack(config2) {
|
|
|
16133
16202
|
// Pass flag to create EventBridge destination
|
|
16134
16203
|
tlsRequired: emailConfig.tlsRequired,
|
|
16135
16204
|
// Require TLS encryption for all emails
|
|
16136
|
-
importExistingEventDestination: shouldImportEventDest
|
|
16205
|
+
importExistingEventDestination: shouldImportEventDest,
|
|
16137
16206
|
// Import if exists to avoid AlreadyExistsException
|
|
16207
|
+
skipResourceImports: config2.skipResourceImports
|
|
16208
|
+
// Skip import flags when resources already in Pulumi state
|
|
16138
16209
|
});
|
|
16139
16210
|
}
|
|
16140
16211
|
let dynamoTables;
|
|
@@ -16484,6 +16555,7 @@ ${pc17.bold("Current Configuration:")}
|
|
|
16484
16555
|
await stack.setConfig("aws:region", { value: region });
|
|
16485
16556
|
await stack.refresh({ onOutput: () => {
|
|
16486
16557
|
} });
|
|
16558
|
+
stackConfig.skipResourceImports = true;
|
|
16487
16559
|
const upResult = await stack.up({ onOutput: () => {
|
|
16488
16560
|
} });
|
|
16489
16561
|
const pulumiOutputs = upResult.outputs;
|
|
@@ -17178,10 +17250,10 @@ async function withTimeout(promise, timeoutMs, operation) {
|
|
|
17178
17250
|
// src/commands/email/destroy.ts
|
|
17179
17251
|
async function getEmailIdentityInfo(domain, region) {
|
|
17180
17252
|
try {
|
|
17181
|
-
const { SESv2Client: SESv2Client8, GetEmailIdentityCommand:
|
|
17253
|
+
const { SESv2Client: SESv2Client8, GetEmailIdentityCommand: GetEmailIdentityCommand6 } = await import("@aws-sdk/client-sesv2");
|
|
17182
17254
|
const ses = new SESv2Client8({ region });
|
|
17183
17255
|
const response = await ses.send(
|
|
17184
|
-
new
|
|
17256
|
+
new GetEmailIdentityCommand6({ EmailIdentity: domain })
|
|
17185
17257
|
);
|
|
17186
17258
|
return {
|
|
17187
17259
|
dkimTokens: response.DkimAttributes?.Tokens || [],
|
|
@@ -17347,6 +17419,7 @@ async function emailDestroy(options) {
|
|
|
17347
17419
|
clack18.log.info("You may need to delete them manually from Route53");
|
|
17348
17420
|
}
|
|
17349
17421
|
}
|
|
17422
|
+
let destroyFailed = false;
|
|
17350
17423
|
try {
|
|
17351
17424
|
await progress.execute(
|
|
17352
17425
|
"Destroying email infrastructure (this may take 2-3 minutes)",
|
|
@@ -17362,10 +17435,11 @@ async function emailDestroy(options) {
|
|
|
17362
17435
|
} catch {
|
|
17363
17436
|
throw new Error("No email infrastructure found to destroy");
|
|
17364
17437
|
}
|
|
17438
|
+
await stack.refresh({ onOutput: () => {
|
|
17439
|
+
} });
|
|
17365
17440
|
await withTimeout(
|
|
17366
17441
|
stack.destroy({ onOutput: () => {
|
|
17367
|
-
} }),
|
|
17368
|
-
// Suppress Pulumi output
|
|
17442
|
+
}, continueOnError: true }),
|
|
17369
17443
|
DEFAULT_PULUMI_TIMEOUT_MS,
|
|
17370
17444
|
"Pulumi destroy"
|
|
17371
17445
|
);
|
|
@@ -17386,36 +17460,51 @@ async function emailDestroy(options) {
|
|
|
17386
17460
|
}
|
|
17387
17461
|
trackError("DESTROY_FAILED", "email destroy", { step: "destroy" });
|
|
17388
17462
|
clack18.log.error("Email infrastructure destruction failed");
|
|
17389
|
-
|
|
17463
|
+
destroyFailed = true;
|
|
17464
|
+
clack18.log.warn(
|
|
17465
|
+
"Some resources may not have been fully removed. You can re-run this command or clean up manually in the AWS console."
|
|
17466
|
+
);
|
|
17390
17467
|
}
|
|
17391
17468
|
await deleteConnectionMetadata(identity.accountId, region);
|
|
17392
17469
|
progress.stop();
|
|
17393
|
-
|
|
17394
|
-
|
|
17395
|
-
|
|
17396
|
-
|
|
17397
|
-
|
|
17398
|
-
|
|
17399
|
-
|
|
17470
|
+
if (destroyFailed) {
|
|
17471
|
+
clack18.outro(
|
|
17472
|
+
pc19.yellow("Email infrastructure partially removed. Metadata cleaned up.")
|
|
17473
|
+
);
|
|
17474
|
+
console.log(
|
|
17475
|
+
`
|
|
17476
|
+
Run ${pc19.cyan("wraps email init")} to redeploy, or clean up remaining resources in the AWS console.
|
|
17477
|
+
`
|
|
17478
|
+
);
|
|
17479
|
+
} else {
|
|
17480
|
+
const deletedItems = ["AWS infrastructure"];
|
|
17481
|
+
if (shouldCleanDNS && hostedZone) {
|
|
17482
|
+
deletedItems.push("Route53 DNS records");
|
|
17483
|
+
}
|
|
17484
|
+
clack18.outro(pc19.green("Email infrastructure has been removed"));
|
|
17485
|
+
if (domain) {
|
|
17486
|
+
console.log(`
|
|
17400
17487
|
${pc19.bold("Cleaned up:")}`);
|
|
17401
|
-
|
|
17402
|
-
|
|
17488
|
+
for (const item of deletedItems) {
|
|
17489
|
+
console.log(` ${pc19.green("\u2713")} ${item}`);
|
|
17490
|
+
}
|
|
17491
|
+
console.log(
|
|
17492
|
+
`
|
|
17493
|
+
${pc19.dim("Note: SPF record was not deleted. Remove 'include:amazonses.com' manually if needed.")}`
|
|
17494
|
+
);
|
|
17403
17495
|
}
|
|
17404
17496
|
console.log(
|
|
17405
17497
|
`
|
|
17406
|
-
${pc19.dim("Note: SPF record was not deleted. Remove 'include:amazonses.com' manually if needed.")}`
|
|
17407
|
-
);
|
|
17408
|
-
}
|
|
17409
|
-
console.log(
|
|
17410
|
-
`
|
|
17411
17498
|
Run ${pc19.cyan("wraps email init")} to deploy infrastructure again.
|
|
17412
17499
|
`
|
|
17413
|
-
|
|
17500
|
+
);
|
|
17501
|
+
}
|
|
17414
17502
|
trackServiceRemoved("email", {
|
|
17415
17503
|
reason: "user_initiated",
|
|
17416
17504
|
region,
|
|
17417
17505
|
duration_ms: Date.now() - startTime,
|
|
17418
|
-
dns_cleaned: shouldCleanDNS
|
|
17506
|
+
dns_cleaned: shouldCleanDNS,
|
|
17507
|
+
partial_failure: destroyFailed
|
|
17419
17508
|
});
|
|
17420
17509
|
}
|
|
17421
17510
|
|
|
@@ -19972,7 +20061,7 @@ Run ${pc25.cyan("wraps email init")} to deploy email infrastructure.
|
|
|
19972
20061
|
throw error;
|
|
19973
20062
|
}
|
|
19974
20063
|
const domains = await listSESDomains(region);
|
|
19975
|
-
const { SESv2Client: SESv2Client8, GetEmailIdentityCommand:
|
|
20064
|
+
const { SESv2Client: SESv2Client8, GetEmailIdentityCommand: GetEmailIdentityCommand6 } = await import("@aws-sdk/client-sesv2");
|
|
19976
20065
|
const sesv2Client = new SESv2Client8({ region });
|
|
19977
20066
|
const metadata = await loadConnectionMetadata(identity.accountId, region);
|
|
19978
20067
|
const trackedDomains = metadata ? getAllTrackedDomains(metadata) : [];
|
|
@@ -19982,7 +20071,7 @@ Run ${pc25.cyan("wraps email init")} to deploy email infrastructure.
|
|
|
19982
20071
|
const tracked = trackedMap.get(d.domain);
|
|
19983
20072
|
try {
|
|
19984
20073
|
const sesIdentity = await sesv2Client.send(
|
|
19985
|
-
new
|
|
20074
|
+
new GetEmailIdentityCommand6({ EmailIdentity: d.domain })
|
|
19986
20075
|
);
|
|
19987
20076
|
return {
|
|
19988
20077
|
domain: d.domain,
|
|
@@ -20853,20 +20942,56 @@ function renderErrorPage(err) {
|
|
|
20853
20942
|
init_esm_shims();
|
|
20854
20943
|
init_events();
|
|
20855
20944
|
import { createHash } from "crypto";
|
|
20856
|
-
import { existsSync as
|
|
20857
|
-
import { mkdir as
|
|
20858
|
-
import { join as
|
|
20945
|
+
import { existsSync as existsSync11 } from "fs";
|
|
20946
|
+
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile7 } from "fs/promises";
|
|
20947
|
+
import { join as join12 } from "path";
|
|
20859
20948
|
import * as clack27 from "@clack/prompts";
|
|
20860
20949
|
import pc28 from "picocolors";
|
|
20861
20950
|
init_config();
|
|
20862
20951
|
init_errors();
|
|
20952
|
+
|
|
20953
|
+
// src/utils/shared/lockfile.ts
|
|
20954
|
+
init_esm_shims();
|
|
20955
|
+
import { existsSync as existsSync10 } from "fs";
|
|
20956
|
+
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile6 } from "fs/promises";
|
|
20957
|
+
import { join as join11 } from "path";
|
|
20958
|
+
function getLockfilePath(wrapsDir) {
|
|
20959
|
+
return join11(wrapsDir, ".wraps", "lockfile.json");
|
|
20960
|
+
}
|
|
20961
|
+
async function loadLockfile(wrapsDir) {
|
|
20962
|
+
const path3 = getLockfilePath(wrapsDir);
|
|
20963
|
+
if (!existsSync10(path3)) {
|
|
20964
|
+
return { version: "1.0.0", lastSync: "", templates: {}, workflows: {} };
|
|
20965
|
+
}
|
|
20966
|
+
try {
|
|
20967
|
+
const content = await readFile4(path3, "utf-8");
|
|
20968
|
+
const parsed = JSON.parse(content);
|
|
20969
|
+
if (!parsed.templates) {
|
|
20970
|
+
parsed.templates = {};
|
|
20971
|
+
}
|
|
20972
|
+
if (!parsed.workflows) {
|
|
20973
|
+
parsed.workflows = {};
|
|
20974
|
+
}
|
|
20975
|
+
return parsed;
|
|
20976
|
+
} catch {
|
|
20977
|
+
return { version: "1.0.0", lastSync: "", templates: {}, workflows: {} };
|
|
20978
|
+
}
|
|
20979
|
+
}
|
|
20980
|
+
async function saveLockfile(wrapsDir, lockfile) {
|
|
20981
|
+
const path3 = getLockfilePath(wrapsDir);
|
|
20982
|
+
const dir = join11(path3, "..");
|
|
20983
|
+
await mkdir4(dir, { recursive: true });
|
|
20984
|
+
await writeFile6(path3, JSON.stringify(lockfile, null, 2), "utf-8");
|
|
20985
|
+
}
|
|
20986
|
+
|
|
20987
|
+
// src/commands/email/templates/push.ts
|
|
20863
20988
|
init_output();
|
|
20864
20989
|
async function templatesPush(options) {
|
|
20865
20990
|
const startTime = Date.now();
|
|
20866
20991
|
const cwd = process.cwd();
|
|
20867
|
-
const wrapsDir =
|
|
20868
|
-
const configPath =
|
|
20869
|
-
if (!
|
|
20992
|
+
const wrapsDir = join12(cwd, "wraps");
|
|
20993
|
+
const configPath = join12(wrapsDir, "wraps.config.ts");
|
|
20994
|
+
if (!existsSync11(configPath)) {
|
|
20870
20995
|
throw errors.wrapsConfigNotFound();
|
|
20871
20996
|
}
|
|
20872
20997
|
if (!options.json) {
|
|
@@ -20876,8 +21001,8 @@ async function templatesPush(options) {
|
|
|
20876
21001
|
progress.start("Loading configuration");
|
|
20877
21002
|
const config2 = await loadWrapsConfig(wrapsDir);
|
|
20878
21003
|
progress.succeed("Configuration loaded");
|
|
20879
|
-
const templatesDir =
|
|
20880
|
-
if (!
|
|
21004
|
+
const templatesDir = join12(wrapsDir, config2.templatesDir || "./templates");
|
|
21005
|
+
if (!existsSync11(templatesDir)) {
|
|
20881
21006
|
throw errors.wrapsConfigNotFound();
|
|
20882
21007
|
}
|
|
20883
21008
|
const templateFiles = await discoverTemplates(templatesDir, options.template);
|
|
@@ -20887,8 +21012,7 @@ async function templatesPush(options) {
|
|
|
20887
21012
|
}
|
|
20888
21013
|
return;
|
|
20889
21014
|
}
|
|
20890
|
-
const
|
|
20891
|
-
const lockfile = await loadLockfile(lockfilePath);
|
|
21015
|
+
const lockfile = await loadLockfile(wrapsDir);
|
|
20892
21016
|
const token = await resolveTokenAsync({ token: options.token });
|
|
20893
21017
|
const remoteTemplateSlugs = await fetchRemoteTemplateSlugs(token, progress);
|
|
20894
21018
|
const compiled = [];
|
|
@@ -20896,8 +21020,8 @@ async function templatesPush(options) {
|
|
|
20896
21020
|
const compileErrors = [];
|
|
20897
21021
|
for (const file of templateFiles) {
|
|
20898
21022
|
const slug = file.replace(/\.tsx?$/, "");
|
|
20899
|
-
const filePath =
|
|
20900
|
-
const source = await
|
|
21023
|
+
const filePath = join12(templatesDir, file);
|
|
21024
|
+
const source = await readFile5(filePath, "utf-8");
|
|
20901
21025
|
const sourceHash = sha256(source);
|
|
20902
21026
|
const localHashMatches = lockfile.templates[slug]?.localHash === sourceHash;
|
|
20903
21027
|
const existsRemotely = remoteTemplateSlugs === null || remoteTemplateSlugs.has(slug);
|
|
@@ -20976,27 +21100,25 @@ async function templatesPush(options) {
|
|
|
20976
21100
|
}
|
|
20977
21101
|
return;
|
|
20978
21102
|
}
|
|
20979
|
-
await pushToSES(compiled, progress);
|
|
20980
|
-
const apiResults = await pushToAPI(
|
|
20981
|
-
compiled,
|
|
20982
|
-
token,
|
|
20983
|
-
config2.org,
|
|
20984
|
-
progress,
|
|
20985
|
-
options.force
|
|
20986
|
-
);
|
|
21103
|
+
const sesResults = await pushToSES(compiled, progress);
|
|
21104
|
+
const apiResults = await pushToAPI(compiled, token, progress, options.force);
|
|
20987
21105
|
for (const t of compiled) {
|
|
21106
|
+
const sesOk = sesResults.find((r) => r.slug === t.slug)?.success;
|
|
20988
21107
|
const apiResult = apiResults.find((r) => r.slug === t.slug);
|
|
20989
|
-
|
|
20990
|
-
|
|
20991
|
-
|
|
20992
|
-
|
|
20993
|
-
|
|
20994
|
-
|
|
20995
|
-
|
|
21108
|
+
const apiOk = apiResult?.success;
|
|
21109
|
+
if (sesOk || apiOk) {
|
|
21110
|
+
lockfile.templates[t.slug] = {
|
|
21111
|
+
id: apiResult?.id,
|
|
21112
|
+
localHash: t.sourceHash,
|
|
21113
|
+
remoteHash: t.sourceHash,
|
|
21114
|
+
sesTemplateName: t.sesTemplateName,
|
|
21115
|
+
lastPushed: (/* @__PURE__ */ new Date()).toISOString()
|
|
21116
|
+
};
|
|
21117
|
+
}
|
|
20996
21118
|
}
|
|
20997
21119
|
lockfile.lastSync = (/* @__PURE__ */ new Date()).toISOString();
|
|
20998
21120
|
lockfile.org = config2.org;
|
|
20999
|
-
await saveLockfile(
|
|
21121
|
+
await saveLockfile(wrapsDir, lockfile);
|
|
21000
21122
|
if (options.json) {
|
|
21001
21123
|
console.log(
|
|
21002
21124
|
JSON.stringify({
|
|
@@ -21054,11 +21176,11 @@ async function compileTemplate(filePath, slug, source, sourceHash, wrapsDir) {
|
|
|
21054
21176
|
}
|
|
21055
21177
|
});
|
|
21056
21178
|
const bundledCode = result.outputFiles[0].text;
|
|
21057
|
-
const projectRoot =
|
|
21058
|
-
const tmpDir =
|
|
21059
|
-
await
|
|
21060
|
-
const tmpPath =
|
|
21061
|
-
await
|
|
21179
|
+
const projectRoot = join12(wrapsDir, "..");
|
|
21180
|
+
const tmpDir = join12(projectRoot, "node_modules", ".wraps-compiled");
|
|
21181
|
+
await mkdir5(tmpDir, { recursive: true });
|
|
21182
|
+
const tmpPath = join12(tmpDir, `${slug}.mjs`);
|
|
21183
|
+
await writeFile7(tmpPath, bundledCode, "utf-8");
|
|
21062
21184
|
const mod = await import(tmpPath);
|
|
21063
21185
|
const Component = mod.default;
|
|
21064
21186
|
const subject = mod.subject || slug;
|
|
@@ -21156,9 +21278,9 @@ async function pushToSES(templates, progress) {
|
|
|
21156
21278
|
UpdateTemplateCommand
|
|
21157
21279
|
} = await import("@aws-sdk/client-ses");
|
|
21158
21280
|
const ses = new SESClient5({ region });
|
|
21159
|
-
|
|
21160
|
-
|
|
21161
|
-
|
|
21281
|
+
const settled = await Promise.allSettled(
|
|
21282
|
+
templates.map(async (t) => {
|
|
21283
|
+
progress.start(`Pushing ${pc28.cyan(t.slug)} to SES`);
|
|
21162
21284
|
const templateData = {
|
|
21163
21285
|
TemplateName: t.sesTemplateName,
|
|
21164
21286
|
SubjectPart: t.subject,
|
|
@@ -21182,12 +21304,18 @@ async function pushToSES(templates, progress) {
|
|
|
21182
21304
|
} else {
|
|
21183
21305
|
await ses.send(new CreateTemplateCommand({ Template: templateData }));
|
|
21184
21306
|
}
|
|
21185
|
-
results.push({ slug: t.slug, success: true });
|
|
21186
21307
|
progress.succeed(`Pushed ${pc28.cyan(t.slug)} to SES`);
|
|
21187
|
-
|
|
21188
|
-
|
|
21189
|
-
|
|
21190
|
-
|
|
21308
|
+
return { slug: t.slug };
|
|
21309
|
+
})
|
|
21310
|
+
);
|
|
21311
|
+
for (let i = 0; i < templates.length; i++) {
|
|
21312
|
+
const result = settled[i];
|
|
21313
|
+
if (result.status === "fulfilled") {
|
|
21314
|
+
results.push({ slug: result.value.slug, success: true });
|
|
21315
|
+
} else {
|
|
21316
|
+
const msg = result.reason instanceof Error ? result.reason.message : String(result.reason);
|
|
21317
|
+
results.push({ slug: templates[i].slug, success: false });
|
|
21318
|
+
progress.fail(`SES push failed for ${templates[i].slug}: ${msg}`);
|
|
21191
21319
|
}
|
|
21192
21320
|
}
|
|
21193
21321
|
return results;
|
|
@@ -21219,7 +21347,7 @@ async function fetchRemoteTemplateSlugs(token, progress) {
|
|
|
21219
21347
|
return null;
|
|
21220
21348
|
}
|
|
21221
21349
|
}
|
|
21222
|
-
async function pushToAPI(templates, token,
|
|
21350
|
+
async function pushToAPI(templates, token, progress, force) {
|
|
21223
21351
|
if (!token) {
|
|
21224
21352
|
progress.info(
|
|
21225
21353
|
"No API token \u2014 skipping dashboard sync. Run: wraps auth login"
|
|
@@ -21341,22 +21469,6 @@ async function pushToAPI(templates, token, _org, progress, force) {
|
|
|
21341
21469
|
}
|
|
21342
21470
|
return results;
|
|
21343
21471
|
}
|
|
21344
|
-
async function loadLockfile(path3) {
|
|
21345
|
-
if (!existsSync10(path3)) {
|
|
21346
|
-
return { version: "1.0.0", lastSync: "", templates: {} };
|
|
21347
|
-
}
|
|
21348
|
-
try {
|
|
21349
|
-
const content = await readFile4(path3, "utf-8");
|
|
21350
|
-
return JSON.parse(content);
|
|
21351
|
-
} catch {
|
|
21352
|
-
return { version: "1.0.0", lastSync: "", templates: {} };
|
|
21353
|
-
}
|
|
21354
|
-
}
|
|
21355
|
-
async function saveLockfile(path3, lockfile) {
|
|
21356
|
-
const dir = join11(path3, "..");
|
|
21357
|
-
await mkdir4(dir, { recursive: true });
|
|
21358
|
-
await writeFile6(path3, JSON.stringify(lockfile, null, 2), "utf-8");
|
|
21359
|
-
}
|
|
21360
21472
|
function sha256(content) {
|
|
21361
21473
|
return createHash("sha256").update(content).digest("hex");
|
|
21362
21474
|
}
|
|
@@ -22696,6 +22808,7 @@ ${pc29.bold("Cost Impact:")}`);
|
|
|
22696
22808
|
await stack.setConfig("aws:region", { value: region });
|
|
22697
22809
|
await stack.refresh({ onOutput: () => {
|
|
22698
22810
|
} });
|
|
22811
|
+
stackConfig.skipResourceImports = true;
|
|
22699
22812
|
const upResult = await stack.up({ onOutput: () => {
|
|
22700
22813
|
} });
|
|
22701
22814
|
const pulumiOutputs = upResult.outputs;
|
|
@@ -23085,9 +23198,8 @@ ${pc29.green("\u2713")} ${pc29.bold("Upgrade complete!")}
|
|
|
23085
23198
|
// src/commands/email/workflows/push.ts
|
|
23086
23199
|
init_esm_shims();
|
|
23087
23200
|
init_events();
|
|
23088
|
-
import { existsSync as
|
|
23089
|
-
import {
|
|
23090
|
-
import { join as join13 } from "path";
|
|
23201
|
+
import { existsSync as existsSync13 } from "fs";
|
|
23202
|
+
import { join as join14 } from "path";
|
|
23091
23203
|
import * as clack29 from "@clack/prompts";
|
|
23092
23204
|
import pc30 from "picocolors";
|
|
23093
23205
|
|
|
@@ -23276,11 +23388,11 @@ function assignPositions(steps, transitions) {
|
|
|
23276
23388
|
// src/utils/email/workflow-ts.ts
|
|
23277
23389
|
init_esm_shims();
|
|
23278
23390
|
import { createHash as createHash2 } from "crypto";
|
|
23279
|
-
import { existsSync as
|
|
23280
|
-
import { mkdir as
|
|
23281
|
-
import { basename, join as
|
|
23391
|
+
import { existsSync as existsSync12 } from "fs";
|
|
23392
|
+
import { mkdir as mkdir6, readdir as readdir3, readFile as readFile6, writeFile as writeFile8 } from "fs/promises";
|
|
23393
|
+
import { basename, join as join13 } from "path";
|
|
23282
23394
|
async function discoverWorkflows(dir, filter) {
|
|
23283
|
-
if (!
|
|
23395
|
+
if (!existsSync12(dir)) {
|
|
23284
23396
|
return [];
|
|
23285
23397
|
}
|
|
23286
23398
|
const entries = await readdir3(dir);
|
|
@@ -23300,11 +23412,11 @@ async function discoverWorkflows(dir, filter) {
|
|
|
23300
23412
|
}
|
|
23301
23413
|
async function parseWorkflowTs(filePath, wrapsDir) {
|
|
23302
23414
|
const { build: build2 } = await import("esbuild");
|
|
23303
|
-
const source = await
|
|
23415
|
+
const source = await readFile6(filePath, "utf-8");
|
|
23304
23416
|
const sourceHash = createHash2("sha256").update(source).digest("hex");
|
|
23305
23417
|
const slug = basename(filePath, ".ts");
|
|
23306
|
-
const shimDir =
|
|
23307
|
-
await
|
|
23418
|
+
const shimDir = join13(wrapsDir, ".wraps", "_shims");
|
|
23419
|
+
await mkdir6(shimDir, { recursive: true });
|
|
23308
23420
|
const clientShimContent = `
|
|
23309
23421
|
// Identity functions for workflow definitions
|
|
23310
23422
|
export const defineWorkflow = (def) => def;
|
|
@@ -23446,8 +23558,8 @@ function durationToSeconds(duration) {
|
|
|
23446
23558
|
return seconds > 0 ? seconds : undefined;
|
|
23447
23559
|
}
|
|
23448
23560
|
`;
|
|
23449
|
-
await
|
|
23450
|
-
|
|
23561
|
+
await writeFile8(
|
|
23562
|
+
join13(shimDir, "wraps-client-shim.mjs"),
|
|
23451
23563
|
clientShimContent,
|
|
23452
23564
|
"utf-8"
|
|
23453
23565
|
);
|
|
@@ -23459,14 +23571,14 @@ function durationToSeconds(duration) {
|
|
|
23459
23571
|
platform: "node",
|
|
23460
23572
|
target: "node20",
|
|
23461
23573
|
alias: {
|
|
23462
|
-
"@wraps.dev/client":
|
|
23574
|
+
"@wraps.dev/client": join13(shimDir, "wraps-client-shim.mjs")
|
|
23463
23575
|
}
|
|
23464
23576
|
});
|
|
23465
23577
|
const bundledCode = result.outputFiles[0].text;
|
|
23466
|
-
const tmpDir =
|
|
23467
|
-
await
|
|
23468
|
-
const tmpPath =
|
|
23469
|
-
await
|
|
23578
|
+
const tmpDir = join13(wrapsDir, ".wraps", "_workflows");
|
|
23579
|
+
await mkdir6(tmpDir, { recursive: true });
|
|
23580
|
+
const tmpPath = join13(tmpDir, `${slug}.mjs`);
|
|
23581
|
+
await writeFile8(tmpPath, bundledCode, "utf-8");
|
|
23470
23582
|
const mod = await import(`${tmpPath}?t=${Date.now()}`);
|
|
23471
23583
|
const definition = mod.default;
|
|
23472
23584
|
if (!definition || typeof definition !== "object") {
|
|
@@ -23817,9 +23929,9 @@ init_output();
|
|
|
23817
23929
|
async function workflowsPush(options) {
|
|
23818
23930
|
const startTime = Date.now();
|
|
23819
23931
|
const cwd = process.cwd();
|
|
23820
|
-
const wrapsDir =
|
|
23821
|
-
const configPath =
|
|
23822
|
-
if (!
|
|
23932
|
+
const wrapsDir = join14(cwd, "wraps");
|
|
23933
|
+
const configPath = join14(wrapsDir, "wraps.config.ts");
|
|
23934
|
+
if (!existsSync13(configPath)) {
|
|
23823
23935
|
throw errors.wrapsConfigNotFound();
|
|
23824
23936
|
}
|
|
23825
23937
|
if (!options.json) {
|
|
@@ -23829,8 +23941,8 @@ async function workflowsPush(options) {
|
|
|
23829
23941
|
progress.start("Loading configuration");
|
|
23830
23942
|
const config2 = await loadWrapsConfig(wrapsDir);
|
|
23831
23943
|
progress.succeed("Configuration loaded");
|
|
23832
|
-
const workflowsDir =
|
|
23833
|
-
if (!
|
|
23944
|
+
const workflowsDir = join14(wrapsDir, config2.workflowsDir || "./workflows");
|
|
23945
|
+
if (!existsSync13(workflowsDir)) {
|
|
23834
23946
|
if (options.json) {
|
|
23835
23947
|
console.log(
|
|
23836
23948
|
JSON.stringify({
|
|
@@ -23859,11 +23971,10 @@ async function workflowsPush(options) {
|
|
|
23859
23971
|
}
|
|
23860
23972
|
return;
|
|
23861
23973
|
}
|
|
23862
|
-
const
|
|
23863
|
-
const
|
|
23864
|
-
const templatesDir = join13(wrapsDir, config2.templatesDir || "./templates");
|
|
23974
|
+
const lockfile = await loadLockfile(wrapsDir);
|
|
23975
|
+
const templatesDir = join14(wrapsDir, config2.templatesDir || "./templates");
|
|
23865
23976
|
let localTemplateSlugs;
|
|
23866
|
-
if (
|
|
23977
|
+
if (existsSync13(templatesDir)) {
|
|
23867
23978
|
const templateFiles = await discoverTemplates(templatesDir);
|
|
23868
23979
|
localTemplateSlugs = new Set(
|
|
23869
23980
|
templateFiles.map((f) => f.replace(/\.tsx?$/, ""))
|
|
@@ -23875,7 +23986,7 @@ async function workflowsPush(options) {
|
|
|
23875
23986
|
const validationErrors = [];
|
|
23876
23987
|
for (const file of workflowFiles) {
|
|
23877
23988
|
const slug = file.replace(/\.ts$/, "");
|
|
23878
|
-
const filePath =
|
|
23989
|
+
const filePath = join14(workflowsDir, file);
|
|
23879
23990
|
progress.start(`Processing ${pc30.cyan(slug)}`);
|
|
23880
23991
|
try {
|
|
23881
23992
|
const parsed = await parseWorkflowTs(filePath, wrapsDir);
|
|
@@ -23998,28 +24109,21 @@ async function workflowsPush(options) {
|
|
|
23998
24109
|
return;
|
|
23999
24110
|
}
|
|
24000
24111
|
const token = await resolveTokenAsync({ token: options.token });
|
|
24001
|
-
const apiResults = await pushToAPI2(
|
|
24002
|
-
toProcess,
|
|
24003
|
-
token,
|
|
24004
|
-
config2.org,
|
|
24005
|
-
progress,
|
|
24006
|
-
options.force
|
|
24007
|
-
);
|
|
24008
|
-
if (!lockfile.workflows) {
|
|
24009
|
-
lockfile.workflows = {};
|
|
24010
|
-
}
|
|
24112
|
+
const apiResults = await pushToAPI2(toProcess, token, progress, options.force);
|
|
24011
24113
|
for (const w of toProcess) {
|
|
24012
24114
|
const apiResult = apiResults.find((r) => r.slug === w.slug);
|
|
24013
|
-
|
|
24014
|
-
|
|
24015
|
-
|
|
24016
|
-
|
|
24017
|
-
|
|
24018
|
-
|
|
24115
|
+
if (apiResult?.success) {
|
|
24116
|
+
lockfile.workflows[w.slug] = {
|
|
24117
|
+
id: apiResult?.id,
|
|
24118
|
+
localHash: w.parsed.sourceHash,
|
|
24119
|
+
remoteHash: w.parsed.sourceHash,
|
|
24120
|
+
lastPushed: (/* @__PURE__ */ new Date()).toISOString()
|
|
24121
|
+
};
|
|
24122
|
+
}
|
|
24019
24123
|
}
|
|
24020
24124
|
lockfile.lastSync = (/* @__PURE__ */ new Date()).toISOString();
|
|
24021
24125
|
lockfile.org = config2.org;
|
|
24022
|
-
await
|
|
24126
|
+
await saveLockfile(wrapsDir, lockfile);
|
|
24023
24127
|
const pushed = apiResults.filter((r) => r.success);
|
|
24024
24128
|
const conflicts = apiResults.filter((r) => r.conflict);
|
|
24025
24129
|
if (options.json) {
|
|
@@ -24068,7 +24172,7 @@ async function workflowsPush(options) {
|
|
|
24068
24172
|
conflict_count: conflicts.length
|
|
24069
24173
|
});
|
|
24070
24174
|
}
|
|
24071
|
-
async function pushToAPI2(workflows, token,
|
|
24175
|
+
async function pushToAPI2(workflows, token, progress, force) {
|
|
24072
24176
|
if (!token) {
|
|
24073
24177
|
progress.info(
|
|
24074
24178
|
"No API token \u2014 skipping dashboard sync. Run: wraps auth login"
|
|
@@ -24192,32 +24296,12 @@ async function pushToAPI2(workflows, token, _org, progress, force) {
|
|
|
24192
24296
|
}
|
|
24193
24297
|
return results;
|
|
24194
24298
|
}
|
|
24195
|
-
async function loadLockfile2(path3) {
|
|
24196
|
-
if (!existsSync12(path3)) {
|
|
24197
|
-
return { version: "1.0.0", lastSync: "", templates: {}, workflows: {} };
|
|
24198
|
-
}
|
|
24199
|
-
try {
|
|
24200
|
-
const content = await readFile6(path3, "utf-8");
|
|
24201
|
-
const parsed = JSON.parse(content);
|
|
24202
|
-
if (!parsed.workflows) {
|
|
24203
|
-
parsed.workflows = {};
|
|
24204
|
-
}
|
|
24205
|
-
return parsed;
|
|
24206
|
-
} catch {
|
|
24207
|
-
return { version: "1.0.0", lastSync: "", templates: {}, workflows: {} };
|
|
24208
|
-
}
|
|
24209
|
-
}
|
|
24210
|
-
async function saveLockfile2(path3, lockfile) {
|
|
24211
|
-
const dir = join13(path3, "..");
|
|
24212
|
-
await mkdir6(dir, { recursive: true });
|
|
24213
|
-
await writeFile8(path3, JSON.stringify(lockfile, null, 2), "utf-8");
|
|
24214
|
-
}
|
|
24215
24299
|
|
|
24216
24300
|
// src/commands/email/workflows/validate.ts
|
|
24217
24301
|
init_esm_shims();
|
|
24218
24302
|
init_events();
|
|
24219
|
-
import { existsSync as
|
|
24220
|
-
import { join as
|
|
24303
|
+
import { existsSync as existsSync14 } from "fs";
|
|
24304
|
+
import { join as join15 } from "path";
|
|
24221
24305
|
import * as clack30 from "@clack/prompts";
|
|
24222
24306
|
import pc31 from "picocolors";
|
|
24223
24307
|
init_errors();
|
|
@@ -24225,9 +24309,9 @@ init_output();
|
|
|
24225
24309
|
async function workflowsValidate(options) {
|
|
24226
24310
|
const startTime = Date.now();
|
|
24227
24311
|
const cwd = process.cwd();
|
|
24228
|
-
const wrapsDir =
|
|
24229
|
-
const configPath =
|
|
24230
|
-
if (!
|
|
24312
|
+
const wrapsDir = join15(cwd, "wraps");
|
|
24313
|
+
const configPath = join15(wrapsDir, "wraps.config.ts");
|
|
24314
|
+
if (!existsSync14(configPath)) {
|
|
24231
24315
|
throw errors.wrapsConfigNotFound();
|
|
24232
24316
|
}
|
|
24233
24317
|
if (!options.json) {
|
|
@@ -24237,8 +24321,8 @@ async function workflowsValidate(options) {
|
|
|
24237
24321
|
progress.start("Loading configuration");
|
|
24238
24322
|
const config2 = await loadWrapsConfig(wrapsDir);
|
|
24239
24323
|
progress.succeed("Configuration loaded");
|
|
24240
|
-
const workflowsDir =
|
|
24241
|
-
if (!
|
|
24324
|
+
const workflowsDir = join15(wrapsDir, config2.workflowsDir || "./workflows");
|
|
24325
|
+
if (!existsSync14(workflowsDir)) {
|
|
24242
24326
|
if (options.json) {
|
|
24243
24327
|
console.log(
|
|
24244
24328
|
JSON.stringify({
|
|
@@ -24267,9 +24351,9 @@ async function workflowsValidate(options) {
|
|
|
24267
24351
|
}
|
|
24268
24352
|
return;
|
|
24269
24353
|
}
|
|
24270
|
-
const templatesDir =
|
|
24354
|
+
const templatesDir = join15(wrapsDir, config2.templatesDir || "./templates");
|
|
24271
24355
|
let localTemplateSlugs;
|
|
24272
|
-
if (
|
|
24356
|
+
if (existsSync14(templatesDir)) {
|
|
24273
24357
|
const templateFiles = await discoverTemplates(templatesDir);
|
|
24274
24358
|
localTemplateSlugs = new Set(
|
|
24275
24359
|
templateFiles.map((f) => f.replace(/\.tsx?$/, ""))
|
|
@@ -24279,7 +24363,7 @@ async function workflowsValidate(options) {
|
|
|
24279
24363
|
const parseErrors = [];
|
|
24280
24364
|
for (const file of workflowFiles) {
|
|
24281
24365
|
const slug = file.replace(/\.ts$/, "");
|
|
24282
|
-
const filePath =
|
|
24366
|
+
const filePath = join15(workflowsDir, file);
|
|
24283
24367
|
progress.start(`Validating ${pc31.cyan(slug)}`);
|
|
24284
24368
|
try {
|
|
24285
24369
|
const parsed = await parseWorkflowTs(filePath, wrapsDir);
|
|
@@ -25155,6 +25239,11 @@ async function deployEventBridge(metadata, region, identity, webhookSecret, prog
|
|
|
25155
25239
|
await stack.setConfig("aws:region", { value: region });
|
|
25156
25240
|
await stack.refresh({ onOutput: () => {
|
|
25157
25241
|
} });
|
|
25242
|
+
const stackState = await stack.exportStack();
|
|
25243
|
+
const resourceCount = stackState.deployment?.resources?.length ?? 0;
|
|
25244
|
+
if (resourceCount > 1) {
|
|
25245
|
+
stackConfig.skipResourceImports = true;
|
|
25246
|
+
}
|
|
25158
25247
|
await stack.up({ onOutput: () => {
|
|
25159
25248
|
} });
|
|
25160
25249
|
});
|
|
@@ -25626,6 +25715,11 @@ Run ${pc34.cyan("wraps email init")} or ${pc34.cyan("wraps sms init")} first.
|
|
|
25626
25715
|
await stack.setConfig("aws:region", { value: region });
|
|
25627
25716
|
await stack.refresh({ onOutput: () => {
|
|
25628
25717
|
} });
|
|
25718
|
+
const stackState = await stack.exportStack();
|
|
25719
|
+
const resourceCount = stackState.deployment?.resources?.length ?? 0;
|
|
25720
|
+
if (resourceCount > 1) {
|
|
25721
|
+
stackConfig.skipResourceImports = true;
|
|
25722
|
+
}
|
|
25629
25723
|
await stack.up({ onOutput: () => {
|
|
25630
25724
|
} });
|
|
25631
25725
|
});
|
|
@@ -26629,7 +26723,7 @@ import { Router as createRouter2 } from "express";
|
|
|
26629
26723
|
init_esm_shims();
|
|
26630
26724
|
init_assume_role();
|
|
26631
26725
|
import { GetSendQuotaCommand, SESClient as SESClient4 } from "@aws-sdk/client-ses";
|
|
26632
|
-
import { GetEmailIdentityCommand as
|
|
26726
|
+
import { GetEmailIdentityCommand as GetEmailIdentityCommand4, SESv2Client as SESv2Client6 } from "@aws-sdk/client-sesv2";
|
|
26633
26727
|
async function fetchSendQuota(roleArn, region) {
|
|
26634
26728
|
const credentials = roleArn ? await assumeRole(roleArn, region) : void 0;
|
|
26635
26729
|
const ses = new SESClient4({ region, credentials });
|
|
@@ -26644,7 +26738,7 @@ async function fetchDomainInfo(roleArn, region, domain) {
|
|
|
26644
26738
|
const credentials = roleArn ? await assumeRole(roleArn, region) : void 0;
|
|
26645
26739
|
const sesv22 = new SESv2Client6({ region, credentials });
|
|
26646
26740
|
const response = await sesv22.send(
|
|
26647
|
-
new
|
|
26741
|
+
new GetEmailIdentityCommand4({
|
|
26648
26742
|
EmailIdentity: domain
|
|
26649
26743
|
})
|
|
26650
26744
|
);
|
|
@@ -27470,7 +27564,7 @@ init_esm_shims();
|
|
|
27470
27564
|
init_assume_role();
|
|
27471
27565
|
import {
|
|
27472
27566
|
GetConfigurationSetCommand,
|
|
27473
|
-
GetEmailIdentityCommand as
|
|
27567
|
+
GetEmailIdentityCommand as GetEmailIdentityCommand5,
|
|
27474
27568
|
SESv2Client as SESv2Client7
|
|
27475
27569
|
} from "@aws-sdk/client-sesv2";
|
|
27476
27570
|
async function fetchConfigurationSet(roleArn, region, configSetName) {
|
|
@@ -27507,7 +27601,7 @@ async function fetchEmailIdentity(roleArn, region, identityName) {
|
|
|
27507
27601
|
const credentials = roleArn ? await assumeRole(roleArn, region) : void 0;
|
|
27508
27602
|
const sesv22 = new SESv2Client7({ region, credentials });
|
|
27509
27603
|
const response = await sesv22.send(
|
|
27510
|
-
new
|
|
27604
|
+
new GetEmailIdentityCommand5({
|
|
27511
27605
|
EmailIdentity: identityName
|
|
27512
27606
|
})
|
|
27513
27607
|
);
|
|
@@ -32950,7 +33044,7 @@ if (nodeMajorVersion < 20) {
|
|
|
32950
33044
|
var __filename2 = fileURLToPath5(import.meta.url);
|
|
32951
33045
|
var __dirname3 = dirname3(__filename2);
|
|
32952
33046
|
var packageJson = JSON.parse(
|
|
32953
|
-
readFileSync3(
|
|
33047
|
+
readFileSync3(join16(__dirname3, "../package.json"), "utf-8")
|
|
32954
33048
|
);
|
|
32955
33049
|
var VERSION = packageJson.version;
|
|
32956
33050
|
setupTabCompletion();
|