trello-cli-unofficial 0.9.5 → 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 CHANGED
@@ -1,3 +1,25 @@
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
+
16
+ ## [0.9.6](https://github.com/JaegerCaiser/trello-cli-unofficial/compare/v0.9.5...v0.9.6) (2025-11-14)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * remove intrusive postinstall script from npm package ([0b8d109](https://github.com/JaegerCaiser/trello-cli-unofficial/commit/0b8d109be026d0723480d7bd1bd8d53691485de2))
22
+
1
23
  ## [0.9.5](https://github.com/JaegerCaiser/trello-cli-unofficial/compare/v0.9.4...v0.9.5) (2025-11-14)
2
24
 
3
25
 
package/README.md CHANGED
@@ -30,27 +30,26 @@ An unofficial Trello CLI using Power-Up authentication, built with Bun for maxim
30
30
  ### Prerequisites
31
31
 
32
32
  - **[Node.js 16+](https://nodejs.org/) (Required)**
33
- - **Bun incluído automaticamente** - Não é necessário instalar separadamente
33
+ - **[Bun](https://bun.sh/) (Required)** - Deve ser instalado separadamente
34
34
  - Trello account with Power-Up enabled
35
35
  - **Supported Platforms:** Linux, macOS, Windows
36
36
 
37
37
  ### NPM Installation (Recommended)
38
38
 
39
- O CLI inclui o Bun automaticamente. Basta instalar e usar imediatamente!
39
+ O CLI requer Bun para funcionar. Instale-o primeiro:
40
40
 
41
41
  ```bash
42
- # Installation - Bun is included automatically
42
+ # 1. Instale o Bun primeiro
43
+ curl -fsSL https://bun.sh/install | bash
44
+ # ou no Windows: powershell -c "irm bun.sh/install.ps1 | iex"
45
+
46
+ # 2. Instale o CLI
43
47
  npm install -g trello-cli-unofficial
44
48
 
45
- # Or with other package managers
46
- bun add -g trello-cli-unofficial
47
- yarn global add trello-cli-unofficial
49
+ # 3. Use
50
+ tcu --version
48
51
  ```
49
52
 
50
- # Option 4: Using PNPM
51
-
52
- pnpm add -g trello-cli-unofficial
53
-
54
53
  # Ready to use immediately!
55
54
 
56
55
  tcu --version
@@ -59,23 +58,20 @@ tcu --version
59
58
 
60
59
  #### Windows Installation
61
60
 
62
- Para usuários Windows, a instalação é simples com qualquer gerenciador de pacotes:
61
+ Para usuários Windows, primeiro instale o Bun, depois o CLI:
63
62
 
64
63
  ```powershell
65
- # Usando NPM (funciona com Node.js)
66
- npm install -g trello-cli-unofficial
64
+ # 1. Instale o Bun
65
+ powershell -c "irm bun.sh/install.ps1 | iex"
67
66
 
68
- # Ou usando Bun (recomendado para melhor performance)
69
- bun add -g trello-cli-unofficial
70
-
71
- # Ou usando Yarn
72
- yarn global add trello-cli-unofficial
67
+ # 2. Instale o CLI
68
+ npm install -g trello-cli-unofficial
73
69
 
74
- # Pronto para usar!
70
+ # 3. Use
75
71
  tcu --version
76
- ````
72
+ ```
77
73
 
78
- **Nota:** No Windows, você pode precisar reiniciar o terminal após a instalação para atualizar o PATH.
74
+ **Nota:** No Windows, você pode precisar reiniciar o terminal após instalar o Bun.
79
75
 
80
76
  ### Manual Installation (Development)
81
77
 
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": "^17.2.3",
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@17.2.3", "", {}, "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w=="],
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 crypto = __require("crypto");
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(/^(['"`])([\s\S]*)\1$/mg, "$2");
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@${version}] ${message}`);
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 _configVault(options) {
264
- const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
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
- let processEnv = process.env;
281
- if (options && options.processEnv != null) {
282
- processEnv = options.processEnv;
283
- }
284
- let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options && options.debug);
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
- const populated = DotenvModule.populate(processEnv, parsedAll, options);
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 aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce);
361
- aesgcm.setAuthTag(authTag);
362
- return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
363
- } catch (error) {
364
- const isRange = error instanceof RangeError;
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
- _debug(`"${key}" is already defined and WAS overwritten`);
398
- } else {
399
- _debug(`"${key}" is already defined and was NOT overwritten`);
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
- } else {
403
- processEnv[key] = parsed[key];
404
- populated[key] = parsed[key];
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
- decrypt,
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
- this.program.name("trello-cli-unofficial").description(t3("commands.description")).version("1.0.0").option("-f, --format <format>", t3("commands.formatOption"), "table").on("option:format", (format) => {
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
- if (process.argv.length === 2) {
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
  }
package/main.ts CHANGED
@@ -3,7 +3,6 @@ import { config } from 'dotenv';
3
3
  import { t } from './src/i18n';
4
4
  import { CommandController } from './src/presentation';
5
5
 
6
- // Load environment variables
7
6
  config();
8
7
 
9
8
  async function main() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "trello-cli-unofficial",
3
3
  "type": "module",
4
- "version": "0.9.5",
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/)",
@@ -71,7 +71,7 @@
71
71
  "version:minor": "bun version minor && git push --follow-tags",
72
72
  "version:major": "bun version major && git push --follow-tags",
73
73
  "prepublishOnly": "bun run validate && bun run build",
74
- "postinstall": "node scripts/check-dependencies.js"
74
+ "prepare": "husky"
75
75
  },
76
76
  "peerDependencies": {
77
77
  "typescript": "^5"
@@ -80,7 +80,7 @@
80
80
  "@types/node": "^24.10.0",
81
81
  "bun": "^1.3.2",
82
82
  "commander": "^14.0.2",
83
- "dotenv": "^17.2.3",
83
+ "dotenv": "^15.0.1",
84
84
  "fs-extra": "^11.3.2",
85
85
  "i18next": "^25.6.1",
86
86
  "inquirer": "^12.10.0"
@@ -94,6 +94,7 @@
94
94
  "@types/inquirer": "^9.0.9",
95
95
  "eslint": "^9.39.1",
96
96
  "eslint-plugin-format": "^1.0.2",
97
+ "husky": "^9.1.7",
97
98
  "lint-staged": "^16.2.6"
98
99
  },
99
100
  "os": [
@@ -101,16 +102,12 @@
101
102
  "linux",
102
103
  "win32"
103
104
  ],
104
- "gitHooks": {
105
- "commit-msg": "bun run commitlint"
106
- },
107
105
  "lint-staged": {
108
106
  "*.{js,ts,tsx}": [
109
- "eslint --fix",
110
- "eslint --max-warnings 0"
107
+ "eslint --fix"
111
108
  ],
112
109
  "*.json": [
113
- "bun run lint:json"
110
+ "eslint"
114
111
  ]
115
112
  }
116
113
  }
@@ -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('1.0.0')
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 (process.argv.length === 2) {
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
  }