@trendify/cli 0.1.9 → 0.1.11

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 (73) hide show
  1. package/dist/app.component.js +1 -1
  2. package/dist/cli.entry.js +2 -2
  3. package/dist/shared/config/env.config.js +1 -1
  4. package/dist/shared/services/cli-update.service.d.ts +7 -1
  5. package/dist/shared/services/cli-update.service.d.ts.map +1 -1
  6. package/dist/shared/services/cli-update.service.js +16 -9
  7. package/package.json +1 -1
  8. package/dist/app.d.ts +0 -14
  9. package/dist/app.d.ts.map +0 -1
  10. package/dist/app.js +0 -448
  11. package/dist/cli-update-service.d.ts +0 -29
  12. package/dist/cli-update-service.d.ts.map +0 -1
  13. package/dist/cli-update-service.js +0 -206
  14. package/dist/cli.d.ts +0 -3
  15. package/dist/cli.d.ts.map +0 -1
  16. package/dist/cli.js +0 -51
  17. package/dist/config/app-paths.d.ts +0 -4
  18. package/dist/config/app-paths.d.ts.map +0 -1
  19. package/dist/config/app-paths.js +0 -5
  20. package/dist/config/env.d.ts +0 -14
  21. package/dist/config/env.d.ts.map +0 -1
  22. package/dist/config/env.js +0 -58
  23. package/dist/modules/auth/auth-service.d.ts +0 -60
  24. package/dist/modules/auth/auth-service.d.ts.map +0 -1
  25. package/dist/modules/auth/auth-service.js +0 -494
  26. package/dist/modules/auth/auth-storage.d.ts +0 -11
  27. package/dist/modules/auth/auth-storage.d.ts.map +0 -1
  28. package/dist/modules/auth/auth-storage.js +0 -65
  29. package/dist/modules/auth/auth-user.d.ts +0 -3
  30. package/dist/modules/auth/auth-user.d.ts.map +0 -1
  31. package/dist/modules/auth/auth-user.js +0 -10
  32. package/dist/modules/auth/page/login-page.d.ts +0 -12
  33. package/dist/modules/auth/page/login-page.d.ts.map +0 -1
  34. package/dist/modules/auth/page/login-page.js +0 -22
  35. package/dist/modules/discovery/components/discovery-step-header.d.ts +0 -7
  36. package/dist/modules/discovery/components/discovery-step-header.d.ts.map +0 -1
  37. package/dist/modules/discovery/components/discovery-step-header.js +0 -5
  38. package/dist/modules/discovery/page/discovery-page.d.ts +0 -11
  39. package/dist/modules/discovery/page/discovery-page.d.ts.map +0 -1
  40. package/dist/modules/discovery/page/discovery-page.js +0 -58
  41. package/dist/modules/profile/page/profile-page.d.ts +0 -12
  42. package/dist/modules/profile/page/profile-page.d.ts.map +0 -1
  43. package/dist/modules/profile/page/profile-page.js +0 -180
  44. package/dist/modules/profile/pages/profile.page.d.ts +0 -12
  45. package/dist/modules/profile/pages/profile.page.d.ts.map +0 -1
  46. package/dist/modules/profile/pages/profile.page.js +0 -180
  47. package/dist/shared/components/action-menu-page.d.ts +0 -13
  48. package/dist/shared/components/action-menu-page.d.ts.map +0 -1
  49. package/dist/shared/components/action-menu-page.js +0 -7
  50. package/dist/shared/components/radio-select.d.ts +0 -12
  51. package/dist/shared/components/radio-select.d.ts.map +0 -1
  52. package/dist/shared/components/radio-select.js +0 -16
  53. package/dist/shared/components/step-header.d.ts +0 -7
  54. package/dist/shared/components/step-header.d.ts.map +0 -1
  55. package/dist/shared/components/step-header.js +0 -5
  56. package/dist/shared/components/text-field.d.ts +0 -12
  57. package/dist/shared/components/text-field.d.ts.map +0 -1
  58. package/dist/shared/components/text-field.js +0 -6
  59. package/dist/shared/constants/app-version.constant.d.ts +0 -2
  60. package/dist/shared/constants/app-version.constant.d.ts.map +0 -1
  61. package/dist/shared/constants/app-version.constant.js +0 -1
  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
  71. package/dist/version.d.ts +0 -2
  72. package/dist/version.d.ts.map +0 -1
  73. package/dist/version.js +0 -1
