@trendify/cli 0.1.22 → 0.1.23

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.
@@ -1 +1 @@
1
- {"version":3,"file":"app.component.d.ts","sourceRoot":"","sources":["../src/app.component.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAqB,KAAK,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAMvG,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,QAAQ,CAAC,uBAAuB,CAAC,EAAE,gBAAgB,CAAC;IACpD,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,oBAAoB,EAAE;QAAE,MAAM,EAAE,WAAW,CAAA;KAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjH,CAAC;AA6DF,KAAK,gBAAgB,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAgFrD,wBAAgB,GAAG,CAAC,EAClB,UAAU,EACV,YAAY,EACZ,mBAA0B,EAC1B,uBAAmC,EACnC,YAAY,GACb,EAAE,QAAQ,2CAifV"}
1
+ {"version":3,"file":"app.component.d.ts","sourceRoot":"","sources":["../src/app.component.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAqB,KAAK,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAMvG,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7C,QAAQ,CAAC,uBAAuB,CAAC,EAAE,gBAAgB,CAAC;IACpD,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,oBAAoB,EAAE;QAAE,MAAM,EAAE,WAAW,CAAA;KAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjH,CAAC;AA6DF,KAAK,gBAAgB,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAiFrD,wBAAgB,GAAG,CAAC,EAClB,UAAU,EACV,YAAY,EACZ,mBAA0B,EAC1B,uBAAmC,EACnC,YAAY,GACb,EAAE,QAAQ,2CAkhBV"}
@@ -66,6 +66,7 @@ const MENU_ITEMS = [
66
66
  ],
67
67
  },
68
68
  ];
