trello-cli-unofficial 0.9.6 → 0.10.0
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 +15 -0
- package/bun.lock +5 -2
- package/dist/main.js +46 -350
- package/dist/trello-cli-unofficial-0.10.0.tgz +0 -0
- package/main.ts +0 -1
- package/package.json +7 -9
- package/src/i18n/locales/en.json +1 -0
- package/src/i18n/locales/pt-BR.json +1 -0
- package/src/presentation/cli/CommandController.ts +17 -4
- package/dist/trello-cli-unofficial-0.9.6.tgz +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
# [0.10.0](https://github.com/JaegerCaiser/trello-cli-unofficial/compare/v0.9.6...v0.10.0) (2025-11-14)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* configure lint-staged to detect JSON issues without auto-fix ([31cf1f9](https://github.com/JaegerCaiser/trello-cli-unofficial/commit/31cf1f9e22b767bb82bd1ba55969af6e9cfa5b55))
|
|
7
|
+
* correct lint-staged configuration and add pre-commit hook ([030b957](https://github.com/JaegerCaiser/trello-cli-unofficial/commit/030b9575707e6062e826de225c5c7c7289807d98))
|
|
8
|
+
* remove dotenv verbose logging messages for cleaner CLI output ([ece06aa](https://github.com/JaegerCaiser/trello-cli-unofficial/commit/ece06aa62bfd92b3a45e3c506c4b9c7829e99e9b))
|
|
9
|
+
* replace manual git hooks with husky ([18d3057](https://github.com/JaegerCaiser/trello-cli-unofficial/commit/18d3057385756a4a75ba186a124b4d6a18f8cb83))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
* implement dynamic version display from package.json ([5d2c9e3](https://github.com/JaegerCaiser/trello-cli-unofficial/commit/5d2c9e30b0ed0dc44d65307e02ee84fbd694192f))
|
|
15
|
+
|
|
1
16
|
## [0.9.6](https://github.com/JaegerCaiser/trello-cli-unofficial/compare/v0.9.5...v0.9.6) (2025-11-14)
|
|
2
17
|
|
|
3
18
|
|
package/bun.lock
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"@types/node": "^24.10.0",
|
|
9
9
|
"bun": "^1.3.2",
|
|
10
10
|
"commander": "^14.0.2",
|
|
11
|
-
"dotenv": "^
|
|
11
|
+
"dotenv": "^15.0.1",
|
|
12
12
|
"fs-extra": "^11.3.2",
|
|
13
13
|
"i18next": "^25.6.1",
|
|
14
14
|
"inquirer": "^12.10.0",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"@types/inquirer": "^9.0.9",
|
|
23
23
|
"eslint": "^9.39.1",
|
|
24
24
|
"eslint-plugin-format": "^1.0.2",
|
|
25
|
+
"husky": "^9.1.7",
|
|
25
26
|
"lint-staged": "^16.2.6",
|
|
26
27
|
},
|
|
27
28
|
"peerDependencies": {
|
|
@@ -372,7 +373,7 @@
|
|
|
372
373
|
|
|
373
374
|
"dot-prop": ["dot-prop@5.3.0", "", { "dependencies": { "is-obj": "^2.0.0" } }, "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q=="],
|
|
374
375
|
|
|
375
|
-
"dotenv": ["dotenv@
|
|
376
|
+
"dotenv": ["dotenv@15.0.1", "", {}, "sha512-4OnbwRfzR+xQThp7uq1xpUS9fmgZ//njexOtPjPSbK3yHGrSHSJnaJRsXderSSm2elfvVj+Y5awDC0I8Oy8rkA=="],
|
|
376
377
|
|
|
377
378
|
"electron-to-chromium": ["electron-to-chromium@1.5.249", "", {}, "sha512-5vcfL3BBe++qZ5kuFhD/p8WOM1N9m3nwvJPULJx+4xf2usSlZFJ0qoNYO2fOX4hi3ocuDcmDobtA+5SFr4OmBg=="],
|
|
378
379
|
|
|
@@ -526,6 +527,8 @@
|
|
|
526
527
|
|
|
527
528
|
"html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="],
|
|
528
529
|
|
|
530
|
+
"husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="],
|
|
531
|
+
|
|
529
532
|
"i18next": ["i18next@25.6.1", "", { "dependencies": { "@babel/runtime": "^7.27.6" }, "peerDependencies": { "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-yUWvdXtalZztmKrKw3yz/AvSP3yKyqIkVPx/wyvoYy9lkLmwzItLxp0iHZLG5hfVQ539Jor4XLO+U+NHIXg7pw=="],
|
|
530
533
|
|
|
531
534
|
"iconv-lite": ["iconv-lite@0.7.0", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ=="],
|
package/dist/main.js
CHANGED
|
@@ -30,114 +30,12 @@ var __export = (target, all) => {
|
|
|
30
30
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
31
31
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
32
32
|
|
|
33
|
-
// node_modules/dotenv/package.json
|
|
34
|
-
var require_package = __commonJS((exports, module) => {
|
|
35
|
-
module.exports = {
|
|
36
|
-
name: "dotenv",
|
|
37
|
-
version: "17.2.3",
|
|
38
|
-
description: "Loads environment variables from .env file",
|
|
39
|
-
main: "lib/main.js",
|
|
40
|
-
types: "lib/main.d.ts",
|
|
41
|
-
exports: {
|
|
42
|
-
".": {
|
|
43
|
-
types: "./lib/main.d.ts",
|
|
44
|
-
require: "./lib/main.js",
|
|
45
|
-
default: "./lib/main.js"
|
|
46
|
-
},
|
|
47
|
-
"./config": "./config.js",
|
|
48
|
-
"./config.js": "./config.js",
|
|
49
|
-
"./lib/env-options": "./lib/env-options.js",
|
|
50
|
-
"./lib/env-options.js": "./lib/env-options.js",
|
|
51
|
-
"./lib/cli-options": "./lib/cli-options.js",
|
|
52
|
-
"./lib/cli-options.js": "./lib/cli-options.js",
|
|
53
|
-
"./package.json": "./package.json"
|
|
54
|
-
},
|
|
55
|
-
scripts: {
|
|
56
|
-
"dts-check": "tsc --project tests/types/tsconfig.json",
|
|
57
|
-
lint: "standard",
|
|
58
|
-
pretest: "npm run lint && npm run dts-check",
|
|
59
|
-
test: "tap run tests/**/*.js --allow-empty-coverage --disable-coverage --timeout=60000",
|
|
60
|
-
"test:coverage": "tap run tests/**/*.js --show-full-coverage --timeout=60000 --coverage-report=text --coverage-report=lcov",
|
|
61
|
-
prerelease: "npm test",
|
|
62
|
-
release: "standard-version"
|
|
63
|
-
},
|
|
64
|
-
repository: {
|
|
65
|
-
type: "git",
|
|
66
|
-
url: "git://github.com/motdotla/dotenv.git"
|
|
67
|
-
},
|
|
68
|
-
homepage: "https://github.com/motdotla/dotenv#readme",
|
|
69
|
-
funding: "https://dotenvx.com",
|
|
70
|
-
keywords: [
|
|
71
|
-
"dotenv",
|
|
72
|
-
"env",
|
|
73
|
-
".env",
|
|
74
|
-
"environment",
|
|
75
|
-
"variables",
|
|
76
|
-
"config",
|
|
77
|
-
"settings"
|
|
78
|
-
],
|
|
79
|
-
readmeFilename: "README.md",
|
|
80
|
-
license: "BSD-2-Clause",
|
|
81
|
-
devDependencies: {
|
|
82
|
-
"@types/node": "^18.11.3",
|
|
83
|
-
decache: "^4.6.2",
|
|
84
|
-
sinon: "^14.0.1",
|
|
85
|
-
standard: "^17.0.0",
|
|
86
|
-
"standard-version": "^9.5.0",
|
|
87
|
-
tap: "^19.2.0",
|
|
88
|
-
typescript: "^4.8.4"
|
|
89
|
-
},
|
|
90
|
-
engines: {
|
|
91
|
-
node: ">=12"
|
|
92
|
-
},
|
|
93
|
-
browser: {
|
|
94
|
-
fs: false
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
});
|
|
98
|
-
|
|
99
33
|
// node_modules/dotenv/lib/main.js
|
|
100
34
|
var require_main = __commonJS((exports, module) => {
|
|
101
35
|
var fs = __require("fs");
|
|
102
36
|
var path = __require("path");
|
|
103
37
|
var os = __require("os");
|
|
104
|
-
var
|
|
105
|
-
var packageJson = require_package();
|
|
106
|
-
var version = packageJson.version;
|
|
107
|
-
var TIPS = [
|
|
108
|
-
"\uD83D\uDD10 encrypt with Dotenvx: https://dotenvx.com",
|
|
109
|
-
"\uD83D\uDD10 prevent committing .env to code: https://dotenvx.com/precommit",
|
|
110
|
-
"\uD83D\uDD10 prevent building .env in docker: https://dotenvx.com/prebuild",
|
|
111
|
-
"\uD83D\uDCE1 add observability to secrets: https://dotenvx.com/ops",
|
|
112
|
-
"\uD83D\uDC65 sync secrets across teammates & machines: https://dotenvx.com/ops",
|
|
113
|
-
"\uD83D\uDDC2️ backup and recover secrets: https://dotenvx.com/ops",
|
|
114
|
-
"✅ audit secrets and track compliance: https://dotenvx.com/ops",
|
|
115
|
-
"\uD83D\uDD04 add secrets lifecycle management: https://dotenvx.com/ops",
|
|
116
|
-
"\uD83D\uDD11 add access controls to secrets: https://dotenvx.com/ops",
|
|
117
|
-
"\uD83D\uDEE0️ run anywhere with `dotenvx run -- yourcommand`",
|
|
118
|
-
"⚙️ specify custom .env file path with { path: '/custom/path/.env' }",
|
|
119
|
-
"⚙️ enable debug logging with { debug: true }",
|
|
120
|
-
"⚙️ override existing env vars with { override: true }",
|
|
121
|
-
"⚙️ suppress all logs with { quiet: true }",
|
|
122
|
-
"⚙️ write to custom object with { processEnv: myObject }",
|
|
123
|
-
"⚙️ load multiple .env files with { path: ['.env.local', '.env'] }"
|
|
124
|
-
];
|
|
125
|
-
function _getRandomTip() {
|
|
126
|
-
return TIPS[Math.floor(Math.random() * TIPS.length)];
|
|
127
|
-
}
|
|
128
|
-
function parseBoolean(value) {
|
|
129
|
-
if (typeof value === "string") {
|
|
130
|
-
return !["false", "0", "no", "off", ""].includes(value.toLowerCase());
|
|
131
|
-
}
|
|
132
|
-
return Boolean(value);
|
|
133
|
-
}
|
|
134
|
-
function supportsAnsi() {
|
|
135
|
-
return process.stdout.isTTY;
|
|
136
|
-
}
|
|
137
|
-
function dim(text) {
|
|
138
|
-
return supportsAnsi() ? `\x1B[2m${text}\x1B[0m` : text;
|
|
139
|
-
}
|
|
140
|
-
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
38
|
+
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
141
39
|
function parse(src) {
|
|
142
40
|
const obj = {};
|
|
143
41
|
let lines = src.toString();
|
|
@@ -149,7 +47,7 @@ var require_main = __commonJS((exports, module) => {
|
|
|
149
47
|
let value = match[2] || "";
|
|
150
48
|
value = value.trim();
|
|
151
49
|
const maybeQuote = value[0];
|
|
152
|
-
value = value.replace(/^(['"
|
|
50
|
+
value = value.replace(/^(['"])([\s\S]*)\1$/mg, "$2");
|
|
153
51
|
if (maybeQuote === '"') {
|
|
154
52
|
value = value.replace(/\\n/g, `
|
|
155
53
|
`);
|
|
@@ -159,269 +57,57 @@ var require_main = __commonJS((exports, module) => {
|
|
|
159
57
|
}
|
|
160
58
|
return obj;
|
|
161
59
|
}
|
|
162
|
-
function _parseVault(options) {
|
|
163
|
-
options = options || {};
|
|
164
|
-
const vaultPath = _vaultPath(options);
|
|
165
|
-
options.path = vaultPath;
|
|
166
|
-
const result = DotenvModule.configDotenv(options);
|
|
167
|
-
if (!result.parsed) {
|
|
168
|
-
const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
|
|
169
|
-
err.code = "MISSING_DATA";
|
|
170
|
-
throw err;
|
|
171
|
-
}
|
|
172
|
-
const keys = _dotenvKey(options).split(",");
|
|
173
|
-
const length = keys.length;
|
|
174
|
-
let decrypted;
|
|
175
|
-
for (let i = 0;i < length; i++) {
|
|
176
|
-
try {
|
|
177
|
-
const key = keys[i].trim();
|
|
178
|
-
const attrs = _instructions(result, key);
|
|
179
|
-
decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
|
|
180
|
-
break;
|
|
181
|
-
} catch (error) {
|
|
182
|
-
if (i + 1 >= length) {
|
|
183
|
-
throw error;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return DotenvModule.parse(decrypted);
|
|
188
|
-
}
|
|
189
|
-
function _warn(message) {
|
|
190
|
-
console.error(`[dotenv@${version}][WARN] ${message}`);
|
|
191
|
-
}
|
|
192
|
-
function _debug(message) {
|
|
193
|
-
console.log(`[dotenv@${version}][DEBUG] ${message}`);
|
|
194
|
-
}
|
|
195
60
|
function _log(message) {
|
|
196
|
-
console.log(`[dotenv
|
|
197
|
-
}
|
|
198
|
-
function _dotenvKey(options) {
|
|
199
|
-
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
|
|
200
|
-
return options.DOTENV_KEY;
|
|
201
|
-
}
|
|
202
|
-
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
|
|
203
|
-
return process.env.DOTENV_KEY;
|
|
204
|
-
}
|
|
205
|
-
return "";
|
|
206
|
-
}
|
|
207
|
-
function _instructions(result, dotenvKey) {
|
|
208
|
-
let uri;
|
|
209
|
-
try {
|
|
210
|
-
uri = new URL(dotenvKey);
|
|
211
|
-
} catch (error) {
|
|
212
|
-
if (error.code === "ERR_INVALID_URL") {
|
|
213
|
-
const err = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
|
|
214
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
215
|
-
throw err;
|
|
216
|
-
}
|
|
217
|
-
throw error;
|
|
218
|
-
}
|
|
219
|
-
const key = uri.password;
|
|
220
|
-
if (!key) {
|
|
221
|
-
const err = new Error("INVALID_DOTENV_KEY: Missing key part");
|
|
222
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
223
|
-
throw err;
|
|
224
|
-
}
|
|
225
|
-
const environment = uri.searchParams.get("environment");
|
|
226
|
-
if (!environment) {
|
|
227
|
-
const err = new Error("INVALID_DOTENV_KEY: Missing environment part");
|
|
228
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
229
|
-
throw err;
|
|
230
|
-
}
|
|
231
|
-
const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
|
|
232
|
-
const ciphertext = result.parsed[environmentKey];
|
|
233
|
-
if (!ciphertext) {
|
|
234
|
-
const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
|
|
235
|
-
err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
|
|
236
|
-
throw err;
|
|
237
|
-
}
|
|
238
|
-
return { ciphertext, key };
|
|
239
|
-
}
|
|
240
|
-
function _vaultPath(options) {
|
|
241
|
-
let possibleVaultPath = null;
|
|
242
|
-
if (options && options.path && options.path.length > 0) {
|
|
243
|
-
if (Array.isArray(options.path)) {
|
|
244
|
-
for (const filepath of options.path) {
|
|
245
|
-
if (fs.existsSync(filepath)) {
|
|
246
|
-
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
} else {
|
|
250
|
-
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
251
|
-
}
|
|
252
|
-
} else {
|
|
253
|
-
possibleVaultPath = path.resolve(process.cwd(), ".env.vault");
|
|
254
|
-
}
|
|
255
|
-
if (fs.existsSync(possibleVaultPath)) {
|
|
256
|
-
return possibleVaultPath;
|
|
257
|
-
}
|
|
258
|
-
return null;
|
|
61
|
+
console.log(`[dotenv][DEBUG] ${message}`);
|
|
259
62
|
}
|
|
260
63
|
function _resolveHome(envPath) {
|
|
261
64
|
return envPath[0] === "~" ? path.join(os.homedir(), envPath.slice(1)) : envPath;
|
|
262
65
|
}
|
|
263
|
-
function
|
|
264
|
-
|
|
265
|
-
const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options && options.quiet);
|
|
266
|
-
if (debug || !quiet) {
|
|
267
|
-
_log("Loading env from encrypted .env.vault");
|
|
268
|
-
}
|
|
269
|
-
const parsed = DotenvModule._parseVault(options);
|
|
270
|
-
let processEnv = process.env;
|
|
271
|
-
if (options && options.processEnv != null) {
|
|
272
|
-
processEnv = options.processEnv;
|
|
273
|
-
}
|
|
274
|
-
DotenvModule.populate(processEnv, parsed, options);
|
|
275
|
-
return { parsed };
|
|
276
|
-
}
|
|
277
|
-
function configDotenv(options) {
|
|
278
|
-
const dotenvPath = path.resolve(process.cwd(), ".env");
|
|
66
|
+
function config(options) {
|
|
67
|
+
let dotenvPath = path.resolve(process.cwd(), ".env");
|
|
279
68
|
let encoding = "utf8";
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options && options.quiet);
|
|
286
|
-
if (options && options.encoding) {
|
|
287
|
-
encoding = options.encoding;
|
|
288
|
-
} else {
|
|
289
|
-
if (debug) {
|
|
290
|
-
_debug("No encoding is specified. UTF-8 is used by default");
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
let optionPaths = [dotenvPath];
|
|
294
|
-
if (options && options.path) {
|
|
295
|
-
if (!Array.isArray(options.path)) {
|
|
296
|
-
optionPaths = [_resolveHome(options.path)];
|
|
297
|
-
} else {
|
|
298
|
-
optionPaths = [];
|
|
299
|
-
for (const filepath of options.path) {
|
|
300
|
-
optionPaths.push(_resolveHome(filepath));
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
let lastError;
|
|
305
|
-
const parsedAll = {};
|
|
306
|
-
for (const path2 of optionPaths) {
|
|
307
|
-
try {
|
|
308
|
-
const parsed = DotenvModule.parse(fs.readFileSync(path2, { encoding }));
|
|
309
|
-
DotenvModule.populate(parsedAll, parsed, options);
|
|
310
|
-
} catch (e) {
|
|
311
|
-
if (debug) {
|
|
312
|
-
_debug(`Failed to load ${path2} ${e.message}`);
|
|
313
|
-
}
|
|
314
|
-
lastError = e;
|
|
69
|
+
const debug = Boolean(options && options.debug);
|
|
70
|
+
const override = Boolean(options && options.override);
|
|
71
|
+
if (options) {
|
|
72
|
+
if (options.path != null) {
|
|
73
|
+
dotenvPath = _resolveHome(options.path);
|
|
315
74
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug);
|
|
319
|
-
quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet);
|
|
320
|
-
if (debug || !quiet) {
|
|
321
|
-
const keysCount = Object.keys(populated).length;
|
|
322
|
-
const shortPaths = [];
|
|
323
|
-
for (const filePath of optionPaths) {
|
|
324
|
-
try {
|
|
325
|
-
const relative = path.relative(process.cwd(), filePath);
|
|
326
|
-
shortPaths.push(relative);
|
|
327
|
-
} catch (e) {
|
|
328
|
-
if (debug) {
|
|
329
|
-
_debug(`Failed to load ${filePath} ${e.message}`);
|
|
330
|
-
}
|
|
331
|
-
lastError = e;
|
|
332
|
-
}
|
|
75
|
+
if (options.encoding != null) {
|
|
76
|
+
encoding = options.encoding;
|
|
333
77
|
}
|
|
334
|
-
_log(`injecting env (${keysCount}) from ${shortPaths.join(",")} ${dim(`-- tip: ${_getRandomTip()}`)}`);
|
|
335
78
|
}
|
|
336
|
-
if (lastError) {
|
|
337
|
-
return { parsed: parsedAll, error: lastError };
|
|
338
|
-
} else {
|
|
339
|
-
return { parsed: parsedAll };
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
function config(options) {
|
|
343
|
-
if (_dotenvKey(options).length === 0) {
|
|
344
|
-
return DotenvModule.configDotenv(options);
|
|
345
|
-
}
|
|
346
|
-
const vaultPath = _vaultPath(options);
|
|
347
|
-
if (!vaultPath) {
|
|
348
|
-
_warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
|
|
349
|
-
return DotenvModule.configDotenv(options);
|
|
350
|
-
}
|
|
351
|
-
return DotenvModule._configVault(options);
|
|
352
|
-
}
|
|
353
|
-
function decrypt(encrypted, keyStr) {
|
|
354
|
-
const key = Buffer.from(keyStr.slice(-64), "hex");
|
|
355
|
-
let ciphertext = Buffer.from(encrypted, "base64");
|
|
356
|
-
const nonce = ciphertext.subarray(0, 12);
|
|
357
|
-
const authTag = ciphertext.subarray(-16);
|
|
358
|
-
ciphertext = ciphertext.subarray(12, -16);
|
|
359
79
|
try {
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
const invalidKeyLength = error.message === "Invalid key length";
|
|
366
|
-
const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
|
|
367
|
-
if (isRange || invalidKeyLength) {
|
|
368
|
-
const err = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
|
|
369
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
370
|
-
throw err;
|
|
371
|
-
} else if (decryptionFailed) {
|
|
372
|
-
const err = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
|
|
373
|
-
err.code = "DECRYPTION_FAILED";
|
|
374
|
-
throw err;
|
|
375
|
-
} else {
|
|
376
|
-
throw error;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
function populate(processEnv, parsed, options = {}) {
|
|
381
|
-
const debug = Boolean(options && options.debug);
|
|
382
|
-
const override = Boolean(options && options.override);
|
|
383
|
-
const populated = {};
|
|
384
|
-
if (typeof parsed !== "object") {
|
|
385
|
-
const err = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
|
|
386
|
-
err.code = "OBJECT_REQUIRED";
|
|
387
|
-
throw err;
|
|
388
|
-
}
|
|
389
|
-
for (const key of Object.keys(parsed)) {
|
|
390
|
-
if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
|
|
391
|
-
if (override === true) {
|
|
392
|
-
processEnv[key] = parsed[key];
|
|
393
|
-
populated[key] = parsed[key];
|
|
394
|
-
}
|
|
395
|
-
if (debug) {
|
|
80
|
+
const parsed = DotenvModule.parse(fs.readFileSync(dotenvPath, { encoding }));
|
|
81
|
+
Object.keys(parsed).forEach(function(key) {
|
|
82
|
+
if (!Object.prototype.hasOwnProperty.call(process.env, key)) {
|
|
83
|
+
process.env[key] = parsed[key];
|
|
84
|
+
} else {
|
|
396
85
|
if (override === true) {
|
|
397
|
-
|
|
398
|
-
}
|
|
399
|
-
|
|
86
|
+
process.env[key] = parsed[key];
|
|
87
|
+
}
|
|
88
|
+
if (debug) {
|
|
89
|
+
if (override === true) {
|
|
90
|
+
_log(`"${key}" is already defined in \`process.env\` and WAS overwritten`);
|
|
91
|
+
} else {
|
|
92
|
+
_log(`"${key}" is already defined in \`process.env\` and was NOT overwritten`);
|
|
93
|
+
}
|
|
400
94
|
}
|
|
401
95
|
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
|
|
96
|
+
});
|
|
97
|
+
return { parsed };
|
|
98
|
+
} catch (e) {
|
|
99
|
+
if (debug) {
|
|
100
|
+
_log(`Failed to load ${dotenvPath} ${e.message}`);
|
|
405
101
|
}
|
|
102
|
+
return { error: e };
|
|
406
103
|
}
|
|
407
|
-
return populated;
|
|
408
104
|
}
|
|
409
105
|
var DotenvModule = {
|
|
410
|
-
configDotenv,
|
|
411
|
-
_configVault,
|
|
412
|
-
_parseVault,
|
|
413
106
|
config,
|
|
414
|
-
|
|
415
|
-
parse,
|
|
416
|
-
populate
|
|
107
|
+
parse
|
|
417
108
|
};
|
|
418
|
-
exports.configDotenv = DotenvModule.configDotenv;
|
|
419
|
-
exports._configVault = DotenvModule._configVault;
|
|
420
|
-
exports._parseVault = DotenvModule._parseVault;
|
|
421
109
|
exports.config = DotenvModule.config;
|
|
422
|
-
exports.decrypt = DotenvModule.decrypt;
|
|
423
110
|
exports.parse = DotenvModule.parse;
|
|
424
|
-
exports.populate = DotenvModule.populate;
|
|
425
111
|
module.exports = DotenvModule;
|
|
426
112
|
});
|
|
427
113
|
|
|
@@ -2941,6 +2627,7 @@ var require_en = __commonJS((exports, module) => {
|
|
|
2941
2627
|
commands: {
|
|
2942
2628
|
description: "Unofficial Trello CLI using Power-Up authentication",
|
|
2943
2629
|
formatOption: "Output format: table, json, csv",
|
|
2630
|
+
versionOption: "output the version number",
|
|
2944
2631
|
deprecated: {
|
|
2945
2632
|
boardsLegacyDescription: '[DEPRECATED] Use "boards list" instead',
|
|
2946
2633
|
boardsLegacyWarning: '⚠️ Warning: "boards" command is deprecated. Use "boards list" instead.',
|
|
@@ -3211,6 +2898,7 @@ var require_pt_BR = __commonJS((exports, module) => {
|
|
|
3211
2898
|
commands: {
|
|
3212
2899
|
description: "CLI não oficial do Trello usando autenticação Power-Up",
|
|
3213
2900
|
formatOption: "Formato de saída: table, json, csv",
|
|
2901
|
+
versionOption: "exibe o número da versão",
|
|
3214
2902
|
deprecated: {
|
|
3215
2903
|
boardsLegacyDescription: '[DEPRECIADO] Use "boards list" ao invés disso',
|
|
3216
2904
|
boardsLegacyWarning: '⚠️ Aviso: comando "boards" está depreciado. Use "boards list" ao invés disso.',
|
|
@@ -31568,6 +31256,9 @@ var init_TrelloCliController = __esm(() => {
|
|
|
31568
31256
|
});
|
|
31569
31257
|
|
|
31570
31258
|
// src/presentation/cli/CommandController.ts
|
|
31259
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
31260
|
+
import { join } from "node:path";
|
|
31261
|
+
|
|
31571
31262
|
class CommandController {
|
|
31572
31263
|
authController;
|
|
31573
31264
|
boardController;
|
|
@@ -31590,8 +31281,14 @@ class CommandController {
|
|
|
31590
31281
|
this.cardController = new CardController(trelloRepository, this.boardController, this.outputFormatter);
|
|
31591
31282
|
}
|
|
31592
31283
|
setupCommands() {
|
|
31593
|
-
|
|
31284
|
+
const packageJsonPath = join(process.cwd(), "package.json");
|
|
31285
|
+
const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
|
|
31286
|
+
const version = packageJson.version;
|
|
31287
|
+
this.program.name("trello-cli-unofficial").description(t3("commands.description")).version(version).option("-f, --format <format>", t3("commands.formatOption"), "table").option("-v", t3("commands.versionOption")).on("option:format", (format) => {
|
|
31594
31288
|
this.outputFormatter.setFormat(format);
|
|
31289
|
+
}).on("option:v", () => {
|
|
31290
|
+
console.log(version);
|
|
31291
|
+
process.exit(0);
|
|
31595
31292
|
});
|
|
31596
31293
|
this.program.command("interactive").alias("i").description(t3("commands.interactive.description")).action(async () => {
|
|
31597
31294
|
const configRepository = new FileConfigRepository;
|
|
@@ -31768,12 +31465,11 @@ class CommandController {
|
|
|
31768
31465
|
});
|
|
31769
31466
|
}
|
|
31770
31467
|
async run() {
|
|
31771
|
-
|
|
31468
|
+
this.program.parse();
|
|
31469
|
+
if (!this.program.args.length && !this.program.opts().version) {
|
|
31772
31470
|
const configRepository = new FileConfigRepository;
|
|
31773
31471
|
const cli = new (await Promise.resolve().then(() => (init_TrelloCliController(), exports_TrelloCliController))).TrelloCliController(configRepository, this.outputFormatter);
|
|
31774
31472
|
await cli.run();
|
|
31775
|
-
} else {
|
|
31776
|
-
this.program.parse();
|
|
31777
31473
|
}
|
|
31778
31474
|
}
|
|
31779
31475
|
}
|
|
Binary file
|
package/main.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trello-cli-unofficial",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.10.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Unofficial Trello CLI using Power-Up authentication, built with Bun for maximum performance",
|
|
7
7
|
"author": "Matheus Caiser <matheus.kaiser@gmail.com> (https://www.mrdeveloper.com.br/)",
|
|
@@ -70,7 +70,8 @@
|
|
|
70
70
|
"version:patch": "bun version patch && git push --follow-tags",
|
|
71
71
|
"version:minor": "bun version minor && git push --follow-tags",
|
|
72
72
|
"version:major": "bun version major && git push --follow-tags",
|
|
73
|
-
"prepublishOnly": "bun run validate && bun run build"
|
|
73
|
+
"prepublishOnly": "bun run validate && bun run build",
|
|
74
|
+
"prepare": "husky"
|
|
74
75
|
},
|
|
75
76
|
"peerDependencies": {
|
|
76
77
|
"typescript": "^5"
|
|
@@ -79,7 +80,7 @@
|
|
|
79
80
|
"@types/node": "^24.10.0",
|
|
80
81
|
"bun": "^1.3.2",
|
|
81
82
|
"commander": "^14.0.2",
|
|
82
|
-
"dotenv": "^
|
|
83
|
+
"dotenv": "^15.0.1",
|
|
83
84
|
"fs-extra": "^11.3.2",
|
|
84
85
|
"i18next": "^25.6.1",
|
|
85
86
|
"inquirer": "^12.10.0"
|
|
@@ -93,6 +94,7 @@
|
|
|
93
94
|
"@types/inquirer": "^9.0.9",
|
|
94
95
|
"eslint": "^9.39.1",
|
|
95
96
|
"eslint-plugin-format": "^1.0.2",
|
|
97
|
+
"husky": "^9.1.7",
|
|
96
98
|
"lint-staged": "^16.2.6"
|
|
97
99
|
},
|
|
98
100
|
"os": [
|
|
@@ -100,16 +102,12 @@
|
|
|
100
102
|
"linux",
|
|
101
103
|
"win32"
|
|
102
104
|
],
|
|
103
|
-
"gitHooks": {
|
|
104
|
-
"commit-msg": "bun run commitlint"
|
|
105
|
-
},
|
|
106
105
|
"lint-staged": {
|
|
107
106
|
"*.{js,ts,tsx}": [
|
|
108
|
-
"eslint --fix"
|
|
109
|
-
"eslint --max-warnings 0"
|
|
107
|
+
"eslint --fix"
|
|
110
108
|
],
|
|
111
109
|
"*.json": [
|
|
112
|
-
"
|
|
110
|
+
"eslint"
|
|
113
111
|
]
|
|
114
112
|
}
|
|
115
113
|
}
|
package/src/i18n/locales/en.json
CHANGED
|
@@ -165,6 +165,7 @@
|
|
|
165
165
|
"commands": {
|
|
166
166
|
"description": "Unofficial Trello CLI using Power-Up authentication",
|
|
167
167
|
"formatOption": "Output format: table, json, csv",
|
|
168
|
+
"versionOption": "output the version number",
|
|
168
169
|
"deprecated": {
|
|
169
170
|
"boardsLegacyDescription": "[DEPRECATED] Use \"boards list\" instead",
|
|
170
171
|
"boardsLegacyWarning": "⚠️ Warning: \"boards\" command is deprecated. Use \"boards list\" instead.",
|
|
@@ -165,6 +165,7 @@
|
|
|
165
165
|
"commands": {
|
|
166
166
|
"description": "CLI não oficial do Trello usando autenticação Power-Up",
|
|
167
167
|
"formatOption": "Formato de saída: table, json, csv",
|
|
168
|
+
"versionOption": "exibe o número da versão",
|
|
168
169
|
"deprecated": {
|
|
169
170
|
"boardsLegacyDescription": "[DEPRECIADO] Use \"boards list\" ao invés disso",
|
|
170
171
|
"boardsLegacyWarning": "⚠️ Aviso: comando \"boards\" está depreciado. Use \"boards list\" ao invés disso.",
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { OutputFormat } from '@/shared';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
2
4
|
|
|
3
5
|
import { AuthenticationService } from '@domain/services';
|
|
4
6
|
import {
|
|
@@ -48,13 +50,23 @@ export class CommandController {
|
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
private setupCommands(): void {
|
|
53
|
+
// Get version from package.json
|
|
54
|
+
const packageJsonPath = join(process.cwd(), 'package.json');
|
|
55
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
56
|
+
const version = packageJson.version;
|
|
57
|
+
|
|
51
58
|
this.program
|
|
52
59
|
.name('trello-cli-unofficial')
|
|
53
60
|
.description(t('commands.description'))
|
|
54
|
-
.version(
|
|
61
|
+
.version(version)
|
|
55
62
|
.option('-f, --format <format>', t('commands.formatOption'), 'table')
|
|
63
|
+
.option('-v', t('commands.versionOption'))
|
|
56
64
|
.on('option:format', (format) => {
|
|
57
65
|
this.outputFormatter.setFormat(format as OutputFormat);
|
|
66
|
+
})
|
|
67
|
+
.on('option:v', () => {
|
|
68
|
+
console.log(version);
|
|
69
|
+
process.exit(0);
|
|
58
70
|
});
|
|
59
71
|
|
|
60
72
|
// Interactive mode
|
|
@@ -414,15 +426,16 @@ export class CommandController {
|
|
|
414
426
|
}
|
|
415
427
|
|
|
416
428
|
async run(): Promise<void> {
|
|
429
|
+
// Parse arguments first to handle global options like --version
|
|
430
|
+
this.program.parse();
|
|
431
|
+
|
|
417
432
|
// Fallback to interactive mode if no command specified
|
|
418
|
-
if (
|
|
433
|
+
if (!this.program.args.length && !this.program.opts().version) {
|
|
419
434
|
const configRepository = new FileConfigRepository();
|
|
420
435
|
const cli = new (
|
|
421
436
|
await import('./TrelloCliController')
|
|
422
437
|
).TrelloCliController(configRepository, this.outputFormatter);
|
|
423
438
|
await cli.run();
|
|
424
|
-
} else {
|
|
425
|
-
this.program.parse();
|
|
426
439
|
}
|
|
427
440
|
}
|
|
428
441
|
}
|
|
Binary file
|