Apply new eslint rules; default to prettier for styling

This commit is contained in:
DaneEveritt 2022-06-26 15:13:52 -04:00
parent f22cce8881
commit dc84af9937
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
218 changed files with 3876 additions and 3564 deletions

View file

@ -8,19 +8,26 @@ import useFilteredObject from '@/plugins/useFilteredObject';
export type ActivityLogFilters = QueryBuilderParams<'ip' | 'event', 'timestamp'>;
const useActivityLogs = (filters?: ActivityLogFilters, config?: ConfigInterface<PaginatedResult<ActivityLog>, AxiosError>): responseInterface<PaginatedResult<ActivityLog>, AxiosError> => {
const key = useUserSWRContentKey([ 'account', 'activity', JSON.stringify(useFilteredObject(filters || {})) ]);
const useActivityLogs = (
filters?: ActivityLogFilters,
config?: ConfigInterface<PaginatedResult<ActivityLog>, AxiosError>
): responseInterface<PaginatedResult<ActivityLog>, AxiosError> => {
const key = useUserSWRContentKey(['account', 'activity', JSON.stringify(useFilteredObject(filters || {}))]);
return useSWR<PaginatedResult<ActivityLog>>(key, async () => {
const { data } = await http.get('/api/client/account/activity', {
params: {
...withQueryBuilderParams(filters),
include: [ 'actor' ],
},
});
return useSWR<PaginatedResult<ActivityLog>>(
key,
async () => {
const { data } = await http.get('/api/client/account/activity', {
params: {
...withQueryBuilderParams(filters),
include: ['actor'],
},
});
return toPaginatedSet(data, Transformers.toActivityLog);
}, { revalidateOnMount: false, ...(config || {}) });
return toPaginatedSet(data, Transformers.toActivityLog);
},
{ revalidateOnMount: false, ...(config || {}) }
);
};
export { useActivityLogs };

View file

@ -7,11 +7,13 @@ export default (description: string, allowedIps: string): Promise<ApiKey & { sec
description,
allowed_ips: allowedIps.length > 0 ? allowedIps.split('\n') : [],
})
.then(({ data }) => resolve({
...rawDataToApiKey(data.attributes),
// eslint-disable-next-line camelcase
secretToken: data.meta?.secret_token ?? '',
}))
.then(({ data }) =>
resolve({
...rawDataToApiKey(data.attributes),
// eslint-disable-next-line camelcase
secretToken: data.meta?.secret_token ?? '',
})
)
.catch(reject);
});
};

View file

