@trendify/cli 0.1.8 → 0.1.10

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.
Files changed (70) hide show
  1. package/dist/cli.entry.js +24 -0
  2. package/dist/shared/config/env.config.js +1 -1
  3. package/dist/shared/constants/app-version.constant.d.ts +1 -1
  4. package/dist/shared/constants/app-version.constant.js +1 -1
  5. package/dist/shared/services/cli-update.service.d.ts.map +1 -1
  6. package/dist/shared/services/cli-update.service.js +61 -1
  7. package/dist/version.d.ts +1 -1
  8. package/dist/version.d.ts.map +1 -1
  9. package/dist/version.js +1 -1
  10. package/package.json +1 -1
  11. package/dist/app.d.ts +0 -14
  12. package/dist/app.d.ts.map +0 -1
  13. package/dist/app.js +0 -448
  14. package/dist/cli-update-service.d.ts +0 -29
  15. package/dist/cli-update-service.d.ts.map +0 -1
  16. package/dist/cli-update-service.js +0 -206
  17. package/dist/cli.d.ts +0 -3
  18. package/dist/cli.d.ts.map +0 -1
  19. package/dist/cli.js +0 -51
  20. package/dist/config/app-paths.d.ts +0 -4
  21. package/dist/config/app-paths.d.ts.map +0 -1
  22. package/dist/config/app-paths.js +0 -5
  23. package/dist/config/env.d.ts +0 -14
  24. package/dist/config/env.d.ts.map +0 -1
  25. package/dist/config/env.js +0 -58
  26. package/dist/modules/auth/auth-service.d.ts +0 -60
  27. package/dist/modules/auth/auth-service.d.ts.map +0 -1
  28. package/dist/modules/auth/auth-service.js +0 -494
  29. package/dist/modules/auth/auth-storage.d.ts +0 -11
  30. package/dist/modules/auth/auth-storage.d.ts.map +0 -1
  31. package/dist/modules/auth/auth-storage.js +0 -65
  32. package/dist/modules/auth/auth-user.d.ts +0 -3
  33. package/dist/modules/auth/auth-user.d.ts.map +0 -1
  34. package/dist/modules/auth/auth-user.js +0 -10
  35. package/dist/modules/auth/page/login-page.d.ts +0 -12
  36. package/dist/modules/auth/page/login-page.d.ts.map +0 -1
  37. package/dist/modules/auth/page/login-page.js +0 -22
  38. package/dist/modules/discovery/components/discovery-step-header.d.ts +0 -7
  39. package/dist/modules/discovery/components/discovery-step-header.d.ts.map +0 -1
  40. package/dist/modules/discovery/components/discovery-step-header.js +0 -5
  41. package/dist/modules/discovery/page/discovery-page.d.ts +0 -11
  42. package/dist/modules/discovery/page/discovery-page.d.ts.map +0 -1
  43. package/dist/modules/discovery/page/discovery-page.js +0 -58
  44. package/dist/modules/profile/page/profile-page.d.ts +0 -12
  45. package/dist/modules/profile/page/profile-page.d.ts.map +0 -1
  46. package/dist/modules/profile/page/profile-page.js +0 -180
  47. package/dist/modules/profile/pages/profile.page.d.ts +0 -12
  48. package/dist/modules/profile/pages/profile.page.d.ts.map +0 -1
  49. package/dist/modules/profile/pages/profile.page.js +0 -180
  50. package/dist/shared/components/action-menu-page.d.ts +0 -13
  51. package/dist/shared/components/action-menu-page.d.ts.map +0 -1
  52. package/dist/shared/components/action-menu-page.js +0 -7
  53. package/dist/shared/components/radio-select.d.ts +0 -12
  54. package/dist/shared/components/radio-select.d.ts.map +0 -1
  55. package/dist/shared/components/radio-select.js +0 -16
  56. package/dist/shared/components/step-header.d.ts +0 -7
  57. package/dist/shared/components/step-header.d.ts.map +0 -1
  58. package/dist/shared/components/step-header.js +0 -5
  59. package/dist/shared/components/text-field.d.ts +0 -12
  60. package/dist/shared/components/text-field.d.ts.map +0 -1
  61. package/dist/shared/components/text-field.js +0 -6
  62. package/dist/shared/template/app-logo.d.ts +0 -2
  63. package/dist/shared/template/app-logo.d.ts.map +0 -1
  64. package/dist/shared/template/app-logo.js +0 -13
  65. package/dist/shared/template/app-menu.d.ts +0 -17
  66. package/dist/shared/template/app-menu.d.ts.map +0 -1
  67. package/dist/shared/template/app-menu.js +0 -85
  68. package/dist/shared/template/app-shell.d.ts +0 -12
  69. package/dist/shared/template/app-shell.d.ts.map +0 -1
  70. package/dist/shared/template/app-shell.js +0 -15
