@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,10 +1,54 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let readline = require("readline");
|
|
3
|
+
//#region src/commands/aws/utils/tty.js
|
|
4
|
+
/**
|
|
5
|
+
* Prompt for a single line of input.
|
|
6
|
+
* @param {string} message - Prompt text shown to the user
|
|
7
|
+
* @returns {Promise<string>}
|
|
8
|
+
*/
|
|
9
|
+
function prompt(message) {
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
const rl = (0, readline.createInterface)({
|
|
12
|
+
input: process.stdin,
|
|
13
|
+
output: process.stdout
|
|
14
|
+
});
|
|
15
|
+
rl.question(message, (answer) => {
|
|
16
|
+
rl.close();
|
|
17
|
+
resolve(answer.trim());
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Prompt the user to pick one option from a numbered list.
|
|
23
|
+
* @param {{ message: string; options: string[] }} params
|
|
24
|
+
* @returns {Promise<number>} Zero-based index of the chosen option
|
|
25
|
+
*/
|
|
26
|
+
async function promptChoice(params) {
|
|
27
|
+
const { message, options } = params;
|
|
28
|
+
if (options.length === 0) throw new Error("promptChoice: no options to choose from");
|
|
29
|
+
console.log(message);
|
|
30
|
+
options.forEach((option, index) => {
|
|
31
|
+
console.log(` ${index + 1}. ${option}`);
|
|
32
|
+
});
|
|
33
|
+
for (;;) {
|
|
34
|
+
const raw = await prompt("Enter number: ");
|
|
35
|
+
const choice = Number.parseInt(raw, 10);
|
|
36
|
+
if (Number.isInteger(choice) && choice >= 1 && choice <= options.length) return choice - 1;
|
|
37
|
+
console.log(`Please enter a number between 1 and ${options.length}.`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Prompt a yes/no question.
|
|
42
|
+
* @param {{ message: string; defaultYes?: boolean }} params
|
|
43
|
+
* @returns {Promise<boolean>}
|
|
44
|
+
*/
|
|
45
|
+
async function promptYesNo(params) {
|
|
46
|
+
const { message, defaultYes = false } = params;
|
|
47
|
+
const answer = (await prompt(`${message}${defaultYes ? " [Y/n]: " : " [y/N]: "}`)).toLowerCase();
|
|
48
|
+
if (answer === "") return defaultYes;
|
|
49
|
+
return answer === "y" || answer === "yes";
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
exports.prompt = prompt;
|
|
53
|
+
exports.promptChoice = promptChoice;
|
|
54
|
+
exports.promptYesNo = promptYesNo;
|
|
@@ -1,11 +1,254 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
require(
|
|
5
|
-
require(
|
|
6
|
-
require(
|
|
7
|
-
require(
|
|
8
|
-
require(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_rolldown_runtime = require("../../../__chunks/VH7oDXx4.cjs");
|
|
3
|
+
const require_commands_aws_utils_tty = require("../../aws/utils/tty.cjs");
|
|
4
|
+
const require_commands_db_create_readonly_user_utils = require("./utils.cjs");
|
|
5
|
+
const require_commands_db_create_readonly_user_mysql = require("./mysql.cjs");
|
|
6
|
+
const require_commands_db_create_readonly_user_postgres = require("./postgres.cjs");
|
|
7
|
+
const require_commands_db_create_readonly_user_schema = require("./schema.cjs");
|
|
8
|
+
let chalk = require("chalk");
|
|
9
|
+
chalk = require_rolldown_runtime.__toESM(chalk, 1);
|
|
10
|
+
let zod = require("zod");
|
|
11
|
+
//#region src/commands/db/create-readonly-user/handler.js
|
|
12
|
+
/**
|
|
13
|
+
* @param {"postgres" | "mysql" | undefined} engineOption
|
|
14
|
+
* @param {string | null} url
|
|
15
|
+
* @returns {Promise<"postgres" | "mysql">}
|
|
16
|
+
*/
|
|
17
|
+
async function resolveEngine(engineOption, url) {
|
|
18
|
+
if (engineOption) return engineOption;
|
|
19
|
+
if (url) {
|
|
20
|
+
const detected = require_commands_db_create_readonly_user_utils.detectEngineFromUrl(url);
|
|
21
|
+
if (detected) return detected;
|
|
22
|
+
}
|
|
23
|
+
const index = await require_commands_aws_utils_tty.promptChoice({
|
|
24
|
+
message: "Choose a database engine:",
|
|
25
|
+
options: ["postgres", "mysql"]
|
|
26
|
+
});
|
|
27
|
+
const chosen = require_commands_db_create_readonly_user_schema.ENGINES[index];
|
|
28
|
+
if (!chosen) throw new Error("No engine selected");
|
|
29
|
+
return chosen;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* @param {{ urlOption?: string; engine: "postgres" | "mysql" }} params
|
|
33
|
+
* @returns {Promise<string>}
|
|
34
|
+
*/
|
|
35
|
+
async function resolveUrl(params) {
|
|
36
|
+
const { urlOption, engine } = params;
|
|
37
|
+
const fromEnv = require_commands_db_create_readonly_user_utils.resolveAdminUrl({
|
|
38
|
+
url: urlOption,
|
|
39
|
+
engine
|
|
40
|
+
});
|
|
41
|
+
if (fromEnv) return fromEnv;
|
|
42
|
+
const raw = await require_commands_aws_utils_tty.prompt(` Admin connection URL (e.g. ${engine === "postgres" ? "postgresql://admin:pass@host:5432/postgres" : "mysql://admin:pass@host:3306/"}): `);
|
|
43
|
+
if (!raw) throw new Error("Admin connection URL is required (pass --url or set DATABASE_URL)");
|
|
44
|
+
return raw;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* @param {{
|
|
48
|
+
* databaseOption?: string;
|
|
49
|
+
* databases: string[];
|
|
50
|
+
* }} params
|
|
51
|
+
* @returns {Promise<{ mode: "all" | "one"; databases: string[] }>}
|
|
52
|
+
*/
|
|
53
|
+
async function resolveScope(params) {
|
|
54
|
+
const { databaseOption, databases } = params;
|
|
55
|
+
if (databaseOption) {
|
|
56
|
+
const normalized = databaseOption.trim().toLowerCase();
|
|
57
|
+
if (normalized === "all" || normalized === "*") return {
|
|
58
|
+
mode: "all",
|
|
59
|
+
databases
|
|
60
|
+
};
|
|
61
|
+
if (!databases.includes(databaseOption)) throw new Error(`Database "${databaseOption}" not found. Available: ${databases.join(", ") || "(none)"}`);
|
|
62
|
+
return {
|
|
63
|
+
mode: "one",
|
|
64
|
+
databases: [databaseOption]
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (databases.length === 0) throw new Error("No user databases found to grant access on.");
|
|
68
|
+
const options = [...databases.map((name) => name), `all (${databases.length} databases)`];
|
|
69
|
+
const index = await require_commands_aws_utils_tty.promptChoice({
|
|
70
|
+
message: "Grant read-only on which database?",
|
|
71
|
+
options
|
|
72
|
+
});
|
|
73
|
+
if (index === options.length - 1) return {
|
|
74
|
+
mode: "all",
|
|
75
|
+
databases
|
|
76
|
+
};
|
|
77
|
+
const chosen = databases[index];
|
|
78
|
+
if (!chosen) throw new Error("No database selected");
|
|
79
|
+
return {
|
|
80
|
+
mode: "one",
|
|
81
|
+
databases: [chosen]
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* @param {string | undefined} usernameOption
|
|
86
|
+
* @returns {Promise<string>}
|
|
87
|
+
*/
|
|
88
|
+
async function resolveUsername(usernameOption) {
|
|
89
|
+
if (usernameOption) return usernameOption;
|
|
90
|
+
const username = await require_commands_aws_utils_tty.prompt(` Read-only username [default: readonly]: `) || "readonly";
|
|
91
|
+
if (!/^[A-Za-z0-9_]+$/.test(username)) throw new Error("Username must contain only letters, numbers, and underscores");
|
|
92
|
+
return username;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* @param {string | undefined} passwordOption
|
|
96
|
+
* @returns {Promise<{ password: string; generated: boolean }>}
|
|
97
|
+
*/
|
|
98
|
+
async function resolvePassword(passwordOption) {
|
|
99
|
+
if (passwordOption) return {
|
|
100
|
+
password: passwordOption,
|
|
101
|
+
generated: false
|
|
102
|
+
};
|
|
103
|
+
if (await require_commands_aws_utils_tty.promptYesNo({
|
|
104
|
+
message: " Generate a random password?",
|
|
105
|
+
defaultYes: true
|
|
106
|
+
})) return {
|
|
107
|
+
password: require_commands_db_create_readonly_user_utils.generatePassword(),
|
|
108
|
+
generated: true
|
|
109
|
+
};
|
|
110
|
+
const password = await require_commands_aws_utils_tty.prompt(" Password: ");
|
|
111
|
+
if (!password) throw new Error("Password is required");
|
|
112
|
+
return {
|
|
113
|
+
password,
|
|
114
|
+
generated: false
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Redact password in a URL for display.
|
|
119
|
+
* @param {string} url
|
|
120
|
+
* @returns {string}
|
|
121
|
+
*/
|
|
122
|
+
function redactUrl(url) {
|
|
123
|
+
try {
|
|
124
|
+
const parsed = new URL(url);
|
|
125
|
+
if (parsed.password) parsed.password = "***";
|
|
126
|
+
return parsed.toString();
|
|
127
|
+
} catch {
|
|
128
|
+
return url;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* `db create-readonly-user` handler.
|
|
133
|
+
* @param {unknown} options
|
|
134
|
+
*/
|
|
135
|
+
async function createReadonlyUserCommand(options) {
|
|
136
|
+
try {
|
|
137
|
+
const { engine: engineOption, url: urlOption, database: databaseOption, username: usernameOption, password: passwordOption, hostPattern: hostPatternOption, ssl: sslOption, yes, dryRun, verbose } = require_commands_db_create_readonly_user_schema.createReadonlyUserOptionsSchema.parse(options);
|
|
138
|
+
console.log(chalk.default.blue("\nCreate read-only database user"));
|
|
139
|
+
console.log("");
|
|
140
|
+
const engine = await resolveEngine(engineOption, require_commands_db_create_readonly_user_utils.resolveAdminUrl({
|
|
141
|
+
url: urlOption,
|
|
142
|
+
engine: engineOption
|
|
143
|
+
}));
|
|
144
|
+
console.log(`Engine: ${engine}`);
|
|
145
|
+
const url = await resolveUrl({
|
|
146
|
+
urlOption,
|
|
147
|
+
engine
|
|
148
|
+
});
|
|
149
|
+
const config = require_commands_db_create_readonly_user_utils.parseConnectionUrl({
|
|
150
|
+
url,
|
|
151
|
+
engine,
|
|
152
|
+
sslOption
|
|
153
|
+
});
|
|
154
|
+
console.log(`Admin: ${config.user}@${config.host}:${config.port}` + (config.database ? `/${config.database}` : ""));
|
|
155
|
+
console.log("");
|
|
156
|
+
const listed = engine === "postgres" ? await require_commands_db_create_readonly_user_postgres.listPostgresDatabases(config) : await require_commands_db_create_readonly_user_mysql.listMysqlDatabases(config);
|
|
157
|
+
if (verbose) {
|
|
158
|
+
console.log(`Found databases: ${listed.join(", ") || "(none)"}`);
|
|
159
|
+
console.log("");
|
|
160
|
+
}
|
|
161
|
+
const scope = await resolveScope({
|
|
162
|
+
databaseOption,
|
|
163
|
+
databases: listed
|
|
164
|
+
});
|
|
165
|
+
console.log(scope.mode === "all" ? `Scope: all (${scope.databases.length} databases)` : `Scope: ${scope.databases[0]}`);
|
|
166
|
+
console.log("");
|
|
167
|
+
const username = await resolveUsername(usernameOption);
|
|
168
|
+
const { password, generated } = await resolvePassword(passwordOption);
|
|
169
|
+
const hostPattern = hostPatternOption ?? "%";
|
|
170
|
+
console.log("");
|
|
171
|
+
console.log("Plan:");
|
|
172
|
+
console.log(` User: ${username}`);
|
|
173
|
+
console.log(` Password: ${generated ? "(generated)" : "(provided)"}${dryRun ? " [dry-run]" : ""}`);
|
|
174
|
+
if (engine === "mysql") console.log(` Host: ${hostPattern}`);
|
|
175
|
+
console.log(scope.mode === "all" ? ` Grants: SELECT on ALL databases (${scope.databases.length})` : ` Grants: SELECT on ${scope.databases[0]}`);
|
|
176
|
+
if (scope.mode === "all" && engine === "postgres") console.log(chalk.default.yellow(" Note: Databases created later will NOT get these grants automatically — re-run this command."));
|
|
177
|
+
console.log("");
|
|
178
|
+
if (!yes && !dryRun) {
|
|
179
|
+
if (!await require_commands_aws_utils_tty.promptYesNo({
|
|
180
|
+
message: "Apply these changes?",
|
|
181
|
+
defaultYes: false
|
|
182
|
+
})) {
|
|
183
|
+
console.log("Aborted.");
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
console.log("");
|
|
187
|
+
}
|
|
188
|
+
const result = engine === "postgres" ? await require_commands_db_create_readonly_user_postgres.applyPostgresReadonly({
|
|
189
|
+
config,
|
|
190
|
+
username,
|
|
191
|
+
password,
|
|
192
|
+
databases: scope.databases,
|
|
193
|
+
dryRun,
|
|
194
|
+
verbose
|
|
195
|
+
}) : await require_commands_db_create_readonly_user_mysql.applyMysqlReadonly({
|
|
196
|
+
config,
|
|
197
|
+
username,
|
|
198
|
+
password,
|
|
199
|
+
databases: scope.mode === "all" ? "all" : scope.databases,
|
|
200
|
+
hostPattern,
|
|
201
|
+
dryRun,
|
|
202
|
+
verbose
|
|
203
|
+
});
|
|
204
|
+
if (dryRun) {
|
|
205
|
+
console.log(chalk.default.cyan("Dry run — SQL that would run:"));
|
|
206
|
+
for (const statement of result.statements) console.log(` ${statement}`);
|
|
207
|
+
console.log("");
|
|
208
|
+
console.log(chalk.default.cyan("No changes made."));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
console.log(chalk.default.green(result.created ? `Created user "${username}" and granted read-only access.` : `Updated user "${username}" password and refreshed read-only grants.`));
|
|
212
|
+
console.log("");
|
|
213
|
+
const sampleDb = scope.mode === "one" ? scope.databases[0] ?? "" : scope.databases[0] ?? "";
|
|
214
|
+
const readonlyUrl = require_commands_db_create_readonly_user_utils.buildReadonlyUrl({
|
|
215
|
+
engine,
|
|
216
|
+
host: config.host,
|
|
217
|
+
port: config.port,
|
|
218
|
+
username,
|
|
219
|
+
password,
|
|
220
|
+
database: sampleDb
|
|
221
|
+
});
|
|
222
|
+
console.log("Connection (secret shown once — copy now):");
|
|
223
|
+
console.log("────────────────────────────────────────────────────────────────");
|
|
224
|
+
console.log(readonlyUrl);
|
|
225
|
+
if (scope.mode === "all") {
|
|
226
|
+
console.log("");
|
|
227
|
+
console.log(chalk.default.gray(` (URL uses database "${sampleDb}" as an example; user can connect to any granted database.)`));
|
|
228
|
+
}
|
|
229
|
+
console.log("────────────────────────────────────────────────────────────────");
|
|
230
|
+
console.log("");
|
|
231
|
+
console.log(chalk.default.gray(`Admin URL used: ${redactUrl(url)}`));
|
|
232
|
+
} catch (error) {
|
|
233
|
+
if (error instanceof zod.ZodError) {
|
|
234
|
+
console.error(chalk.default.red("\n❌ Invalid command options:"));
|
|
235
|
+
error.errors.forEach((err) => {
|
|
236
|
+
console.error(chalk.default.red(` ${err.path.join(".")}: ${err.message}`));
|
|
237
|
+
});
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
const verbose = options?.verbose || false;
|
|
241
|
+
console.error(chalk.default.red("\n❌ create-readonly-user failed:"));
|
|
242
|
+
if (error instanceof Error) {
|
|
243
|
+
console.error(chalk.default.red(` ${error.message}`));
|
|
244
|
+
if (verbose && error.stack) {
|
|
245
|
+
console.error(chalk.default.gray("\nStack trace:"));
|
|
246
|
+
console.error(chalk.default.gray(error.stack));
|
|
247
|
+
}
|
|
248
|
+
} else console.error(chalk.default.red(` ${String(error)}`));
|
|
249
|
+
console.error(chalk.default.yellow("\n💡 Pass --url or set DATABASE_URL. Use --verbose for details.\n"));
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
//#endregion
|
|
254
|
+
exports.createReadonlyUserCommand = createReadonlyUserCommand;
|
|
@@ -1,40 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
var _NWZGFHKHcjs = require('../../../__chunks/NWZGFHKH.cjs');
|
|
24
|
-
require('../../../__chunks/CMUD7LLN.cjs');
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
exports.DEFAULT_MYSQL_HOST_PATTERN = _H74JSDBUcjs.DEFAULT_MYSQL_HOST_PATTERN; exports.DEFAULT_READONLY_USERNAME = _H74JSDBUcjs.DEFAULT_READONLY_USERNAME; exports.ENGINES = _H74JSDBUcjs.ENGINES; exports.buildReadonlyUrl = _NWZGFHKHcjs.buildReadonlyUrl; exports.createReadonlyUserCommand = _LXDF5QVZcjs.createReadonlyUserCommand; exports.createReadonlyUserOptionsSchema = _H74JSDBUcjs.createReadonlyUserOptionsSchema; exports.detectEngineFromUrl = _NWZGFHKHcjs.detectEngineFromUrl; exports.generatePassword = _NWZGFHKHcjs.generatePassword; exports.isSystemDatabase = _NWZGFHKHcjs.isSystemDatabase; exports.parseConnectionUrl = _NWZGFHKHcjs.parseConnectionUrl; exports.quoteIdent = _NWZGFHKHcjs.quoteIdent; exports.quoteLiteral = _NWZGFHKHcjs.quoteLiteral; exports.resolveAdminUrl = _NWZGFHKHcjs.resolveAdminUrl; exports.resolveSsl = _NWZGFHKHcjs.resolveSsl;
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_commands_db_create_readonly_user_utils = require("./utils.cjs");
|
|
3
|
+
const require_commands_db_create_readonly_user_schema = require("./schema.cjs");
|
|
4
|
+
const require_commands_db_create_readonly_user_handler = require("./handler.cjs");
|
|
5
|
+
exports.DEFAULT_MYSQL_HOST_PATTERN = require_commands_db_create_readonly_user_schema.DEFAULT_MYSQL_HOST_PATTERN;
|
|
6
|
+
exports.DEFAULT_READONLY_USERNAME = require_commands_db_create_readonly_user_schema.DEFAULT_READONLY_USERNAME;
|
|
7
|
+
exports.ENGINES = require_commands_db_create_readonly_user_schema.ENGINES;
|
|
8
|
+
exports.buildReadonlyUrl = require_commands_db_create_readonly_user_utils.buildReadonlyUrl;
|
|
9
|
+
exports.createReadonlyUserCommand = require_commands_db_create_readonly_user_handler.createReadonlyUserCommand;
|
|
10
|
+
exports.createReadonlyUserOptionsSchema = require_commands_db_create_readonly_user_schema.createReadonlyUserOptionsSchema;
|
|
11
|
+
exports.detectEngineFromUrl = require_commands_db_create_readonly_user_utils.detectEngineFromUrl;
|
|
12
|
+
exports.generatePassword = require_commands_db_create_readonly_user_utils.generatePassword;
|
|
13
|
+
exports.isSystemDatabase = require_commands_db_create_readonly_user_utils.isSystemDatabase;
|
|
14
|
+
exports.parseConnectionUrl = require_commands_db_create_readonly_user_utils.parseConnectionUrl;
|
|
15
|
+
exports.quoteIdent = require_commands_db_create_readonly_user_utils.quoteIdent;
|
|
16
|
+
exports.quoteLiteral = require_commands_db_create_readonly_user_utils.quoteLiteral;
|
|
17
|
+
exports.resolveAdminUrl = require_commands_db_create_readonly_user_utils.resolveAdminUrl;
|
|
18
|
+
exports.resolveSsl = require_commands_db_create_readonly_user_utils.resolveSsl;
|
|
@@ -1,9 +1,102 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_rolldown_runtime = require("../../../__chunks/VH7oDXx4.cjs");
|
|
3
|
+
const require_commands_db_create_readonly_user_utils = require("./utils.cjs");
|
|
4
|
+
let mysql2_promise = require("mysql2/promise");
|
|
5
|
+
mysql2_promise = require_rolldown_runtime.__toESM(mysql2_promise, 1);
|
|
6
|
+
//#region src/commands/db/create-readonly-user/mysql.js
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {import("./utils.js").ConnectionConfig} ConnectionConfig
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* @param {ConnectionConfig} config
|
|
12
|
+
* @returns {Promise<import("mysql2/promise").Connection>}
|
|
13
|
+
*/
|
|
14
|
+
async function createConnection(config) {
|
|
15
|
+
return mysql2_promise.default.createConnection({
|
|
16
|
+
host: config.host,
|
|
17
|
+
port: config.port,
|
|
18
|
+
user: config.user,
|
|
19
|
+
password: config.password,
|
|
20
|
+
database: config.database || void 0,
|
|
21
|
+
ssl: config.ssl && typeof config.ssl === "object" ? config.ssl : void 0,
|
|
22
|
+
multipleStatements: false
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* List schemas/databases visible to the admin user (excluding system schemas).
|
|
27
|
+
* @param {ConnectionConfig} config
|
|
28
|
+
* @returns {Promise<string[]>}
|
|
29
|
+
*/
|
|
30
|
+
async function listMysqlDatabases(config) {
|
|
31
|
+
const connection = await createConnection(config);
|
|
32
|
+
try {
|
|
33
|
+
const [rows] = await connection.query("SHOW DATABASES");
|
|
34
|
+
return rows.map((row) => row.Database ?? "").filter((name) => Boolean(name)).filter((name) => !require_commands_db_create_readonly_user_utils.isSystemDatabase({
|
|
35
|
+
engine: "mysql",
|
|
36
|
+
name
|
|
37
|
+
})).sort((a, b) => a.localeCompare(b));
|
|
38
|
+
} finally {
|
|
39
|
+
await connection.end();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Create/update a MySQL user and grant SELECT on one database or *.* .
|
|
44
|
+
* @param {{
|
|
45
|
+
* config: ConnectionConfig;
|
|
46
|
+
* username: string;
|
|
47
|
+
* password: string;
|
|
48
|
+
* databases: string[] | "all";
|
|
49
|
+
* hostPattern: string;
|
|
50
|
+
* dryRun?: boolean;
|
|
51
|
+
* verbose?: boolean;
|
|
52
|
+
* }} params
|
|
53
|
+
* @returns {Promise<{ created: boolean; statements: string[]; databases: string[] | "all" }>}
|
|
54
|
+
*/
|
|
55
|
+
async function applyMysqlReadonly(params) {
|
|
56
|
+
const { config, username, password, databases, hostPattern, dryRun = false, verbose = false } = params;
|
|
57
|
+
const userLiteral = require_commands_db_create_readonly_user_utils.quoteLiteral(username);
|
|
58
|
+
const hostLiteral = require_commands_db_create_readonly_user_utils.quoteLiteral(hostPattern);
|
|
59
|
+
const passwordLiteral = require_commands_db_create_readonly_user_utils.quoteLiteral(password);
|
|
60
|
+
const account = `${userLiteral}@${hostLiteral}`;
|
|
61
|
+
/** @type {string[]} */
|
|
62
|
+
const statements = [];
|
|
63
|
+
const createSql = `CREATE USER IF NOT EXISTS ${account} IDENTIFIED BY ${passwordLiteral}`;
|
|
64
|
+
const alterSql = `ALTER USER ${account} IDENTIFIED BY ${passwordLiteral}`;
|
|
65
|
+
/** @type {string[]} */
|
|
66
|
+
const grantSqls = [];
|
|
67
|
+
if (databases === "all") grantSqls.push(`GRANT SELECT, SHOW VIEW, SHOW DATABASES ON *.* TO ${account}`);
|
|
68
|
+
else for (const database of databases) {
|
|
69
|
+
const dbIdent = require_commands_db_create_readonly_user_utils.quoteIdent({
|
|
70
|
+
engine: "mysql",
|
|
71
|
+
name: database
|
|
72
|
+
});
|
|
73
|
+
grantSqls.push(`GRANT SELECT, SHOW VIEW ON ${dbIdent}.* TO ${account}`);
|
|
74
|
+
}
|
|
75
|
+
const flushSql = "FLUSH PRIVILEGES";
|
|
76
|
+
statements.push(createSql, alterSql, ...grantSqls, flushSql);
|
|
77
|
+
if (dryRun) return {
|
|
78
|
+
created: true,
|
|
79
|
+
statements: statements.map((sql) => sql.includes("IDENTIFIED BY") ? sql.replace(/IDENTIFIED BY '.*'/, "IDENTIFIED BY ***") : sql),
|
|
80
|
+
databases
|
|
81
|
+
};
|
|
82
|
+
const connection = await createConnection(config);
|
|
83
|
+
try {
|
|
84
|
+
if (verbose) console.log(` Connected to MySQL as ${config.user}@${config.host}`);
|
|
85
|
+
const [existingRows] = await connection.query("SELECT 1 AS ok FROM mysql.user WHERE User = ? AND Host = ? LIMIT 1", [username, hostPattern]);
|
|
86
|
+
const existed = Array.isArray(existingRows) && existingRows.length > 0;
|
|
87
|
+
await connection.query(createSql);
|
|
88
|
+
await connection.query(alterSql);
|
|
89
|
+
for (const grantSql of grantSqls) await connection.query(grantSql);
|
|
90
|
+
await connection.query(flushSql);
|
|
91
|
+
return {
|
|
92
|
+
created: !existed,
|
|
93
|
+
statements: statements.map((sql) => sql.includes("IDENTIFIED BY") ? sql.replace(/IDENTIFIED BY '.*'/, "IDENTIFIED BY ***") : sql),
|
|
94
|
+
databases
|
|
95
|
+
};
|
|
96
|
+
} finally {
|
|
97
|
+
await connection.end();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
exports.applyMysqlReadonly = applyMysqlReadonly;
|
|
102
|
+
exports.listMysqlDatabases = listMysqlDatabases;
|