@pachca/cli 2026.3.7 → 2026.3.9
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 +12 -0
- package/dist/base-command.js +1 -43
- package/dist/commands/auth/list.js +0 -1
- package/dist/commands/auth/login.js +0 -9
- package/dist/commands/auth/status.js +0 -10
- package/dist/commands/bots/list-events.js +0 -1
- package/dist/commands/bots/remove-event.js +0 -1
- package/dist/commands/bots/update.js +0 -1
- package/dist/commands/chats/archive.js +0 -1
- package/dist/commands/chats/create.js +0 -1
- package/dist/commands/chats/get.js +0 -1
- package/dist/commands/chats/list.js +0 -1
- package/dist/commands/chats/unarchive.js +0 -1
- package/dist/commands/chats/update.js +0 -1
- package/dist/commands/commands.js +5 -12
- package/dist/commands/common/custom-properties.js +0 -1
- package/dist/commands/common/get-exports.js +0 -1
- package/dist/commands/common/request-export.js +0 -1
- package/dist/commands/common/uploads.js +0 -1
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/group-tags/create.js +0 -1
- package/dist/commands/group-tags/delete.js +0 -1
- package/dist/commands/group-tags/get.js +0 -1
- package/dist/commands/group-tags/list-users.js +0 -1
- package/dist/commands/group-tags/list.js +0 -1
- package/dist/commands/group-tags/update.js +0 -1
- package/dist/commands/link-previews/add.js +0 -1
- package/dist/commands/members/add-group-tags.js +0 -1
- package/dist/commands/members/add.js +0 -1
- package/dist/commands/members/leave.js +0 -1
- package/dist/commands/members/list.js +0 -1
- package/dist/commands/members/remove-group-tag.js +0 -1
- package/dist/commands/members/remove.js +0 -1
- package/dist/commands/members/update.js +0 -1
- package/dist/commands/messages/create.js +0 -1
- package/dist/commands/messages/delete.js +0 -1
- package/dist/commands/messages/get.js +0 -1
- package/dist/commands/messages/list.js +0 -1
- package/dist/commands/messages/pin.js +0 -1
- package/dist/commands/messages/unpin.js +0 -1
- package/dist/commands/messages/update.js +0 -1
- package/dist/commands/profile/delete-status.js +0 -1
- package/dist/commands/profile/get-status.js +0 -1
- package/dist/commands/profile/get.js +0 -1
- package/dist/commands/profile/update-status.js +0 -1
- package/dist/commands/reactions/add.js +0 -1
- package/dist/commands/reactions/list.js +0 -1
- package/dist/commands/reactions/remove.js +0 -1
- package/dist/commands/read-member/list-readers.js +0 -1
- package/dist/commands/search/list-chats.js +0 -1
- package/dist/commands/search/list-messages.js +0 -1
- package/dist/commands/search/list-users.js +0 -1
- package/dist/commands/security/list.js +0 -1
- package/dist/commands/tasks/create.js +0 -1
- package/dist/commands/tasks/delete.js +0 -1
- package/dist/commands/tasks/get.js +0 -1
- package/dist/commands/tasks/list.js +0 -1
- package/dist/commands/tasks/update.js +0 -1
- package/dist/commands/threads/add.js +0 -1
- package/dist/commands/threads/get.js +0 -1
- package/dist/commands/upgrade.js +111 -0
- package/dist/commands/upload.js +0 -1
- package/dist/commands/users/create.js +0 -1
- package/dist/commands/users/delete.js +0 -1
- package/dist/commands/users/get-status.js +0 -1
- package/dist/commands/users/get.js +0 -1
- package/dist/commands/users/list.js +0 -1
- package/dist/commands/users/remove-status.js +0 -1
- package/dist/commands/users/update-status.js +0 -1
- package/dist/commands/users/update.js +0 -1
- package/dist/commands/views/open.js +0 -1
- package/dist/data/changelog.json +42 -0
- package/dist/hooks/init.js +77 -23
- package/dist/hooks/postrun.js +3 -66
- package/dist/profiles.js +0 -8
- package/oclif.manifest.json +248 -256
- package/package.json +1 -1
- package/dist/commands/auth/refresh.js +0 -67
|
@@ -24,7 +24,6 @@ export default class TasksGet extends BaseCommand {
|
|
|
24
24
|
async run() {
|
|
25
25
|
const { args, flags } = await this.parse(TasksGet);
|
|
26
26
|
this.parsedFlags = flags;
|
|
27
|
-
this.checkScope("tasks:read");
|
|
28
27
|
const { data } = await this.apiRequest({
|
|
29
28
|
method: 'GET',
|
|
30
29
|
path: `/tasks/${args.id}`,
|
|
@@ -23,7 +23,6 @@ export default class ThreadsAdd extends BaseCommand {
|
|
|
23
23
|
async run() {
|
|
24
24
|
const { args, flags } = await this.parse(ThreadsAdd);
|
|
25
25
|
this.parsedFlags = flags;
|
|
26
|
-
this.checkScope("threads:create");
|
|
27
26
|
const { data } = await this.apiRequest({
|
|
28
27
|
method: 'POST',
|
|
29
28
|
path: `/messages/${args.id}/thread`,
|
|
@@ -19,7 +19,6 @@ export default class ThreadsGet extends BaseCommand {
|
|
|
19
19
|
async run() {
|
|
20
20
|
const { args, flags } = await this.parse(ThreadsGet);
|
|
21
21
|
this.parsedFlags = flags;
|
|
22
|
-
this.checkScope("threads:read");
|
|
23
22
|
const { data } = await this.apiRequest({
|
|
24
23
|
method: 'GET',
|
|
25
24
|
path: `/threads/${args.id}`,
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import semver from 'semver';
|
|
5
|
+
import { BaseCommand } from '../base-command.js';
|
|
6
|
+
/**
|
|
7
|
+
* Detect how CLI was installed by examining the executable path.
|
|
8
|
+
*/
|
|
9
|
+
function detectPackageManager(binPath) {
|
|
10
|
+
const resolved = fs.realpathSync(binPath);
|
|
11
|
+
// Homebrew: /opt/homebrew/... or /usr/local/Cellar/...
|
|
12
|
+
if (resolved.includes('/homebrew/') || resolved.includes('/Cellar/')) {
|
|
13
|
+
return { name: 'homebrew', cmd: 'brew', args: ['upgrade', '@pachca/cli'] };
|
|
14
|
+
}
|
|
15
|
+
// Bun global: ~/.bun/install/global/ or contains /bun/
|
|
16
|
+
if (resolved.includes('/bun/') || resolved.includes('.bun/')) {
|
|
17
|
+
return { name: 'bun', cmd: 'bun', args: ['install', '-g', '@pachca/cli@latest'] };
|
|
18
|
+
}
|
|
19
|
+
// pnpm global: contains /pnpm/
|
|
20
|
+
if (resolved.includes('/pnpm/')) {
|
|
21
|
+
return { name: 'pnpm', cmd: 'pnpm', args: ['install', '-g', '@pachca/cli@latest'] };
|
|
22
|
+
}
|
|
23
|
+
// yarn global: contains /yarn/
|
|
24
|
+
if (resolved.includes('/yarn/')) {
|
|
25
|
+
return { name: 'yarn', cmd: 'yarn', args: ['global', 'add', '@pachca/cli@latest'] };
|
|
26
|
+
}
|
|
27
|
+
// Default: npm
|
|
28
|
+
return { name: 'npm', cmd: 'npm', args: ['install', '-g', '@pachca/cli@latest'] };
|
|
29
|
+
}
|
|
30
|
+
export default class Upgrade extends BaseCommand {
|
|
31
|
+
static description = 'Обновить CLI до последней версии';
|
|
32
|
+
static examples = [
|
|
33
|
+
'<%= config.bin %> upgrade',
|
|
34
|
+
];
|
|
35
|
+
static flags = {
|
|
36
|
+
...BaseCommand.baseFlags,
|
|
37
|
+
};
|
|
38
|
+
async run() {
|
|
39
|
+
const { flags } = await this.parse(Upgrade);
|
|
40
|
+
this.parsedFlags = flags;
|
|
41
|
+
const currentVersion = this.config.version;
|
|
42
|
+
const format = this.getOutputFormat();
|
|
43
|
+
// Fetch latest version from npm registry
|
|
44
|
+
let latest;
|
|
45
|
+
try {
|
|
46
|
+
const response = await fetch('https://registry.npmjs.org/@pachca/cli');
|
|
47
|
+
if (response.ok) {
|
|
48
|
+
const data = (await response.json());
|
|
49
|
+
latest = data['dist-tags']?.latest;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Fallback: try cached version
|
|
54
|
+
}
|
|
55
|
+
if (!latest) {
|
|
56
|
+
try {
|
|
57
|
+
const versionFile = path.join(this.config.cacheDir, 'version');
|
|
58
|
+
if (fs.existsSync(versionFile)) {
|
|
59
|
+
const cached = JSON.parse(fs.readFileSync(versionFile, 'utf-8'));
|
|
60
|
+
latest = cached.latest;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// ignore
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (!latest) {
|
|
68
|
+
if (format === 'json') {
|
|
69
|
+
this.output({ upgraded: false, current: currentVersion, error: 'Cannot determine latest version' });
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
process.stderr.write('✗ Не удалось определить последнюю версию\n');
|
|
73
|
+
}
|
|
74
|
+
this.exit(1);
|
|
75
|
+
}
|
|
76
|
+
if (semver.valid(currentVersion) && semver.valid(latest) && !semver.gt(latest, currentVersion)) {
|
|
77
|
+
if (format === 'json') {
|
|
78
|
+
this.output({ upgraded: false, current: currentVersion, latest });
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
process.stderr.write(`✔ CLI уже обновлён (${currentVersion})\n`);
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const pm = detectPackageManager(process.argv[1] || this.config.binPath || '');
|
|
86
|
+
if (format !== 'json' && process.stderr.isTTY) {
|
|
87
|
+
process.stderr.write(`Обновление ${currentVersion} → ${latest} (${pm.name})...\n`);
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
execFileSync(pm.cmd, pm.args, {
|
|
91
|
+
stdio: format === 'json' ? 'ignore' : 'inherit',
|
|
92
|
+
});
|
|
93
|
+
if (format === 'json') {
|
|
94
|
+
this.output({ upgraded: true, from: currentVersion, to: latest, package_manager: pm.name });
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
process.stderr.write(`\n✔ Обновлено до ${latest}\n`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
if (format === 'json') {
|
|
102
|
+
this.output({ upgraded: false, current: currentVersion, latest, package_manager: pm.name, error: `${pm.cmd} failed` });
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
process.stderr.write(`\n✗ Не удалось обновить через ${pm.name}. Попробуйте вручную:\n`);
|
|
106
|
+
process.stderr.write(` ${pm.cmd} ${pm.args.join(' ')}\n`);
|
|
107
|
+
}
|
|
108
|
+
this.exit(1);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
package/dist/commands/upload.js
CHANGED
|
@@ -21,7 +21,6 @@ export default class Upload extends BaseCommand {
|
|
|
21
21
|
async run() {
|
|
22
22
|
const { args, flags } = await this.parse(Upload);
|
|
23
23
|
this.parsedFlags = flags;
|
|
24
|
-
this.checkScope('uploads:write');
|
|
25
24
|
// Step 1: Get upload params
|
|
26
25
|
const { data: uploadData } = await this.apiRequest({
|
|
27
26
|
method: 'POST',
|
|
@@ -85,7 +85,6 @@ export default class UsersCreate extends BaseCommand {
|
|
|
85
85
|
this.validationError(missingRequired.map((f) => ({ message: `Обязательный флаг --${f.flag} не передан`, flag: f.flag })), { hint: "Обязательные: --email <string>. pachca introspect users create" });
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
-
this.checkScope("users:create");
|
|
89
88
|
const body = {
|
|
90
89
|
user: {
|
|
91
90
|
first_name: flags['first-name'],
|
|
@@ -24,7 +24,6 @@ export default class UsersGetStatus extends BaseCommand {
|
|
|
24
24
|
async run() {
|
|
25
25
|
const { args, flags } = await this.parse(UsersGetStatus);
|
|
26
26
|
this.parsedFlags = flags;
|
|
27
|
-
this.checkScope("user_status:read");
|
|
28
27
|
const { data } = await this.apiRequest({
|
|
29
28
|
method: 'GET',
|
|
30
29
|
path: `/users/${args.user_id}/status`,
|
|
@@ -24,7 +24,6 @@ export default class UsersGet extends BaseCommand {
|
|
|
24
24
|
async run() {
|
|
25
25
|
const { args, flags } = await this.parse(UsersGet);
|
|
26
26
|
this.parsedFlags = flags;
|
|
27
|
-
this.checkScope("users:read");
|
|
28
27
|
const { data } = await this.apiRequest({
|
|
29
28
|
method: 'GET',
|
|
30
29
|
path: `/users/${args.id}`,
|
|
@@ -76,7 +76,6 @@ export default class UsersUpdateStatus extends BaseCommand {
|
|
|
76
76
|
if (validationErrors.length > 0) {
|
|
77
77
|
this.validationError(validationErrors);
|
|
78
78
|
}
|
|
79
|
-
this.checkScope("user_status:write");
|
|
80
79
|
const body = { status: {
|
|
81
80
|
emoji: flags['emoji'],
|
|
82
81
|
title: flags['title'],
|
|
@@ -58,7 +58,6 @@ export default class UsersUpdate extends BaseCommand {
|
|
|
58
58
|
async run() {
|
|
59
59
|
const { args, flags } = await this.parse(UsersUpdate);
|
|
60
60
|
this.parsedFlags = flags;
|
|
61
|
-
this.checkScope("users:update");
|
|
62
61
|
const body = { user: {
|
|
63
62
|
first_name: flags['first-name'],
|
|
64
63
|
last_name: flags['last-name'],
|
package/dist/data/changelog.json
CHANGED
|
@@ -1,4 +1,46 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "2026.3.9",
|
|
4
|
+
"date": "19 марта 2026",
|
|
5
|
+
"changes": [
|
|
6
|
+
{
|
|
7
|
+
"type": "~",
|
|
8
|
+
"command": "all",
|
|
9
|
+
"description": "Убрана клиентская валидация скоупов — проверка разрешений теперь только на стороне API (403)"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"type": "~",
|
|
13
|
+
"command": "auth login",
|
|
14
|
+
"description": "Профиль больше не сохраняет список скоупов — только тип, имя и email"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"type": "-",
|
|
18
|
+
"command": "auth refresh",
|
|
19
|
+
"description": "Команда удалена — кеширование скоупов больше не используется"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"version": "2026.3.8",
|
|
25
|
+
"date": "17 марта 2026",
|
|
26
|
+
"changes": [
|
|
27
|
+
{
|
|
28
|
+
"type": "+",
|
|
29
|
+
"command": "upgrade",
|
|
30
|
+
"description": "Команда pachca upgrade — обновление CLI до последней версии"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"type": "-",
|
|
34
|
+
"command": "init hook",
|
|
35
|
+
"description": "Ошибки авторизации теперь выводятся в JSON при -o json (раньше формат игнорировался)"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"type": "-",
|
|
39
|
+
"command": "update banner",
|
|
40
|
+
"description": "Баннер обновления теперь показывается даже при ошибках команд"
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
},
|
|
2
44
|
{
|
|
3
45
|
"version": "2026.3.7",
|
|
4
46
|
"date": "16 марта 2026",
|
package/dist/hooks/init.js
CHANGED
|
@@ -1,7 +1,29 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import semver from 'semver';
|
|
6
|
+
import ansis from 'ansis';
|
|
7
|
+
import { getDefaults, resolveToken, TokenNotFoundError, ProfileNotFoundError, } from '../profiles.js';
|
|
3
8
|
import { outputError } from '../output.js';
|
|
4
|
-
import { defaultOutputFormat } from '../utils.js';
|
|
9
|
+
import { defaultOutputFormat, isInteractive } from '../utils.js';
|
|
10
|
+
/**
|
|
11
|
+
* Resolve output format from argv before flags are parsed by oclif.
|
|
12
|
+
*/
|
|
13
|
+
function resolveOutputFromArgv() {
|
|
14
|
+
if (process.argv.includes('--json'))
|
|
15
|
+
return 'json';
|
|
16
|
+
const outputIdx = Math.max(process.argv.indexOf('-o'), process.argv.indexOf('--output'));
|
|
17
|
+
if (outputIdx !== -1) {
|
|
18
|
+
const val = process.argv[outputIdx + 1];
|
|
19
|
+
if (val && ['json', 'yaml', 'csv', 'table'].includes(val))
|
|
20
|
+
return val;
|
|
21
|
+
}
|
|
22
|
+
const defaults = getDefaults();
|
|
23
|
+
if (defaults.output)
|
|
24
|
+
return defaults.output;
|
|
25
|
+
return defaultOutputFormat();
|
|
26
|
+
}
|
|
5
27
|
// Commands that don't require auth
|
|
6
28
|
const SKIP_AUTH = new Set([
|
|
7
29
|
'auth:login',
|
|
@@ -20,12 +42,62 @@ const SKIP_AUTH = new Set([
|
|
|
20
42
|
'guide',
|
|
21
43
|
'introspect',
|
|
22
44
|
'changelog',
|
|
45
|
+
'upgrade',
|
|
23
46
|
'help',
|
|
24
47
|
]);
|
|
25
48
|
const hook = async function (opts) {
|
|
26
49
|
const commandId = opts.id;
|
|
27
50
|
if (!commandId)
|
|
28
51
|
return;
|
|
52
|
+
// Register update banner on process exit (fires even when command fails)
|
|
53
|
+
if (isInteractive() && !process.env.PACHCA_SKIP_NEW_VERSION_CHECK) {
|
|
54
|
+
const cacheDir = opts.config.cacheDir;
|
|
55
|
+
const versionFile = path.join(cacheDir, 'version');
|
|
56
|
+
const currentVersion = opts.config.version;
|
|
57
|
+
process.on('exit', () => {
|
|
58
|
+
try {
|
|
59
|
+
if (fs.existsSync(versionFile)) {
|
|
60
|
+
const cached = JSON.parse(fs.readFileSync(versionFile, 'utf-8'));
|
|
61
|
+
const latest = cached.latest;
|
|
62
|
+
if (latest && semver.valid(latest) && semver.valid(currentVersion) && semver.gt(latest, currentVersion)) {
|
|
63
|
+
const box = [
|
|
64
|
+
'',
|
|
65
|
+
ansis.yellow(`╭${'─'.repeat(37)}╮`),
|
|
66
|
+
ansis.yellow(`│ Доступна новая версия: ${latest.padEnd(12)}│`),
|
|
67
|
+
ansis.yellow(`│ pachca upgrade${' '.repeat(21)}│`),
|
|
68
|
+
ansis.yellow(`╰${'─'.repeat(37)}╯`),
|
|
69
|
+
'',
|
|
70
|
+
].join('\n');
|
|
71
|
+
process.stderr.write(box);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// ignore
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
// Background refresh if cache is stale (>1h)
|
|
80
|
+
try {
|
|
81
|
+
let shouldRefresh = true;
|
|
82
|
+
if (fs.existsSync(versionFile)) {
|
|
83
|
+
const stat = fs.statSync(versionFile);
|
|
84
|
+
shouldRefresh = Date.now() - stat.mtimeMs > 60 * 60 * 1000;
|
|
85
|
+
}
|
|
86
|
+
if (shouldRefresh) {
|
|
87
|
+
if (!fs.existsSync(cacheDir)) {
|
|
88
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
89
|
+
}
|
|
90
|
+
const scriptPath = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'get-version.js');
|
|
91
|
+
if (fs.existsSync(scriptPath)) {
|
|
92
|
+
const child = spawn(process.execPath, [scriptPath, versionFile], { detached: true, stdio: 'ignore' });
|
|
93
|
+
child.unref();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// ignore
|
|
99
|
+
}
|
|
100
|
+
}
|
|
29
101
|
// Skip auth for exempt commands
|
|
30
102
|
if (SKIP_AUTH.has(commandId))
|
|
31
103
|
return;
|
|
@@ -58,28 +130,10 @@ const hook = async function (opts) {
|
|
|
58
130
|
// Verify auth exists
|
|
59
131
|
try {
|
|
60
132
|
const { profileName, profile } = resolveToken({ token: argvToken, profile: argvProfile });
|
|
61
|
-
// Refresh bot scopes if stale (>24h)
|
|
62
|
-
if (profileName && profile?.type === 'bot' && profile.scopes_refreshed_at) {
|
|
63
|
-
const refreshedAt = new Date(profile.scopes_refreshed_at).getTime();
|
|
64
|
-
const now = Date.now();
|
|
65
|
-
const twentyFourHours = 24 * 60 * 60 * 1000;
|
|
66
|
-
if (now - refreshedAt > twentyFourHours) {
|
|
67
|
-
try {
|
|
68
|
-
const response = await request({ method: 'GET', path: '/oauth/token/info', token: profile.token }, { quiet: true });
|
|
69
|
-
const wrapper = response.data;
|
|
70
|
-
profile.scopes = wrapper.data.scopes || [];
|
|
71
|
-
profile.scopes_refreshed_at = new Date().toISOString();
|
|
72
|
-
setProfile(profileName, profile);
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
// Silently ignore refresh errors — use cached scopes
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
133
|
}
|
|
80
134
|
catch (error) {
|
|
81
135
|
if (error instanceof TokenNotFoundError) {
|
|
82
|
-
const format =
|
|
136
|
+
const format = resolveOutputFromArgv();
|
|
83
137
|
if (format === 'json' || !process.stderr.isTTY) {
|
|
84
138
|
outputError({ error: 'Token not found', type: 'PACHCA_AUTH_ERROR', code: null, hint: 'pachca auth login --token <your-token>' }, format);
|
|
85
139
|
}
|
|
@@ -94,7 +148,7 @@ const hook = async function (opts) {
|
|
|
94
148
|
process.exit(3);
|
|
95
149
|
}
|
|
96
150
|
if (error instanceof ProfileNotFoundError) {
|
|
97
|
-
const format =
|
|
151
|
+
const format = resolveOutputFromArgv();
|
|
98
152
|
outputError({ error: `Profile "${error.profileName}" not found`, type: 'PACHCA_USAGE_ERROR', code: null, hint: 'pachca auth list' }, format);
|
|
99
153
|
process.exit(2);
|
|
100
154
|
}
|
package/dist/hooks/postrun.js
CHANGED
|
@@ -1,67 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { spawn } from 'node:child_process';
|
|
5
|
-
import semver from 'semver';
|
|
6
|
-
import ansis from 'ansis';
|
|
7
|
-
import { isInteractive } from '../utils.js';
|
|
8
|
-
const hook = async function (opts) {
|
|
9
|
-
// Don't show update banner in non-interactive mode
|
|
10
|
-
if (!isInteractive())
|
|
11
|
-
return;
|
|
12
|
-
if (process.env.PACHCA_SKIP_NEW_VERSION_CHECK)
|
|
13
|
-
return;
|
|
14
|
-
const cacheDir = opts.config.cacheDir;
|
|
15
|
-
const versionFile = path.join(cacheDir, 'version');
|
|
16
|
-
// Check if version file exists and show banner
|
|
17
|
-
try {
|
|
18
|
-
if (fs.existsSync(versionFile)) {
|
|
19
|
-
const cached = JSON.parse(fs.readFileSync(versionFile, 'utf-8'));
|
|
20
|
-
const latest = cached.latest;
|
|
21
|
-
const currentVersion = opts.config.version;
|
|
22
|
-
if (latest && semver.valid(latest) && semver.valid(currentVersion)) {
|
|
23
|
-
if (semver.gt(latest, currentVersion)) {
|
|
24
|
-
const box = [
|
|
25
|
-
'',
|
|
26
|
-
ansis.yellow(`╭${'─'.repeat(37)}╮`),
|
|
27
|
-
ansis.yellow(`│ Доступна новая версия: ${latest.padEnd(12)}│`),
|
|
28
|
-
ansis.yellow(`│ npm install -g @pachca/cli${' '.repeat(9)}│`),
|
|
29
|
-
ansis.yellow(`╰${'─'.repeat(37)}╯`),
|
|
30
|
-
'',
|
|
31
|
-
].join('\n');
|
|
32
|
-
process.stderr.write(box);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
// Ignore cache read errors
|
|
39
|
-
}
|
|
40
|
-
// Check if we should refresh version cache (mtime > 24h)
|
|
41
|
-
try {
|
|
42
|
-
let shouldRefresh = true;
|
|
43
|
-
if (fs.existsSync(versionFile)) {
|
|
44
|
-
const stat = fs.statSync(versionFile);
|
|
45
|
-
const ageMs = Date.now() - stat.mtimeMs;
|
|
46
|
-
shouldRefresh = ageMs > 60 * 60 * 1000;
|
|
47
|
-
}
|
|
48
|
-
if (shouldRefresh) {
|
|
49
|
-
if (!fs.existsSync(cacheDir)) {
|
|
50
|
-
fs.mkdirSync(cacheDir, { recursive: true });
|
|
51
|
-
}
|
|
52
|
-
// Spawn detached background process to fetch latest version
|
|
53
|
-
const scriptPath = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'get-version.js');
|
|
54
|
-
if (fs.existsSync(scriptPath)) {
|
|
55
|
-
const child = spawn(process.execPath, [scriptPath, versionFile], {
|
|
56
|
-
detached: true,
|
|
57
|
-
stdio: 'ignore',
|
|
58
|
-
});
|
|
59
|
-
child.unref();
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
catch {
|
|
64
|
-
// Ignore errors in update check
|
|
65
|
-
}
|
|
66
|
-
};
|
|
1
|
+
// Banner and version refresh moved to init hook (process.on('exit'))
|
|
2
|
+
// so they fire even when commands fail.
|
|
3
|
+
const hook = async function () { };
|
|
67
4
|
export default hook;
|
package/dist/profiles.js
CHANGED
|
@@ -171,14 +171,6 @@ export function getConfigFilePermissions() {
|
|
|
171
171
|
const stat = fs.statSync(configPath);
|
|
172
172
|
return (stat.mode & 0o777).toString(8);
|
|
173
173
|
}
|
|
174
|
-
export function invalidateScopes(profileName) {
|
|
175
|
-
const config = readConfig();
|
|
176
|
-
if (config.profiles?.[profileName]) {
|
|
177
|
-
config.profiles[profileName].scopes = [];
|
|
178
|
-
config.profiles[profileName].scopes_refreshed_at = undefined;
|
|
179
|
-
writeConfig(config);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
174
|
export class TokenNotFoundError extends Error {
|
|
183
175
|
constructor() {
|
|
184
176
|
super('Token not found');
|