@mtndev/cli 2.0.0 → 2.0.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/CHANGELOG.md +13 -0
- package/cjs/__chunks/VH7oDXx4.cjs +28 -0
- package/cjs/commands/aws/ec2/allow-ip/handler.cjs +261 -12
- package/cjs/commands/aws/ec2/allow-ip/index.cjs +25 -55
- package/cjs/commands/aws/ec2/allow-ip/schema.cjs +33 -13
- package/cjs/commands/aws/ec2/allow-ip/utils.cjs +379 -39
- package/cjs/commands/aws/iam/admin-group.cjs +111 -15
- package/cjs/commands/aws/iam/break-glass/handler.cjs +127 -12
- package/cjs/commands/aws/iam/break-glass/index.cjs +7 -19
- package/cjs/commands/aws/iam/break-glass/schema.cjs +21 -12
- package/cjs/commands/aws/iam/check-admin/handler.cjs +89 -10
- package/cjs/commands/aws/iam/check-admin/index.cjs +7 -17
- package/cjs/commands/aws/iam/check-admin/schema.cjs +19 -12
- package/cjs/commands/aws/iam/policies/s3-restrictions-deny-non-s3-services.json +20 -0
- package/cjs/commands/aws/iam/policies/sts-federation.json +11 -0
- package/cjs/commands/aws/iam/policies/user-admins-deny-list.json +175 -0
- package/cjs/commands/aws/iam/policies/user-admins-deny-regions-list.json +41 -0
- package/cjs/commands/aws/iam/policies/user-admins-self-service-iam.json +56 -0
- package/cjs/commands/aws/iam/policies/user-admins-write-list.json +117 -0
- package/cjs/commands/aws/iam/remove-admin/handler.cjs +120 -11
- package/cjs/commands/aws/iam/remove-admin/index.cjs +7 -18
- package/cjs/commands/aws/iam/remove-admin/schema.cjs +22 -12
- package/cjs/commands/aws/iam/setup-acl/handler.cjs +227 -14
- package/cjs/commands/aws/iam/setup-acl/index.cjs +13 -33
- package/cjs/commands/aws/iam/setup-acl/schema.cjs +19 -7
- package/cjs/commands/aws/iam/setup-acl/utils.cjs +305 -20
- package/cjs/commands/aws/iam/users/handler.cjs +59 -12
- package/cjs/commands/aws/iam/users/index.cjs +18 -41
- package/cjs/commands/aws/iam/users/schema.cjs +17 -7
- package/cjs/commands/aws/iam/users/utils.cjs +454 -30
- package/cjs/commands/aws/index.cjs +223 -229
- package/cjs/commands/aws/route53/add-record/handler.cjs +264 -18
- package/cjs/commands/aws/route53/add-record/index.cjs +26 -57
- package/cjs/commands/aws/route53/add-record/schema.cjs +43 -11
- package/cjs/commands/aws/route53/add-record/utils.cjs +404 -37
- package/cjs/commands/aws/route53/remove-record/handler.cjs +114 -14
- package/cjs/commands/aws/route53/remove-record/index.cjs +5 -18
- package/cjs/commands/aws/route53/remove-record/schema.cjs +22 -8
- package/cjs/commands/aws/schema.cjs +19 -10
- package/cjs/commands/aws/ses/send-email/handler.cjs +73 -12
- package/cjs/commands/aws/ses/send-email/index.cjs +9 -23
- package/cjs/commands/aws/ses/send-email/schema.cjs +24 -7
- package/cjs/commands/aws/ses/send-email/utils.cjs +87 -11
- package/cjs/commands/aws/ses/smtp-password.cjs +72 -10
- package/cjs/commands/aws/utils/exec-aws.cjs +145 -16
- package/cjs/commands/aws/utils/resolve-policy-path.cjs +15 -6
- package/cjs/commands/aws/utils/resolve-profile.cjs +93 -11
- package/cjs/commands/aws/utils/tty.cjs +54 -10
- package/cjs/commands/db/create-readonly-user/handler.cjs +254 -11
- package/cjs/commands/db/create-readonly-user/index.cjs +18 -40
- package/cjs/commands/db/create-readonly-user/mysql.cjs +102 -9
- package/cjs/commands/db/create-readonly-user/postgres.cjs +209 -9
- package/cjs/commands/db/create-readonly-user/schema.cjs +39 -12
- package/cjs/commands/db/create-readonly-user/utils.cjs +160 -22
- package/cjs/commands/db/index.cjs +46 -44
- package/cjs/commands/doppler/handler.cjs +95 -11
- package/cjs/commands/doppler/index.cjs +33 -68
- package/cjs/commands/doppler/schema.cjs +130 -14
- package/cjs/commands/doppler/set-secret.cjs +378 -19
- package/cjs/commands/doppler/utils/exec.cjs +106 -12
- package/cjs/commands/doppler/utils.cjs +412 -34
- package/cjs/commands/icons/handler.cjs +82 -8
- package/cjs/commands/icons/index.cjs +15 -31
- package/cjs/commands/icons/schema.cjs +101 -13
- package/cjs/commands/icons/utils.cjs +131 -13
- package/cjs/commands/index.cjs +54 -161
- package/cjs/commands/schema.cjs +25 -8
- package/cjs/index.cjs +3 -4
- package/esm/commands/aws/ec2/allow-ip/handler.js +258 -12
- package/esm/commands/aws/ec2/allow-ip/index.js +4 -55
- package/esm/commands/aws/ec2/allow-ip/schema.js +29 -13
- package/esm/commands/aws/ec2/allow-ip/utils.js +363 -39
- package/esm/commands/aws/iam/admin-group.js +104 -15
- package/esm/commands/aws/iam/break-glass/handler.js +124 -12
- package/esm/commands/aws/iam/break-glass/index.js +4 -19
- package/esm/commands/aws/iam/break-glass/schema.js +19 -12
- package/esm/commands/aws/iam/check-admin/handler.js +86 -10
- package/esm/commands/aws/iam/check-admin/index.js +4 -17
- package/esm/commands/aws/iam/check-admin/schema.js +17 -12
- package/esm/commands/aws/iam/policies/s3-restrictions-deny-non-s3-services.json +20 -0
- package/esm/commands/aws/iam/policies/sts-federation.json +11 -0
- package/esm/commands/aws/iam/policies/user-admins-deny-list.json +175 -0
- package/esm/commands/aws/iam/policies/user-admins-deny-regions-list.json +41 -0
- package/esm/commands/aws/iam/policies/user-admins-self-service-iam.json +56 -0
- package/esm/commands/aws/iam/policies/user-admins-write-list.json +117 -0
- package/esm/commands/aws/iam/remove-admin/handler.js +117 -11
- package/esm/commands/aws/iam/remove-admin/index.js +4 -18
- package/esm/commands/aws/iam/remove-admin/schema.js +20 -12
- package/esm/commands/aws/iam/setup-acl/handler.js +224 -14
- package/esm/commands/aws/iam/setup-acl/index.js +4 -33
- package/esm/commands/aws/iam/setup-acl/schema.js +18 -7
- package/esm/commands/aws/iam/setup-acl/utils.js +298 -20
- package/esm/commands/aws/iam/users/handler.js +56 -12
- package/esm/commands/aws/iam/users/index.js +4 -41
- package/esm/commands/aws/iam/users/schema.js +16 -7
- package/esm/commands/aws/iam/users/utils.js +440 -30
- package/esm/commands/aws/index.js +142 -229
- package/esm/commands/aws/route53/add-record/handler.js +258 -18
- package/esm/commands/aws/route53/add-record/index.js +4 -57
- package/esm/commands/aws/route53/add-record/schema.js +40 -11
- package/esm/commands/aws/route53/add-record/utils.js +389 -37
- package/esm/commands/aws/route53/remove-record/handler.js +111 -14
- package/esm/commands/aws/route53/remove-record/index.js +3 -18
- package/esm/commands/aws/route53/remove-record/schema.js +21 -8
- package/esm/commands/aws/schema.js +16 -10
- package/esm/commands/aws/ses/send-email/handler.js +70 -12
- package/esm/commands/aws/ses/send-email/index.js +4 -23
- package/esm/commands/aws/ses/send-email/schema.js +23 -7
- package/esm/commands/aws/ses/send-email/utils.js +84 -11
- package/esm/commands/aws/ses/smtp-password.js +69 -10
- package/esm/commands/aws/utils/exec-aws.js +136 -15
- package/esm/commands/aws/utils/resolve-policy-path.js +14 -6
- package/esm/commands/aws/utils/resolve-profile.js +88 -11
- package/esm/commands/aws/utils/tty.js +51 -10
- package/esm/commands/db/create-readonly-user/handler.js +251 -11
- package/esm/commands/db/create-readonly-user/index.js +4 -40
- package/esm/commands/db/create-readonly-user/mysql.js +98 -9
- package/esm/commands/db/create-readonly-user/postgres.js +205 -9
- package/esm/commands/db/create-readonly-user/schema.js +35 -12
- package/esm/commands/db/create-readonly-user/utils.js +151 -22
- package/esm/commands/db/index.js +31 -44
- package/esm/commands/doppler/handler.js +92 -11
- package/esm/commands/doppler/index.js +6 -68
- package/esm/commands/doppler/schema.js +125 -15
- package/esm/commands/doppler/set-secret.js +370 -19
- package/esm/commands/doppler/utils/exec.js +100 -12
- package/esm/commands/doppler/utils.js +396 -34
- package/esm/commands/icons/handler.js +79 -8
- package/esm/commands/icons/index.js +4 -31
- package/esm/commands/icons/schema.js +97 -15
- package/esm/commands/icons/utils.js +125 -13
- package/esm/commands/index.js +47 -155
- package/esm/commands/schema.js +22 -7
- package/esm/index.js +3 -4
- package/package.json +5 -2
- package/vitest.config.ts +11 -0
- package/cjs/__chunks/2FSYDFUV.cjs +0 -146
- package/cjs/__chunks/3A5ZYU5M.cjs +0 -105
- package/cjs/__chunks/3BY5Y4W7.cjs +0 -1
- package/cjs/__chunks/3NOHGUCF.cjs +0 -9
- package/cjs/__chunks/3T2LXW7J.cjs +0 -387
- package/cjs/__chunks/4SFWHCB3.cjs +0 -133
- package/cjs/__chunks/4XT5JEAS.cjs +0 -1
- package/cjs/__chunks/AZEB4H4I.cjs +0 -208
- package/cjs/__chunks/B2KFW7T7.cjs +0 -1
- package/cjs/__chunks/B5ENMOCD.cjs +0 -288
- package/cjs/__chunks/B6XM5KSF.cjs +0 -338
- package/cjs/__chunks/BDU2UCE5.cjs +0 -1
- package/cjs/__chunks/BLMSMR5E.cjs +0 -46
- package/cjs/__chunks/CMUD7LLN.cjs +0 -47
- package/cjs/__chunks/DTQ2LB3I.cjs +0 -49
- package/cjs/__chunks/FM5MVRQF.cjs +0 -23
- package/cjs/__chunks/FRHST54J.cjs +0 -135
- package/cjs/__chunks/FU4VP2LN.cjs +0 -1
- package/cjs/__chunks/G5K4PVIL.cjs +0 -26
- package/cjs/__chunks/GU3R54MK.cjs +0 -127
- package/cjs/__chunks/GUL36IFZ.cjs +0 -61
- package/cjs/__chunks/GZMTNK5N.cjs +0 -1
- package/cjs/__chunks/H74JSDBU.cjs +0 -30
- package/cjs/__chunks/INFOPAHN.cjs +0 -117
- package/cjs/__chunks/J36P6UNE.cjs +0 -75
- package/cjs/__chunks/JB7T7PKQ.cjs +0 -538
- package/cjs/__chunks/JSL2JDMW.cjs +0 -1
- package/cjs/__chunks/K4QNHRTP.cjs +0 -163
- package/cjs/__chunks/KU76LC42.cjs +0 -192
- package/cjs/__chunks/LFDSHANP.cjs +0 -34
- package/cjs/__chunks/LHE24ECK.cjs +0 -192
- package/cjs/__chunks/LIKQ3SI4.cjs +0 -1
- package/cjs/__chunks/LXDF5QVZ.cjs +0 -313
- package/cjs/__chunks/LXOOJR2R.cjs +0 -74
- package/cjs/__chunks/N5MXFOQZ.cjs +0 -167
- package/cjs/__chunks/N7D56LPP.cjs +0 -25
- package/cjs/__chunks/NFXQNOQH.cjs +0 -393
- package/cjs/__chunks/NIMXXHJQ.cjs +0 -92
- package/cjs/__chunks/NLKJIUEX.cjs +0 -126
- package/cjs/__chunks/NT2XXAI6.cjs +0 -89
- package/cjs/__chunks/NWZGFHKH.cjs +0 -121
- package/cjs/__chunks/R3GUC7O7.cjs +0 -110
- package/cjs/__chunks/RPVAXPJ4.cjs +0 -1
- package/cjs/__chunks/S3LVCWPN.cjs +0 -23
- package/cjs/__chunks/SBBNW2BF.cjs +0 -249
- package/cjs/__chunks/T2A7TN4F.cjs +0 -81
- package/cjs/__chunks/TKNNDDIB.cjs +0 -97
- package/cjs/__chunks/TNSRDJPR.cjs +0 -1
- package/cjs/__chunks/UWHPE2GI.cjs +0 -20
- package/cjs/__chunks/W6K7BV74.cjs +0 -1
- package/cjs/__chunks/WBOQ6AUN.cjs +0 -320
- package/cjs/__chunks/WHGN5PZI.cjs +0 -299
- package/cjs/__chunks/WOYF2L6T.cjs +0 -11
- package/cjs/__chunks/X26XY2N6.cjs +0 -18
- package/cjs/__chunks/XMKOKRXZ.cjs +0 -16
- package/cjs/__chunks/XTJPQ3EX.cjs +0 -1
- package/cjs/__chunks/YRHFKTW2.cjs +0 -63
- package/cjs/__chunks/ZMDIOZPT.cjs +0 -22
- package/cjs/commands/aws/iam/policies/s3-restrictions-deny-non-s3-services.cjs +0 -28
- package/cjs/commands/aws/iam/policies/sts-federation.cjs +0 -19
- package/cjs/commands/aws/iam/policies/user-admins-deny-list.cjs +0 -183
- package/cjs/commands/aws/iam/policies/user-admins-deny-regions-list.cjs +0 -49
- package/cjs/commands/aws/iam/policies/user-admins-self-service-iam.cjs +0 -64
- package/cjs/commands/aws/iam/policies/user-admins-write-list.cjs +0 -125
- package/esm/__chunks/2FTTEFEK.js +0 -97
- package/esm/__chunks/33UYMUQD.js +0 -338
- package/esm/__chunks/3BKWTHLJ.js +0 -25
- package/esm/__chunks/3HE4BEJX.js +0 -105
- package/esm/__chunks/3QLI5BDL.js +0 -387
- package/esm/__chunks/5GIUAFXL.js +0 -89
- package/esm/__chunks/5ZBVGSOK.js +0 -0
- package/esm/__chunks/6G4PXXKF.js +0 -75
- package/esm/__chunks/73BJG53F.js +0 -11
- package/esm/__chunks/7VF4Q43Q.js +0 -0
- package/esm/__chunks/AEDEAYF5.js +0 -0
- package/esm/__chunks/AZCP3SFJ.js +0 -0
- package/esm/__chunks/B2DVQ2UL.js +0 -61
- package/esm/__chunks/CVQVHLW5.js +0 -0
- package/esm/__chunks/D62SPZXC.js +0 -0
- package/esm/__chunks/DLEJ25GZ.js +0 -121
- package/esm/__chunks/DMYFNF54.js +0 -192
- package/esm/__chunks/DNFTUMGD.js +0 -23
- package/esm/__chunks/DVKD6YSR.js +0 -49
- package/esm/__chunks/EMSH4P76.js +0 -20
- package/esm/__chunks/FFKFVMIE.js +0 -167
- package/esm/__chunks/FL7AILGH.js +0 -133
- package/esm/__chunks/FNXUONAV.js +0 -110
- package/esm/__chunks/G4NJHFFU.js +0 -320
- package/esm/__chunks/HJSXC6HP.js +0 -117
- package/esm/__chunks/IEOGAQYI.js +0 -46
- package/esm/__chunks/IZFGBYGE.js +0 -34
- package/esm/__chunks/J34UVKLA.js +0 -26
- package/esm/__chunks/JZPBBBIG.js +0 -74
- package/esm/__chunks/KWUJP5MG.js +0 -135
- package/esm/__chunks/M35URMT4.js +0 -313
- package/esm/__chunks/NF3M2L6C.js +0 -81
- package/esm/__chunks/O3CCA76Q.js +0 -22
- package/esm/__chunks/PNPPDYKC.js +0 -299
- package/esm/__chunks/QFXN4EHM.js +0 -393
- package/esm/__chunks/QKDDLIWD.js +0 -146
- package/esm/__chunks/QSE66AKY.js +0 -208
- package/esm/__chunks/QUF7PS4R.js +0 -18
- package/esm/__chunks/S7IJPJ4R.js +0 -126
- package/esm/__chunks/SD3E3EPH.js +0 -163
- package/esm/__chunks/SJXQJ7RS.js +0 -92
- package/esm/__chunks/SNCKIAOR.js +0 -0
- package/esm/__chunks/T3TTUHTW.js +0 -30
- package/esm/__chunks/TIOVE6HR.js +0 -0
- package/esm/__chunks/TXKMEIDQ.js +0 -0
- package/esm/__chunks/U7HAE2RF.js +0 -288
- package/esm/__chunks/UXWY7BYE.js +0 -63
- package/esm/__chunks/VKAKISRG.js +0 -192
- package/esm/__chunks/WD2YR6I7.js +0 -0
- package/esm/__chunks/WOZFZKFY.js +0 -0
- package/esm/__chunks/XI7GZDE2.js +0 -0
- package/esm/__chunks/XOUWDB3T.js +0 -249
- package/esm/__chunks/XQN2TA4S.js +0 -23
- package/esm/__chunks/XXK32TIM.js +0 -16
- package/esm/__chunks/YGWTVPZE.js +0 -538
- package/esm/__chunks/YRG7PT33.js +0 -127
- package/esm/__chunks/ZHKVJO2U.js +0 -47
- package/esm/__chunks/ZO55YUSY.js +0 -9
- package/esm/commands/aws/iam/policies/s3-restrictions-deny-non-s3-services.js +0 -28
- package/esm/commands/aws/iam/policies/sts-federation.js +0 -19
- package/esm/commands/aws/iam/policies/user-admins-deny-list.js +0 -183
- package/esm/commands/aws/iam/policies/user-admins-deny-regions-list.js +0 -49
- package/esm/commands/aws/iam/policies/user-admins-self-service-iam.js +0 -64
- package/esm/commands/aws/iam/policies/user-admins-write-list.js +0 -125
|
@@ -1,57 +1,4 @@
|
|
|
1
|
-
import "
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
resolveName,
|
|
6
|
-
resolveRecordType
|
|
7
|
-
} from "../../../../__chunks/G4NJHFFU.js";
|
|
8
|
-
import {
|
|
9
|
-
bareHostedZoneId,
|
|
10
|
-
deleteResourceRecordSet,
|
|
11
|
-
findCnameConflicts,
|
|
12
|
-
findHostedZone,
|
|
13
|
-
formatValues,
|
|
14
|
-
getRecordSetsAtName,
|
|
15
|
-
getResourceRecordSet,
|
|
16
|
-
hostedZoneLabel,
|
|
17
|
-
listHostedZones,
|
|
18
|
-
normalizeRecordValue,
|
|
19
|
-
planRecordChange,
|
|
20
|
-
resolveRecordName,
|
|
21
|
-
upsertResourceRecordSet,
|
|
22
|
-
withTrailingDot,
|
|
23
|
-
withoutTrailingDot
|
|
24
|
-
} from "../../../../__chunks/33UYMUQD.js";
|
|
25
|
-
import {
|
|
26
|
-
DEFAULT_TTL,
|
|
27
|
-
RECORD_TYPES,
|
|
28
|
-
addRecordOptionsSchema
|
|
29
|
-
} from "../../../../__chunks/IEOGAQYI.js";
|
|
30
|
-
import "../../../../__chunks/FNXUONAV.js";
|
|
31
|
-
import "../../../../__chunks/5GIUAFXL.js";
|
|
32
|
-
import "../../../../__chunks/73BJG53F.js";
|
|
33
|
-
import "../../../../__chunks/ZHKVJO2U.js";
|
|
34
|
-
export {
|
|
35
|
-
DEFAULT_TTL,
|
|
36
|
-
RECORD_TYPES,
|
|
37
|
-
addRecordCommand,
|
|
38
|
-
addRecordOptionsSchema,
|
|
39
|
-
bareHostedZoneId,
|
|
40
|
-
deleteResourceRecordSet,
|
|
41
|
-
findCnameConflicts,
|
|
42
|
-
findHostedZone,
|
|
43
|
-
formatValues,
|
|
44
|
-
getRecordSetsAtName,
|
|
45
|
-
getResourceRecordSet,
|
|
46
|
-
hostedZoneLabel,
|
|
47
|
-
listHostedZones,
|
|
48
|
-
normalizeRecordValue,
|
|
49
|
-
planRecordChange,
|
|
50
|
-
resolveHostedZone,
|
|
51
|
-
resolveName,
|
|
52
|
-
resolveRecordName,
|
|
53
|
-
resolveRecordType,
|
|
54
|
-
upsertResourceRecordSet,
|
|
55
|
-
withTrailingDot,
|
|
56
|
-
withoutTrailingDot
|
|
57
|
-
};
|
|
1
|
+
import { DEFAULT_TTL, RECORD_TYPES, addRecordOptionsSchema } from "./schema.js";
|
|
2
|
+
import { bareHostedZoneId, deleteResourceRecordSet, findCnameConflicts, findHostedZone, formatValues, getRecordSetsAtName, getResourceRecordSet, hostedZoneLabel, listHostedZones, normalizeRecordValue, planRecordChange, resolveRecordName, upsertResourceRecordSet, withTrailingDot, withoutTrailingDot } from "./utils.js";
|
|
3
|
+
import { addRecordCommand, resolveHostedZone, resolveName, resolveRecordType } from "./handler.js";
|
|
4
|
+
export { DEFAULT_TTL, RECORD_TYPES, addRecordCommand, addRecordOptionsSchema, bareHostedZoneId, deleteResourceRecordSet, findCnameConflicts, findHostedZone, formatValues, getRecordSetsAtName, getResourceRecordSet, hostedZoneLabel, listHostedZones, normalizeRecordValue, planRecordChange, resolveHostedZone, resolveName, resolveRecordName, resolveRecordType, upsertResourceRecordSet, withTrailingDot, withoutTrailingDot };
|
|
@@ -1,11 +1,40 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { profileField, verboseField } from "../../schema.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
//#region src/commands/aws/route53/add-record/schema.js
|
|
4
|
+
/**
|
|
5
|
+
* Common Route53 record types offered in the interactive picker.
|
|
6
|
+
* Alias records are not supported by this command.
|
|
7
|
+
*/
|
|
8
|
+
const RECORD_TYPES = [
|
|
9
|
+
"A",
|
|
10
|
+
"AAAA",
|
|
11
|
+
"CNAME",
|
|
12
|
+
"TXT",
|
|
13
|
+
"MX",
|
|
14
|
+
"NS",
|
|
15
|
+
"SRV",
|
|
16
|
+
"CAA"
|
|
17
|
+
];
|
|
18
|
+
/**
|
|
19
|
+
* Default TTL (seconds) when creating or replacing a record set.
|
|
20
|
+
*/
|
|
21
|
+
const DEFAULT_TTL = 300;
|
|
22
|
+
/**
|
|
23
|
+
* Zod schema for `aws route53 add-record` options.
|
|
24
|
+
*/
|
|
25
|
+
const addRecordOptionsSchema = z.object({
|
|
26
|
+
profile: profileField,
|
|
27
|
+
zone: z.string().optional().describe("Hosted zone name or ID (e.g. mountaindev.com or Z123…). Skips the zone picker when set."),
|
|
28
|
+
type: z.string().optional().transform((value) => value === void 0 ? void 0 : value.toUpperCase()).refine((value) => value === void 0 || typeof value === "string" && RECORD_TYPES.includes(value), { message: `Record type must be one of: ${RECORD_TYPES.join(", ")}` }).describe(`DNS record type (${RECORD_TYPES.join(", ")})`),
|
|
29
|
+
name: z.string().optional().describe("Record name relative to the zone (e.g. \"redline\") or a fully-qualified name"),
|
|
30
|
+
value: z.string().optional().describe("Record value (e.g. a CNAME target or A address)"),
|
|
31
|
+
ttl: z.number().int().positive().optional().describe(`TTL in seconds (default: 300)`),
|
|
32
|
+
yes: z.boolean().optional().default(false).describe("Skip the confirmation prompt"),
|
|
33
|
+
dryRun: z.boolean().optional().default(false).describe("Preview the change without calling Route53"),
|
|
34
|
+
verbose: verboseField
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* @typedef {z.infer<typeof addRecordOptionsSchema>} AddRecordOptions
|
|
38
|
+
*/
|
|
39
|
+
//#endregion
|
|
40
|
+
export { DEFAULT_TTL, RECORD_TYPES, addRecordOptionsSchema };
|
|
@@ -1,37 +1,389 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
1
|
+
import { runAws } from "../../utils/exec-aws.js";
|
|
2
|
+
import "./schema.js";
|
|
3
|
+
//#region src/commands/aws/route53/add-record/utils.js
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {Object} HostedZone
|
|
6
|
+
* @property {string} id - Bare hosted zone ID (without /hostedzone/ prefix)
|
|
7
|
+
* @property {string} name - Zone name with trailing dot (e.g. mountaindev.com.)
|
|
8
|
+
* @property {boolean} privateZone
|
|
9
|
+
* @property {number} recordCount
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {Object} ResourceRecordSet
|
|
13
|
+
* @property {string} name
|
|
14
|
+
* @property {string} type
|
|
15
|
+
* @property {number | undefined} ttl
|
|
16
|
+
* @property {string[]} values
|
|
17
|
+
* @property {boolean} isAlias
|
|
18
|
+
* @property {any} [aliasTarget] - Raw AliasTarget block (present when isAlias)
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Strip the `/hostedzone/` prefix from a Route53 hosted zone Id.
|
|
22
|
+
* @param {string} rawId
|
|
23
|
+
* @returns {string}
|
|
24
|
+
*/
|
|
25
|
+
function bareHostedZoneId(rawId) {
|
|
26
|
+
return rawId.replace(/^\/hostedzone\//, "");
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Ensure a DNS name ends with a trailing dot (Route53 FQDN form).
|
|
30
|
+
* @param {string} name
|
|
31
|
+
* @returns {string}
|
|
32
|
+
*/
|
|
33
|
+
function withTrailingDot(name) {
|
|
34
|
+
const trimmed = name.trim();
|
|
35
|
+
if (trimmed === "") return trimmed;
|
|
36
|
+
return trimmed.endsWith(".") ? trimmed : `${trimmed}.`;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Strip a trailing dot for display.
|
|
40
|
+
* @param {string} name
|
|
41
|
+
* @returns {string}
|
|
42
|
+
*/
|
|
43
|
+
function withoutTrailingDot(name) {
|
|
44
|
+
return name.endsWith(".") ? name.slice(0, -1) : name;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* List hosted zones for the profile.
|
|
48
|
+
* @param {{ profile?: string; verbose?: boolean }} params
|
|
49
|
+
* @returns {HostedZone[]}
|
|
50
|
+
*/
|
|
51
|
+
function listHostedZones(params) {
|
|
52
|
+
const { profile, verbose } = params;
|
|
53
|
+
const data = runAws({
|
|
54
|
+
profile,
|
|
55
|
+
args: ["route53", "list-hosted-zones"],
|
|
56
|
+
verbose
|
|
57
|
+
});
|
|
58
|
+
/** @type {HostedZone[]} */
|
|
59
|
+
const zones = [];
|
|
60
|
+
for (const zone of data.HostedZones ?? []) {
|
|
61
|
+
const id = bareHostedZoneId(String(zone.Id ?? ""));
|
|
62
|
+
const name = withTrailingDot(String(zone.Name ?? ""));
|
|
63
|
+
if (!id || !name) continue;
|
|
64
|
+
zones.push({
|
|
65
|
+
id,
|
|
66
|
+
name,
|
|
67
|
+
privateZone: Boolean(zone.Config?.PrivateZone),
|
|
68
|
+
recordCount: Number(zone.ResourceRecordSetCount ?? 0)
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return zones.sort((a, b) => a.name.localeCompare(b.name));
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Resolve a hosted zone from a name (mountaindev.com) or bare/prefixed ID.
|
|
75
|
+
* @param {{ zones: HostedZone[]; zoneInput: string }} params
|
|
76
|
+
* @returns {HostedZone | null}
|
|
77
|
+
*/
|
|
78
|
+
function findHostedZone(params) {
|
|
79
|
+
const { zones, zoneInput } = params;
|
|
80
|
+
const input = zoneInput.trim();
|
|
81
|
+
if (!input) return null;
|
|
82
|
+
const bareId = bareHostedZoneId(input);
|
|
83
|
+
const byId = zones.find((zone) => zone.id === bareId);
|
|
84
|
+
if (byId) return byId;
|
|
85
|
+
const normalized = withTrailingDot(input).toLowerCase();
|
|
86
|
+
const matches = zones.filter((zone) => zone.name.toLowerCase() === normalized);
|
|
87
|
+
if (matches.length === 1) return matches[0] ?? null;
|
|
88
|
+
if (matches.length > 1) return matches.find((zone) => !zone.privateZone) ?? matches[0] ?? null;
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Build a display label for a hosted zone in the picker.
|
|
93
|
+
* @param {HostedZone} zone
|
|
94
|
+
* @returns {string}
|
|
95
|
+
*/
|
|
96
|
+
function hostedZoneLabel(zone) {
|
|
97
|
+
const visibility = zone.privateZone ? "private" : "public";
|
|
98
|
+
return `${withoutTrailingDot(zone.name)} (${zone.id}, ${visibility}, ${zone.recordCount} records)`;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Turn a relative or absolute name into a Route53 FQDN under the zone.
|
|
102
|
+
* Apex / "@" / empty → the zone apex.
|
|
103
|
+
* @param {{ nameInput: string; zoneName: string }} params
|
|
104
|
+
* @returns {string} FQDN with trailing dot
|
|
105
|
+
*/
|
|
106
|
+
function resolveRecordName(params) {
|
|
107
|
+
const { nameInput, zoneName } = params;
|
|
108
|
+
const zoneFqdn = withTrailingDot(zoneName);
|
|
109
|
+
const raw = nameInput.trim();
|
|
110
|
+
if (raw === "" || raw === "@") return zoneFqdn;
|
|
111
|
+
const asFqdn = withTrailingDot(raw);
|
|
112
|
+
const zoneLower = zoneFqdn.toLowerCase();
|
|
113
|
+
if (asFqdn.toLowerCase() === zoneLower) return zoneFqdn;
|
|
114
|
+
if (asFqdn.toLowerCase().endsWith(`.${zoneLower}`)) return asFqdn;
|
|
115
|
+
return withTrailingDot(`${raw.replace(/\.$/, "")}.${withoutTrailingDot(zoneFqdn)}`);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Fetch every resource record set at an exact name, across all types.
|
|
119
|
+
* Paginates when needed; Route53 list is ordered by name then type.
|
|
120
|
+
* @param {{
|
|
121
|
+
* profile?: string;
|
|
122
|
+
* hostedZoneId: string;
|
|
123
|
+
* name: string;
|
|
124
|
+
* verbose?: boolean;
|
|
125
|
+
* }} params
|
|
126
|
+
* @returns {ResourceRecordSet[]}
|
|
127
|
+
*/
|
|
128
|
+
function getRecordSetsAtName(params) {
|
|
129
|
+
const { profile, hostedZoneId, name, verbose } = params;
|
|
130
|
+
const targetName = withTrailingDot(name).toLowerCase();
|
|
131
|
+
let startRecordName = withTrailingDot(name);
|
|
132
|
+
/** @type {string | undefined} */
|
|
133
|
+
let startRecordType;
|
|
134
|
+
/** @type {string | undefined} */
|
|
135
|
+
let nextRecordIdentifier;
|
|
136
|
+
/** @type {ResourceRecordSet[]} */
|
|
137
|
+
const collected = [];
|
|
138
|
+
for (let page = 0; page < 20; page += 1) {
|
|
139
|
+
/** @type {string[]} */
|
|
140
|
+
const args = [
|
|
141
|
+
"route53",
|
|
142
|
+
"list-resource-record-sets",
|
|
143
|
+
"--hosted-zone-id",
|
|
144
|
+
hostedZoneId,
|
|
145
|
+
"--max-items",
|
|
146
|
+
"100"
|
|
147
|
+
];
|
|
148
|
+
if (startRecordName) args.push("--start-record-name", startRecordName);
|
|
149
|
+
if (startRecordType) args.push("--start-record-type", startRecordType);
|
|
150
|
+
if (nextRecordIdentifier) args.push("--start-record-identifier", nextRecordIdentifier);
|
|
151
|
+
const data = runAws({
|
|
152
|
+
profile,
|
|
153
|
+
args,
|
|
154
|
+
verbose
|
|
155
|
+
});
|
|
156
|
+
const sets = data.ResourceRecordSets ?? [];
|
|
157
|
+
for (const set of sets) {
|
|
158
|
+
const setName = withTrailingDot(String(set.Name ?? "")).toLowerCase();
|
|
159
|
+
if (setName === targetName) {
|
|
160
|
+
collected.push(normalizeRecordSet(set));
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (setName > targetName) return collected;
|
|
164
|
+
}
|
|
165
|
+
if (!(data.IsTruncated === true)) return collected;
|
|
166
|
+
startRecordName = data.NextRecordName ? String(data.NextRecordName) : startRecordName;
|
|
167
|
+
startRecordType = data.NextRecordType ? String(data.NextRecordType) : void 0;
|
|
168
|
+
nextRecordIdentifier = data.NextRecordIdentifier ? String(data.NextRecordIdentifier) : void 0;
|
|
169
|
+
}
|
|
170
|
+
return collected;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Fetch a single resource record set by exact name + type, if it exists.
|
|
174
|
+
* @param {{
|
|
175
|
+
* profile?: string;
|
|
176
|
+
* hostedZoneId: string;
|
|
177
|
+
* name: string;
|
|
178
|
+
* type: string;
|
|
179
|
+
* verbose?: boolean;
|
|
180
|
+
* }} params
|
|
181
|
+
* @returns {ResourceRecordSet | null}
|
|
182
|
+
*/
|
|
183
|
+
function getResourceRecordSet(params) {
|
|
184
|
+
const { type, ...rest } = params;
|
|
185
|
+
const targetType = type.toUpperCase();
|
|
186
|
+
return getRecordSetsAtName(rest).find((set) => set.type === targetType) ?? null;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Route53 forbids a CNAME from coexisting with any other record type at the
|
|
190
|
+
* same name. Given the type about to be written and the record sets already at
|
|
191
|
+
* that name, return the sets that would conflict (empty when there is none).
|
|
192
|
+
* A same-type set is an overwrite, not a conflict.
|
|
193
|
+
* @param {{ existingSets: ResourceRecordSet[]; type: string }} params
|
|
194
|
+
* @returns {ResourceRecordSet[]}
|
|
195
|
+
*/
|
|
196
|
+
function findCnameConflicts(params) {
|
|
197
|
+
const { existingSets, type } = params;
|
|
198
|
+
const upperType = type.toUpperCase();
|
|
199
|
+
return existingSets.filter((set) => {
|
|
200
|
+
if (set.type === upperType) return false;
|
|
201
|
+
return upperType === "CNAME" || set.type === "CNAME";
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* @param {any} set
|
|
206
|
+
* @returns {ResourceRecordSet}
|
|
207
|
+
*/
|
|
208
|
+
function normalizeRecordSet(set) {
|
|
209
|
+
const values = (set.ResourceRecords ?? []).map((record) => String(record.Value ?? ""));
|
|
210
|
+
return {
|
|
211
|
+
name: withTrailingDot(String(set.Name ?? "")),
|
|
212
|
+
type: String(set.Type ?? "").toUpperCase(),
|
|
213
|
+
ttl: typeof set.TTL === "number" ? set.TTL : void 0,
|
|
214
|
+
values,
|
|
215
|
+
isAlias: Boolean(set.AliasTarget),
|
|
216
|
+
aliasTarget: set.AliasTarget ?? void 0
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Format existing values for console display.
|
|
221
|
+
* @param {string[]} values
|
|
222
|
+
* @returns {string}
|
|
223
|
+
*/
|
|
224
|
+
function formatValues(values) {
|
|
225
|
+
if (values.length === 0) return "(none)";
|
|
226
|
+
if (values.length === 1) return values[0] ?? "(none)";
|
|
227
|
+
return values.map((value) => `\n - ${value}`).join("");
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Normalize a single record value for a given type (trailing dots, TXT quotes).
|
|
231
|
+
* @param {{ type: string; value: string }} params
|
|
232
|
+
* @returns {string}
|
|
233
|
+
*/
|
|
234
|
+
function normalizeRecordValue(params) {
|
|
235
|
+
const { type, value } = params;
|
|
236
|
+
const trimmed = value.trim();
|
|
237
|
+
if (type === "CNAME" || type === "NS" || type === "MX" || type === "SRV") {
|
|
238
|
+
if (type === "MX") {
|
|
239
|
+
const parts = trimmed.split(/\s+/);
|
|
240
|
+
if (parts.length >= 2) return `${parts[0]} ${withTrailingDot(parts.slice(1).join(" "))}`;
|
|
241
|
+
}
|
|
242
|
+
if (type === "SRV") {
|
|
243
|
+
const parts = trimmed.split(/\s+/);
|
|
244
|
+
if (parts.length >= 4) return `${parts.slice(0, 3).join(" ")} ${withTrailingDot(parts.slice(3).join(" "))}`;
|
|
245
|
+
}
|
|
246
|
+
return withTrailingDot(trimmed);
|
|
247
|
+
}
|
|
248
|
+
if (type === "TXT") {
|
|
249
|
+
if (trimmed.startsWith("\"") && trimmed.endsWith("\"") || trimmed.startsWith("'") && trimmed.endsWith("'")) return trimmed;
|
|
250
|
+
return `"${trimmed}"`;
|
|
251
|
+
}
|
|
252
|
+
return trimmed;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Decide how the new value relates to an existing RRSet.
|
|
256
|
+
* @param {{
|
|
257
|
+
* existing: ResourceRecordSet | null;
|
|
258
|
+
* newValue: string;
|
|
259
|
+
* mode?: "replace" | "append";
|
|
260
|
+
* }} params
|
|
261
|
+
* @returns {{
|
|
262
|
+
* action: "create" | "overwrite" | "append" | "noop";
|
|
263
|
+
* finalValues: string[];
|
|
264
|
+
* summary: string;
|
|
265
|
+
* }}
|
|
266
|
+
*/
|
|
267
|
+
function planRecordChange(params) {
|
|
268
|
+
const { existing, newValue, mode = "replace" } = params;
|
|
269
|
+
if (!existing) return {
|
|
270
|
+
action: "create",
|
|
271
|
+
finalValues: [newValue],
|
|
272
|
+
summary: "Adding a new record (nothing exists at this name + type)."
|
|
273
|
+
};
|
|
274
|
+
if (existing.isAlias) return {
|
|
275
|
+
action: "overwrite",
|
|
276
|
+
finalValues: [newValue],
|
|
277
|
+
summary: "Overwriting an existing ALIAS record with a standard record set."
|
|
278
|
+
};
|
|
279
|
+
const alreadyPresent = existing.values.some((value) => value === newValue || value === `"${newValue}"`);
|
|
280
|
+
if (alreadyPresent && mode !== "replace") return {
|
|
281
|
+
action: "noop",
|
|
282
|
+
finalValues: existing.values,
|
|
283
|
+
summary: "Record already has this value. Nothing to do."
|
|
284
|
+
};
|
|
285
|
+
if (alreadyPresent && mode === "replace" && existing.values.length === 1 && existing.values[0] === newValue) return {
|
|
286
|
+
action: "noop",
|
|
287
|
+
finalValues: existing.values,
|
|
288
|
+
summary: "Record already has exactly this value. Nothing to do."
|
|
289
|
+
};
|
|
290
|
+
if (mode === "append") return {
|
|
291
|
+
action: "append",
|
|
292
|
+
finalValues: [...existing.values, newValue],
|
|
293
|
+
summary: `Adding to the existing ${existing.type} record (${existing.values.length} value(s) → ${existing.values.length + 1}).`
|
|
294
|
+
};
|
|
295
|
+
return {
|
|
296
|
+
action: "overwrite",
|
|
297
|
+
finalValues: [newValue],
|
|
298
|
+
summary: existing.values.length === 1 ? `Overwriting existing value:\n ${existing.values[0]}\n → ${newValue}` : `Replacing ${existing.values.length} existing values with a single new value.`
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Submit a Route53 UPSERT for a simple (non-alias) resource record set.
|
|
303
|
+
* @param {{
|
|
304
|
+
* profile?: string;
|
|
305
|
+
* hostedZoneId: string;
|
|
306
|
+
* name: string;
|
|
307
|
+
* type: string;
|
|
308
|
+
* ttl: number;
|
|
309
|
+
* values: string[];
|
|
310
|
+
* verbose?: boolean;
|
|
311
|
+
* }} params
|
|
312
|
+
* @returns {any} ChangeInfo from Route53
|
|
313
|
+
*/
|
|
314
|
+
function upsertResourceRecordSet(params) {
|
|
315
|
+
const { profile, hostedZoneId, name, type, ttl, values, verbose } = params;
|
|
316
|
+
const changeBatch = {
|
|
317
|
+
Comment: `mtn aws route53 add-record: ${type} ${name}`,
|
|
318
|
+
Changes: [{
|
|
319
|
+
Action: "UPSERT",
|
|
320
|
+
ResourceRecordSet: {
|
|
321
|
+
Name: withTrailingDot(name),
|
|
322
|
+
Type: type,
|
|
323
|
+
TTL: ttl ?? 300,
|
|
324
|
+
ResourceRecords: values.map((value) => ({ Value: value }))
|
|
325
|
+
}
|
|
326
|
+
}]
|
|
327
|
+
};
|
|
328
|
+
const data = runAws({
|
|
329
|
+
profile,
|
|
330
|
+
args: [
|
|
331
|
+
"route53",
|
|
332
|
+
"change-resource-record-sets",
|
|
333
|
+
"--hosted-zone-id",
|
|
334
|
+
hostedZoneId,
|
|
335
|
+
"--change-batch",
|
|
336
|
+
JSON.stringify(changeBatch)
|
|
337
|
+
],
|
|
338
|
+
verbose
|
|
339
|
+
});
|
|
340
|
+
return data.ChangeInfo ?? data;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Submit a Route53 DELETE for an existing resource record set. Route53 requires
|
|
344
|
+
* the record's exact current definition, so this is driven by the record set
|
|
345
|
+
* returned from {@link getResourceRecordSet} — alias records reuse their
|
|
346
|
+
* AliasTarget; standard records reuse their TTL + values.
|
|
347
|
+
* @param {{
|
|
348
|
+
* profile?: string;
|
|
349
|
+
* hostedZoneId: string;
|
|
350
|
+
* record: ResourceRecordSet;
|
|
351
|
+
* verbose?: boolean;
|
|
352
|
+
* }} params
|
|
353
|
+
* @returns {any} ChangeInfo from Route53
|
|
354
|
+
*/
|
|
355
|
+
function deleteResourceRecordSet(params) {
|
|
356
|
+
const { profile, hostedZoneId, record, verbose } = params;
|
|
357
|
+
/** @type {Record<string, any>} */
|
|
358
|
+
const resourceRecordSet = {
|
|
359
|
+
Name: withTrailingDot(record.name),
|
|
360
|
+
Type: record.type
|
|
361
|
+
};
|
|
362
|
+
if (record.isAlias && record.aliasTarget) resourceRecordSet.AliasTarget = record.aliasTarget;
|
|
363
|
+
else {
|
|
364
|
+
resourceRecordSet.TTL = record.ttl ?? 300;
|
|
365
|
+
resourceRecordSet.ResourceRecords = record.values.map((value) => ({ Value: value }));
|
|
366
|
+
}
|
|
367
|
+
const changeBatch = {
|
|
368
|
+
Comment: `mtn aws route53 remove-record: ${record.type} ${record.name}`,
|
|
369
|
+
Changes: [{
|
|
370
|
+
Action: "DELETE",
|
|
371
|
+
ResourceRecordSet: resourceRecordSet
|
|
372
|
+
}]
|
|
373
|
+
};
|
|
374
|
+
const data = runAws({
|
|
375
|
+
profile,
|
|
376
|
+
args: [
|
|
377
|
+
"route53",
|
|
378
|
+
"change-resource-record-sets",
|
|
379
|
+
"--hosted-zone-id",
|
|
380
|
+
hostedZoneId,
|
|
381
|
+
"--change-batch",
|
|
382
|
+
JSON.stringify(changeBatch)
|
|
383
|
+
],
|
|
384
|
+
verbose
|
|
385
|
+
});
|
|
386
|
+
return data.ChangeInfo ?? data;
|
|
387
|
+
}
|
|
388
|
+
//#endregion
|
|
389
|
+
export { bareHostedZoneId, deleteResourceRecordSet, findCnameConflicts, findHostedZone, formatValues, getRecordSetsAtName, getResourceRecordSet, hostedZoneLabel, listHostedZones, normalizeRecordValue, planRecordChange, resolveRecordName, upsertResourceRecordSet, withTrailingDot, withoutTrailingDot };
|
|
@@ -1,14 +1,111 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
} from "
|
|
4
|
-
import "
|
|
5
|
-
import "
|
|
6
|
-
import "
|
|
7
|
-
import "
|
|
8
|
-
import "
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import { promptYesNo } from "../../utils/tty.js";
|
|
2
|
+
import { AwsCliError, getCallerIdentity, requireCommands } from "../../utils/exec-aws.js";
|
|
3
|
+
import { resolveProfile } from "../../utils/resolve-profile.js";
|
|
4
|
+
import { deleteResourceRecordSet, formatValues, getResourceRecordSet, hostedZoneLabel, withoutTrailingDot } from "../add-record/utils.js";
|
|
5
|
+
import { resolveHostedZone, resolveName, resolveRecordType } from "../add-record/handler.js";
|
|
6
|
+
import { removeRecordOptionsSchema } from "./schema.js";
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
import { ZodError } from "zod";
|
|
9
|
+
//#region src/commands/aws/route53/remove-record/handler.js
|
|
10
|
+
/**
|
|
11
|
+
* `aws route53 remove-record` handler: interactively (or via flags) delete a
|
|
12
|
+
* Route53 resource record set, showing the record before it is removed.
|
|
13
|
+
* @param {unknown} options
|
|
14
|
+
*/
|
|
15
|
+
async function removeRecordCommand(options) {
|
|
16
|
+
try {
|
|
17
|
+
const { profile: profileOption, zone: zoneOption, type: typeOption, name: nameOption, yes, dryRun, verbose } = removeRecordOptionsSchema.parse(options);
|
|
18
|
+
const profile = await resolveProfile({ profile: profileOption });
|
|
19
|
+
if (!profile) {
|
|
20
|
+
console.error(chalk.red("Error: pass --profile or set AWS_PROFILE."));
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
requireCommands(["aws"]);
|
|
24
|
+
const identity = getCallerIdentity({
|
|
25
|
+
profile,
|
|
26
|
+
verbose
|
|
27
|
+
});
|
|
28
|
+
console.log("Caller:");
|
|
29
|
+
console.log(` Account: ${identity.Account}`);
|
|
30
|
+
console.log(` Arn: ${identity.Arn}`);
|
|
31
|
+
console.log("");
|
|
32
|
+
const zone = await resolveHostedZone({
|
|
33
|
+
profile,
|
|
34
|
+
zoneOption,
|
|
35
|
+
verbose
|
|
36
|
+
});
|
|
37
|
+
console.log(`Hosted zone: ${hostedZoneLabel(zone)}`);
|
|
38
|
+
console.log("");
|
|
39
|
+
const type = await resolveRecordType(typeOption);
|
|
40
|
+
const name = await resolveName({
|
|
41
|
+
nameOption,
|
|
42
|
+
zoneName: zone.name
|
|
43
|
+
});
|
|
44
|
+
const existing = getResourceRecordSet({
|
|
45
|
+
profile,
|
|
46
|
+
hostedZoneId: zone.id,
|
|
47
|
+
name,
|
|
48
|
+
type,
|
|
49
|
+
verbose
|
|
50
|
+
});
|
|
51
|
+
if (!existing) {
|
|
52
|
+
console.log(chalk.yellow(`No ${type} record at ${withoutTrailingDot(name)}. Nothing to remove.`));
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
console.log("Record to remove:");
|
|
56
|
+
console.log(` Name: ${withoutTrailingDot(name)}`);
|
|
57
|
+
console.log(` Type: ${type}`);
|
|
58
|
+
if (existing.isAlias) console.log(` Alias: ${withoutTrailingDot(String(existing.aliasTarget?.DNSName ?? ""))}`);
|
|
59
|
+
else {
|
|
60
|
+
if (existing.ttl !== void 0) console.log(` TTL: ${existing.ttl}`);
|
|
61
|
+
console.log(` Value:${formatValues(existing.values)}`);
|
|
62
|
+
}
|
|
63
|
+
console.log("");
|
|
64
|
+
if (dryRun) {
|
|
65
|
+
console.log(chalk.cyan("Dry run — no changes made."));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (!yes) {
|
|
69
|
+
if (!await promptYesNo({
|
|
70
|
+
message: `Delete this ${type} record?`,
|
|
71
|
+
defaultYes: false
|
|
72
|
+
})) {
|
|
73
|
+
console.log("Aborted.");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const changeInfo = deleteResourceRecordSet({
|
|
78
|
+
profile,
|
|
79
|
+
hostedZoneId: zone.id,
|
|
80
|
+
record: existing,
|
|
81
|
+
verbose
|
|
82
|
+
});
|
|
83
|
+
console.log("");
|
|
84
|
+
console.log(chalk.green(`Done. Deleted ${type} ${withoutTrailingDot(name)}.`));
|
|
85
|
+
if (changeInfo?.Id) {
|
|
86
|
+
console.log(` Change ID: ${changeInfo.Id}`);
|
|
87
|
+
console.log(` Status: ${changeInfo.Status ?? "PENDING"}`);
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (error instanceof ZodError) {
|
|
91
|
+
console.error(chalk.red("\n❌ Invalid command options:"));
|
|
92
|
+
error.errors.forEach((err) => {
|
|
93
|
+
console.error(chalk.red(` ${err.path.join(".")}: ${err.message}`));
|
|
94
|
+
});
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
const verbose = options?.verbose || false;
|
|
98
|
+
console.error(chalk.red("\n❌ remove-record failed:"));
|
|
99
|
+
if (error instanceof AwsCliError || error instanceof Error) {
|
|
100
|
+
console.error(chalk.red(` ${error.message}`));
|
|
101
|
+
if (verbose && error.stack) {
|
|
102
|
+
console.error(chalk.gray("\nStack trace:"));
|
|
103
|
+
console.error(chalk.gray(error.stack));
|
|
104
|
+
}
|
|
105
|
+
} else console.error(chalk.red(` ${String(error)}`));
|
|
106
|
+
console.error(chalk.yellow("\n💡 Use --verbose for detailed error information\n"));
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { removeRecordCommand };
|
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
import "
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
} from "../../../../__chunks/QKDDLIWD.js";
|
|
5
|
-
import {
|
|
6
|
-
removeRecordOptionsSchema
|
|
7
|
-
} from "../../../../__chunks/IZFGBYGE.js";
|
|
8
|
-
import "../../../../__chunks/G4NJHFFU.js";
|
|
9
|
-
import "../../../../__chunks/33UYMUQD.js";
|
|
10
|
-
import "../../../../__chunks/IEOGAQYI.js";
|
|
11
|
-
import "../../../../__chunks/FNXUONAV.js";
|
|
12
|
-
import "../../../../__chunks/5GIUAFXL.js";
|
|
13
|
-
import "../../../../__chunks/73BJG53F.js";
|
|
14
|
-
import "../../../../__chunks/ZHKVJO2U.js";
|
|
15
|
-
export {
|
|
16
|
-
removeRecordCommand,
|
|
17
|
-
removeRecordOptionsSchema
|
|
18
|
-
};
|
|
1
|
+
import { removeRecordOptionsSchema } from "./schema.js";
|
|
2
|
+
import { removeRecordCommand } from "./handler.js";
|
|
3
|
+
export { removeRecordCommand, removeRecordOptionsSchema };
|