@@ -1,58 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState } from 'react';
3
- import { Box, Text, useInput } from 'ink';
4
- import { ActionMenuPage } from '../../../shared/components/action-menu-page.js';
5
- import { StepHeader } from '../../../shared/components/step-header.js';
6
- import { TextField } from '../../../shared/components/text-field.js';
7
- const SCOPE_OPTIONS = [
8
- {
9
- value: 'amplo',
10
- label: 'Mais ampla',
11
- description: 'Busca caminhos mais abrangentes em torno do tema informado.',
12
- },
13
- {
14
- value: 'restrito',
15
- label: 'Mais restrita',
16
- description: 'Foca em recortes mais especificos e direcionados do tema.',
17
- },
18
- ];
19
- export function DiscoveryPage({ onCancel, onComplete }) {
20
- const [step, setStep] = useState('theme');
21
- const [theme, setTheme] = useState('');
22
- const [selectedIndex, setSelectedIndex] = useState(0);
23
- useInput((input, key) => {
24
- if (key.escape) {
25
- onCancel();
26
- return;
27
- }
28
- if (step !== 'scope') {
29
- return;
30
- }
31
- if (key.upArrow) {
32
- setSelectedIndex((current) => current === 0 ? SCOPE_OPTIONS.length - 1 : current - 1);
33
- return;
34
- }
35
- if (key.downArrow) {
36
- setSelectedIndex((current) => current === SCOPE_OPTIONS.length - 1 ? 0 : current + 1);
37
- return;
38
- }
39
- if (key.return) {
40
- const option = SCOPE_OPTIONS[selectedIndex];
41
- if (option) {
42
- onComplete({
43
- scope: option.value,
44
- theme: theme.trim(),
45
- });
46
- }
47
- }
48
- });
49
- if (step === 'theme') {
50
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Qual e o tema da descoberta?", subtitle: "Digite o tema e pressione Enter para continuar." }), _jsx(TextField, { placeholder: "Ex.: IA generativa", value: theme, onChange: setTheme, onSubmit: (value) => {
51
- if (value.trim()) {
52
- setTheme(value);
53
- setStep('scope');
54
- }
55
- } }), _jsx(Text, { dimColor: true, children: "Esc volta para o menu inicial." })] }));
56
- }
57
- return (_jsx(ActionMenuPage, { title: "Como voce quer seguir com esse tema?", subtitle: `Tema selecionado: "${theme.trim()}". Escolha o tipo de exploracao.`, options: SCOPE_OPTIONS, selectedIndex: selectedIndex, hintText: "Use as setas para navegar. Enter confirma. Esc volta ao menu." }));
58
- }
@@ -1,12 +0,0 @@
1
- import { type AuthUser } from '@supabase/supabase-js';
2
- import { type AuthService } from '../../auth/auth-service.js';
3
- type NotificationTone = 'error' | 'info' | 'success';
4
- type ProfilePageProps = {
5
- readonly authService: AuthService;
6
- readonly onBack: () => void;
7
- readonly onNotificationChange: (notification: string | null, tone?: NotificationTone) => void;
8
- readonly user: AuthUser;
9
- };
10
- export declare function ProfilePage({ authService, onBack, onNotificationChange, user }: ProfilePageProps): import("react/jsx-runtime").JSX.Element;
11
- export {};
12
- //# sourceMappingURL=profile-page.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"profile-page.d.ts","sourceRoot":"","sources":["../../../../src/modules/profile/page/profile-page.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAItD,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAM9D,KAAK,gBAAgB,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAKrD,KAAK,gBAAgB,GAAG;IACtB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;IAC5B,QAAQ,CAAC,oBAAoB,EAAE,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC9F,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;CACzB,CAAC;AAwBF,wBAAgB,WAAW,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,oBAAoB,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CAwQhG"}
@@ -1,180 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Text, useInput } from 'ink';
3
- import { useEffect, useState } from 'react';
4
- import { getUserDisplayName } from '../../auth/auth-user.js';
5
- import { ActionMenuPage } from '../../../shared/components/action-menu-page.js';
6
- import { StepHeader } from '../../../shared/components/step-header.js';
7
- import { TextField } from '../../../shared/components/text-field.js';
8
- const PROFILE_ACTIONS = [
9
- {
10
- value: 'change-display-name',
11
- label: 'Alterar display name',
12
- description: 'Atualiza o nome exibido diretamente no Supabase.',
13
- },
14
- {
15
- value: 'change-password',
16
- label: 'Alterar senha',
17
- description: 'Troca a senha da conta autenticada.',
18
- },
19
- {
20
- value: 'back',
21
- label: 'Voltar ao menu',
22
- description: 'Retorna ao menu principal da CLI.',
23
- },
24
- ];
25
- function isReauthenticationRequired(errorCode) {
26
- return errorCode === 'reauthentication_needed' || errorCode === 'reauth_nonce_missing';
27
- }
28
- export function ProfilePage({ authService, onBack, onNotificationChange, user }) {
29
- const currentDisplayName = getUserDisplayName(user);
30
- const [step, setStep] = useState('menu');
31
- const [selectedActionIndex, setSelectedActionIndex] = useState(0);
32
- const [displayName, setDisplayName] = useState(currentDisplayName ?? '');
33
- const [newPassword, setNewPassword] = useState('');
34
- const [confirmPassword, setConfirmPassword] = useState('');
35
- const [passwordFocus, setPasswordFocus] = useState('new-password');
36
- const [nonce, setNonce] = useState('');
37
- const [pendingPassword, setPendingPassword] = useState('');
38
- const [busy, setBusy] = useState(false);
39
- useEffect(() => {
40
- setDisplayName(currentDisplayName ?? '');
41
- }, [currentDisplayName]);
42
- function resetPasswordFlow() {
43
- setNewPassword('');
44
- setConfirmPassword('');
45
- setNonce('');
46
- setPendingPassword('');
47
- setPasswordFocus('new-password');
48
- }
49
- function returnToProfileMenu() {
50
- setStep('menu');
51
- setSelectedActionIndex(0);
52
- resetPasswordFlow();
53
- setDisplayName(currentDisplayName ?? '');
54
- }
55
- async function handleDisplayNameSubmit() {
56
- const trimmedDisplayName = displayName.trim();
57
- if (!trimmedDisplayName) {
58
- onNotificationChange('Informe um display name valido para continuar.', 'error');
59
- return;
60
- }
61
- if (trimmedDisplayName === currentDisplayName) {
62
- onNotificationChange('O display name informado ja esta em uso na sua conta.', 'info');
63
- returnToProfileMenu();
64
- return;
65
- }
66
- setBusy(true);
67
- const result = await authService.updateDisplayName(trimmedDisplayName);
68
- setBusy(false);
69
- if (result.error) {
70
- onNotificationChange(result.error, 'error');
71
- return;
72
- }
73
- onNotificationChange(`Display name atualizado para "${trimmedDisplayName}".`, 'success');
74
- returnToProfileMenu();
75
- }
76
- async function requestPasswordReauthentication(password) {
77
- const reauthenticationResult = await authService.sendPasswordReauthenticationCode();
78
- if (reauthenticationResult.error) {
79
- onNotificationChange(reauthenticationResult.error, 'error');
80
- return;
81
- }
82
- setPendingPassword(password);
83
- setNonce('');
84
- setStep('confirm-password-code');
85
- onNotificationChange('O Supabase enviou um codigo de verificacao. Digite esse codigo para concluir a troca de senha.', 'info');
86
- }
87
- async function handlePasswordSubmit(password, currentNonce) {
88
- if (!password.trim()) {
89
- onNotificationChange('Informe a nova senha para continuar.', 'error');
90
- return;
91
- }
92
- setBusy(true);
93
- const result = await authService.updatePassword(password, currentNonce);
94
- setBusy(false);
95
- if (result.error) {
96
- if (isReauthenticationRequired(result.errorCode) && !currentNonce) {
97
- await requestPasswordReauthentication(password);
98
- return;
99
- }
100
- onNotificationChange(result.error, 'error');
101
- return;
102
- }
103
- onNotificationChange('Senha atualizada com sucesso.', 'success');
104
- returnToProfileMenu();
105
- }
106
- async function handleNewPasswordSubmit() {
107
- if (!newPassword.trim() || !confirmPassword.trim()) {
108
- onNotificationChange('Preencha a nova senha e a confirmacao.', 'error');
109
- return;
110
- }
111
- if (newPassword !== confirmPassword) {
112
- onNotificationChange('A confirmacao de senha nao confere.', 'error');
113
- return;
114
- }
115
- await handlePasswordSubmit(newPassword);
116
- }
117
- async function handlePasswordNonceSubmit() {
118
- const trimmedNonce = nonce.trim();
119
- if (!trimmedNonce) {
120
- onNotificationChange('Informe o codigo de verificacao enviado pelo Supabase.', 'error');
121
- return;
122
- }
123
- await handlePasswordSubmit(pendingPassword, trimmedNonce);
124
- }
125
- useInput((_input, key) => {
126
- if (busy) {
127
- return;
128
- }
129
- if (step === 'menu') {
130
- if (key.escape) {
131
- onBack();
132
- return;
133
- }
134
- if (key.upArrow) {
135
- setSelectedActionIndex((current) => (current === 0 ? PROFILE_ACTIONS.length - 1 : current - 1));
136
- return;
137
- }
138
- if (key.downArrow) {
139
- setSelectedActionIndex((current) => (current === PROFILE_ACTIONS.length - 1 ? 0 : current + 1));
140
- return;
141
- }
142
- if (key.return) {
143
- const action = PROFILE_ACTIONS[selectedActionIndex];
144
- if (!action || action.value === 'back') {
145
- onBack();
146
- return;
147
- }
148
- onNotificationChange(null);
149
- setStep(action.value);
150
- }
151
- return;
152
- }
153
- if (key.escape) {
154
- onNotificationChange(null);
155
- returnToProfileMenu();
156
- return;
157
- }
158
- if (step === 'change-password' && (key.tab || key.upArrow || key.downArrow)) {
159
- setPasswordFocus((current) => (current === 'new-password' ? 'confirm-password' : 'new-password'));
160
- }
161
- });
162
- if (step === 'menu') {
163
- return (_jsxs(ActionMenuPage, { title: "Profile", subtitle: "Escolha uma acao para gerenciar sua conta autenticada.", options: PROFILE_ACTIONS, selectedIndex: selectedActionIndex, hintText: "Use as setas para navegar. Enter confirma. Esc volta ao menu.", children: [_jsxs(Text, { children: ["Email: ", user.email ?? 'nao informado'] }), _jsxs(Text, { children: ["Display name: ", currentDisplayName ?? 'nao definido'] })] }));
164
- }
165
- if (step === 'change-display-name') {
166
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Alterar display name", subtitle: `Atual: ${currentDisplayName ?? 'nao definido'}. Digite o novo nome e pressione Enter.` }), _jsx(TextField, { placeholder: "Ex.: Leonardo", value: displayName, onChange: setDisplayName, onSubmit: () => {
167
- void handleDisplayNameSubmit();
168
- } }), _jsx(Text, { dimColor: true, children: "Esc volta para o menu de profile." })] }));
169
- }
170
- if (step === 'confirm-password-code') {
171
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Confirmar troca de senha", subtitle: "Digite o codigo recebido por email ou telefone para concluir a troca da senha." }), _jsx(TextField, { placeholder: "Codigo de verificacao", value: nonce, onChange: setNonce, onSubmit: () => {
172
- void handlePasswordNonceSubmit();
173
- } }), _jsx(Text, { dimColor: true, children: "Esc volta para o menu de profile." })] }));
174
- }
175
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Alterar senha", subtitle: "Defina a nova senha. Se o Supabase pedir reautenticacao, um codigo sera enviado automaticamente." }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { color: passwordFocus === 'new-password' ? 'greenBright' : 'white', children: "Nova senha" }), _jsx(TextField, { focus: passwordFocus === 'new-password', mask: "*", placeholder: "Digite a nova senha", value: newPassword, onChange: setNewPassword, onSubmit: () => {
176
- setPasswordFocus('confirm-password');
177
- } })] }), _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: passwordFocus === 'confirm-password' ? 'greenBright' : 'white', children: "Confirmar senha" }), _jsx(TextField, { focus: passwordFocus === 'confirm-password', mask: "*", placeholder: "Repita a nova senha", value: confirmPassword, onChange: setConfirmPassword, onSubmit: () => {
178
- void handleNewPasswordSubmit();
179
- } })] }), _jsx(Text, { dimColor: true, children: "Tab ou setas alternam o campo ativo. Enter envia. Esc volta ao menu de profile." })] }));
180
- }
@@ -1,12 +0,0 @@
1
- import { type AuthUser } from '@supabase/supabase-js';
2
- import { type AuthService } from '../../auth/services/auth.service.js';
3
- type NotificationTone = 'error' | 'info' | 'success';
4
- type ProfilePageProps = {
5
- readonly authService: AuthService;
6
- readonly onBack: () => void;
7
- readonly onNotificationChange: (notification: string | null, tone?: NotificationTone) => void;
8
- readonly user: AuthUser;
9
- };
10
- export declare function ProfilePage({ authService, onBack, onNotificationChange, user }: ProfilePageProps): import("react/jsx-runtime").JSX.Element;
11
- export {};
12
- //# sourceMappingURL=profile.page.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"profile.page.d.ts","sourceRoot":"","sources":["../../../../src/modules/profile/pages/profile.page.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAOvE,KAAK,gBAAgB,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAKrD,KAAK,gBAAgB,GAAG;IACtB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;IAC5B,QAAQ,CAAC,oBAAoB,EAAE,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,CAAC,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC9F,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;CACzB,CAAC;AAwBF,wBAAgB,WAAW,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,oBAAoB,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CAwQhG"}
@@ -1,180 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Text, useInput } from 'ink';
3
- import { useEffect, useState } from 'react';
4
- import { getUserDisplayName } from '../../auth/utils/auth-user.util.js';
5
- import { ActionMenuPage } from '../../../shared/components/action-menu.component.js';
6
- import { StepHeader } from '../../../shared/components/step-header.component.js';
7
- import { TextField } from '../../../shared/components/text-field.component.js';
8
- const PROFILE_ACTIONS = [
9
- {
10
- value: 'change-display-name',
11
- label: 'Alterar display name',
12
- description: 'Atualiza o nome exibido diretamente no Supabase.',
13
- },
14
- {
15
- value: 'change-password',
16
- label: 'Alterar senha',
17
- description: 'Troca a senha da conta autenticada.',
18
- },
19
- {
20
- value: 'back',
21
- label: 'Voltar ao menu',
22
- description: 'Retorna ao menu principal da CLI.',
23
- },
24
- ];
25
- function isReauthenticationRequired(errorCode) {
26
- return errorCode === 'reauthentication_needed' || errorCode === 'reauth_nonce_missing';
27
- }
28
- export function ProfilePage({ authService, onBack, onNotificationChange, user }) {
29
- const currentDisplayName = getUserDisplayName(user);
30
- const [step, setStep] = useState('menu');
31
- const [selectedActionIndex, setSelectedActionIndex] = useState(0);
32
- const [displayName, setDisplayName] = useState(currentDisplayName ?? '');
33
- const [newPassword, setNewPassword] = useState('');
34
- const [confirmPassword, setConfirmPassword] = useState('');
35
- const [passwordFocus, setPasswordFocus] = useState('new-password');
36
- const [nonce, setNonce] = useState('');
37
- const [pendingPassword, setPendingPassword] = useState('');
38
- const [busy, setBusy] = useState(false);
39
- useEffect(() => {
40
- setDisplayName(currentDisplayName ?? '');
41
- }, [currentDisplayName]);
42
- function resetPasswordFlow() {
43
- setNewPassword('');
44
- setConfirmPassword('');
45
- setNonce('');
46
- setPendingPassword('');
47
- setPasswordFocus('new-password');
48
- }
49
- function returnToProfileMenu() {
50
- setStep('menu');
51
- setSelectedActionIndex(0);
52
- resetPasswordFlow();
53
- setDisplayName(currentDisplayName ?? '');
54
- }
55
- async function handleDisplayNameSubmit() {
56
- const trimmedDisplayName = displayName.trim();
57
- if (!trimmedDisplayName) {
58
- onNotificationChange('Informe um display name valido para continuar.', 'error');
59
- return;
60
- }
61
- if (trimmedDisplayName === currentDisplayName) {
62
- onNotificationChange('O display name informado ja esta em uso na sua conta.', 'info');
63
- returnToProfileMenu();
64
- return;
65
- }
66
- setBusy(true);
67
- const result = await authService.updateDisplayName(trimmedDisplayName);
68
- setBusy(false);
69
- if (result.error) {
70
- onNotificationChange(result.error, 'error');
71
- return;
72
- }
73
- onNotificationChange(`Display name atualizado para "${trimmedDisplayName}".`, 'success');
74
- returnToProfileMenu();
75
- }
76
- async function requestPasswordReauthentication(password) {
77
- const reauthenticationResult = await authService.sendPasswordReauthenticationCode();
78
- if (reauthenticationResult.error) {
79
- onNotificationChange(reauthenticationResult.error, 'error');
80
- return;
81
- }
82
- setPendingPassword(password);
83
- setNonce('');
84
- setStep('confirm-password-code');
85
- onNotificationChange('O Supabase enviou um codigo de verificacao. Digite esse codigo para concluir a troca de senha.', 'info');
86
- }
87
- async function handlePasswordSubmit(password, currentNonce) {
88
- if (!password.trim()) {
89
- onNotificationChange('Informe a nova senha para continuar.', 'error');
90
- return;
91
- }
92
- setBusy(true);
93
- const result = await authService.updatePassword(password, currentNonce);
94
- setBusy(false);
95
- if (result.error) {
96
- if (isReauthenticationRequired(result.errorCode) && !currentNonce) {
97
- await requestPasswordReauthentication(password);
98
- return;
99
- }
100
- onNotificationChange(result.error, 'error');
101
- return;
102
- }
103
- onNotificationChange('Senha atualizada com sucesso.', 'success');
104
- returnToProfileMenu();
105
- }
106
- async function handleNewPasswordSubmit() {
107
- if (!newPassword.trim() || !confirmPassword.trim()) {
108
- onNotificationChange('Preencha a nova senha e a confirmacao.', 'error');
109
- return;
110
- }
111
- if (newPassword !== confirmPassword) {
112
- onNotificationChange('A confirmacao de senha nao confere.', 'error');
113
- return;
114
- }
115
- await handlePasswordSubmit(newPassword);
116
- }
117
- async function handlePasswordNonceSubmit() {
118
- const trimmedNonce = nonce.trim();
119
- if (!trimmedNonce) {
120
- onNotificationChange('Informe o codigo de verificacao enviado pelo Supabase.', 'error');
121
- return;
122
- }
123
- await handlePasswordSubmit(pendingPassword, trimmedNonce);
124
- }
125
- useInput((_input, key) => {
126
- if (busy) {
127
- return;
128
- }
129
- if (step === 'menu') {
130
- if (key.escape) {
131
- onBack();
132
- return;
133
- }
134
- if (key.upArrow) {
135
- setSelectedActionIndex((current) => (current === 0 ? PROFILE_ACTIONS.length - 1 : current - 1));
136
- return;
137
- }
138
- if (key.downArrow) {
139
- setSelectedActionIndex((current) => (current === PROFILE_ACTIONS.length - 1 ? 0 : current + 1));
140
- return;
141
- }
142
- if (key.return) {
143
- const action = PROFILE_ACTIONS[selectedActionIndex];
144
- if (!action || action.value === 'back') {
145
- onBack();
146
- return;
147
- }
148
- onNotificationChange(null);
149
- setStep(action.value);
150
- }
151
- return;
152
- }
153
- if (key.escape) {
154
- onNotificationChange(null);
155
- returnToProfileMenu();
156
- return;
157
- }
158
- if (step === 'change-password' && (key.tab || key.upArrow || key.downArrow)) {
159
- setPasswordFocus((current) => (current === 'new-password' ? 'confirm-password' : 'new-password'));
160
- }
161
- });
162
- if (step === 'menu') {
163
- return (_jsxs(ActionMenuPage, { title: "Profile", subtitle: "Escolha uma acao para gerenciar sua conta autenticada.", options: PROFILE_ACTIONS, selectedIndex: selectedActionIndex, hintText: "Use as setas para navegar. Enter confirma. Esc volta ao menu.", children: [_jsxs(Text, { children: ["Email: ", user.email ?? 'nao informado'] }), _jsxs(Text, { children: ["Display name: ", currentDisplayName ?? 'nao definido'] })] }));
164
- }
165
- if (step === 'change-display-name') {
166
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Alterar display name", subtitle: `Atual: ${currentDisplayName ?? 'nao definido'}. Digite o novo nome e pressione Enter.` }), _jsx(TextField, { placeholder: "Ex.: Leonardo", value: displayName, onChange: setDisplayName, onSubmit: () => {
167
- void handleDisplayNameSubmit();
168
- } }), _jsx(Text, { dimColor: true, children: "Esc volta para o menu de profile." })] }));
169
- }
170
- if (step === 'confirm-password-code') {
171
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Confirmar troca de senha", subtitle: "Digite o codigo recebido por email ou telefone para concluir a troca da senha." }), _jsx(TextField, { placeholder: "Codigo de verificacao", value: nonce, onChange: setNonce, onSubmit: () => {
172
- void handlePasswordNonceSubmit();
173
- } }), _jsx(Text, { dimColor: true, children: "Esc volta para o menu de profile." })] }));
174
- }
175
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: "Alterar senha", subtitle: "Defina a nova senha. Se o Supabase pedir reautenticacao, um codigo sera enviado automaticamente." }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { color: passwordFocus === 'new-password' ? 'greenBright' : 'white', children: "Nova senha" }), _jsx(TextField, { focus: passwordFocus === 'new-password', mask: "*", placeholder: "Digite a nova senha", value: newPassword, onChange: setNewPassword, onSubmit: () => {
176
- setPasswordFocus('confirm-password');
177
- } })] }), _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: passwordFocus === 'confirm-password' ? 'greenBright' : 'white', children: "Confirmar senha" }), _jsx(TextField, { focus: passwordFocus === 'confirm-password', mask: "*", placeholder: "Repita a nova senha", value: confirmPassword, onChange: setConfirmPassword, onSubmit: () => {
178
- void handleNewPasswordSubmit();
179
- } })] }), _jsx(Text, { dimColor: true, children: "Tab ou setas alternam o campo ativo. Enter envia. Esc volta ao menu de profile." })] }));
180
- }
@@ -1,13 +0,0 @@
1
- import { type ReactNode } from 'react';
2
- import { type RadioOption } from './radio-select.js';
3
- type ActionMenuPageProps<TValue extends string> = {
4
- readonly children?: ReactNode;
5
- readonly hintText: string;
6
- readonly options: readonly RadioOption<TValue>[];
7
- readonly selectedIndex: number;
8
- readonly subtitle: string;
9
- readonly title: string;
10
- };
11
- export declare function ActionMenuPage<TValue extends string>({ children, hintText, options, selectedIndex, subtitle, title, }: ActionMenuPageProps<TValue>): import("react/jsx-runtime").JSX.Element;
12
- export {};
13
- //# sourceMappingURL=action-menu-page.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"action-menu-page.d.ts","sourceRoot":"","sources":["../../../src/shared/components/action-menu-page.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGlE,KAAK,mBAAmB,CAAC,MAAM,SAAS,MAAM,IAAI;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;IACjD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,wBAAgB,cAAc,CAAC,MAAM,SAAS,MAAM,EAAE,EACpD,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,aAAa,EACb,QAAQ,EACR,KAAK,GACN,EAAE,mBAAmB,CAAC,MAAM,CAAC,2CAS7B"}
@@ -1,7 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- import { RadioSelect } from './radio-select.js';
4
- import { StepHeader } from './step-header.js';
5
- export function ActionMenuPage({ children, hintText, options, selectedIndex, subtitle, title, }) {
6
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StepHeader, { title: title, subtitle: subtitle }), children ? _jsx(Box, { flexDirection: "column", marginBottom: 1, children: children }) : null, _jsx(RadioSelect, { options: options, selectedIndex: selectedIndex }), _jsx(Text, { dimColor: true, children: hintText })] }));
7
- }
@@ -1,12 +0,0 @@
1
- export type RadioOption<TValue extends string> = {
2
- readonly description: string;
3
- readonly label: string;
4
- readonly value: TValue;
5
- };
6
- type RadioSelectProps<TValue extends string> = {
7
- readonly options: readonly RadioOption<TValue>[];
8
- readonly selectedIndex: number;
9
- };
10
- export declare function RadioSelect<TValue extends string>({ options, selectedIndex }: RadioSelectProps<TValue>): import("react/jsx-runtime").JSX.Element;
11
- export {};
12
- //# sourceMappingURL=radio-select.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"radio-select.d.ts","sourceRoot":"","sources":["../../../src/shared/components/radio-select.tsx"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,CAAC,MAAM,SAAS,MAAM,IAAI;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,gBAAgB,CAAC,MAAM,SAAS,MAAM,IAAI;IAC7C,QAAQ,CAAC,OAAO,EAAE,SAAS,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;IACjD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC,CAAC;AAUF,wBAAgB,WAAW,CAAC,MAAM,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,gBAAgB,CAAC,MAAM,CAAC,2CAoBtG"}
@@ -1,16 +0,0 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- function truncate(text, maxLength) {
4
- if (text.length <= maxLength) {
5
- return text;
6
- }
7
- return `${text.slice(0, maxLength - 1)}…`;
8
- }
9
- export function RadioSelect({ options, selectedIndex }) {
10
- return (_jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, width: 72, children: options.map((option, index) => {
11
- const selected = index === selectedIndex;
12
- const label = truncate(option.label, 20).padEnd(20, ' ');
13
- const description = truncate(option.description, 40);
14
- return (_jsxs(Box, { children: [_jsxs(Text, { color: selected ? 'greenBright' : 'white', children: [selected ? '◉ ' : '○ ', label] }), _jsxs(Text, { dimColor: true, children: [" ", description] })] }, option.value));
15
- }) }));
16
- }
@@ -1,7 +0,0 @@
1
- type StepHeaderProps = {
2
- readonly subtitle: string;
3
- readonly title: string;
4
- };
5
- export declare function StepHeader({ subtitle, title }: StepHeaderProps): import("react/jsx-runtime").JSX.Element;
6
- export {};
7
- //# sourceMappingURL=step-header.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"step-header.d.ts","sourceRoot":"","sources":["../../../src/shared/components/step-header.tsx"],"names":[],"mappings":"AAEA,KAAK,eAAe,GAAG;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,eAAe,2CAO9D"}
@@ -1,5 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- export function StepHeader({ subtitle, title }) {
4
- return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { color: "yellow", children: title }), _jsx(Text, { dimColor: true, children: subtitle })] }));
5
- }
@@ -1,12 +0,0 @@
1
- type TextFieldProps = {
2
- readonly focus?: boolean;
3
- readonly mask?: string;
4
- readonly onChange: (value: string) => void;
5
- readonly onSubmit?: (value: string) => void;
6
- readonly placeholder: string;
7
- readonly value: string;
8
- readonly width?: number;
9
- };
10
- export declare function TextField({ focus, mask, onChange, onSubmit, placeholder, value, width }: TextFieldProps): import("react/jsx-runtime").JSX.Element;
11
- export {};
12
- //# sourceMappingURL=text-field.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"text-field.d.ts","sourceRoot":"","sources":["../../../src/shared/components/text-field.tsx"],"names":[],"mappings":"AAGA,KAAK,cAAc,GAAG;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,wBAAgB,SAAS,CAAC,EAAE,KAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,KAAU,EAAE,EAAE,cAAc,2CAanH"}
@@ -1,6 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Box } from 'ink';
3
- import TextInput from 'ink-text-input';
4
- export function TextField({ focus = true, mask, onChange, onSubmit, placeholder, value, width = 72 }) {
5
- return (_jsx(Box, { borderStyle: "round", borderColor: "green", paddingX: 1, width: width, children: _jsx(TextInput, { focus: focus, mask: mask, placeholder: placeholder, value: value, onChange: onChange, onSubmit: onSubmit }) }));
6
- }
@@ -1,2 +0,0 @@
1
- export declare const APP_VERSION = "0.1.8";
2
- //# sourceMappingURL=app-version.constant.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"app-version.constant.d.ts","sourceRoot":"","sources":["../../../src/shared/constants/app-version.constant.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,UAAU,CAAC"}
@@ -1 +0,0 @@
1
- export const APP_VERSION = '0.1.8';
@@ -1,2 +0,0 @@
1
- export declare function AppLogo(): import("react/jsx-runtime").JSX.Element;
2
- //# sourceMappingURL=app-logo.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"app-logo.d.ts","sourceRoot":"","sources":["../../../src/shared/template/app-logo.tsx"],"names":[],"mappings":"AAWA,wBAAgB,OAAO,4CAUtB"}
@@ -1,13 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Text } from 'ink';
3
- const LOGO_LINES = [
4
- '████████╗██████╗ ███████╗███╗ ██╗██████╗ ██╗███████╗██╗ ██╗',
5
- '╚══██╔══╝██╔══██╗██╔════╝████╗ ██║██╔══██╗██║██╔════╝╚██╗ ██╔╝',
6
- ' ██║ ██████╔╝█████╗ ██╔██╗ ██║██║ ██║██║█████╗ ╚████╔╝ ',
7
- ' ██║ ██╔══██╗██╔══╝ ██║╚██╗██║██║ ██║██║██╔══╝ ╚██╔╝ ',
8
- ' ██║ ██║ ██║███████╗██║ ╚████║██████╔╝██║██║ ██║ ',
9
- ' ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝╚═════╝ ╚═╝╚═╝ ╚═╝ ',
10
- ];
11
- export function AppLogo() {
12
- return (_jsx(Box, { flexDirection: "column", marginBottom: 1, children: LOGO_LINES.map((line) => (_jsx(Text, { color: "greenBright", children: line }, line))) }));
13
- }
@@ -1,17 +0,0 @@
1
- export type AppMenuItem = {
2
- readonly aliases: readonly string[];
3
- readonly comando: string;
4
- readonly descricao: string;
5
- readonly id: string;
6
- readonly palavrasChave: readonly string[];
7
- readonly titulo: string;
8
- };
9
- type AppMenuProps = {
10
- readonly initialInput: string;
11
- readonly items: readonly AppMenuItem[];
12
- readonly onInputChange?: (value: string) => void;
13
- readonly onSelect: (item: AppMenuItem) => void;
14
- };
15
- export declare function AppMenu({ initialInput, items, onInputChange, onSelect }: AppMenuProps): import("react/jsx-runtime").JSX.Element;
16
- export {};
17
- //# sourceMappingURL=app-menu.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"app-menu.d.ts","sourceRoot":"","sources":["../../../src/shared/template/app-menu.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;CAChD,CAAC;AAwDF,wBAAgB,OAAO,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,YAAY,2CAyErF"}