69
+ const UPDATE_CHECK_DELAYS_MS = [15_000, 60_000, 180_000, 300_000, 600_000];
69
70
  const LOGOUT_OPTIONS = [
70
71
  {
71
72
  value: 'cancel',
@@ -231,16 +232,44 @@ export function App({ appVersion, initialInput, initialNotification = null, init
231
232
  });
232
233
  useEffect(() => {
233
234
  let active = true;
235
+ let timeout = null;
236
+ let delayIndex = 0;
237
+ let checking = false;
238
+ const scheduleNextCheck = () => {
239
+ if (!active) {
240
+ return;
241
+ }
242
+ const delay = UPDATE_CHECK_DELAYS_MS[Math.min(delayIndex, UPDATE_CHECK_DELAYS_MS.length - 1)];
243
+ timeout = setTimeout(() => {
244
+ void checkUpdates();
245
+ }, delay);
246
+ delayIndex += 1;
247
+ };
234
248
  const checkUpdates = async () => {
249
+ if (checking) {
250
+ scheduleNextCheck();
251
+ return;
252
+ }
253
+ checking = true;
235
254
  const result = await checkForCliUpdate();
255
+ checking = false;
236
256
  if (!active) {
237
257
  return;
238
258
  }
239
- setCliUpdate(result);
259
+ setCliUpdate((current) => {
260
+ if (result.status === 'error' && current.status !== 'checking' && current.status !== 'error') {
261
+ return current;
262
+ }
263
+ return result;
264
+ });
265
+ scheduleNextCheck();
240
266
  };
241
267
  void checkUpdates();
242
268
  return () => {
243
269
  active = false;
270
+ if (timeout) {
271
+ clearTimeout(timeout);
272
+ }
244
273
  };
245
274
  }, [appVersion]);
246
275
  useEffect(() => {
@@ -1 +1 @@
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
+ {"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;AAwSD,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,5 @@
1
1
  import { chmodSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
2
- import { spawn } from 'node:child_process';
2
+ import { spawn, spawnSync } from 'node:child_process';
3
3
  import { tmpdir } from 'node:os';
4
4
  import { join } from 'node:path';
5
5
  import { randomUUID } from 'node:crypto';
@@ -109,7 +109,14 @@ function runCommand(command, args) {
109
109
  });
110
110
  }
111
111
  async function fetchLatestPublishedVersion(packageName) {
112
- const commandResult = await runCommand(getNpmCommand(), ['view', packageName, 'version', '--json', '--silent']);
112
+ const commandResult = await runCommand(getNpmCommand(), [
113
+ 'view',
114
+ packageName,
115
+ 'version',
116
+ '--json',
117
+ '--silent',
118
+ '--prefer-online',
119
+ ]);
113
120
  if (commandResult.code !== 0) {
114
121
  const message = commandResult.stderr.trim() || commandResult.stdout.trim() || 'Falha ao consultar o npm.';
115
122
  throw new Error(message);
@@ -132,119 +139,98 @@ async function fetchLatestPublishedVersion(packageName) {
132
139
  throw new Error('Nao foi possivel interpretar a versao publicada retornada pelo npm.');
133
140
  }
134
141
  function getUpdaterScriptPath() {
135
- return join(tmpdir(), `trendify-cli-updater-${randomUUID()}.cjs`);
142
+ return join(tmpdir(), `trendify-cli-updater-${randomUUID()}.sh`);
136
143
  }
137
- function buildUpdaterScriptFileContents() {
138
- return `#!/usr/bin/env node
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
- }
150
-
151
- process.stdout.write('\\u001b[2J\\u001b[3J\\u001b[H');
152
- };
153
-
154
- const releaseRawMode = () => {
155
- if (process.stdin.isTTY && typeof process.stdin.setRawMode === 'function') {
156
- try {
157
- process.stdin.setRawMode(false);
158
- } catch {}
159
- }
160
- };
161
-
162
- const isParentAlive = () => {
163
- if (!Number.isInteger(payload.parentPid) || payload.parentPid <= 0) {
164
- return false;
165
- }
166
-
167
- try {
168
- process.kill(payload.parentPid, 0);
169
- return true;
170
- } catch {
171
- return false;
172
- }
173
- };
174
-
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',
144
+ function shellEscape(value) {
145
+ return `'${value.replace(/'/gu, `'\\''`)}'`;
146
+ }
147
+ function resolveTerminalPath() {
148
+ if (!process.stdin.isTTY && !process.stdout.isTTY) {
149
+ return null;
150
+ }
151
+ const ttyResult = spawnSync('tty', [], {
152
+ encoding: 'utf8',
153
+ stdio: ['inherit', 'pipe', 'ignore'],
186
154
  });
155
+ if (ttyResult.status !== 0) {
156
+ return null;
157
+ }
158
+ const ttyPath = ttyResult.stdout.trim();
159
+ if (!ttyPath || ttyPath === 'not a tty') {
160
+ return null;
161
+ }
162
+ return ttyPath;
163
+ }
164
+ function buildShellCommand(command, args) {
165
+ return [shellEscape(command), ...args.map((arg) => shellEscape(arg))].join(' ');
166
+ }
167
+ function buildUpdaterScriptFileContents(params) {
168
+ const updateCommand = buildShellCommand(params.npmCommand, [
169
+ 'install',
170
+ '--global',
171
+ `${params.packageName}@${params.latestVersion}`,
172
+ ]);
173
+ const relaunchCommand = buildShellCommand(params.nodePath, [
174
+ ...params.execArgs,
175
+ params.entrypoint,
176
+ ...params.cliArgs,
177
+ ]);
178
+ return `#!/bin/sh
179
+ set -eu
187
180
 
188
- child.on('error', reject);
189
- child.on('close', (code) => resolve(code ?? 1));
190
- });
181
+ PARENT_PID=${params.parentPid}
182
+ TTY_PATH=${params.ttyPath ? shellEscape(params.ttyPath) : "''"}
183
+ SCRIPT_PATH=${shellEscape(params.scriptPath)}
191
184
 
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
- });
185
+ cleanup() {
186
+ rm -f "$SCRIPT_PATH" >/dev/null 2>&1 || true
187
+ }
198
188
 
199
- child.on('error', reject);
200
- child.on('spawn', () => resolve());
201
- });
189
+ wait_for_parent_exit() {
190
+ while kill -0 "$PARENT_PID" >/dev/null 2>&1; do
191
+ sleep 0.1
192
+ done
193
+ }
202
194
 
203
- const cleanupTempScript = () => {
204
- if (typeof payload.scriptPath !== 'string' || payload.scriptPath.length === 0) {
205
- return;
206
- }
195
+ bind_terminal() {
196
+ if [ -z "$TTY_PATH" ] || [ ! -e "$TTY_PATH" ]; then
197
+ return 0
198
+ fi
199
+
200
+ exec <"$TTY_PATH" >"$TTY_PATH" 2>"$TTY_PATH"
201
+ }
207
202
 
208
- try {
209
- unlinkSync(payload.scriptPath);
210
- } catch {}
211
- };
203
+ reset_terminal() {
204
+ if [ -z "$TTY_PATH" ] || [ ! -e "$TTY_PATH" ]; then
205
+ return 0
206
+ fi
212
207
 
213
- const main = async () => {
214
- await waitForParentExit();
215
- releaseRawMode();
216
- resetTerminalScreen();
208
+ stty sane <"$TTY_PATH" >/dev/null 2>&1 || true
209
+ printf '\\033c'
210
+ printf '\\033[2J\\033[3J\\033[H'
211
+ }
217
212
 
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
- );
213
+ wait_for_parent_exit
214
+ sleep 0.4
215
+ bind_terminal
216
+ reset_terminal
225
217
 
226
- const npmExitCode = await runCommand(payload.npmCommand, ['install', '--global', \`\${payload.packageName}@\${payload.latestVersion}\`]);
218
+ printf 'Atualizando o CLI de v%s para v%s.\\n' ${shellEscape(params.currentVersion)} ${shellEscape(params.latestVersion)}
219
+ printf 'Pacote npm: %s\\n\\n' ${shellEscape(params.packageName)}
227
220
 
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
- }
221
+ if ! ${updateCommand}; then
222
+ printf '\\nFalha ao atualizar automaticamente.\\n' >&2
223
+ cleanup
224
+ exit 1
225
+ fi
233
226
 
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
- };
227
+ sleep 0.4
228
+ reset_terminal
229
+ printf 'CLI atualizada com sucesso para v%s.\\n\\n' ${shellEscape(params.latestVersion)}
230
+ sleep 0.5
242
231
 
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
- });
232
+ cleanup
233
+ exec ${relaunchCommand}
248
234
  `;
249
235
  }
250
236
  async function spawnDetachedUpdaterProcess(packageName, currentVersion, latestVersion) {
@@ -253,27 +239,29 @@ async function spawnDetachedUpdaterProcess(packageName, currentVersion, latestVe
253
239
  throw new Error('Nao foi possivel identificar o entrypoint atual da CLI para reiniciar o processo.');
254
240
  }
255
241
  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,
242
+ const ttyPath = resolveTerminalPath();
243
+ const scriptContents = buildUpdaterScriptFileContents({
244
+ cliArgs: process.argv.slice(2),
263
245
  currentVersion,
246
+ entrypoint,
247
+ execArgs: process.execArgv,
264
248
  latestVersion,
265
- packageName,
266
- npmCommand: getNpmCommand(),
267
249
  nodePath: process.execPath,
268
- execArgv: process.execArgv,
269
- cliArgv: [entrypoint, ...process.argv.slice(2)],
250
+ npmCommand: getNpmCommand(),
251
+ packageName,
252
+ parentPid: process.pid,
270
253
  scriptPath,
254
+ ttyPath,
271
255
  });
256
+ writeFileSync(scriptPath, scriptContents, 'utf8');
257
+ if (process.platform !== 'win32') {
258
+ chmodSync(scriptPath, 0o700);
259
+ }
272
260
  await new Promise((resolve, reject) => {
273
- const child = spawn(process.execPath, [scriptPath, payload], {
261
+ const child = spawn('/bin/sh', [scriptPath], {
274
262
  detached: true,
275
263
  env: process.env,
276
- stdio: 'inherit',
264
+ stdio: 'ignore',
277
265
  });
278
266
  child.on('error', (error) => {
279
267
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trendify/cli",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
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",