package/dist/cli.entry.js CHANGED
@@ -25,6 +25,30 @@ if (args.includes('--version') || args.includes('-v')) {
25
25
  process.stdout.write(`${APP_VERSION}\n`);
26
26
  process.exit(0);
27
27
  }
28
+ function supportsInteractiveInkInput() {
29
+ if (!process.stdin.isTTY || typeof process.stdin.setRawMode !== 'function') {
30
+ return false;
31
+ }
32
+ const previousRawMode = process.stdin.isRaw === true;
33
+ try {
34
+ process.stdin.setRawMode(true);
35
+ process.stdin.setRawMode(previousRawMode);
36
+ return true;
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
42
+ function printNonInteractiveFallback() {
43
+ process.stdout.write(`Trendify CLI v${APP_VERSION}\n`);
44
+ process.stdout.write('A interface interativa nao conseguiu acessar o terminal em modo raw.\n');
45
+ process.stdout.write('Se voce acabou de atualizar a CLI, feche esta execucao e rode o comando novamente.\n');
46
+ process.stdout.write('Se o problema continuar, execute em um terminal interativo comum, sem pipe/redirecionamento.\n');
47
+ }
48
+ if (!supportsInteractiveInkInput()) {
49
+ printNonInteractiveFallback();
50
+ process.exit(1);
51
+ }
28
52
  console.clear();
29
53
  let appInstance;
30
54
  function mountApp(feedback = null) {
@@ -4,7 +4,7 @@ import { fileURLToPath } from 'node:url';
4
4
  import { config as loadEnv } from 'dotenv';
5
5
  const currentFilePath = fileURLToPath(import.meta.url);
6
6
  const currentDirectory = dirname(currentFilePath);
7
- const appRootDirectory = resolve(currentDirectory, '..', '..');
7
+ const appRootDirectory = resolve(currentDirectory, '..', '..', '..');
8
8
  const workspaceRootDirectory = resolve(appRootDirectory, '..', '..');
9
9
  const ENV_FILE_PATHS = [
10
10
  resolve(appRootDirectory, '.env'),
@@ -1,2 +1,2 @@
1
- export declare const APP_VERSION = "0.1.7";
1
+ export declare const APP_VERSION = "0.1.8";
2
2
  //# sourceMappingURL=app-version.constant.d.ts.map
@@ -1 +1 @@
1
- export const APP_VERSION = '0.1.7';
1
+ export const APP_VERSION = '0.1.8';
@@ -1 +1 @@
1
- {"version":3,"file":"cli-update.service.d.ts","sourceRoot":"","sources":["../../../src/shared/services/cli-update.service.ts"],"names":[],"mappings":"AAMA,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;AA4MN,wBAAsB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA6B7F;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":"AAMA,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;AA0QN,wBAAsB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA6B7F;AAED,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAwB/G"}
@@ -140,8 +140,67 @@ async function restartCli() {
140
140
  if (!entrypoint) {
141
141
  throw new Error('Nao foi possivel identificar o entrypoint atual da CLI para reiniciar o processo.');
142
142
  }
143
+ const helperScript = `
144
+ const { spawn } = require('node:child_process');
145
+
146
+ const parentPid = Number(process.argv[1]);
147
+ const nodePath = process.argv[2];
148
+ const execArgv = JSON.parse(process.argv[3]);
149
+ const cliArgv = JSON.parse(process.argv[4]);
150
+
151
+ const canSignalParent = Number.isInteger(parentPid) && parentPid > 0;
152
+
153
+ const isParentAlive = () => {
154
+ if (!canSignalParent) {
155
+ return false;
156
+ }
157
+
158
+ try {
159
+ process.kill(parentPid, 0);
160
+ return true;
161
+ } catch (error) {
162
+ return false;
163
+ }
164
+ };
165
+
166
+ const launchCli = () => {
167
+ const child = spawn(nodePath, [...execArgv, ...cliArgv], {
168
+ env: process.env,
169
+ stdio: 'inherit',
170
+ });
171
+
172
+ child.on('error', (error) => {
173
+ process.stderr.write(\`Falha ao reiniciar a CLI atualizada: \${error.message}\\n\`);
174
+ process.exit(1);
175
+ });
176
+
177
+ child.on('spawn', () => {
178
+ process.exit(0);
179
+ });
180
+ };
181
+
182
+ const waitForParentToExit = () => {
183
+ if (!isParentAlive()) {
184
+ setTimeout(launchCli, 150);
185
+ return;
186
+ }
187
+
188
+ setTimeout(waitForParentToExit, 100);
189
+ };
190
+
191
+ waitForParentToExit();
192
+ `.trim();
193
+ const helperArgs = [
194
+ '-e',
195
+ helperScript,
196
+ String(process.pid),
197
+ process.execPath,
198
+ JSON.stringify(process.execArgv),
199
+ JSON.stringify([entrypoint, ...process.argv.slice(2)]),
200
+ ];
143
201
  await new Promise((resolve, reject) => {
144
- const child = spawn(process.execPath, [...process.execArgv, entrypoint, ...process.argv.slice(2)], {
202
+ const child = spawn(process.execPath, helperArgs, {
203
+ detached: true,
145
204
  env: process.env,
146
205
  stdio: 'inherit',
147
206
  });
@@ -149,6 +208,7 @@ async function restartCli() {
149
208
  reject(error);
150
209
  });
151
210
  child.on('spawn', () => {
211
+ child.unref();
152
212
  resolve();
153
213
  });
154
214
  });
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const APP_VERSION = "0.1.8";
1
+ export declare const APP_VERSION = "0.1.10";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,UAAU,CAAC"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,WAAW,CAAC"}
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const APP_VERSION = '0.1.8';
1
+ export const APP_VERSION = '0.1.10';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trendify/cli",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
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",
package/dist/app.d.ts DELETED
@@ -1,14 +0,0 @@
1
- import { type CliUpdateCheckResult } from './cli-update-service.js';
2
- export type AppProps = {
3
- readonly appVersion: string;
4
- readonly initialInput: string;
5
- readonly initialNotification?: string | null;
6
- readonly initialNotificationTone?: NotificationTone;
7
- readonly onSelfUpdate: (update: Extract<CliUpdateCheckResult, {
8
- status: 'available';
9
- }>) => void | Promise<void>;
10
- };
11
- type NotificationTone = 'error' | 'info' | 'success';
12
- export declare function App({ appVersion, initialInput, initialNotification, initialNotificationTone, onSelfUpdate, }: AppProps): import("react/jsx-runtime").JSX.Element;
13
- export {};
14
- //# sourceMappingURL=app.d.ts.map
package/dist/app.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAqB,KAAK,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAMvF,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;AAyFrD,wBAAgB,GAAG,CAAC,EAClB,UAAU,EACV,YAAY,EACZ,mBAA0B,EAC1B,uBAAmC,EACnC,YAAY,GACb,EAAE,QAAQ,2CAmfV"}
package/dist/app.js DELETED
@@ -1,448 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Text, useApp, useInput } from 'ink';
3
- import { useEffect, useMemo, useState } from 'react';
4
- import { DiscoveryPage } from './modules/discovery/page/discovery-page.js';
5
- import { getUserDisplayName } from './modules/auth/auth-user.js';
6
- import { getAuthBootstrapResult, } from './modules/auth/auth-service.js';
7
- import { LoginPage } from './modules/auth/page/login-page.js';
8
- import { ProfilePage } from './modules/profile/page/profile-page.js';
9
- import { checkForCliUpdate } from './cli-update-service.js';
10
- import { ActionMenuPage } from './shared/components/action-menu-page.js';
11
- import { AppMenu } from './shared/template/app-menu.js';
12
- import { AppShell } from './shared/template/app-shell.js';
13
- const MENU_ITEMS = [
14
- {
15
- id: 'discovery',
16
- titulo: 'Descobrir Temas',
17
- comando: 'discovery',
18
- aliases: ['descobrir', 'Descobrir', 'temas', 'Temas'],
19
- descricao: 'Inicia o fluxo de descoberta e coleta o tema da busca.',
20
- palavrasChave: ['tema', 'Tema', 'descoberta', 'Descoberta', 'pesquisa', 'Pesquisa', 'amplo', 'restrito'],
21
- },
22
- {
23
- id: 'profile',
24
- titulo: 'Meu Perfil',
25
- comando: 'profile',
26
- aliases: ['perfil', 'Perfil', 'conta', 'Conta', 'usuário', 'usuario', 'Usuário', 'Usuario'],
27
- descricao: 'Abre os fluxos de alteração de senha e display name.',
28
- palavrasChave: [
29
- 'senha',
30
- 'Senha',
31
- 'display name',
32
- 'Display Name',
33
- 'nome',
34
- 'Nome',
35
- 'usuário',
36
- 'usuario',
37
- 'Supabase',
38
- 'supabase',
39
- ],
40
- },
41
- {
42
- id: 'logout',
43
- titulo: 'Encerrar Sessão',
44
- comando: 'logout',
45
- aliases: ['sair-da-conta', 'sair da conta', 'Sair da Conta', 'deslogar', 'Deslogar'],
46
- descricao: 'Remove a sessão salva localmente e volta para a tela de login.',
47
- palavrasChave: ['auth', 'login', 'Login', 'conta', 'Conta', 'sessão', 'sessao', 'Sessão', 'Sessao', 'Supabase'],
48
- },
49
- {
50
- id: 'exit',
51
- titulo: 'Sair',
52
- comando: 'sair',
53
- aliases: ['exit', 'quit', 'sair', 'Sair'],
54
- descricao: 'Sai do sistema sem perder a sessão do usuário ativa.',
55
- palavrasChave: [
56
- 'fechar',
57
- 'Fechar',
58
- 'encerrar',
59
- 'Encerrar',
60
- 'finalizar',
61
- 'Finalizar',
62
- 'sessão',
63
- 'sessao',
64
- 'usuário',
65
- 'usuario',
66
- ],
67
- },
68
- ];
69
- const LOGOUT_OPTIONS = [
70
- {
71
- value: 'cancel',
72
- label: 'Voltar ao menu',
73
- description: 'Cancela a saida da conta e retorna para os comandos.',
74
- },
75
- {
76
- value: 'confirm',
77
- label: 'Encerrar sessao',
78
- description: 'Remove a sessao local e exige novo login para continuar.',
79
- },
80
- ];
81
- function formatScopeLabel(scope) {
82
- return scope === 'amplo' ? 'mais ampla' : 'mais restrita';
83
- }
84
- function formatWorkspaceRole(role) {
85
- if (role === 'owner') {
86
- return 'Proprietario';
87
- }
88
- if (role === 'admin') {
89
- return 'Administrador';
90
- }
91
- return 'Membro';
92
- }
93
- function getAuthenticatedUserLabel(user) {
94
- if (!user) {
95
- return 'usuario autenticado';
96
- }
97
- return getUserDisplayName(user) ?? user.email ?? 'usuario autenticado';
98
- }
99
- function getActiveWorkspaceLabel(workspace) {
100
- return workspace?.name ?? 'espaco de trabalho';
101
- }
102
- function getWelcomeTitle(user) {
103
- const displayName = user ? getUserDisplayName(user) : null;
104
- if (displayName) {
105
- return `Bem-vindo de volta, ${displayName} 👋`;
106
- }
107
- return 'Bem-vindo de volta. 👋';
108
- }
109
- function buildMenuItems(cliUpdate) {
110
- if (cliUpdate.status !== 'available') {
111
- return MENU_ITEMS;
112
- }
113
- const [discoveryItem, profileItem, logoutItem, exitItem] = MENU_ITEMS;
114
- if (!discoveryItem || !profileItem || !logoutItem || !exitItem) {
115
- return MENU_ITEMS;
116
- }
117
- return [
118
- discoveryItem,
119
- profileItem,
120
- {
121
- id: 'update-cli',
122
- titulo: `Atualizar CLI para v${cliUpdate.latestVersion}`,
123
- comando: 'atualizar-cli',
124
- aliases: ['update', 'upgrade', 'atualizar', 'atualizar-cli', 'Atualizar CLI'],
125
- descricao: `Instala a versao ${cliUpdate.latestVersion} do CLI e reinicia a aplicacao.`,
126
- palavrasChave: [
127
- 'versao',
128
- 'nova versao',
129
- 'ultima versao',
130
- 'npm',
131
- 'upgrade',
132
- 'update',
133
- 'atualizacao',
134
- 'atualizar',
135
- ],
136
- },
137
- logoutItem,
138
- exitItem,
139
- ];
140
- }
141
- export function App({ appVersion, initialInput, initialNotification = null, initialNotificationTone = 'success', onSelfUpdate, }) {
142
- const { exit } = useApp();
143
- const authBootstrap = useMemo(() => getAuthBootstrapResult(), []);
144
- const authService = authBootstrap.ok ? authBootstrap.authService : null;
145
- const sessionStorageFilePath = authService?.getSessionStorageFilePath() ?? '~/.trendify/auth/storage.json';
146
- const [screen, setScreen] = useState('menu');
147
- const [notification, setNotification] = useState(initialNotification);
148
- const [notificationTone, setNotificationTone] = useState(initialNotificationTone);
149
- const [menuKey, setMenuKey] = useState(0);
150
- const [authStatus, setAuthStatus] = useState(authBootstrap.ok ? 'booting' : 'config-error');
151
- const [authUser, setAuthUser] = useState(null);
152
- const [availableWorkspaces, setAvailableWorkspaces] = useState([]);
153
- const [activeWorkspace, setActiveWorkspace] = useState(null);
154
- const [email, setEmail] = useState('');
155
- const [password, setPassword] = useState('');
156
- const [authBusy, setAuthBusy] = useState(false);
157
- const [logoutSelectionIndex, setLogoutSelectionIndex] = useState(0);
158
- const [workspaceSelectionIndex, setWorkspaceSelectionIndex] = useState(0);
159
- const [cliUpdate, setCliUpdate] = useState({
160
- currentVersion: appVersion,
161
- packageName: '@trendify/cli',
162
- status: 'checking',
163
- });
164
- const menuItems = useMemo(() => buildMenuItems(cliUpdate), [cliUpdate]);
165
- function resetAuthenticatedContext() {
166
- setAuthUser(null);
167
- setAvailableWorkspaces([]);
168
- setActiveWorkspace(null);
169
- setWorkspaceSelectionIndex(0);
170
- }
171
- function applyAuthenticatedSnapshot(snapshot) {
172
- setAuthStatus('authenticated');
173
- setAuthUser(snapshot.user);
174
- setAvailableWorkspaces(snapshot.workspaces);
175
- setActiveWorkspace(snapshot.activeWorkspace);
176
- setWorkspaceSelectionIndex(0);
177
- if (snapshot.requiresWorkspaceSelection) {
178
- setScreen('select-workspace');
179
- return;
180
- }
181
- setScreen('menu');
182
- setMenuKey((current) => current + 1);
183
- }
184
- useInput((input, key) => {
185
- if (key.ctrl && input === 'c') {
186
- exit();
187
- }
188
- });
189
- useInput((_input, key) => {
190
- if (screen !== 'confirm-logout' || authBusy) {
191
- return;
192
- }
193
- if (key.escape) {
194
- setScreen('menu');
195
- setLogoutSelectionIndex(0);
196
- return;
197
- }
198
- if (key.upArrow) {
199
- setLogoutSelectionIndex((current) => (current === 0 ? LOGOUT_OPTIONS.length - 1 : current - 1));
200
- return;
201
- }
202
- if (key.downArrow) {
203
- setLogoutSelectionIndex((current) => (current === LOGOUT_OPTIONS.length - 1 ? 0 : current + 1));
204
- return;
205
- }
206
- if (key.return) {
207
- const option = LOGOUT_OPTIONS[logoutSelectionIndex];
208
- if (option?.value === 'confirm') {
209
- void handleLogout();
210
- return;
211
- }
212
- setScreen('menu');
213
- setLogoutSelectionIndex(0);
214
- setNotification('Encerramento de sessao cancelado.');
215
- setNotificationTone('info');
216
- }
217
- });
218
- useInput((_input, key) => {
219
- if (screen !== 'select-workspace' || authBusy) {
220
- return;
221
- }
222
- if (!availableWorkspaces.length) {
223
- return;
224
- }
225
- if (key.escape) {
226
- void handleLogout();
227
- return;
228
- }
229
- if (key.upArrow) {
230
- setWorkspaceSelectionIndex((current) => (current === 0 ? availableWorkspaces.length - 1 : current - 1));
231
- return;
232
- }
233
- if (key.downArrow) {
234
- setWorkspaceSelectionIndex((current) => (current === availableWorkspaces.length - 1 ? 0 : current + 1));
235
- return;
236
- }
237
- if (key.return) {
238
- void handleWorkspaceSelection();
239
- }
240
- });
241
- useEffect(() => {
242
- let active = true;
243
- const checkUpdates = async () => {
244
- const result = await checkForCliUpdate(appVersion);
245
- if (!active) {
246
- return;
247
- }
248
- setCliUpdate(result);
249
- };
250
- void checkUpdates();
251
- return () => {
252
- active = false;
253
- };
254
- }, [appVersion]);
255
- useEffect(() => {
256
- if (!authService) {
257
- return;
258
- }
259
- let active = true;
260
- setAuthBusy(true);
261
- const restoreSession = async () => {
262
- const result = await authService.restoreSession();
263
- if (!active) {
264
- return;
265
- }
266
- if (result.error) {
267
- setNotification(result.error);
268
- setNotificationTone('error');
269
- }
270
- if (result.data?.user) {
271
- applyAuthenticatedSnapshot(result.data);
272
- if (result.data.requiresWorkspaceSelection) {
273
- setNotification('Escolha o espaco de trabalho que deseja usar nesta sessao.');
274
- setNotificationTone('info');
275
- }
276
- }
277
- else {
278
- setAuthStatus('unauthenticated');
279
- resetAuthenticatedContext();
280
- }
281
- setAuthBusy(false);
282
- };
283
- void restoreSession();
284
- const { data: { subscription }, } = authService.onAuthStateChange((snapshot) => {
285
- if (!active) {
286
- return;
287
- }
288
- if (snapshot.user) {
289
- setAuthUser(snapshot.user);
290
- return;
291
- }
292
- setAuthStatus('unauthenticated');
293
- resetAuthenticatedContext();
294
- setScreen('menu');
295
- setMenuKey((current) => current + 1);
296
- });
297
- return () => {
298
- active = false;
299
- subscription.unsubscribe();
300
- };
301
- }, [authService]);
302
- async function handleLogin() {
303
- if (!authService || authBusy) {
304
- return;
305
- }
306
- const trimmedEmail = email.trim();
307
- if (!trimmedEmail || !password.trim()) {
308
- setNotification('Preencha email e senha para continuar.');
309
- setNotificationTone('error');
310
- return;
311
- }
312
- setAuthBusy(true);
313
- setNotification(null);
314
- const result = await authService.signInWithPassword(trimmedEmail, password);
315
- setAuthBusy(false);
316
- if (result.error || !result.data?.user) {
317
- setPassword('');
318
- setNotification(result.error ?? 'Nao foi possivel autenticar este usuario.');
319
- setNotificationTone('error');
320
- setAuthStatus('unauthenticated');
321
- resetAuthenticatedContext();
322
- return;
323
- }
324
- applyAuthenticatedSnapshot(result.data);
325
- setPassword('');
326
- if (result.data.requiresWorkspaceSelection) {
327
- setNotification('Login concluido. Escolha o espaco de trabalho para continuar.');
328
- setNotificationTone('info');
329
- return;
330
- }
331
- setNotification(null);
332
- }
333
- async function handleWorkspaceSelection() {
334
- if (!authService || authBusy || !availableWorkspaces.length) {
335
- return;
336
- }
337
- const workspace = availableWorkspaces[workspaceSelectionIndex];
338
- if (!workspace) {
339
- return;
340
- }
341
- setAuthBusy(true);
342
- const result = await authService.selectWorkspace(workspace.id);
343
- setAuthBusy(false);
344
- if (result.error || !result.data) {
345
- setNotification(result.error ?? 'Nao foi possivel ativar este espaco de trabalho.');
346
- setNotificationTone('error');
347
- return;
348
- }
349
- setActiveWorkspace(result.data);
350
- setScreen('menu');
351
- setMenuKey((current) => current + 1);
352
- setNotification(`Espaco de trabalho ativo: ${result.data.name}.`);
353
- setNotificationTone('success');
354
- }
355
- async function handleLogout() {
356
- if (!authService || authBusy) {
357
- return;
358
- }
359
- setAuthBusy(true);
360
- const result = await authService.signOut();
361
- setAuthBusy(false);
362
- if (result.error) {
363
- setNotification(result.error);
364
- setNotificationTone('error');
365
- return;
366
- }
367
- setScreen('menu');
368
- setEmail('');
369
- setPassword('');
370
- resetAuthenticatedContext();
371
- setMenuKey((current) => current + 1);
372
- setLogoutSelectionIndex(0);
373
- setNotification('Sessao local removida. Faca login novamente para continuar.');
374
- setNotificationTone('success');
375
- }
376
- if (!authBootstrap.ok) {
377
- return (_jsx(AppShell, { appVersion: appVersion, title: "Configuracao do Supabase pendente.", subtitle: "Defina as variaveis de ambiente antes de usar a CLI.", notification: authBootstrap.error, notificationTone: "error", children: _jsx(Text, { children: "Crie um arquivo .env com base em .env.example e preencha as chaves do projeto Supabase." }) }));
378
- }
379
- if (authStatus === 'booting') {
380
- return (_jsx(AppShell, { appVersion: appVersion, title: "Validando sua sessao.", subtitle: "A CLI esta consultando o Supabase para restaurar a sessao e o espaco de trabalho atual.", notification: notification, notificationTone: notificationTone, children: _jsx(Text, { dimColor: true, children: authBusy ? 'Aguarde alguns instantes...' : 'Pronto para autenticar.' }) }));
381
- }
382
- if (authStatus === 'unauthenticated') {
383
- return (_jsx(AppShell, { appVersion: appVersion, title: "Login obrigatorio.", subtitle: "Somente usuarios vinculados a um espaco de trabalho no Supabase podem usar a CLI.", notification: notification, notificationTone: notificationTone, children: _jsx(LoginPage, { busy: authBusy, email: email, password: password, sessionStorageFilePath: sessionStorageFilePath, onEmailChange: setEmail, onPasswordChange: setPassword, onSubmit: () => {
384
- void handleLogin();
385
- } }) }));
386
- }
387
- if (screen === 'select-workspace') {
388
- const workspaceOptions = availableWorkspaces.map((workspace) => ({
389
- value: workspace.id,
390
- label: workspace.name,
391
- description: `${workspace.slug} • ${formatWorkspaceRole(workspace.role)}`,
392
- }));
393
- return (_jsx(AppShell, { appVersion: appVersion, title: "Escolha o espaco de trabalho", subtitle: `Conta autenticada para ${getAuthenticatedUserLabel(authUser)}. Selecione onde deseja operar.`, notification: notification, notificationTone: notificationTone, children: _jsx(ActionMenuPage, { title: "Espaco de trabalho ativo", subtitle: "Esse contexto sera usado nas consultas protegidas e nas regras de seguranca por linha.", options: workspaceOptions, selectedIndex: workspaceSelectionIndex, hintText: "Use as setas para navegar. Enter ativa o espaco. Esc encerra a sessao.", children: _jsxs(Text, { children: ["Conta: ", authUser?.email ?? 'nao informado'] }) }) }));
394
- }
395
- if (screen === 'discovery') {
396
- return (_jsx(AppShell, { appVersion: appVersion, title: "Discovery", subtitle: `Sessao ativa para ${getAuthenticatedUserLabel(authUser)} em ${getActiveWorkspaceLabel(activeWorkspace)}.`, notification: notification, notificationTone: notificationTone, children: _jsx(DiscoveryPage, { onCancel: () => {
397
- setScreen('menu');
398
- setMenuKey((current) => current + 1);
399
- }, onComplete: ({ theme, scope }) => {
400
- setNotification(`Discovery finalizado: tema "${theme}" com abordagem ${formatScopeLabel(scope)}.`);
401
- setNotificationTone('success');
402
- setScreen('menu');
403
- setMenuKey((current) => current + 1);
404
- } }) }));
405
- }
406
- if (screen === 'profile' && authService && authUser) {
407
- return (_jsx(AppShell, { appVersion: appVersion, title: "Profile", subtitle: `Sessao ativa para ${getAuthenticatedUserLabel(authUser)} em ${getActiveWorkspaceLabel(activeWorkspace)}.`, notification: notification, notificationTone: notificationTone, children: _jsx(ProfilePage, { authService: authService, user: authUser, onBack: () => {
408
- setScreen('menu');
409
- setMenuKey((current) => current + 1);
410
- }, onNotificationChange: (nextNotification, nextTone = 'success') => {
411
- setNotification(nextNotification);
412
- setNotificationTone(nextTone);
413
- } }) }));
414
- }
415
- if (screen === 'confirm-logout') {
416
- return (_jsx(AppShell, { appVersion: appVersion, title: "Confirmar encerramento de sessao", subtitle: `Voce esta autenticado como ${getAuthenticatedUserLabel(authUser)} em ${getActiveWorkspaceLabel(activeWorkspace)}.`, notification: notification, notificationTone: notificationTone, children: _jsx(ActionMenuPage, { title: "Tem certeza que deseja encerrar a sessao atual?", subtitle: "Se confirmar, a CLI vai remover a sessao salva localmente e pedir login novamente.", options: LOGOUT_OPTIONS, selectedIndex: logoutSelectionIndex, hintText: "Use as setas para navegar. Enter confirma. Esc volta ao menu." }) }));
417
- }
418
- return (_jsxs(AppShell, { appVersion: appVersion, title: getWelcomeTitle(authUser), subtitle: `Workspace: ${getActiveWorkspaceLabel(activeWorkspace)}\n\nUse a barra para abrir os comandos.`, notification: notification, notificationTone: notificationTone, children: [cliUpdate.status === 'available' ? (_jsxs(Text, { color: "yellowBright", children: ["Nova versao disponivel: v", cliUpdate.latestVersion, ". Abra o menu com / e escolha \"Atualizar CLI\"."] })) : null, _jsx(AppMenu, { initialInput: menuKey === 0 ? initialInput : '', items: menuItems, onInputChange: () => {
419
- if (notification) {
420
- setNotification(null);
421
- }
422
- }, onSelect: (item) => {
423
- if (item.id === 'update-cli' && cliUpdate.status === 'available') {
424
- void onSelfUpdate(cliUpdate);
425
- return;
426
- }
427
- if (item.id === 'logout') {
428
- setNotification(null);
429
- setNotificationTone('info');
430
- setLogoutSelectionIndex(0);
431
- setScreen('confirm-logout');
432
- return;
433
- }
434
- if (item.id === 'profile') {
435
- setNotification(null);
436
- setNotificationTone('success');
437
- setScreen('profile');
438
- return;
439
- }
440
- if (item.id === 'exit') {
441
- exit();
442
- return;
443
- }
444
- setNotification(null);
445
- setNotificationTone('success');
446
- setScreen('discovery');
447
- } }, menuKey)] }));
448
- }
@@ -1,29 +0,0 @@
1
- export type CliUpdateCheckResult = {
2
- readonly currentVersion: string;
3
- readonly packageName: string;
4
- readonly status: 'checking';
5
- } | {
6
- readonly currentVersion: string;
7
- readonly latestVersion: string;
8
- readonly packageName: string;
9
- readonly status: 'available';
10
- } | {
11
- readonly currentVersion: string;
12
- readonly latestVersion: string;
13
- readonly packageName: string;
14
- readonly status: 'current';
15
- } | {
16
- readonly currentVersion: string;
17
- readonly message: string;
18
- readonly packageName: string;
19
- readonly status: 'error';
20
- };
21
- export type CliSelfUpdateResult = {
22
- readonly ok: true;
23
- } | {
24
- readonly error: string;
25
- readonly ok: false;
26
- };
27
- export declare function checkForCliUpdate(currentVersion: string): Promise<CliUpdateCheckResult>;
28
- export declare function runCliSelfUpdate(packageName: string, latestVersion: string): Promise<CliSelfUpdateResult>;
29
- //# sourceMappingURL=cli-update-service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli-update-service.d.ts","sourceRoot":"","sources":["../src/cli-update-service.ts"],"names":[],"mappings":"AAMA,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;AA4MN,wBAAsB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA6B7F;AAED,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAwB/G"}