trackfw 0.1.2
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/bin/.gitkeep +0 -0
- package/bin/trackfw +22 -0
- package/package.json +40 -0
- package/scripts/.gitkeep +0 -0
- package/scripts/postinstall.js +203 -0
package/bin/.gitkeep
ADDED
|
File without changes
|
package/bin/trackfw
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
'use strict'
|
|
4
|
+
|
|
5
|
+
const { spawnSync } = require('child_process')
|
|
6
|
+
const path = require('path')
|
|
7
|
+
const fs = require('fs')
|
|
8
|
+
|
|
9
|
+
const isWindows = process.platform === 'win32'
|
|
10
|
+
const binaryName = isWindows ? 'trackfw-bin.exe' : 'trackfw-bin'
|
|
11
|
+
const binaryPath = path.join(__dirname, binaryName)
|
|
12
|
+
|
|
13
|
+
if (!fs.existsSync(binaryPath)) {
|
|
14
|
+
console.error(
|
|
15
|
+
'trackfw: binário não encontrado em ' + binaryPath + '\n' +
|
|
16
|
+
'Tente reinstalar: npm install -g trackfw'
|
|
17
|
+
)
|
|
18
|
+
process.exit(1)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const result = spawnSync(binaryPath, process.argv.slice(2), { stdio: 'inherit' })
|
|
22
|
+
process.exit(result.status ?? 1)
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "trackfw",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Governed software delivery framework: ADR → REQ → ROADMAP → kanban",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"cli",
|
|
7
|
+
"adr",
|
|
8
|
+
"roadmap",
|
|
9
|
+
"governance",
|
|
10
|
+
"delivery"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/kgsaran/trackfw",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/kgsaran/trackfw"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"bin": {
|
|
19
|
+
"trackfw": "./bin/trackfw"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"postinstall": "node scripts/postinstall.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"bin/",
|
|
26
|
+
"scripts/"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=14"
|
|
30
|
+
},
|
|
31
|
+
"os": [
|
|
32
|
+
"linux",
|
|
33
|
+
"darwin",
|
|
34
|
+
"win32"
|
|
35
|
+
],
|
|
36
|
+
"cpu": [
|
|
37
|
+
"x64",
|
|
38
|
+
"arm64"
|
|
39
|
+
]
|
|
40
|
+
}
|
package/scripts/.gitkeep
ADDED
|
File without changes
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const https = require('https');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const os = require('os');
|
|
9
|
+
const child_process = require('child_process');
|
|
10
|
+
const zlib = require('zlib');
|
|
11
|
+
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Mapeamento de plataforma e arquitetura
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
const PLATFORM_MAP = {
|
|
17
|
+
linux: 'linux',
|
|
18
|
+
darwin: 'darwin',
|
|
19
|
+
win32: 'windows',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const ARCH_MAP = {
|
|
23
|
+
x64: 'amd64',
|
|
24
|
+
arm64: 'arm64',
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const platform = PLATFORM_MAP[process.platform];
|
|
28
|
+
const arch = ARCH_MAP[process.arch];
|
|
29
|
+
|
|
30
|
+
if (!platform || !arch) {
|
|
31
|
+
console.warn(
|
|
32
|
+
'trackfw: plataforma não suportada, pulando instalação do binário'
|
|
33
|
+
);
|
|
34
|
+
process.exit(0);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Versão — lida do package.json do wrapper npm
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
const pkgPath = path.join(__dirname, '..', 'package.json');
|
|
42
|
+
const { version } = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
43
|
+
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// URL de download
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
const isWindows = platform === 'windows';
|
|
49
|
+
const ext = isWindows ? '.zip' : '.tar.gz';
|
|
50
|
+
const archiveName = `trackfw_${version}_${platform}_${arch}${ext}`;
|
|
51
|
+
const downloadUrl = `https://github.com/kgsaran/trackfw/releases/download/v${version}/${archiveName}`;
|
|
52
|
+
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Destino final do binário
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
const binDir = path.join(__dirname, '..', 'bin');
|
|
58
|
+
const binName = isWindows ? 'trackfw-bin.exe' : 'trackfw-bin';
|
|
59
|
+
const binDest = path.join(binDir, binName);
|
|
60
|
+
|
|
61
|
+
// Garantir que o diretório bin existe
|
|
62
|
+
if (!fs.existsSync(binDir)) {
|
|
63
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// Helpers
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Baixa uma URL para um arquivo local, seguindo redirects 301/302.
|
|
72
|
+
* @param {string} url
|
|
73
|
+
* @param {string} destFile
|
|
74
|
+
* @returns {Promise<void>}
|
|
75
|
+
*/
|
|
76
|
+
function download(url, destFile) {
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
const file = fs.createWriteStream(destFile);
|
|
79
|
+
|
|
80
|
+
function get(currentUrl) {
|
|
81
|
+
https
|
|
82
|
+
.get(currentUrl, (res) => {
|
|
83
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
84
|
+
// Seguir redirect
|
|
85
|
+
const location = res.headers['location'];
|
|
86
|
+
if (!location) {
|
|
87
|
+
reject(new Error('Redirect sem Location header'));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
res.resume(); // descartar body
|
|
91
|
+
get(location);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (res.statusCode !== 200) {
|
|
96
|
+
reject(
|
|
97
|
+
new Error(
|
|
98
|
+
`Falha ao baixar ${currentUrl}: HTTP ${res.statusCode}`
|
|
99
|
+
)
|
|
100
|
+
);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
res.pipe(file);
|
|
105
|
+
file.on('finish', () => file.close(resolve));
|
|
106
|
+
file.on('error', (err) => {
|
|
107
|
+
fs.unlink(destFile, () => {});
|
|
108
|
+
reject(err);
|
|
109
|
+
});
|
|
110
|
+
})
|
|
111
|
+
.on('error', (err) => {
|
|
112
|
+
fs.unlink(destFile, () => {});
|
|
113
|
+
reject(err);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
get(url);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Extrai um arquivo .tar.gz ou .zip para um diretório.
|
|
123
|
+
* @param {string} archiveFile caminho do arquivo baixado
|
|
124
|
+
* @param {string} destDir diretório de destino da extração
|
|
125
|
+
*/
|
|
126
|
+
function extract(archiveFile, destDir) {
|
|
127
|
+
if (isWindows) {
|
|
128
|
+
child_process.execSync(
|
|
129
|
+
`powershell -command "Expand-Archive -Path '${archiveFile}' -DestinationPath '${destDir}' -Force"`,
|
|
130
|
+
{ stdio: 'inherit' }
|
|
131
|
+
);
|
|
132
|
+
} else {
|
|
133
|
+
child_process.execSync(
|
|
134
|
+
`tar -xzf "${archiveFile}" -C "${destDir}"`,
|
|
135
|
+
{ stdio: 'inherit' }
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Remove um arquivo ou diretório silenciosamente.
|
|
142
|
+
* @param {string} target
|
|
143
|
+
*/
|
|
144
|
+
function cleanup(target) {
|
|
145
|
+
try {
|
|
146
|
+
if (!fs.existsSync(target)) return;
|
|
147
|
+
const stat = fs.statSync(target);
|
|
148
|
+
if (stat.isDirectory()) {
|
|
149
|
+
// Node 14 não tem rm({recursive}) confiável em todas as versões; usar rmdir
|
|
150
|
+
fs.rmdirSync(target, { recursive: true });
|
|
151
|
+
} else {
|
|
152
|
+
fs.unlinkSync(target);
|
|
153
|
+
}
|
|
154
|
+
} catch (_) {
|
|
155
|
+
// Limpeza é best-effort — não falhar por causa disso
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
// Função principal
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
|
|
163
|
+
async function main() {
|
|
164
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'trackfw-'));
|
|
165
|
+
const tmpFile = path.join(tmpDir, archiveName);
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
console.log(`trackfw: baixando binário para ${platform}/${arch} v${version}...`);
|
|
169
|
+
console.log(` ${downloadUrl}`);
|
|
170
|
+
|
|
171
|
+
await download(downloadUrl, tmpFile);
|
|
172
|
+
|
|
173
|
+
console.log('trackfw: extraindo arquivo...');
|
|
174
|
+
extract(tmpFile, tmpDir);
|
|
175
|
+
|
|
176
|
+
// GoReleaser extrai o binário com o nome original ("trackfw" / "trackfw.exe")
|
|
177
|
+
const extractedBinName = isWindows ? 'trackfw.exe' : 'trackfw';
|
|
178
|
+
const extractedBin = path.join(tmpDir, extractedBinName);
|
|
179
|
+
|
|
180
|
+
if (!fs.existsSync(extractedBin)) {
|
|
181
|
+
throw new Error(
|
|
182
|
+
`Binário não encontrado após extração: ${extractedBin}`
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
fs.renameSync(extractedBin, binDest);
|
|
187
|
+
|
|
188
|
+
if (!isWindows) {
|
|
189
|
+
fs.chmodSync(binDest, 0o755);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
console.log('trackfw: binário instalado com sucesso');
|
|
193
|
+
} finally {
|
|
194
|
+
cleanup(tmpFile);
|
|
195
|
+
cleanup(tmpDir);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
main().catch((err) => {
|
|
200
|
+
console.error('trackfw: erro ao instalar binário:', err.message);
|
|
201
|
+
// Sair com 0 para não bloquear CIs que não precisam do binário pré-instalado
|
|
202
|
+
process.exit(0);
|
|
203
|
+
});
|