@trendify/cli 0.1.16 → 0.1.18

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/dist/cli.entry.js CHANGED
@@ -71,8 +71,8 @@ function mountApp(feedback = null) {
71
71
  await unmountApp();
72
72
  resetTerminalScreen();
73
73
  process.stdout.write([
74
- `Atualizando o CLI de v${update.currentVersion} para v${update.latestVersion}.`,
75
- `Pacote npm: ${update.packageName}`,
74
+ `Preparando a atualizacao do CLI para v${update.latestVersion}.`,
75
+ 'O atualizador externo vai assumir o processo em seguida.',
76
76
  '',
77
77
  ].join('\n'));
78
78
  const result = await runCliSelfUpdate(update.packageName, update.latestVersion);
@@ -1 +1 @@
1
- {"version":3,"file":"cli-update.service.d.ts","sourceRoot":"","sources":["../../../src/shared/services/cli-update.service.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,oBAAoB,GAC5B;IACE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B,GACD;IACE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B,GACD;IACE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;CAC5B,GACD;IACE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEN,MAAM,MAAM,mBAAmB,GAC3B;IACE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;CACnB,GACD;IACE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;CACpB,CAAC;AAEN,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC,CAAC;AA4CF,wBAAgB,uBAAuB,IAAI,wBAAwB,CAElE;AAgOD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CA6BvE;AAED,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAwB/G"}
1
+ {"version":3,"file":"cli-update.service.d.ts","sourceRoot":"","sources":["../../../src/shared/services/cli-update.service.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,oBAAoB,GAC5B;IACE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B,GACD;IACE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;CAC9B,GACD;IACE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;CAC5B,GACD;IACE,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEN,MAAM,MAAM,mBAAmB,GAC3B;IACE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;CACnB,GACD;IACE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;CACpB,CAAC;AAEN,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC,CAAC;AA4CF,wBAAgB,uBAAuB,IAAI,wBAAwB,CAElE;AAgSD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CA6BvE;AAED,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAY/G"}
@@ -1,5 +1,8 @@
1
- import { readFileSync } from 'node:fs';
1
+ import { chmodSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
2
2
  import { spawn } from 'node:child_process';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { randomUUID } from 'node:crypto';
3
6
  const DEFAULT_PACKAGE_NAME = '@trendify/cli';
4
7
  const DEFAULT_PACKAGE_VERSION = '0.0.0';
5
8
  const VERSION_PATTERN = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/u;
@@ -128,90 +131,155 @@ async function fetchLatestPublishedVersion(packageName) {
128
131
  }
129
132
  throw new Error('Nao foi possivel interpretar a versao publicada retornada pelo npm.');
130
133
  }
131
- async function runCommandWithInheritedStdio(command, args) {
132
- return new Promise((resolve, reject) => {
133
- const child = spawn(command, [...args], {
134
- env: process.env,
135
- stdio: 'inherit',
136
- });
137
- child.on('error', (error) => {
138
- reject(error);
139
- });
140
- child.on('close', (code) => {
141
- resolve(code ?? 1);
142
- });
143
- });
134
+ function getUpdaterScriptPath() {
135
+ return join(tmpdir(), `trendify-cli-updater-${randomUUID()}.cjs`);
144
136
  }
145
- async function restartCli() {
146
- const entrypoint = process.argv[1];
147
- if (!entrypoint) {
148
- throw new Error('Nao foi possivel identificar o entrypoint atual da CLI para reiniciar o processo.');
149
- }
150
- const helperScript = `
137
+ function buildUpdaterScriptFileContents() {
138
+ return `#!/usr/bin/env node
151
139
  const { spawn } = require('node:child_process');
140
+ const { unlinkSync } = require('node:fs');
141
+
142
+ const payload = JSON.parse(process.argv[2] ?? '{}');
143
+
144
+ const wait = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
145
+
146
+ const resetTerminalScreen = () => {
147
+ if (!process.stdout.isTTY) {
148
+ return;
149
+ }
152
150
 
153
- const parentPid = Number(process.argv[1]);
154
- const nodePath = process.argv[2];
155
- const execArgv = JSON.parse(process.argv[3]);
156
- const cliArgv = JSON.parse(process.argv[4]);
151
+ process.stdout.write('\\u001b[2J\\u001b[3J\\u001b[H');
152
+ };
157
153
 
158
- const canSignalParent = Number.isInteger(parentPid) && parentPid > 0;
154
+ const releaseRawMode = () => {
155
+ if (process.stdin.isTTY && typeof process.stdin.setRawMode === 'function') {
156
+ try {
157
+ process.stdin.setRawMode(false);
158
+ } catch {}
159
+ }
160
+ };
159
161
 
160
162
  const isParentAlive = () => {
161
- if (!canSignalParent) {
163
+ if (!Number.isInteger(payload.parentPid) || payload.parentPid <= 0) {
162
164
  return false;
163
165
  }
164
166
 
165
167
  try {
166
- process.kill(parentPid, 0);
168
+ process.kill(payload.parentPid, 0);
167
169
  return true;
168
- } catch (error) {
170
+ } catch {
169
171
  return false;
170
172
  }
171
173
  };
172
174
 
173
- const launchCli = () => {
174
- const child = spawn(nodePath, [...execArgv, ...cliArgv], {
175
- env: process.env,
176
- stdio: 'inherit',
177
- });
175
+ const waitForParentExit = async () => {
176
+ while (isParentAlive()) {
177
+ await wait(100);
178
+ }
179
+ };
180
+
181
+ const runCommand = (command, args) =>
182
+ new Promise((resolve, reject) => {
183
+ const child = spawn(command, args, {
184
+ env: process.env,
185
+ stdio: 'inherit',
186
+ });
178
187
 
179
- child.on('error', (error) => {
180
- process.stderr.write(\`Falha ao reiniciar a CLI atualizada: \${error.message}\\n\`);
181
- process.exit(1);
188
+ child.on('error', reject);
189
+ child.on('close', (code) => resolve(code ?? 1));
182
190
  });
183
191
 
184
- child.on('spawn', () => {
185
- process.exit(0);
192
+ const launchUpdatedCli = async () =>
193
+ new Promise((resolve, reject) => {
194
+ const child = spawn(payload.nodePath, [...payload.execArgv, ...payload.cliArgv], {
195
+ env: process.env,
196
+ stdio: 'inherit',
197
+ });
198
+
199
+ child.on('error', reject);
200
+ child.on('spawn', () => resolve());
186
201
  });
187
- };
188
202
 
189
- const waitForParentToExit = () => {
190
- if (!isParentAlive()) {
191
- setTimeout(launchCli, 150);
203
+ const cleanupTempScript = () => {
204
+ if (typeof payload.scriptPath !== 'string' || payload.scriptPath.length === 0) {
192
205
  return;
193
206
  }
194
207
 
195
- setTimeout(waitForParentToExit, 100);
208
+ try {
209
+ unlinkSync(payload.scriptPath);
210
+ } catch {}
196
211
  };
197
212
 
198
- waitForParentToExit();
199
- `.trim();
200
- const helperArgs = [
201
- '-e',
202
- helperScript,
203
- String(process.pid),
204
- process.execPath,
205
- JSON.stringify(process.execArgv),
206
- JSON.stringify([entrypoint, ...process.argv.slice(2)]),
207
- ];
213
+ const main = async () => {
214
+ await waitForParentExit();
215
+ releaseRawMode();
216
+ resetTerminalScreen();
217
+
218
+ process.stdout.write(
219
+ [
220
+ \`Atualizando o CLI de v\${payload.currentVersion} para v\${payload.latestVersion}.\`,
221
+ \`Pacote npm: \${payload.packageName}\`,
222
+ '',
223
+ ].join('\\n'),
224
+ );
225
+
226
+ const npmExitCode = await runCommand(payload.npmCommand, ['install', '--global', \`\${payload.packageName}@\${payload.latestVersion}\`]);
227
+
228
+ if (npmExitCode !== 0) {
229
+ process.stderr.write(\`\\nFalha ao atualizar automaticamente: o npm encerrou com codigo \${npmExitCode}.\\n\`);
230
+ cleanupTempScript();
231
+ process.exit(npmExitCode);
232
+ }
233
+
234
+ releaseRawMode();
235
+ resetTerminalScreen();
236
+ process.stdout.write(\`CLI atualizada com sucesso para v\${payload.latestVersion}.\\n\\n\`);
237
+ await wait(150);
238
+ await launchUpdatedCli();
239
+ cleanupTempScript();
240
+ process.exit(0);
241
+ };
242
+
243
+ main().catch((error) => {
244
+ process.stderr.write(\`\\nFalha ao concluir a atualizacao externa: \${error?.message ?? String(error)}\\n\`);
245
+ cleanupTempScript();
246
+ process.exit(1);
247
+ });
248
+ `;
249
+ }
250
+ async function spawnDetachedUpdaterProcess(packageName, currentVersion, latestVersion) {
251
+ const entrypoint = process.argv[1];
252
+ if (!entrypoint) {
253
+ throw new Error('Nao foi possivel identificar o entrypoint atual da CLI para reiniciar o processo.');
254
+ }
255
+ const scriptPath = getUpdaterScriptPath();
256
+ const scriptContents = buildUpdaterScriptFileContents();
257
+ writeFileSync(scriptPath, scriptContents, 'utf8');
258
+ if (process.platform !== 'win32') {
259
+ chmodSync(scriptPath, 0o700);
260
+ }
261
+ const payload = JSON.stringify({
262
+ parentPid: process.pid,
263
+ currentVersion,
264
+ latestVersion,
265
+ packageName,
266
+ npmCommand: getNpmCommand(),
267
+ nodePath: process.execPath,
268
+ execArgv: process.execArgv,
269
+ cliArgv: [entrypoint, ...process.argv.slice(2)],
270
+ scriptPath,
271
+ });
208
272
  await new Promise((resolve, reject) => {
209
- const child = spawn(process.execPath, helperArgs, {
273
+ const child = spawn(process.execPath, [scriptPath, payload], {
210
274
  detached: true,
211
275
  env: process.env,
212
276
  stdio: 'inherit',
213
277
  });
214
278
  child.on('error', (error) => {
279
+ try {
280
+ unlinkSync(scriptPath);
281
+ }
282
+ catch { }
215
283
  reject(error);
216
284
  });
217
285
  child.on('spawn', () => {
@@ -250,18 +318,8 @@ export async function checkForCliUpdate() {
250
318
  }
251
319
  export async function runCliSelfUpdate(packageName, latestVersion) {
252
320
  try {
253
- const exitCode = await runCommandWithInheritedStdio(getNpmCommand(), [
254
- 'install',
255
- '--global',
256
- `${packageName}@${latestVersion}`,
257
- ]);
258
- if (exitCode !== 0) {
259
- return {
260
- error: `O npm encerrou a atualizacao com codigo ${exitCode}.`,
261
- ok: false,
262
- };
263
- }
264
- await restartCli();
321
+ const { packageVersion } = readInstalledPackageMetadata();
322
+ await spawnDetachedUpdaterProcess(packageName, packageVersion, latestVersion);
265
323
  return { ok: true };
266
324
  }
267
325
  catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trendify/cli",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "description": "CLI do Trendify para descoberta de temas e fluxos de conta.",
5
5
  "type": "module",
6
6
  "main": "dist/cli.entry.js",