@trendify/cli 0.1.5 → 0.1.7
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/app.d.ts +9 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +194 -46
- package/dist/cli-update-service.d.ts +29 -0
- package/dist/cli-update-service.d.ts.map +1 -0
- package/dist/cli-update-service.js +206 -0
- package/dist/cli.js +24 -1
- package/dist/modules/auth/auth-service.d.ts +22 -1
- package/dist/modules/auth/auth-service.d.ts.map +1 -1
- package/dist/modules/auth/auth-service.js +224 -18
- package/dist/modules/auth/page/login-page.d.ts.map +1 -1
- package/dist/modules/auth/page/login-page.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/app.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
import { type CliUpdateCheckResult } from './cli-update-service.js';
|
|
1
2
|
export type AppProps = {
|
|
2
3
|
readonly appVersion: string;
|
|
3
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>;
|
|
4
10
|
};
|
|
5
|
-
|
|
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 {};
|
|
6
14
|
//# sourceMappingURL=app.d.ts.map
|
package/dist/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"
|
|
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
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Text, useApp, useInput } from 'ink';
|
|
3
3
|
import { useEffect, useMemo, useState } from 'react';
|
|
4
4
|
import { DiscoveryPage } from './modules/discovery/page/discovery-page.js';
|
|
5
5
|
import { getUserDisplayName } from './modules/auth/auth-user.js';
|
|
6
|
-
import { getAuthBootstrapResult } from './modules/auth/auth-service.js';
|
|
6
|
+
import { getAuthBootstrapResult, } from './modules/auth/auth-service.js';
|
|
7
7
|
import { LoginPage } from './modules/auth/page/login-page.js';
|
|
8
8
|
import { ProfilePage } from './modules/profile/page/profile-page.js';
|
|
9
|
+
import { checkForCliUpdate } from './cli-update-service.js';
|
|
9
10
|
import { ActionMenuPage } from './shared/components/action-menu-page.js';
|
|
10
11
|
import { AppMenu } from './shared/template/app-menu.js';
|
|
11
12
|
import { AppShell } from './shared/template/app-shell.js';
|
|
@@ -80,34 +81,106 @@ const LOGOUT_OPTIONS = [
|
|
|
80
81
|
function formatScopeLabel(scope) {
|
|
81
82
|
return scope === 'amplo' ? 'mais ampla' : 'mais restrita';
|
|
82
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
|
+
}
|
|
83
93
|
function getAuthenticatedUserLabel(user) {
|
|
84
94
|
if (!user) {
|
|
85
95
|
return 'usuario autenticado';
|
|
86
96
|
}
|
|
87
97
|
return getUserDisplayName(user) ?? user.email ?? 'usuario autenticado';
|
|
88
98
|
}
|
|
99
|
+
function getActiveWorkspaceLabel(workspace) {
|
|
100
|
+
return workspace?.name ?? 'espaco de trabalho';
|
|
101
|
+
}
|
|
89
102
|
function getWelcomeTitle(user) {
|
|
90
103
|
const displayName = user ? getUserDisplayName(user) : null;
|
|
91
104
|
if (displayName) {
|
|
92
|
-
return `Bem-vindo de volta, ${displayName}
|
|
105
|
+
return `Bem-vindo de volta, ${displayName} 👋`;
|
|
93
106
|
}
|
|
94
|
-
return 'Bem-vindo de volta.';
|
|
107
|
+
return 'Bem-vindo de volta. 👋';
|
|
95
108
|
}
|
|
96
|
-
|
|
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, }) {
|
|
97
142
|
const { exit } = useApp();
|
|
98
143
|
const authBootstrap = useMemo(() => getAuthBootstrapResult(), []);
|
|
99
144
|
const authService = authBootstrap.ok ? authBootstrap.authService : null;
|
|
100
145
|
const sessionStorageFilePath = authService?.getSessionStorageFilePath() ?? '~/.trendify/auth/storage.json';
|
|
101
146
|
const [screen, setScreen] = useState('menu');
|
|
102
|
-
const [notification, setNotification] = useState(
|
|
103
|
-
const [notificationTone, setNotificationTone] = useState(
|
|
147
|
+
const [notification, setNotification] = useState(initialNotification);
|
|
148
|
+
const [notificationTone, setNotificationTone] = useState(initialNotificationTone);
|
|
104
149
|
const [menuKey, setMenuKey] = useState(0);
|
|
105
150
|
const [authStatus, setAuthStatus] = useState(authBootstrap.ok ? 'booting' : 'config-error');
|
|
106
151
|
const [authUser, setAuthUser] = useState(null);
|
|
152
|
+
const [availableWorkspaces, setAvailableWorkspaces] = useState([]);
|
|
153
|
+
const [activeWorkspace, setActiveWorkspace] = useState(null);
|
|
107
154
|
const [email, setEmail] = useState('');
|
|
108
155
|
const [password, setPassword] = useState('');
|
|
109
156
|
const [authBusy, setAuthBusy] = useState(false);
|
|
110
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
|
+
}
|
|
111
184
|
useInput((input, key) => {
|
|
112
185
|
if (key.ctrl && input === 'c') {
|
|
113
186
|
exit();
|
|
@@ -142,6 +215,43 @@ export function App({ appVersion, initialInput }) {
|
|
|
142
215
|
setNotificationTone('info');
|
|
143
216
|
}
|
|
144
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]);
|
|
145
255
|
useEffect(() => {
|
|
146
256
|
if (!authService) {
|
|
147
257
|
return;
|
|
@@ -158,12 +268,15 @@ export function App({ appVersion, initialInput }) {
|
|
|
158
268
|
setNotificationTone('error');
|
|
159
269
|
}
|
|
160
270
|
if (result.data?.user) {
|
|
161
|
-
|
|
162
|
-
|
|
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
|
+
}
|
|
163
276
|
}
|
|
164
277
|
else {
|
|
165
278
|
setAuthStatus('unauthenticated');
|
|
166
|
-
|
|
279
|
+
resetAuthenticatedContext();
|
|
167
280
|
}
|
|
168
281
|
setAuthBusy(false);
|
|
169
282
|
};
|
|
@@ -173,13 +286,11 @@ export function App({ appVersion, initialInput }) {
|
|
|
173
286
|
return;
|
|
174
287
|
}
|
|
175
288
|
if (snapshot.user) {
|
|
176
|
-
setAuthStatus('authenticated');
|
|
177
289
|
setAuthUser(snapshot.user);
|
|
178
|
-
setScreen((current) => (current === 'menu' || current === 'discovery' || current === 'profile' ? current : 'menu'));
|
|
179
290
|
return;
|
|
180
291
|
}
|
|
181
292
|
setAuthStatus('unauthenticated');
|
|
182
|
-
|
|
293
|
+
resetAuthenticatedContext();
|
|
183
294
|
setScreen('menu');
|
|
184
295
|
setMenuKey((current) => current + 1);
|
|
185
296
|
});
|
|
@@ -207,15 +318,39 @@ export function App({ appVersion, initialInput }) {
|
|
|
207
318
|
setNotification(result.error ?? 'Nao foi possivel autenticar este usuario.');
|
|
208
319
|
setNotificationTone('error');
|
|
209
320
|
setAuthStatus('unauthenticated');
|
|
321
|
+
resetAuthenticatedContext();
|
|
210
322
|
return;
|
|
211
323
|
}
|
|
212
|
-
|
|
213
|
-
setAuthUser(result.data.user);
|
|
324
|
+
applyAuthenticatedSnapshot(result.data);
|
|
214
325
|
setPassword('');
|
|
215
|
-
|
|
216
|
-
|
|
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);
|
|
217
350
|
setScreen('menu');
|
|
218
351
|
setMenuKey((current) => current + 1);
|
|
352
|
+
setNotification(`Espaco de trabalho ativo: ${result.data.name}.`);
|
|
353
|
+
setNotificationTone('success');
|
|
219
354
|
}
|
|
220
355
|
async function handleLogout() {
|
|
221
356
|
if (!authService || authBusy) {
|
|
@@ -232,6 +367,7 @@ export function App({ appVersion, initialInput }) {
|
|
|
232
367
|
setScreen('menu');
|
|
233
368
|
setEmail('');
|
|
234
369
|
setPassword('');
|
|
370
|
+
resetAuthenticatedContext();
|
|
235
371
|
setMenuKey((current) => current + 1);
|
|
236
372
|
setLogoutSelectionIndex(0);
|
|
237
373
|
setNotification('Sessao local removida. Faca login novamente para continuar.');
|
|
@@ -241,15 +377,23 @@ export function App({ appVersion, initialInput }) {
|
|
|
241
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." }) }));
|
|
242
378
|
}
|
|
243
379
|
if (authStatus === 'booting') {
|
|
244
|
-
return (_jsx(AppShell, { appVersion: appVersion, title: "Validando sua sessao.", subtitle: "A CLI esta consultando o Supabase para restaurar
|
|
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.' }) }));
|
|
245
381
|
}
|
|
246
382
|
if (authStatus === 'unauthenticated') {
|
|
247
|
-
return (_jsx(AppShell, { appVersion: appVersion, title: "Login obrigatorio.", subtitle: "Somente usuarios
|
|
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: () => {
|
|
248
384
|
void handleLogin();
|
|
249
385
|
} }) }));
|
|
250
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
|
+
}
|
|
251
395
|
if (screen === 'discovery') {
|
|
252
|
-
return (_jsx(AppShell, { appVersion: appVersion, title: "Discovery", subtitle: `Sessao ativa para ${getAuthenticatedUserLabel(authUser)}.`, notification: notification, notificationTone: notificationTone, children: _jsx(DiscoveryPage, { onCancel: () => {
|
|
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: () => {
|
|
253
397
|
setScreen('menu');
|
|
254
398
|
setMenuKey((current) => current + 1);
|
|
255
399
|
}, onComplete: ({ theme, scope }) => {
|
|
@@ -260,7 +404,7 @@ export function App({ appVersion, initialInput }) {
|
|
|
260
404
|
} }) }));
|
|
261
405
|
}
|
|
262
406
|
if (screen === 'profile' && authService && authUser) {
|
|
263
|
-
return (_jsx(AppShell, { appVersion: appVersion, title: "Profile", subtitle: `Sessao ativa para ${getAuthenticatedUserLabel(authUser)}.`, notification: notification, notificationTone: notificationTone, children: _jsx(ProfilePage, { authService: authService, user: authUser, onBack: () => {
|
|
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: () => {
|
|
264
408
|
setScreen('menu');
|
|
265
409
|
setMenuKey((current) => current + 1);
|
|
266
410
|
}, onNotificationChange: (nextNotification, nextTone = 'success') => {
|
|
@@ -269,32 +413,36 @@ export function App({ appVersion, initialInput }) {
|
|
|
269
413
|
} }) }));
|
|
270
414
|
}
|
|
271
415
|
if (screen === 'confirm-logout') {
|
|
272
|
-
return (_jsx(AppShell, { appVersion: appVersion, title: "Confirmar encerramento de sessao", subtitle: `Voce esta autenticado como ${getAuthenticatedUserLabel(authUser)}.`, 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." }) }));
|
|
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." }) }));
|
|
273
417
|
}
|
|
274
|
-
return (
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
+
}
|
|
287
444
|
setNotification(null);
|
|
288
445
|
setNotificationTone('success');
|
|
289
|
-
setScreen('
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
if (item.id === 'exit') {
|
|
293
|
-
exit();
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
setNotification(null);
|
|
297
|
-
setNotificationTone('success');
|
|
298
|
-
setScreen('discovery');
|
|
299
|
-
} }, menuKey) }));
|
|
446
|
+
setScreen('discovery');
|
|
447
|
+
} }, menuKey)] }));
|
|
300
448
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
const DEFAULT_PACKAGE_NAME = '@trendify/cli';
|
|
4
|
+
const VERSION_PATTERN = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/u;
|
|
5
|
+
function getPackageManifestPath() {
|
|
6
|
+
return new URL('../package.json', import.meta.url);
|
|
7
|
+
}
|
|
8
|
+
function getNpmCommand() {
|
|
9
|
+
return process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
10
|
+
}
|
|
11
|
+
function toErrorMessage(error) {
|
|
12
|
+
if (error instanceof Error && error.message.trim()) {
|
|
13
|
+
return error.message;
|
|
14
|
+
}
|
|
15
|
+
return 'Nao foi possivel concluir a operacao.';
|
|
16
|
+
}
|
|
17
|
+
function readInstalledPackageMetadata() {
|
|
18
|
+
try {
|
|
19
|
+
const manifestContents = readFileSync(getPackageManifestPath(), 'utf8');
|
|
20
|
+
const manifest = JSON.parse(manifestContents);
|
|
21
|
+
const packageName = typeof manifest.name === 'string' && manifest.name.trim().length > 0
|
|
22
|
+
? manifest.name.trim()
|
|
23
|
+
: DEFAULT_PACKAGE_NAME;
|
|
24
|
+
return { packageName };
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return { packageName: DEFAULT_PACKAGE_NAME };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function parseVersion(version) {
|
|
31
|
+
const match = VERSION_PATTERN.exec(version.trim());
|
|
32
|
+
if (!match) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const [, major, minor, patch, prerelease] = match;
|
|
36
|
+
if (!major || !minor || !patch) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
major: Number.parseInt(major, 10),
|
|
41
|
+
minor: Number.parseInt(minor, 10),
|
|
42
|
+
patch: Number.parseInt(patch, 10),
|
|
43
|
+
prerelease: prerelease ?? null,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function compareVersions(left, right) {
|
|
47
|
+
const parsedLeft = parseVersion(left);
|
|
48
|
+
const parsedRight = parseVersion(right);
|
|
49
|
+
if (!parsedLeft || !parsedRight) {
|
|
50
|
+
return left.localeCompare(right, undefined, { numeric: true, sensitivity: 'base' });
|
|
51
|
+
}
|
|
52
|
+
if (parsedLeft.major !== parsedRight.major) {
|
|
53
|
+
return parsedLeft.major - parsedRight.major;
|
|
54
|
+
}
|
|
55
|
+
if (parsedLeft.minor !== parsedRight.minor) {
|
|
56
|
+
return parsedLeft.minor - parsedRight.minor;
|
|
57
|
+
}
|
|
58
|
+
if (parsedLeft.patch !== parsedRight.patch) {
|
|
59
|
+
return parsedLeft.patch - parsedRight.patch;
|
|
60
|
+
}
|
|
61
|
+
if (parsedLeft.prerelease === parsedRight.prerelease) {
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
if (parsedLeft.prerelease === null) {
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
67
|
+
if (parsedRight.prerelease === null) {
|
|
68
|
+
return -1;
|
|
69
|
+
}
|
|
70
|
+
return parsedLeft.prerelease.localeCompare(parsedRight.prerelease, undefined, {
|
|
71
|
+
numeric: true,
|
|
72
|
+
sensitivity: 'base',
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function runCommand(command, args) {
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
const child = spawn(command, [...args], {
|
|
78
|
+
env: process.env,
|
|
79
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
80
|
+
});
|
|
81
|
+
let stdout = '';
|
|
82
|
+
let stderr = '';
|
|
83
|
+
child.stdout.on('data', (chunk) => {
|
|
84
|
+
stdout += chunk.toString();
|
|
85
|
+
});
|
|
86
|
+
child.stderr.on('data', (chunk) => {
|
|
87
|
+
stderr += chunk.toString();
|
|
88
|
+
});
|
|
89
|
+
child.on('error', (error) => {
|
|
90
|
+
reject(error);
|
|
91
|
+
});
|
|
92
|
+
child.on('close', (code) => {
|
|
93
|
+
resolve({
|
|
94
|
+
code: code ?? 1,
|
|
95
|
+
stderr,
|
|
96
|
+
stdout,
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async function fetchLatestPublishedVersion(packageName) {
|
|
102
|
+
const commandResult = await runCommand(getNpmCommand(), ['view', packageName, 'version', '--json', '--silent']);
|
|
103
|
+
if (commandResult.code !== 0) {
|
|
104
|
+
const message = commandResult.stderr.trim() || commandResult.stdout.trim() || 'Falha ao consultar o npm.';
|
|
105
|
+
throw new Error(message);
|
|
106
|
+
}
|
|
107
|
+
const stdout = commandResult.stdout.trim();
|
|
108
|
+
if (!stdout) {
|
|
109
|
+
throw new Error('O npm nao retornou a versao publicada mais recente.');
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const parsedOutput = JSON.parse(stdout);
|
|
113
|
+
if (typeof parsedOutput === 'string' && parsedOutput.trim()) {
|
|
114
|
+
return parsedOutput.trim();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
if (stdout) {
|
|
119
|
+
return stdout.replace(/^"+|"+$/gu, '').trim();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
throw new Error('Nao foi possivel interpretar a versao publicada retornada pelo npm.');
|
|
123
|
+
}
|
|
124
|
+
async function runCommandWithInheritedStdio(command, args) {
|
|
125
|
+
return new Promise((resolve, reject) => {
|
|
126
|
+
const child = spawn(command, [...args], {
|
|
127
|
+
env: process.env,
|
|
128
|
+
stdio: 'inherit',
|
|
129
|
+
});
|
|
130
|
+
child.on('error', (error) => {
|
|
131
|
+
reject(error);
|
|
132
|
+
});
|
|
133
|
+
child.on('close', (code) => {
|
|
134
|
+
resolve(code ?? 1);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
async function restartCli() {
|
|
139
|
+
const entrypoint = process.argv[1];
|
|
140
|
+
if (!entrypoint) {
|
|
141
|
+
throw new Error('Nao foi possivel identificar o entrypoint atual da CLI para reiniciar o processo.');
|
|
142
|
+
}
|
|
143
|
+
await new Promise((resolve, reject) => {
|
|
144
|
+
const child = spawn(process.execPath, [...process.execArgv, entrypoint, ...process.argv.slice(2)], {
|
|
145
|
+
env: process.env,
|
|
146
|
+
stdio: 'inherit',
|
|
147
|
+
});
|
|
148
|
+
child.on('error', (error) => {
|
|
149
|
+
reject(error);
|
|
150
|
+
});
|
|
151
|
+
child.on('spawn', () => {
|
|
152
|
+
resolve();
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
export async function checkForCliUpdate(currentVersion) {
|
|
157
|
+
const { packageName } = readInstalledPackageMetadata();
|
|
158
|
+
try {
|
|
159
|
+
const latestVersion = await fetchLatestPublishedVersion(packageName);
|
|
160
|
+
if (compareVersions(latestVersion, currentVersion) > 0) {
|
|
161
|
+
return {
|
|
162
|
+
currentVersion,
|
|
163
|
+
latestVersion,
|
|
164
|
+
packageName,
|
|
165
|
+
status: 'available',
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
currentVersion,
|
|
170
|
+
latestVersion,
|
|
171
|
+
packageName,
|
|
172
|
+
status: 'current',
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
return {
|
|
177
|
+
currentVersion,
|
|
178
|
+
message: toErrorMessage(error),
|
|
179
|
+
packageName,
|
|
180
|
+
status: 'error',
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
export async function runCliSelfUpdate(packageName, latestVersion) {
|
|
185
|
+
try {
|
|
186
|
+
const exitCode = await runCommandWithInheritedStdio(getNpmCommand(), [
|
|
187
|
+
'install',
|
|
188
|
+
'--global',
|
|
189
|
+
`${packageName}@${latestVersion}`,
|
|
190
|
+
]);
|
|
191
|
+
if (exitCode !== 0) {
|
|
192
|
+
return {
|
|
193
|
+
error: `O npm encerrou a atualizacao com codigo ${exitCode}.`,
|
|
194
|
+
ok: false,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
await restartCli();
|
|
198
|
+
return { ok: true };
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
return {
|
|
202
|
+
error: toErrorMessage(error),
|
|
203
|
+
ok: false,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { render } from 'ink';
|
|
4
4
|
import { App } from './app.js';
|
|
5
|
+
import { runCliSelfUpdate } from './cli-update-service.js';
|
|
5
6
|
import { APP_VERSION } from './version.js';
|
|
6
7
|
const args = process.argv.slice(2);
|
|
7
8
|
const initialInput = args
|
|
@@ -25,4 +26,26 @@ if (args.includes('--version') || args.includes('-v')) {
|
|
|
25
26
|
process.exit(0);
|
|
26
27
|
}
|
|
27
28
|
console.clear();
|
|
28
|
-
|
|
29
|
+
let appInstance;
|
|
30
|
+
function mountApp(feedback = null) {
|
|
31
|
+
appInstance = render(_jsx(App, { appVersion: APP_VERSION, initialInput: initialInput, initialNotification: feedback?.message ?? null, initialNotificationTone: feedback?.tone ?? 'success', onSelfUpdate: async (update) => {
|
|
32
|
+
appInstance.unmount();
|
|
33
|
+
console.clear();
|
|
34
|
+
process.stdout.write([
|
|
35
|
+
`Atualizando o CLI de v${update.currentVersion} para v${update.latestVersion}.`,
|
|
36
|
+
`Pacote npm: ${update.packageName}`,
|
|
37
|
+
'',
|
|
38
|
+
].join('\n'));
|
|
39
|
+
const result = await runCliSelfUpdate(update.packageName, update.latestVersion);
|
|
40
|
+
if (result.ok) {
|
|
41
|
+
process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
process.stdout.write(`\nFalha ao atualizar automaticamente: ${result.error}\n`);
|
|
44
|
+
process.stdout.write('A CLI atual continuara disponivel.\n');
|
|
45
|
+
mountApp({
|
|
46
|
+
message: `Nao foi possivel atualizar a CLI automaticamente. ${result.error}`,
|
|
47
|
+
tone: 'error',
|
|
48
|
+
});
|
|
49
|
+
} }));
|
|
50
|
+
}
|
|
51
|
+
mountApp();
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
import { type AuthSession, type AuthUser } from '@supabase/supabase-js';
|
|
1
|
+
import { type AuthSession, type AuthUser, type SupabaseClient } from '@supabase/supabase-js';
|
|
2
2
|
import { type CliEnv } from '../../config/env.js';
|
|
3
|
+
export type WorkspaceRole = 'admin' | 'member' | 'owner';
|
|
4
|
+
export type WorkspaceMembership = {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly role: WorkspaceRole;
|
|
8
|
+
readonly slug: string;
|
|
9
|
+
};
|
|
3
10
|
export type AuthSnapshot = {
|
|
11
|
+
readonly activeWorkspace: WorkspaceMembership | null;
|
|
12
|
+
readonly requiresWorkspaceSelection: boolean;
|
|
4
13
|
readonly session: AuthSession | null;
|
|
5
14
|
readonly user: AuthUser | null;
|
|
15
|
+
readonly workspaces: readonly WorkspaceMembership[];
|
|
6
16
|
};
|
|
7
17
|
export type AuthActionResult<TData> = {
|
|
8
18
|
readonly data: TData | null;
|
|
@@ -19,21 +29,32 @@ export type AuthBootstrapResult = {
|
|
|
19
29
|
};
|
|
20
30
|
export declare class AuthService {
|
|
21
31
|
private readonly client;
|
|
32
|
+
private readonly storage;
|
|
33
|
+
private readonly env;
|
|
22
34
|
private readonly storageFilePath;
|
|
23
35
|
static create(env: CliEnv): AuthService;
|
|
24
36
|
private constructor();
|
|
37
|
+
private activeWorkspaceId;
|
|
25
38
|
getSessionStorageFilePath(): string;
|
|
26
39
|
onAuthStateChange(listener: (snapshot: AuthSnapshot) => void): {
|
|
27
40
|
data: {
|
|
28
41
|
subscription: import("@supabase/supabase-js").Subscription;
|
|
29
42
|
};
|
|
30
43
|
};
|
|
44
|
+
getActiveWorkspaceId(): string | null;
|
|
45
|
+
getWorkspaceScopedClient(): Promise<AuthActionResult<SupabaseClient>>;
|
|
31
46
|
restoreSession(): Promise<AuthActionResult<AuthSnapshot>>;
|
|
32
47
|
signInWithPassword(email: string, password: string): Promise<AuthActionResult<AuthSnapshot>>;
|
|
33
48
|
signOut(): Promise<AuthActionResult<null>>;
|
|
49
|
+
selectWorkspace(workspaceId: string): Promise<AuthActionResult<WorkspaceMembership>>;
|
|
34
50
|
updateDisplayName(displayName: string): Promise<AuthActionResult<AuthUser>>;
|
|
35
51
|
sendPasswordReauthenticationCode(): Promise<AuthActionResult<null>>;
|
|
36
52
|
updatePassword(password: string, nonce?: string): Promise<AuthActionResult<AuthUser>>;
|
|
53
|
+
private buildAuthenticatedSnapshot;
|
|
54
|
+
private listMyWorkspaces;
|
|
55
|
+
private readStoredActiveWorkspaceId;
|
|
56
|
+
private storeActiveWorkspaceId;
|
|
57
|
+
private clearStoredActiveWorkspaceId;
|
|
37
58
|
}
|
|
38
59
|
export declare function getAuthBootstrapResult(): AuthBootstrapResult;
|
|
39
60
|
//# sourceMappingURL=auth-service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-service.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/auth-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,QAAQ,
|
|
1
|
+
{"version":3,"file":"auth-service.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/auth-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAA6B,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAM7E,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEzD,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,eAAe,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrD,QAAQ,CAAC,0BAA0B,EAAE,OAAO,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,gBAAgB,CAAC,KAAK,IAChC;IACE,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC,CAAC;AAEJ,MAAM,MAAM,mBAAmB,GAC3B;IACE,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;CACnB,GACD;IACE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;CACpB,CAAC;AAqCN,qBAAa,WAAW;IAiBpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,eAAe;WAnBpB,MAAM,CAAC,GAAG,EAAE,MAAM;IAehC,OAAO;IASP,OAAO,CAAC,iBAAiB,CAAgB;IAElC,yBAAyB,IAAI,MAAM;IAInC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI;;;;;IAY5D,oBAAoB,IAAI,MAAM,GAAG,IAAI;IAI/B,wBAAwB,IAAI,OAAO,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;IA6DrE,cAAc,IAAI,OAAO,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;IA6DzD,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAiC5F,OAAO,IAAI,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IA4B1C,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;IAgDpF,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAmE3E,gCAAgC,IAAI,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IA0BnE,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YA2CpF,0BAA0B;YAmD1B,gBAAgB;YAgChB,2BAA2B;YAO3B,sBAAsB;YAKtB,4BAA4B;CAI3C;AAID,wBAAgB,sBAAsB,IAAI,mBAAmB,CAoB5D"}
|
|
@@ -3,14 +3,39 @@ import { TRENDIFY_AUTH_STORAGE_FILE } from '../../config/app-paths.js';
|
|
|
3
3
|
import { getCliEnvValidationResult } from '../../config/env.js';
|
|
4
4
|
import { FileStorage } from './auth-storage.js';
|
|
5
5
|
const AUTH_STORAGE_KEY = 'trendify.auth.token';
|
|
6
|
+
const ACTIVE_WORKSPACE_STORAGE_KEY = 'trendify.auth.active-workspace-id';
|
|
6
7
|
function toAuthErrorMessage(error, fallbackMessage) {
|
|
7
8
|
if (error && typeof error === 'object' && 'message' in error && typeof error.message === 'string') {
|
|
8
9
|
return error.message;
|
|
9
10
|
}
|
|
10
11
|
return fallbackMessage;
|
|
11
12
|
}
|
|
13
|
+
function isWorkspaceRole(value) {
|
|
14
|
+
return value === 'owner' || value === 'admin' || value === 'member';
|
|
15
|
+
}
|
|
16
|
+
function normalizeWorkspaceMembership(value) {
|
|
17
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const candidate = value;
|
|
21
|
+
const id = typeof candidate.workspace_id === 'string' ? candidate.workspace_id.trim() : '';
|
|
22
|
+
const name = typeof candidate.workspace_name === 'string' ? candidate.workspace_name.trim() : '';
|
|
23
|
+
const slug = typeof candidate.workspace_slug === 'string' ? candidate.workspace_slug.trim() : '';
|
|
24
|
+
const role = candidate.role;
|
|
25
|
+
if (!id || !name || !slug || !isWorkspaceRole(role)) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
id,
|
|
30
|
+
name,
|
|
31
|
+
role,
|
|
32
|
+
slug,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
12
35
|
export class AuthService {
|
|
13
36
|
client;
|
|
37
|
+
storage;
|
|
38
|
+
env;
|
|
14
39
|
storageFilePath;
|
|
15
40
|
static create(env) {
|
|
16
41
|
const storage = new FileStorage(TRENDIFY_AUTH_STORAGE_FILE);
|
|
@@ -23,23 +48,85 @@ export class AuthService {
|
|
|
23
48
|
storageKey: AUTH_STORAGE_KEY,
|
|
24
49
|
},
|
|
25
50
|
});
|
|
26
|
-
return new AuthService(client, TRENDIFY_AUTH_STORAGE_FILE);
|
|
51
|
+
return new AuthService(client, storage, env, TRENDIFY_AUTH_STORAGE_FILE);
|
|
27
52
|
}
|
|
28
|
-
constructor(client, storageFilePath) {
|
|
53
|
+
constructor(client, storage, env, storageFilePath) {
|
|
29
54
|
this.client = client;
|
|
55
|
+
this.storage = storage;
|
|
56
|
+
this.env = env;
|
|
30
57
|
this.storageFilePath = storageFilePath;
|
|
58
|
+
this.activeWorkspaceId = null;
|
|
31
59
|
}
|
|
60
|
+
activeWorkspaceId;
|
|
32
61
|
getSessionStorageFilePath() {
|
|
33
62
|
return this.storageFilePath;
|
|
34
63
|
}
|
|
35
64
|
onAuthStateChange(listener) {
|
|
36
65
|
return this.client.auth.onAuthStateChange((_event, session) => {
|
|
37
66
|
listener({
|
|
67
|
+
activeWorkspace: null,
|
|
68
|
+
requiresWorkspaceSelection: false,
|
|
38
69
|
session,
|
|
39
70
|
user: session?.user ?? null,
|
|
71
|
+
workspaces: [],
|
|
40
72
|
});
|
|
41
73
|
});
|
|
42
74
|
}
|
|
75
|
+
getActiveWorkspaceId() {
|
|
76
|
+
return this.activeWorkspaceId;
|
|
77
|
+
}
|
|
78
|
+
async getWorkspaceScopedClient() {
|
|
79
|
+
try {
|
|
80
|
+
const { data: { session }, error, } = await this.client.auth.getSession();
|
|
81
|
+
if (error) {
|
|
82
|
+
return {
|
|
83
|
+
data: null,
|
|
84
|
+
error: error.message,
|
|
85
|
+
errorCode: error.code ?? null,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (!session?.access_token) {
|
|
89
|
+
return {
|
|
90
|
+
data: null,
|
|
91
|
+
error: 'Nao existe uma sessao ativa para criar um cliente com espaco de trabalho.',
|
|
92
|
+
errorCode: null,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const activeWorkspaceId = this.activeWorkspaceId ?? (await this.readStoredActiveWorkspaceId());
|
|
96
|
+
if (!activeWorkspaceId) {
|
|
97
|
+
return {
|
|
98
|
+
data: null,
|
|
99
|
+
error: 'Selecione um espaco de trabalho antes de consultar dados protegidos.',
|
|
100
|
+
errorCode: null,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const workspaceClient = createClient(this.env.supabaseUrl, this.env.supabasePublishableDefaultKey, {
|
|
104
|
+
auth: {
|
|
105
|
+
autoRefreshToken: false,
|
|
106
|
+
detectSessionInUrl: false,
|
|
107
|
+
persistSession: false,
|
|
108
|
+
},
|
|
109
|
+
global: {
|
|
110
|
+
headers: {
|
|
111
|
+
Authorization: `Bearer ${session.access_token}`,
|
|
112
|
+
'x-tenant-id': activeWorkspaceId,
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
return {
|
|
117
|
+
data: workspaceClient,
|
|
118
|
+
error: null,
|
|
119
|
+
errorCode: null,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
return {
|
|
124
|
+
data: null,
|
|
125
|
+
error: toAuthErrorMessage(error, 'Nao foi possivel preparar o cliente do espaco de trabalho atual.'),
|
|
126
|
+
errorCode: null,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
43
130
|
async restoreSession() {
|
|
44
131
|
try {
|
|
45
132
|
const { data: { session }, error: sessionError, } = await this.client.auth.getSession();
|
|
@@ -53,8 +140,11 @@ export class AuthService {
|
|
|
53
140
|
if (!session) {
|
|
54
141
|
return {
|
|
55
142
|
data: {
|
|
143
|
+
activeWorkspace: null,
|
|
144
|
+
requiresWorkspaceSelection: false,
|
|
56
145
|
session: null,
|
|
57
146
|
user: null,
|
|
147
|
+
workspaces: [],
|
|
58
148
|
},
|
|
59
149
|
error: null,
|
|
60
150
|
errorCode: null,
|
|
@@ -63,23 +153,20 @@ export class AuthService {
|
|
|
63
153
|
const { data: { user }, error: userError, } = await this.client.auth.getUser();
|
|
64
154
|
if (userError || !user) {
|
|
65
155
|
await this.client.auth.signOut({ scope: 'local' });
|
|
156
|
+
await this.clearStoredActiveWorkspaceId();
|
|
66
157
|
return {
|
|
67
158
|
data: {
|
|
159
|
+
activeWorkspace: null,
|
|
160
|
+
requiresWorkspaceSelection: false,
|
|
68
161
|
session: null,
|
|
69
162
|
user: null,
|
|
163
|
+
workspaces: [],
|
|
70
164
|
},
|
|
71
165
|
error: userError?.message ?? 'Sua sessao expirou. Faca login novamente.',
|
|
72
166
|
errorCode: userError?.code ?? null,
|
|
73
167
|
};
|
|
74
168
|
}
|
|
75
|
-
return
|
|
76
|
-
data: {
|
|
77
|
-
session,
|
|
78
|
-
user,
|
|
79
|
-
},
|
|
80
|
-
error: null,
|
|
81
|
-
errorCode: null,
|
|
82
|
-
};
|
|
169
|
+
return await this.buildAuthenticatedSnapshot(session, user);
|
|
83
170
|
}
|
|
84
171
|
catch (error) {
|
|
85
172
|
return {
|
|
@@ -109,14 +196,7 @@ export class AuthService {
|
|
|
109
196
|
errorCode: null,
|
|
110
197
|
};
|
|
111
198
|
}
|
|
112
|
-
return
|
|
113
|
-
data: {
|
|
114
|
-
session: data.session,
|
|
115
|
-
user: data.user,
|
|
116
|
-
},
|
|
117
|
-
error: null,
|
|
118
|
-
errorCode: null,
|
|
119
|
-
};
|
|
199
|
+
return await this.buildAuthenticatedSnapshot(data.session, data.user);
|
|
120
200
|
}
|
|
121
201
|
catch (error) {
|
|
122
202
|
return {
|
|
@@ -136,6 +216,7 @@ export class AuthService {
|
|
|
136
216
|
errorCode: error.code ?? null,
|
|
137
217
|
};
|
|
138
218
|
}
|
|
219
|
+
await this.clearStoredActiveWorkspaceId();
|
|
139
220
|
return {
|
|
140
221
|
data: null,
|
|
141
222
|
error: null,
|
|
@@ -150,6 +231,47 @@ export class AuthService {
|
|
|
150
231
|
};
|
|
151
232
|
}
|
|
152
233
|
}
|
|
234
|
+
async selectWorkspace(workspaceId) {
|
|
235
|
+
const trimmedWorkspaceId = workspaceId.trim();
|
|
236
|
+
if (!trimmedWorkspaceId) {
|
|
237
|
+
return {
|
|
238
|
+
data: null,
|
|
239
|
+
error: 'Informe um espaco de trabalho valido para continuar.',
|
|
240
|
+
errorCode: null,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
try {
|
|
244
|
+
const workspaceResult = await this.listMyWorkspaces();
|
|
245
|
+
if (workspaceResult.error || !workspaceResult.data) {
|
|
246
|
+
return {
|
|
247
|
+
data: null,
|
|
248
|
+
error: workspaceResult.error ?? 'Nao foi possivel carregar os espacos de trabalho disponiveis.',
|
|
249
|
+
errorCode: workspaceResult.errorCode,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
const selectedWorkspace = workspaceResult.data.find((workspace) => workspace.id === trimmedWorkspaceId);
|
|
253
|
+
if (!selectedWorkspace) {
|
|
254
|
+
return {
|
|
255
|
+
data: null,
|
|
256
|
+
error: 'Esse espaco de trabalho nao esta disponivel para a sua conta.',
|
|
257
|
+
errorCode: null,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
await this.storeActiveWorkspaceId(selectedWorkspace.id);
|
|
261
|
+
return {
|
|
262
|
+
data: selectedWorkspace,
|
|
263
|
+
error: null,
|
|
264
|
+
errorCode: null,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
return {
|
|
269
|
+
data: null,
|
|
270
|
+
error: toAuthErrorMessage(error, 'Nao foi possivel selecionar o espaco de trabalho agora.'),
|
|
271
|
+
errorCode: null,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
153
275
|
async updateDisplayName(displayName) {
|
|
154
276
|
try {
|
|
155
277
|
const { data: { user: currentUser }, error: currentUserError, } = await this.client.auth.getUser();
|
|
@@ -268,6 +390,90 @@ export class AuthService {
|
|
|
268
390
|
};
|
|
269
391
|
}
|
|
270
392
|
}
|
|
393
|
+
async buildAuthenticatedSnapshot(session, user) {
|
|
394
|
+
const workspaceResult = await this.listMyWorkspaces();
|
|
395
|
+
if (workspaceResult.error || !workspaceResult.data) {
|
|
396
|
+
return {
|
|
397
|
+
data: null,
|
|
398
|
+
error: workspaceResult.error ?? 'Nao foi possivel carregar os espacos de trabalho desta conta.',
|
|
399
|
+
errorCode: workspaceResult.errorCode,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
if (workspaceResult.data.length === 0) {
|
|
403
|
+
await this.clearStoredActiveWorkspaceId();
|
|
404
|
+
return {
|
|
405
|
+
data: null,
|
|
406
|
+
error: 'Sua conta nao esta vinculada a nenhum espaco de trabalho. Fale com um administrador.',
|
|
407
|
+
errorCode: 'workspace_membership_missing',
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
const storedActiveWorkspaceId = await this.readStoredActiveWorkspaceId();
|
|
411
|
+
const storedWorkspace = storedActiveWorkspaceId
|
|
412
|
+
? workspaceResult.data.find((workspace) => workspace.id === storedActiveWorkspaceId)
|
|
413
|
+
: null;
|
|
414
|
+
const singleWorkspace = workspaceResult.data.length === 1 ? workspaceResult.data[0] ?? null : null;
|
|
415
|
+
const activeWorkspace = storedWorkspace ?? singleWorkspace;
|
|
416
|
+
const requiresWorkspaceSelection = activeWorkspace === null;
|
|
417
|
+
if (activeWorkspace) {
|
|
418
|
+
await this.storeActiveWorkspaceId(activeWorkspace.id);
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
await this.clearStoredActiveWorkspaceId();
|
|
422
|
+
}
|
|
423
|
+
return {
|
|
424
|
+
data: {
|
|
425
|
+
activeWorkspace,
|
|
426
|
+
requiresWorkspaceSelection,
|
|
427
|
+
session,
|
|
428
|
+
user,
|
|
429
|
+
workspaces: workspaceResult.data,
|
|
430
|
+
},
|
|
431
|
+
error: null,
|
|
432
|
+
errorCode: null,
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
async listMyWorkspaces() {
|
|
436
|
+
try {
|
|
437
|
+
const { data, error } = await this.client.rpc('list_my_workspaces');
|
|
438
|
+
if (error) {
|
|
439
|
+
return {
|
|
440
|
+
data: null,
|
|
441
|
+
error: error.message,
|
|
442
|
+
errorCode: error.code ?? null,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
const workspaces = Array.isArray(data)
|
|
446
|
+
? data
|
|
447
|
+
.map(normalizeWorkspaceMembership)
|
|
448
|
+
.filter((workspace) => workspace !== null)
|
|
449
|
+
: [];
|
|
450
|
+
return {
|
|
451
|
+
data: workspaces,
|
|
452
|
+
error: null,
|
|
453
|
+
errorCode: null,
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
catch (error) {
|
|
457
|
+
return {
|
|
458
|
+
data: null,
|
|
459
|
+
error: toAuthErrorMessage(error, 'Nao foi possivel consultar os espacos de trabalho desta conta.'),
|
|
460
|
+
errorCode: null,
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
async readStoredActiveWorkspaceId() {
|
|
465
|
+
const storedValue = await this.storage.getItem(ACTIVE_WORKSPACE_STORAGE_KEY);
|
|
466
|
+
const trimmedValue = storedValue?.trim() ?? '';
|
|
467
|
+
return trimmedValue ? trimmedValue : null;
|
|
468
|
+
}
|
|
469
|
+
async storeActiveWorkspaceId(workspaceId) {
|
|
470
|
+
this.activeWorkspaceId = workspaceId;
|
|
471
|
+
await this.storage.setItem(ACTIVE_WORKSPACE_STORAGE_KEY, workspaceId);
|
|
472
|
+
}
|
|
473
|
+
async clearStoredActiveWorkspaceId() {
|
|
474
|
+
this.activeWorkspaceId = null;
|
|
475
|
+
await this.storage.removeItem(ACTIVE_WORKSPACE_STORAGE_KEY);
|
|
476
|
+
}
|
|
271
477
|
}
|
|
272
478
|
let cachedAuthBootstrap = null;
|
|
273
479
|
export function getAuthBootstrapResult() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login-page.d.ts","sourceRoot":"","sources":["../../../../src/modules/auth/page/login-page.tsx"],"names":[],"mappings":"AAIA,KAAK,cAAc,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,QAAQ,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;CACzC,CAAC;AAIF,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,sBAAsB,GACvB,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"login-page.d.ts","sourceRoot":"","sources":["../../../../src/modules/auth/page/login-page.tsx"],"names":[],"mappings":"AAIA,KAAK,cAAc,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,QAAQ,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;CACzC,CAAC;AAIF,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,sBAAsB,GACvB,EAAE,cAAc,2CAsDhB"}
|
|
@@ -12,7 +12,7 @@ export function LoginPage({ busy, email, onEmailChange, onPasswordChange, onSubm
|
|
|
12
12
|
setFocusField((current) => (current === 'email' ? 'password' : 'email'));
|
|
13
13
|
}
|
|
14
14
|
});
|
|
15
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Entre com um usuario ja cadastrado no Supabase para liberar os comandos internos." }), _jsx(Text, { dimColor: true, children: "Cadastro nao esta habilitado nesta CLI." }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: focusField === 'email' ? 'greenBright' : 'white', children: "Email" }), _jsx(TextField, { focus: focusField === 'email', placeholder: "voce@empresa.com", value: email, onChange: onEmailChange, onSubmit: (value) => {
|
|
15
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Entre com um usuario ja cadastrado no Supabase para liberar os comandos internos." }), _jsx(Text, { dimColor: true, children: "Apos o login, a CLI tambem valida o espaco de trabalho vinculado a sua conta." }), _jsx(Text, { dimColor: true, children: "Cadastro nao esta habilitado nesta CLI." }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: focusField === 'email' ? 'greenBright' : 'white', children: "Email" }), _jsx(TextField, { focus: focusField === 'email', placeholder: "voce@empresa.com", value: email, onChange: onEmailChange, onSubmit: (value) => {
|
|
16
16
|
if (value.trim()) {
|
|
17
17
|
setFocusField('password');
|
|
18
18
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const APP_VERSION = "0.1.
|
|
1
|
+
export declare const APP_VERSION = "0.1.7";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const APP_VERSION = '0.1.
|
|
1
|
+
export const APP_VERSION = '0.1.7';
|