@ -5,15 +5,19 @@ import { SSHKey, Transformers } from '@definitions/user';
import { AxiosError } from 'axios';
const useSSHKeys = (config?: ConfigInterface<SSHKey[], AxiosError>) => {
const key = useUserSWRContentKey([ 'account', 'ssh-keys' ]);
const key = useUserSWRContentKey(['account', 'ssh-keys']);
return useSWR(key, async () => {
const { data } = await http.get('/api/client/account/ssh-keys');
return useSWR(
key,
async () => {
const { data } = await http.get('/api/client/account/ssh-keys');
return (data as FractalResponseList).data.map((datum: any) => {
return Transformers.toSSHKey(datum.attributes);
});
}, { revalidateOnMount: false, ...(config || {}) });
return (data as FractalResponseList).data.map((datum: any) => {
return Transformers.toSSHKey(datum.attributes);
});
},
{ revalidateOnMount: false, ...(config || {}) }
);
};
const createSSHKey = async (name: string, publicKey: string): Promise<SSHKey> => {

View file

@ -15,12 +15,14 @@ export interface LoginData {
export default ({ username, password, recaptchaData }: LoginData): Promise<LoginResponse> => {
return new Promise((resolve, reject) => {
http.get('/sanctum/csrf-cookie')
.then(() => http.post('/auth/login', {
user: username,
password,
'g-recaptcha-response': recaptchaData,
}))
.then(response => {
.then(() =>
http.post('/auth/login', {
user: username,
password,
'g-recaptcha-response': recaptchaData,
})
)
.then((response) => {
if (!(response.data instanceof Object)) {
return reject(new Error('An error occurred while processing the login request.'));
}

View file

@ -6,12 +6,14 @@ export default (token: string, code: string, recoveryToken?: string): Promise<Lo
http.post('/auth/login/checkpoint', {
confirmation_token: token,
authentication_code: code,
recovery_token: (recoveryToken && recoveryToken.length > 0) ? recoveryToken : undefined,
recovery_token: recoveryToken && recoveryToken.length > 0 ? recoveryToken : undefined,
})
.then(response => resolve({
complete: response.data.data.complete,
intended: response.data.data.intended || undefined,
}))
.then((response) =>
resolve({
complete: response.data.data.complete,
intended: response.data.data.intended || undefined,
})
)
.catch(reject);
});
};

View file

@ -19,10 +19,12 @@ export default (email: string, data: Data): Promise<PasswordResetResponse> => {
password: data.password,
password_confirmation: data.passwordConfirmation,
})
.then(response => resolve({
redirectTo: response.data.redirect_to,
sendToLogin: response.data.send_to_login,
}))
.then((response) =>
resolve({
redirectTo: response.data.redirect_to,
sendToLogin: response.data.send_to_login,
})
)
.catch(reject);
});
};

View file

@ -3,7 +3,7 @@ import http from '@/api/http';
export default (email: string, recaptchaData?: string): Promise<string> => {
return new Promise((resolve, reject) => {
http.post('/auth/password', { email, 'g-recaptcha-response': recaptchaData })
.then(response => resolve(response.data.status || ''))
.then((response) => resolve(response.data.status || ''))
.catch(reject);
});
};

View file

@ -12,9 +12,21 @@ type TransformerFunc<T> = (callback: FractalResponseData) => T;
const isList = (data: FractalResponseList | FractalResponseData): data is FractalResponseList => data.object === 'list';
function transform<T, M>(data: null | undefined, transformer: TransformerFunc<T>, missing?: M): M;
function transform<T, M>(data: FractalResponseData | null | undefined, transformer: TransformerFunc<T>, missing?: M): T | M;
function transform<T, M>(data: FractalResponseList | FractalPaginatedResponse | null | undefined, transformer: TransformerFunc<T>, missing?: M): T[] | M;
function transform<T> (data: FractalResponseData | FractalResponseList | FractalPaginatedResponse | null | undefined, transformer: TransformerFunc<T>, missing = undefined) {
function transform<T, M>(
data: FractalResponseData | null | undefined,
transformer: TransformerFunc<T>,
missing?: M
): T | M;
function transform<T, M>(
data: FractalResponseList | FractalPaginatedResponse | null | undefined,
transformer: TransformerFunc<T>,
missing?: M
): T[] | M;
function transform<T>(
data: FractalResponseData | FractalResponseList | FractalPaginatedResponse | null | undefined,
transformer: TransformerFunc<T>,
missing = undefined
) {
if (data === undefined || data === null) {
return missing;
}
@ -30,9 +42,9 @@ function transform<T> (data: FractalResponseData | FractalResponseList | Fractal
return transformer(data);
}
function toPaginatedSet<T extends TransformerFunc<Model>> (
function toPaginatedSet<T extends TransformerFunc<Model>>(
response: FractalPaginatedResponse,
transformer: T,
transformer: T
): PaginatedResult<ReturnType<T>> {
return {
items: transform(response, transformer) as ReturnType<T>[],

View file

@ -22,7 +22,7 @@ interface ModelWithRelationships extends Model {
*/
type WithLoaded<M extends ModelWithRelationships, R extends keyof M['relationships']> = M & {
relationships: MarkRequired<M['relationships'], R>;
}
};
/**
* Helper type that allows you to infer the type of an object by giving

View file

@ -9,7 +9,7 @@ interface User extends Model {
twoFactorEnabled: boolean;
createdAt: Date;
permissions: SubuserPermission[];
can (permission: SubuserPermission): boolean;
can(permission: SubuserPermission): boolean;
}
interface SSHKey extends Model {
@ -30,5 +30,5 @@ interface ActivityLog extends Model<'actor'> {
timestamp: Date;
relationships: {
actor: User | null;
}
};
}

View file

@ -10,7 +10,7 @@ export default class Transformers {
fingerprint: data.fingerprint,
createdAt: new Date(data.created_at),
};
}
};
static toUser = ({ attributes }: FractalResponseData): Models.User => {
return {
@ -21,11 +21,11 @@ export default class Transformers {
twoFactorEnabled: attributes['2fa_enabled'],
permissions: attributes.permissions || [],
createdAt: new Date(attributes.created_at),
can (permission): boolean {
can(permission): boolean {
return this.permissions.includes(permission);
},
};
}
};
static toActivityLog = ({ attributes }: FractalResponseData): Models.ActivityLog => {
const { actor } = attributes.relationships || {};
@ -43,8 +43,7 @@ export default class Transformers {
actor: transform(actor as FractalResponseData, this.toUser, null),
},
};
}
};
}
export class MetaTransformers {
}
export class MetaTransformers {}

View file

@ -15,10 +15,12 @@ export default ({ query, ...params }: QueryParams): Promise<PaginatedResult<Serv
...params,
},
})
.then(({ data }) => resolve({
items: (data.data || []).map((datum: any) => rawDataToServerObject(datum)),
pagination: getPaginationSet(data.meta.pagination),
}))
.then(({ data }) =>
resolve({
items: (data.data || []).map((datum: any) => rawDataToServerObject(datum)),
pagination: getPaginationSet(data.meta.pagination),
})
)
.catch(reject);
});
};

View file

@ -11,7 +11,7 @@ const http: AxiosInstance = axios.create({
},
});
http.interceptors.request.use(req => {
http.interceptors.request.use((req) => {
if (!req.url?.endsWith('/resources')) {
store.getActions().progress.startContinuous();
}
@ -19,17 +19,20 @@ http.interceptors.request.use(req => {
return req;
});
http.interceptors.response.use(resp => {
if (!resp.request?.url?.endsWith('/resources')) {
http.interceptors.response.use(
(resp) => {
if (!resp.request?.url?.endsWith('/resources')) {
store.getActions().progress.setComplete();
}
return resp;
},
(error) => {
store.getActions().progress.setComplete();
throw error;
}
return resp;
}, error => {
store.getActions().progress.setComplete();
throw error;
});
);
export default http;
@ -37,7 +40,7 @@ export default http;
* Converts an error into a human readable response. Mostly just a generic helper to
* make sure we display the message from the server back to the user if we can.
*/
export function httpErrorToHuman (error: any): string {
export function httpErrorToHuman(error: any): string {
if (error.response && error.response.data) {
let { data } = error.response;
@ -104,7 +107,7 @@ export interface PaginationDataSet {
totalPages: number;
}
export function getPaginationSet (data: any): PaginationDataSet {
export function getPaginationSet(data: any): PaginationDataSet {
return {
total: data.total,
count: data.count,
@ -142,11 +145,11 @@ export const withQueryBuilderParams = (data?: QueryBuilderParams): Record<string
const sorts = Object.keys(data.sorts || {}).reduce((arr, key) => {
const value = data.sorts?.[key];
if (!value || ![ 'asc', 'desc', 1, -1 ].includes(value)) {
if (!value || !['asc', 'desc', 1, -1].includes(value)) {
return arr;
}
return [ ...arr, (value === -1 || value === 'desc' ? '-' : '') + key ];
return [...arr, (value === -1 || value === 'desc' ? '-' : '') + key];
}, [] as string[]);
return {

View file

@ -3,14 +3,17 @@ import { AxiosError } from 'axios';
import { History } from 'history';
export const setupInterceptors = (history: History) => {
http.interceptors.response.use(resp => resp, (error: AxiosError) => {
if (error.response?.status === 400) {
if (error.response?.data.errors?.[0].code === 'TwoFactorAuthRequiredException') {
if (!window.location.pathname.startsWith('/account')) {
history.replace('/account', { twoFactorRedirect: true });
http.interceptors.response.use(
(resp) => resp,
(error: AxiosError) => {
if (error.response?.status === 400) {
if (error.response?.data.errors?.[0].code === 'TwoFactorAuthRequiredException') {
if (!window.location.pathname.startsWith('/account')) {
history.replace('/account', { twoFactorRedirect: true });
}
}
}
throw error;
}
throw error;
});
);
};

View file

@ -9,20 +9,27 @@ import { ServerContext } from '@/state/server';
export type ActivityLogFilters = QueryBuilderParams<'ip' | 'event', 'timestamp'>;
const useActivityLogs = (filters?: ActivityLogFilters, config?: ConfigInterface<PaginatedResult<ActivityLog>, AxiosError>): responseInterface<PaginatedResult<ActivityLog>, AxiosError> => {
const uuid = ServerContext.useStoreState(state => state.server.data?.uuid);
const key = useUserSWRContentKey([ 'server', 'activity', useFilteredObject(filters || {}) ]);
const useActivityLogs = (
filters?: ActivityLogFilters,
config?: ConfigInterface<PaginatedResult<ActivityLog>, AxiosError>
): responseInterface<PaginatedResult<ActivityLog>, AxiosError> => {
const uuid = ServerContext.useStoreState((state) => state.server.data?.uuid);
const key = useUserSWRContentKey(['server', 'activity', useFilteredObject(filters || {})]);
return useSWR<PaginatedResult<ActivityLog>>(key, async () => {
const { data } = await http.get(`/api/client/servers/${uuid}/activity`, {
params: {
...withQueryBuilderParams(filters),
include: [ 'actor' ],
},
});
return useSWR<PaginatedResult<ActivityLog>>(
key,
async () => {
const { data } = await http.get(`/api/client/servers/${uuid}/activity`, {
params: {
...withQueryBuilderParams(filters),
include: ['actor'],
},
});
return toPaginatedSet(data, Transformers.toActivityLog);
}, { revalidateOnMount: false, ...(config || {}) });
return toPaginatedSet(data, Transformers.toActivityLog);
},
{ revalidateOnMount: false, ...(config || {}) }
);
};
export { useActivityLogs };

View file

@ -3,13 +3,17 @@ import http from '@/api/http';
export default (uuid: string, data: { connectionsFrom: string; databaseName: string }): Promise<ServerDatabase> => {
return new Promise((resolve, reject) => {
http.post(`/api/client/servers/${uuid}/databases`, {
database: data.databaseName,
remote: data.connectionsFrom,
}, {
params: { include: 'password' },
})
.then(response => resolve(rawDataToServerDatabase(response.data.attributes)))
http.post(
`/api/client/servers/${uuid}/databases`,
{
database: data.databaseName,
remote: data.connectionsFrom,
},
{
params: { include: 'password' },
}
)
.then((response) => resolve(rawDataToServerDatabase(response.data.attributes)))
.catch(reject);
});
};

View file

@ -15,7 +15,8 @@ export const rawDataToServerDatabase = (data: any): ServerDatabase => ({
username: data.username,
connectionString: `${data.host.address}:${data.host.port}`,
allowConnectionsFrom: data.connections_from,
password: data.relationships && data.relationships.password ? data.relationships.password.attributes.password : undefined,
password:
data.relationships && data.relationships.password ? data.relationships.password.attributes.password : undefined,
});
export default (uuid: string, includePassword = true): Promise<ServerDatabase[]> => {
@ -23,9 +24,9 @@ export default (uuid: string, includePassword = true): Promise<ServerDatabase[]>
http.get(`/api/client/servers/${uuid}/databases`, {
params: includePassword ? { include: 'password' } : undefined,
})
.then(response => resolve(
(response.data.data || []).map((item: any) => rawDataToServerDatabase(item.attributes))
))
.then((response) =>
resolve((response.data.data || []).map((item: any) => rawDataToServerDatabase(item.attributes)))
)
.catch(reject);
});
};

View file

@ -3,10 +3,15 @@ import http from '@/api/http';
import { rawDataToFileObject } from '@/api/transformers';
export default async (uuid: string, directory: string, files: string[]): Promise<FileObject> => {
const { data } = await http.post(`/api/client/servers/${uuid}/files/compress`, { root: directory, files }, {
timeout: 60000,
timeoutErrorMessage: 'It looks like this archive is taking a long time to generate. It will appear once completed.',
});
const { data } = await http.post(
`/api/client/servers/${uuid}/files/compress`,
{ root: directory, files },
{
timeout: 60000,
timeoutErrorMessage:
'It looks like this archive is taking a long time to generate. It will appear once completed.',
}
);
return rawDataToFileObject(data);
};

View file

@ -1,8 +1,13 @@
import http from '@/api/http';
export default async (uuid: string, directory: string, file: string): Promise<void> => {
await http.post(`/api/client/servers/${uuid}/files/decompress`, { root: directory, file }, {
timeout: 300000,
timeoutErrorMessage: 'It looks like this archive is taking a long time to be unarchived. Once completed the unarchived files will appear.',
});
await http.post(
`/api/client/servers/${uuid}/files/decompress`,
{ root: directory, file },
{
timeout: 300000,
timeoutErrorMessage:
'It looks like this archive is taking a long time to be unarchived. Once completed the unarchived files will appear.',
}
);
};

View file

@ -4,7 +4,7 @@ export default (server: string, file: string): Promise<string> => {
return new Promise((resolve, reject) => {
http.get(`/api/client/servers/${server}/files/contents`, {
params: { file },
transformResponse: res => res,
transformResponse: (res) => res,
responseType: 'text',
})
.then(({ data }) => resolve(data))

View file

@ -5,7 +5,7 @@ export interface FileObject {
key: string;
name: string;
mode: string;
modeBits: string,
modeBits: string;
size: number;
isFile: boolean;
isSymlink: boolean;

View file

@ -58,24 +58,30 @@ export const rawDataToServerObject = ({ attributes: data }: FractalResponseData)
ip: data.sftp_details.ip,
port: data.sftp_details.port,
},
description: data.description ? ((data.description.length > 0) ? data.description : null) : null,
description: data.description ? (data.description.length > 0 ? data.description : null) : null,
limits: { ...data.limits },
eggFeatures: data.egg_features || [],
featureLimits: { ...data.feature_limits },
isInstalling: data.status === 'installing' || data.status === 'install_failed',
isTransferring: data.is_transferring,
variables: ((data.relationships?.variables as FractalResponseList | undefined)?.data || []).map(rawDataToServerEggVariable),
allocations: ((data.relationships?.allocations as FractalResponseList | undefined)?.data || []).map(rawDataToServerAllocation),
variables: ((data.relationships?.variables as FractalResponseList | undefined)?.data || []).map(
rawDataToServerEggVariable
),
allocations: ((data.relationships?.allocations as FractalResponseList | undefined)?.data || []).map(
rawDataToServerAllocation
),
});
export default (uuid: string): Promise<[ Server, string[] ]> => {
export default (uuid: string): Promise<[Server, string[]]> => {
return new Promise((resolve, reject) => {
http.get(`/api/client/servers/${uuid}`)
.then(({ data }) => resolve([
rawDataToServerObject(data),
// eslint-disable-next-line camelcase
data.meta?.is_server_owner ? [ '*' ] : (data.meta?.user_permissions || []),
]))
.then(({ data }) =>
resolve([
rawDataToServerObject(data),
// eslint-disable-next-line camelcase
data.meta?.is_server_owner ? ['*'] : data.meta?.user_permissions || [],
])
)
.catch(reject);
});
};

View file

@ -16,16 +16,18 @@ export interface ServerStats {
export default (server: string): Promise<ServerStats> => {
return new Promise((resolve, reject) => {
http.get(`/api/client/servers/${server}/resources`)
.then(({ data: { attributes } }) => resolve({
status: attributes.current_state,
isSuspended: attributes.is_suspended,
memoryUsageInBytes: attributes.resources.memory_bytes,
cpuUsagePercent: attributes.resources.cpu_absolute,
diskUsageInBytes: attributes.resources.disk_bytes,
networkRxInBytes: attributes.resources.network_rx_bytes,
networkTxInBytes: attributes.resources.network_tx_bytes,
uptime: attributes.resources.uptime,
}))
.then(({ data: { attributes } }) =>
resolve({
status: attributes.current_state,
isSuspended: attributes.is_suspended,
memoryUsageInBytes: attributes.resources.memory_bytes,
cpuUsagePercent: attributes.resources.cpu_absolute,
diskUsageInBytes: attributes.resources.disk_bytes,
networkRxInBytes: attributes.resources.network_rx_bytes,
networkTxInBytes: attributes.resources.network_tx_bytes,
uptime: attributes.resources.uptime,
})
)
.catch(reject);
});
};

View file

@ -8,10 +8,12 @@ interface Response {
export default (server: string): Promise<Response> => {
return new Promise((resolve, reject) => {
http.get(`/api/client/servers/${server}/websocket`)
.then(({ data }) => resolve({
token: data.data.token,
socket: data.data.socket,
}))
.then(({ data }) =>
resolve({
token: data.data.token,
socket: data.data.socket,
})
)
.catch(reject);
});
};

View file

@ -1,4 +1,5 @@
import { Allocation } from '@/api/server/getServer';
import http from '@/api/http';
export default async (uuid: string, id: number): Promise<Allocation> => await http.delete(`/api/client/servers/${uuid}/network/allocations/${id}`);
export default async (uuid: string, id: number): Promise<Allocation> =>
await http.delete(`/api/client/servers/${uuid}/network/allocations/${id}`);

View file

@ -1,7 +1,7 @@
import { rawDataToServerSchedule, Schedule } from '@/api/server/schedules/getServerSchedules';
import http from '@/api/http';
type Data = Pick<Schedule, 'cron' | 'name' | 'onlyWhenOnline' | 'isActive'> & { id?: number }
type Data = Pick<Schedule, 'cron' | 'name' | 'onlyWhenOnline' | 'isActive'> & { id?: number };
export default async (uuid: string, schedule: Data): Promise<Schedule> => {
const { data } = await http.post(`/api/client/servers/${uuid}/schedules${schedule.id ? `/${schedule.id}` : ''}`, {

View file

@ -9,12 +9,15 @@ interface Data {
}
export default async (uuid: string, schedule: number, task: number | undefined, data: Data): Promise<Task> => {
const { data: response } = await http.post(`/api/client/servers/${uuid}/schedules/${schedule}/tasks${task ? `/${task}` : ''}`, {
action: data.action,
payload: data.payload,
continue_on_failure: data.continueOnFailure,
time_offset: data.timeOffset,
});
const { data: response } = await http.post(
`/api/client/servers/${uuid}/schedules/${schedule}/tasks${task ? `/${task}` : ''}`,
{
action: data.action,
payload: data.payload,
continue_on_failure: data.continueOnFailure,
time_offset: data.timeOffset,
}
);
return rawDataToServerTask(response.attributes);
};

View file

@ -5,7 +5,7 @@ export default (uuid: string, schedule: number): Promise<Schedule> => {
return new Promise((resolve, reject) => {
http.get(`/api/client/servers/${uuid}/schedules/${schedule}`, {
params: {
include: [ 'tasks' ],
include: ['tasks'],
},
})
.then(({ data }) => resolve(rawDataToServerSchedule(data.attributes)))

View file

@ -69,7 +69,7 @@ export const rawDataToServerSchedule = (data: any): Schedule => ({
export default async (uuid: string): Promise<Schedule[]> => {
const { data } = await http.get(`/api/client/servers/${uuid}/schedules`, {
params: {
include: [ 'tasks' ],
include: ['tasks'],
},
});

View file

@ -2,8 +2,8 @@ import http from '@/api/http';
import { ServerEggVariable } from '@/api/server/types';
import { rawDataToServerEggVariable } from '@/api/transformers';
export default async (uuid: string, key: string, value: string): Promise<[ ServerEggVariable, string ]> => {
export default async (uuid: string, key: string, value: string): Promise<[ServerEggVariable, string]> => {
const { data } = await http.put(`/api/client/servers/${uuid}/startup/variable`, { key, value });
return [ rawDataToServerEggVariable(data), data.meta.startup_command ];
return [rawDataToServerEggVariable(data), data.meta.startup_command];
};

View file

@ -12,7 +12,7 @@ export default (uuid: string, params: Params, subuser?: Subuser): Promise<Subuse
http.post(`/api/client/servers/${uuid}/users${subuser ? `/${subuser.uuid}` : ''}`, {
...params,
})
.then(data => resolve(rawDataToServerSubuser(data.data)))
.then((data) => resolve(rawDataToServerSubuser(data.data)))
.catch(reject);
});
};

View file

@ -9,7 +9,7 @@ export const rawDataToServerSubuser = (data: FractalResponseData): Subuser => ({
twoFactorEnabled: data.attributes['2fa_enabled'],
createdAt: new Date(data.attributes.created_at),
permissions: data.attributes.permissions || [],
can: permission => (data.attributes.permissions || []).indexOf(permission) >= 0,
can: (permission) => (data.attributes.permissions || []).indexOf(permission) >= 0,
});
export default (uuid: string): Promise<Subuser[]> => {

View file

@ -5,11 +5,15 @@ import { rawDataToServerAllocation } from '@/api/transformers';
import { Allocation } from '@/api/server/getServer';
export default () => {
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
const uuid = ServerContext.useStoreState((state) => state.server.data!.uuid);
return useSWR<Allocation[]>([ 'server:allocations', uuid ], async () => {
const { data } = await http.get(`/api/client/servers/${uuid}/network/allocations`);
return useSWR<Allocation[]>(
['server:allocations', uuid],
async () => {
const { data } = await http.get(`/api/client/servers/${uuid}/network/allocations`);
return (data.data || []).map(rawDataToServerAllocation);
}, { revalidateOnFocus: false, revalidateOnMount: false });
return (data.data || []).map(rawDataToServerAllocation);
},
{ revalidateOnFocus: false, revalidateOnMount: false }
);
};

View file

@ -16,15 +16,15 @@ type BackupResponse = PaginatedResult<ServerBackup> & { backupCount: number };
export default () => {
const { page } = useContext(Context);
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
const uuid = ServerContext.useStoreState((state) => state.server.data!.uuid);
return useSWR<BackupResponse>([ 'server:backups', uuid, page ], async () => {
return useSWR<BackupResponse>(['server:backups', uuid, page], async () => {
const { data } = await http.get(`/api/client/servers/${uuid}/backups`, { params: { page } });
return ({
return {
items: (data.data || []).map(rawDataToServerBackup),
pagination: getPaginationSet(data.meta.pagination),
backupCount: data.meta.backup_count,
});
};
});
};

View file

@ -9,14 +9,19 @@ interface Response {
dockerImages: Record<string, string>;
}
export default (uuid: string, initialData?: Response | null, config?: ConfigInterface<Response>) => useSWR([ uuid, '/startup' ], async (): Promise<Response> => {
const { data } = await http.get(`/api/client/servers/${uuid}/startup`);
export default (uuid: string, initialData?: Response | null, config?: ConfigInterface<Response>) =>
useSWR(
[uuid, '/startup'],
async (): Promise<Response> => {
const { data } = await http.get(`/api/client/servers/${uuid}/startup`);
const variables = ((data as FractalResponseList).data || []).map(rawDataToServerEggVariable);
const variables = ((data as FractalResponseList).data || []).map(rawDataToServerEggVariable);
return {
variables,
invocation: data.meta.startup_command,
dockerImages: data.meta.docker_images || {},
};
}, { initialData: initialData || undefined, errorRetryCount: 3, ...(config || {}) });
return {
variables,
invocation: data.meta.startup_command,
dockerImages: data.meta.docker_images || {},
};
},
{ initialData: initialData || undefined, errorRetryCount: 3, ...(config || {}) }
);

View file

@ -25,33 +25,31 @@ export const rawDataToFileObject = (data: FractalResponseData): FileObject => ({
modifiedAt: new Date(data.attributes.modified_at),
isArchiveType: function () {
return this.isFile && [
'application/vnd.rar', // .rar
'application/x-rar-compressed', // .rar (2)
'application/x-tar', // .tar
'application/x-br', // .tar.br
'application/x-bzip2', // .tar.bz2, .bz2
'application/gzip', // .tar.gz, .gz
'application/x-gzip',
'application/x-lzip', // .tar.lz4, .lz4 (not sure if this mime type is correct)
'application/x-sz', // .tar.sz, .sz (not sure if this mime type is correct)
'application/x-xz', // .tar.xz, .xz
'application/zstd', // .tar.zst, .zst
'application/zip', // .zip
].indexOf(this.mimetype) >= 0;
return (
this.isFile &&
[
'application/vnd.rar', // .rar
'application/x-rar-compressed', // .rar (2)
'application/x-tar', // .tar
'application/x-br', // .tar.br
'application/x-bzip2', // .tar.bz2, .bz2
'application/gzip', // .tar.gz, .gz
'application/x-gzip',
'application/x-lzip', // .tar.lz4, .lz4 (not sure if this mime type is correct)
'application/x-sz', // .tar.sz, .sz (not sure if this mime type is correct)
'application/x-xz', // .tar.xz, .xz
'application/zstd', // .tar.zst, .zst
'application/zip', // .zip
].indexOf(this.mimetype) >= 0
);
},
isEditable: function () {
if (this.isArchiveType() || !this.isFile) return false;
const matches = [
'application/jar',
'application/octet-stream',
'inode/directory',
/^image\//,
];
const matches = ['application/jar', 'application/octet-stream', 'inode/directory', /^image\//];
return matches.every(m => !this.mimetype.match(m));
return matches.every((m) => !this.mimetype.match(m));
},
});