2023-03-06 07:21:29 -05:00
|
|
|
import { invoke } from "@tauri-apps/api";
|
|
|
|
|
import { JSONRPCClient, S3SIService, StdioTransport } from "jsonrpc";
|
2023-03-08 17:38:39 -05:00
|
|
|
import { ExportOpts, Log, LoggerLevel, State } from "jsonrpc/types";
|
2023-03-08 16:36:14 -05:00
|
|
|
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
|
2023-03-06 07:21:29 -05:00
|
|
|
|
|
|
|
|
const client = new JSONRPCClient<S3SIService>({
|
|
|
|
|
transport: new StdioTransport()
|
|
|
|
|
}).getProxy();
|
2023-03-08 16:36:14 -05:00
|
|
|
const LOG_SUB = new Set<(logs: Log[]) => void>();
|
2023-03-06 07:21:29 -05:00
|
|
|
|
2023-03-08 12:03:57 -05:00
|
|
|
async function getLogs() {
|
|
|
|
|
while (true) {
|
|
|
|
|
const r = await client.getLogs()
|
|
|
|
|
|
|
|
|
|
if (r.error) {
|
|
|
|
|
throw new Error(r.error.message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const { level, msg } of r.result) {
|
|
|
|
|
switch (level) {
|
|
|
|
|
case 'debug':
|
|
|
|
|
console.debug(...msg);
|
|
|
|
|
break;
|
|
|
|
|
case 'log':
|
|
|
|
|
console.log(...msg);
|
|
|
|
|
break;
|
|
|
|
|
case 'warn':
|
|
|
|
|
console.warn(...msg);
|
|
|
|
|
break;
|
|
|
|
|
case 'error':
|
|
|
|
|
console.error(...msg);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-03-08 16:36:14 -05:00
|
|
|
for (const cb of LOG_SUB) {
|
|
|
|
|
cb(r.result);
|
|
|
|
|
}
|
2023-03-08 12:03:57 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
getLogs()
|
|
|
|
|
|
2023-03-08 17:38:39 -05:00
|
|
|
export function addLog(...log: Log[]) {
|
|
|
|
|
for (const cb of LOG_SUB) {
|
|
|
|
|
cb(log);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-08 16:36:14 -05:00
|
|
|
const LOG_CONTEXT = createContext<{
|
|
|
|
|
logs: Log[],
|
|
|
|
|
renderedLogs: React.ReactNode[]
|
|
|
|
|
}>({
|
|
|
|
|
logs: [],
|
|
|
|
|
renderedLogs: [],
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const useLog = () => {
|
|
|
|
|
return useContext(LOG_CONTEXT);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-08 17:38:39 -05:00
|
|
|
function renderMsg(i: any) {
|
|
|
|
|
if (i instanceof Error) {
|
|
|
|
|
return i.message
|
|
|
|
|
}
|
|
|
|
|
return String(i)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const DISPLAY_MAP: Record<LoggerLevel, string> = {
|
|
|
|
|
debug: 'DEBUG',
|
|
|
|
|
log: 'INFO',
|
|
|
|
|
warn: 'WARN',
|
|
|
|
|
error: 'ERROR',
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-08 16:36:14 -05:00
|
|
|
function renderLevel(log: Log) {
|
2023-03-08 17:38:39 -05:00
|
|
|
return `[${DISPLAY_MAP[log.level]}]`.padEnd(7)
|
2023-03-08 16:36:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderLog(log: Log) {
|
2023-03-08 17:38:39 -05:00
|
|
|
return `${renderLevel(log)} ${log.msg.map(renderMsg).join(' ')}`
|
2023-03-08 16:36:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const LogProvider: React.FC<{ limit?: number, children?: React.ReactNode }> = ({ children, limit = 10 }) => {
|
|
|
|
|
const [logs, setLogs] = useState<Log[]>([]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const cb = (logs: Log[]) => {
|
|
|
|
|
setLogs(old => [...old, ...logs].slice(-limit));
|
|
|
|
|
}
|
|
|
|
|
LOG_SUB.add(cb);
|
|
|
|
|
return () => {
|
|
|
|
|
LOG_SUB.delete(cb);
|
|
|
|
|
}
|
|
|
|
|
}, [limit])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const renderedLogs = useMemo(() => logs.map(renderLog), [logs])
|
|
|
|
|
|
|
|
|
|
return <LOG_CONTEXT.Provider value={{
|
|
|
|
|
logs,
|
|
|
|
|
renderedLogs,
|
|
|
|
|
}}>
|
|
|
|
|
{children}
|
|
|
|
|
</LOG_CONTEXT.Provider>
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-06 07:21:29 -05:00
|
|
|
export const useLogin = () => {
|
|
|
|
|
const login = useCallback(async () => {
|
|
|
|
|
const result = await client.loginSteps();
|
|
|
|
|
if (result.error) {
|
|
|
|
|
throw new Error(result.error.message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const login: string | null = await invoke('open_login_window', {
|
|
|
|
|
url: result.result.url
|
|
|
|
|
})
|
|
|
|
|
if (login === null || login === '') {
|
|
|
|
|
console.log('user cancel login');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const loginResult: { url: string } = JSON.parse(login);
|
|
|
|
|
const sessionToken = await client.loginSteps({
|
|
|
|
|
authCodeVerifier: result.result.authCodeVerifier,
|
|
|
|
|
login: loginResult.url,
|
|
|
|
|
})
|
|
|
|
|
if (sessionToken.error) {
|
|
|
|
|
throw new Error(sessionToken.error.message);
|
|
|
|
|
}
|
|
|
|
|
return sessionToken.result;
|
|
|
|
|
}, [])
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
login
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-03-08 12:03:57 -05:00
|
|
|
|
|
|
|
|
export async function run(state: State, opts: ExportOpts) {
|
|
|
|
|
const r = await client.run(state, opts);
|
|
|
|
|
if (r.error) {
|
|
|
|
|
throw new Error(r.error.message);
|
|
|
|
|
}
|
|
|
|
|
return r.result;
|
|
|
|
|
}
|
2023-03-09 09:08:42 -05:00
|
|
|
|
|
|
|
|
export async function ensureTokenValid(state: State) {
|
|
|
|
|
const r = await client.ensureTokenValid(state);
|
|
|
|
|
if (r.error) {
|
|
|
|
|
throw new Error(r.error.message);
|
|
|
|
|
}
|
|
|
|
|
return r.result;
|
|
|
|
|
}
|