mirror of
https://github.com/unraid/api.git
synced 2026-01-05 16:09:49 -06:00
feat: disable all legacy dashboard and network logic
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
[api]
|
||||
version="3.8.1+fc0d7f4a"
|
||||
version="3.8.1+7405443f"
|
||||
extraOrigins="https://google.com,https://test.com"
|
||||
[local]
|
||||
[notifier]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[api]
|
||||
version="3.8.1+fc0d7f4a"
|
||||
version="3.8.1+7405443f"
|
||||
extraOrigins="https://google.com,https://test.com"
|
||||
[local]
|
||||
[notifier]
|
||||
@@ -16,9 +16,9 @@ regWizTime="1611175408732_0951-1653-3509-FBA155FA23C0"
|
||||
idtoken=""
|
||||
accesstoken=""
|
||||
refreshtoken=""
|
||||
allowedOrigins="/var/run/unraid-notifications.sock, /var/run/unraid-php.sock, /var/run/unraid-cli.sock, http://localhost:8080, https://localhost:4443, https://tower.local:4443, https://192.168.1.150:4443, https://tower:4443, https://192-168-1-150.thisisfourtyrandomcharacters012345678900.myunraid.net:4443, https://85-121-123-122.thisisfourtyrandomcharacters012345678900.myunraid.net:8443, https://10-252-0-1.hash.myunraid.net:4443, https://10-252-1-1.hash.myunraid.net:4443, https://10-253-3-1.hash.myunraid.net:4443, https://10-253-4-1.hash.myunraid.net:4443, https://10-253-5-1.hash.myunraid.net:4443, https://10-100-0-1.hash.myunraid.net:4443, https://10-123-1-2.hash.myunraid.net:4443, https://221-123-121-112.hash.myunraid.net:4443, https://google.com, https://test.com, https://connect.myunraid.net, https://connect-staging.myunraid.net, https://dev-my.myunraid.net:4000, https://studio.apollographql.com"
|
||||
allowedOrigins="/var/run/unraid-notifications.sock, /var/run/unraid-php.sock, /var/run/unraid-cli.sock, http://localhost:8080, https://localhost:4443, https://tower.local:4443, https://192.168.1.150:4443, https://tower:4443, https://192-168-1-150.thisisfourtyrandomcharacters012345678900.myunraid.net:4443, https://85-121-123-122.thisisfourtyrandomcharacters012345678900.myunraid.net:8443, https://10-252-0-1.hash.myunraid.net:4443, https://10-252-1-1.hash.myunraid.net:4443, https://10-253-3-1.hash.myunraid.net:4443, https://10-253-4-1.hash.myunraid.net:4443, https://10-253-5-1.hash.myunraid.net:4443, https://10-100-0-1.hash.myunraid.net:4443, https://10-100-0-2.hash.myunraid.net:4443, https://10-123-1-2.hash.myunraid.net:4443, https://221-123-121-112.hash.myunraid.net:4443, https://google.com, https://test.com, https://connect.myunraid.net, https://connect-staging.myunraid.net, https://dev-my.myunraid.net:4000, https://studio.apollographql.com"
|
||||
dynamicRemoteAccessType="DISABLED"
|
||||
[upc]
|
||||
apikey="unupc_fab6ff6ffe51040595c6d9ffb63a353ba16cc2ad7d93f813a2e80a5810"
|
||||
[connectionStatus]
|
||||
minigraph="PRE_INIT"
|
||||
minigraph="CONNECTED"
|
||||
|
||||
@@ -27,6 +27,7 @@ x-volumes: &volumes
|
||||
|
||||
networks:
|
||||
mothership_default:
|
||||
external: true
|
||||
services:
|
||||
|
||||
dev:
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"build:docker": "./scripts/dc.sh run --rm builder",
|
||||
"build-pkg": "./scripts/build.mjs",
|
||||
"codegen": "MOTHERSHIP_GRAPHQL_LINK='https://staging.mothership.unraid.net/ws' graphql-codegen --config codegen.yml -r dotenv/config './.env.staging'",
|
||||
"codegen:watch": "DOTENV_CONFIG_PATH='./.env.staging' graphql-codegen-esm --config codegen.yml --watch -r dotenv/config",
|
||||
"codegen:watch": "DOTENV_CONFIG_PATH='./.env.staging' graphql-codegen --config codegen.yml --watch -r dotenv/config",
|
||||
"codegen:local": "NODE_TLS_REJECT_UNAUTHORIZED=0 MOTHERSHIP_GRAPHQL_LINK='https://mothership.localhost/ws' graphql-codegen-esm --config codegen.yml --watch",
|
||||
"tsc": "tsc --noEmit",
|
||||
"lint": "DEBUG=eslint:cli-engine eslint . --config .eslintrc.cjs",
|
||||
|
||||
154
api/src/common/dashboard/generate-server-data.ts
Normal file
154
api/src/common/dashboard/generate-server-data.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
import { ConnectListAllDomainsFlags } from '@vmngr/libvirt';
|
||||
import { getHypervisor } from '@app/core/utils/vms/get-hypervisor';
|
||||
import { getUnraidVersion } from '@app/common/dashboard/get-unraid-version';
|
||||
import { bootTimestamp } from '@app/common/dashboard/boot-timestamp';
|
||||
import { getters, store } from '@app/store';
|
||||
|
||||
import { API_VERSION } from '@app/environment';
|
||||
import { DynamicRemoteAccessType } from '@app/remoteAccess/types';
|
||||
import {
|
||||
DashboardService,
|
||||
Dashboard,
|
||||
DashboardArray,
|
||||
ArrayState,
|
||||
} from '@app/graphql/generated/api/types';
|
||||
import convert from 'convert';
|
||||
import { getArrayData } from '@app/core/modules/array/get-array-data';
|
||||
import { hostname } from 'os';
|
||||
|
||||
const getVmSummary = async (): Promise<Dashboard['vms']> => {
|
||||
try {
|
||||
const hypervisor = await getHypervisor();
|
||||
if (!hypervisor) {
|
||||
return {
|
||||
installed: 0,
|
||||
started: 0,
|
||||
};
|
||||
}
|
||||
|
||||
const activeDomains = (await hypervisor.connectListAllDomains(
|
||||
ConnectListAllDomainsFlags.ACTIVE
|
||||
)) as unknown[];
|
||||
const inactiveDomains = (await hypervisor.connectListAllDomains(
|
||||
ConnectListAllDomainsFlags.INACTIVE
|
||||
)) as unknown[];
|
||||
return {
|
||||
installed: activeDomains.length + inactiveDomains.length,
|
||||
started: activeDomains.length,
|
||||
};
|
||||
} catch {
|
||||
return {
|
||||
installed: 0,
|
||||
started: 0,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const getDynamicRemoteAccessService = (): DashboardService | null => {
|
||||
const { config, dynamicRemoteAccess } = store.getState();
|
||||
const enabledStatus = config.remote.dynamicRemoteAccessType;
|
||||
|
||||
return {
|
||||
name: 'dynamic-remote-access',
|
||||
online: enabledStatus !== DynamicRemoteAccessType.DISABLED,
|
||||
version: dynamicRemoteAccess.runningType,
|
||||
uptime: {
|
||||
timestamp: bootTimestamp.toISOString(),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const services = (): Dashboard['services'] => {
|
||||
const dynamicRemoteAccess = getDynamicRemoteAccessService();
|
||||
return [
|
||||
{
|
||||
name: 'unraid-api',
|
||||
online: true,
|
||||
uptime: {
|
||||
timestamp: bootTimestamp.toISOString(),
|
||||
},
|
||||
version: API_VERSION,
|
||||
},
|
||||
...(dynamicRemoteAccess ? [dynamicRemoteAccess] : []),
|
||||
];
|
||||
};
|
||||
|
||||
const KBToB = (kb: number | string): number =>
|
||||
convert(Number(kb), 'KB').to('B');
|
||||
|
||||
export const getArray = (): DashboardArray => {
|
||||
const array = getArrayData();
|
||||
if (!array) {
|
||||
return {
|
||||
state: ArrayState.STOPPED,
|
||||
capacity: {
|
||||
bytes: { free: 0, used: 0, total: 0 },
|
||||
disks: { free: '0', used: '0', total: '0' },
|
||||
kilobytes: { free: '0', used: '0', total: '0' },
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
state: array.state ?? ArrayState.STOPPED,
|
||||
capacity: array.capacity,
|
||||
};
|
||||
};
|
||||
|
||||
const getData = async (): Promise<Dashboard> => {
|
||||
const emhttp = getters.emhttp();
|
||||
const docker = getters.docker();
|
||||
|
||||
return {
|
||||
id: hostname() ?? 'unraid',
|
||||
vars: {
|
||||
regState: emhttp.var.regState,
|
||||
regTy: emhttp.var.regTy,
|
||||
flashGuid: emhttp.var.flashGuid,
|
||||
serverName: emhttp.var.name,
|
||||
serverDescription: emhttp.var.comment,
|
||||
},
|
||||
apps: {
|
||||
installed: docker.installed ?? 0,
|
||||
started: docker.running ?? 0,
|
||||
},
|
||||
versions: {
|
||||
unraid: await getUnraidVersion(),
|
||||
},
|
||||
os: {
|
||||
hostname: emhttp.var.name,
|
||||
uptime: bootTimestamp.toISOString(),
|
||||
},
|
||||
vms: await getVmSummary(),
|
||||
array: getArray(),
|
||||
services: services(),
|
||||
display: {
|
||||
case: {
|
||||
url: '',
|
||||
icon: '',
|
||||
error: '',
|
||||
base64: '',
|
||||
},
|
||||
},
|
||||
config: emhttp.var.configValid
|
||||
? { valid: true }
|
||||
: {
|
||||
valid: false,
|
||||
error:
|
||||
{
|
||||
error: 'UNKNOWN_ERROR',
|
||||
invalid: 'INVALID',
|
||||
nokeyserver: 'NO_KEY_SERVER',
|
||||
withdrawn: 'WITHDRAWN',
|
||||
}[emhttp.var.configState] ?? 'UNKNOWN_ERROR',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides a way to get dashboard data from the GraphQL client without the need for publishing to mothership
|
||||
* @returns Dashboard data
|
||||
*/
|
||||
export const dashboardDataServer = async (): Promise<Dashboard> => {
|
||||
return await getData();
|
||||
};
|
||||
@@ -2,7 +2,7 @@
|
||||
import * as Types from '@app/graphql/generated/api/types';
|
||||
|
||||
import { z } from 'zod'
|
||||
import { AllowedOriginInput, ApiKey, ApiKeyResponse, ArrayType, ArrayCapacity, ArrayDisk, ArrayDiskFsColor, ArrayDiskStatus, ArrayDiskType, ArrayPendingState, ArrayState, Baseboard, Capacity, Case, Cloud, CloudResponse, Config, ConfigErrorState, ConnectSignInInput, ConnectUserInfoInput, ContainerHostConfig, ContainerMount, ContainerPort, ContainerPortType, ContainerState, Devices, Disk, DiskFsType, DiskInterfaceType, DiskPartition, DiskSmartStatus, Display, DockerContainer, DockerNetwork, Flash, Gpu, Importance, Info, InfoApps, InfoCpu, InfoMemory, KeyFile, Me, MemoryFormFactor, MemoryLayout, MemoryType, MinigraphStatus, MinigraphqlResponse, Mount, Network, Notification, NotificationFilter, NotificationInput, NotificationType, Os, Owner, ParityCheck, Partition, Pci, ProfileModel, Registration, RegistrationState, RelayResponse, RemoteAccess, Server, ServerStatus, Service, SetupRemoteAccessInput, Share, System, Temperature, Theme, UnassignedDevice, Uptime, Usb, User, UserAccount, Vars, Versions, VmDomain, VmState, Vms, WAN_ACCESS_TYPE, WAN_FORWARD_TYPE, Welcome, addApiKeyInput, addUserInput, arrayDiskInput, authenticateInput, deleteUserInput, mdState, registrationType, updateApikeyInput, usersInput } from '@app/graphql/generated/api/types'
|
||||
import { AccessUrl, AccessUrlInput, AllowedOriginInput, ApiKey, ApiKeyResponse, ArrayType, ArrayCapacity, ArrayCapacityBytes, ArrayDisk, ArrayDiskFsColor, ArrayDiskStatus, ArrayDiskType, ArrayPendingState, ArrayState, Baseboard, Capacity, Case, Cloud, CloudResponse, Config, ConfigErrorState, ConnectSignInInput, ConnectUserInfoInput, ContainerHostConfig, ContainerMount, ContainerPort, ContainerPortType, ContainerState, Dashboard, DashboardApps, DashboardArray, DashboardCase, DashboardConfig, DashboardDisplay, DashboardOs, DashboardService, DashboardServiceInput, DashboardServiceUptime, DashboardServiceUptimeInput, DashboardTwoFactor, DashboardTwoFactorLocal, DashboardTwoFactorRemote, DashboardVars, DashboardVersions, DashboardVms, Devices, Disk, DiskFsType, DiskInterfaceType, DiskPartition, DiskSmartStatus, Display, DockerContainer, DockerNetwork, Flash, Gpu, Importance, Info, InfoApps, InfoCpu, InfoMemory, KeyFile, Me, MemoryFormFactor, MemoryLayout, MemoryType, MinigraphStatus, MinigraphqlResponse, Mount, Network, NetworkInput, Notification, NotificationFilter, NotificationInput, NotificationType, Os, Owner, ParityCheck, Partition, Pci, ProfileModel, Registration, RegistrationState, RelayResponse, RemoteAccess, Server, ServerStatus, Service, SetupRemoteAccessInput, Share, System, Temperature, Theme, URL_TYPE, UnassignedDevice, Uptime, Usb, User, UserAccount, Vars, Versions, VmDomain, VmState, Vms, WAN_ACCESS_TYPE, WAN_FORWARD_TYPE, Welcome, addApiKeyInput, addUserInput, arrayDiskInput, authenticateInput, deleteUserInput, mdState, registrationType, updateApikeyInput, usersInput } from '@app/graphql/generated/api/types'
|
||||
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
|
||||
|
||||
type Properties<T> = Required<{
|
||||
@@ -55,6 +55,8 @@ export const TemperatureSchema = z.nativeEnum(Temperature);
|
||||
|
||||
export const ThemeSchema = z.nativeEnum(Theme);
|
||||
|
||||
export const URL_TYPESchema = z.nativeEnum(URL_TYPE);
|
||||
|
||||
export const VmStateSchema = z.nativeEnum(VmState);
|
||||
|
||||
export const WAN_ACCESS_TYPESchema = z.nativeEnum(WAN_ACCESS_TYPE);
|
||||
@@ -65,6 +67,25 @@ export const mdStateSchema = z.nativeEnum(mdState);
|
||||
|
||||
export const registrationTypeSchema = z.nativeEnum(registrationType);
|
||||
|
||||
export function AccessUrlSchema(): z.ZodObject<Properties<AccessUrl>> {
|
||||
return z.object({
|
||||
__typename: z.literal('AccessUrl').optional(),
|
||||
ipv4: definedNonNullAnySchema.nullish(),
|
||||
ipv6: definedNonNullAnySchema.nullish(),
|
||||
name: z.string().nullish(),
|
||||
type: URL_TYPESchema
|
||||
})
|
||||
}
|
||||
|
||||
export function AccessUrlInputSchema(): z.ZodObject<Properties<AccessUrlInput>> {
|
||||
return z.object({
|
||||
ipv4: definedNonNullAnySchema.nullish(),
|
||||
ipv6: definedNonNullAnySchema.nullish(),
|
||||
name: z.string().nullish(),
|
||||
type: URL_TYPESchema
|
||||
})
|
||||
}
|
||||
|
||||
export function AllowedOriginInputSchema(): z.ZodObject<Properties<AllowedOriginInput>> {
|
||||
return z.object({
|
||||
origins: z.array(z.string())
|
||||
@@ -107,11 +128,21 @@ export function ArrayTypeSchema(): z.ZodObject<Properties<ArrayType>> {
|
||||
export function ArrayCapacitySchema(): z.ZodObject<Properties<ArrayCapacity>> {
|
||||
return z.object({
|
||||
__typename: z.literal('ArrayCapacity').optional(),
|
||||
bytes: ArrayCapacityBytesSchema().nullish(),
|
||||
disks: CapacitySchema(),
|
||||
kilobytes: CapacitySchema()
|
||||
})
|
||||
}
|
||||
|
||||
export function ArrayCapacityBytesSchema(): z.ZodObject<Properties<ArrayCapacityBytes>> {
|
||||
return z.object({
|
||||
__typename: z.literal('ArrayCapacityBytes').optional(),
|
||||
free: z.number().nullish(),
|
||||
total: z.number().nullish(),
|
||||
used: z.number().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function ArrayDiskSchema(): z.ZodObject<Properties<ArrayDisk>> {
|
||||
return z.object({
|
||||
__typename: z.literal('ArrayDisk').optional(),
|
||||
@@ -248,6 +279,155 @@ export function ContainerPortSchema(): z.ZodObject<Properties<ContainerPort>> {
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardSchema(): z.ZodObject<Properties<Dashboard>> {
|
||||
return z.object({
|
||||
__typename: z.literal('Dashboard').optional(),
|
||||
apps: DashboardAppsSchema().nullish(),
|
||||
array: DashboardArraySchema().nullish(),
|
||||
config: DashboardConfigSchema().nullish(),
|
||||
display: DashboardDisplaySchema().nullish(),
|
||||
id: z.string(),
|
||||
lastPublish: z.string().nullish(),
|
||||
network: NetworkSchema().nullish(),
|
||||
online: z.boolean().nullish(),
|
||||
os: DashboardOsSchema().nullish(),
|
||||
services: z.array(DashboardServiceSchema().nullable()).nullish(),
|
||||
twoFactor: DashboardTwoFactorSchema().nullish(),
|
||||
vars: DashboardVarsSchema().nullish(),
|
||||
versions: DashboardVersionsSchema().nullish(),
|
||||
vms: DashboardVmsSchema().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardAppsSchema(): z.ZodObject<Properties<DashboardApps>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardApps').optional(),
|
||||
installed: z.number().nullish(),
|
||||
started: z.number().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardArraySchema(): z.ZodObject<Properties<DashboardArray>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardArray').optional(),
|
||||
capacity: ArrayCapacitySchema().nullish(),
|
||||
state: z.string().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardCaseSchema(): z.ZodObject<Properties<DashboardCase>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardCase').optional(),
|
||||
base64: z.string().nullish(),
|
||||
error: z.string().nullish(),
|
||||
icon: z.string().nullish(),
|
||||
url: z.string().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardConfigSchema(): z.ZodObject<Properties<DashboardConfig>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardConfig').optional(),
|
||||
error: z.string().nullish(),
|
||||
valid: z.boolean().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardDisplaySchema(): z.ZodObject<Properties<DashboardDisplay>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardDisplay').optional(),
|
||||
case: DashboardCaseSchema().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardOsSchema(): z.ZodObject<Properties<DashboardOs>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardOs').optional(),
|
||||
hostname: z.string().nullish(),
|
||||
uptime: z.string().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardServiceSchema(): z.ZodObject<Properties<DashboardService>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardService').optional(),
|
||||
name: z.string().nullish(),
|
||||
online: z.boolean().nullish(),
|
||||
uptime: DashboardServiceUptimeSchema().nullish(),
|
||||
version: z.string().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardServiceInputSchema(): z.ZodObject<Properties<DashboardServiceInput>> {
|
||||
return z.object({
|
||||
name: z.string(),
|
||||
online: z.boolean(),
|
||||
uptime: z.lazy(() => DashboardServiceUptimeInputSchema().nullish()),
|
||||
version: z.string()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardServiceUptimeSchema(): z.ZodObject<Properties<DashboardServiceUptime>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardServiceUptime').optional(),
|
||||
timestamp: z.string().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardServiceUptimeInputSchema(): z.ZodObject<Properties<DashboardServiceUptimeInput>> {
|
||||
return z.object({
|
||||
timestamp: z.string()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardTwoFactorSchema(): z.ZodObject<Properties<DashboardTwoFactor>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardTwoFactor').optional(),
|
||||
local: DashboardTwoFactorLocalSchema().nullish(),
|
||||
remote: DashboardTwoFactorRemoteSchema().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardTwoFactorLocalSchema(): z.ZodObject<Properties<DashboardTwoFactorLocal>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardTwoFactorLocal').optional(),
|
||||
enabled: z.boolean().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardTwoFactorRemoteSchema(): z.ZodObject<Properties<DashboardTwoFactorRemote>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardTwoFactorRemote').optional(),
|
||||
enabled: z.boolean().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardVarsSchema(): z.ZodObject<Properties<DashboardVars>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardVars').optional(),
|
||||
flashGuid: z.string().nullish(),
|
||||
regState: z.string().nullish(),
|
||||
regTy: z.string().nullish(),
|
||||
serverDescription: z.string().nullish(),
|
||||
serverName: z.string().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardVersionsSchema(): z.ZodObject<Properties<DashboardVersions>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardVersions').optional(),
|
||||
unraid: z.string().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DashboardVmsSchema(): z.ZodObject<Properties<DashboardVms>> {
|
||||
return z.object({
|
||||
__typename: z.literal('DashboardVms').optional(),
|
||||
installed: z.number().nullish(),
|
||||
started: z.number().nullish()
|
||||
})
|
||||
}
|
||||
|
||||
export function DevicesSchema(): z.ZodObject<Properties<Devices>> {
|
||||
return z.object({
|
||||
__typename: z.literal('Devices').optional(),
|
||||
@@ -503,6 +683,7 @@ export function MountSchema(): z.ZodObject<Properties<Mount>> {
|
||||
export function NetworkSchema(): z.ZodObject<Properties<Network>> {
|
||||
return z.object({
|
||||
__typename: z.literal('Network').optional(),
|
||||
accessUrls: z.array(AccessUrlSchema()).nullish(),
|
||||
carrierChanges: z.string().nullish(),
|
||||
duplex: z.string().nullish(),
|
||||
iface: z.string().nullish(),
|
||||
@@ -518,6 +699,12 @@ export function NetworkSchema(): z.ZodObject<Properties<Network>> {
|
||||
})
|
||||
}
|
||||
|
||||
export function NetworkInputSchema(): z.ZodObject<Properties<NetworkInput>> {
|
||||
return z.object({
|
||||
accessUrls: z.array(z.lazy(() => AccessUrlInputSchema()))
|
||||
})
|
||||
}
|
||||
|
||||
export function NotificationSchema(): z.ZodObject<Properties<Notification>> {
|
||||
return z.object({
|
||||
__typename: z.literal('Notification').optional(),
|
||||
|
||||
@@ -20,9 +20,25 @@ export type Scalars = {
|
||||
JSON: { input: { [key: string]: any }; output: { [key: string]: any }; }
|
||||
Long: { input: number; output: number; }
|
||||
Port: { input: number; output: number; }
|
||||
URL: { input: URL; output: URL; }
|
||||
UUID: { input: string; output: string; }
|
||||
};
|
||||
|
||||
export type AccessUrl = {
|
||||
__typename?: 'AccessUrl';
|
||||
ipv4?: Maybe<Scalars['URL']['output']>;
|
||||
ipv6?: Maybe<Scalars['URL']['output']>;
|
||||
name?: Maybe<Scalars['String']['output']>;
|
||||
type: URL_TYPE;
|
||||
};
|
||||
|
||||
export type AccessUrlInput = {
|
||||
ipv4?: InputMaybe<Scalars['URL']['input']>;
|
||||
ipv6?: InputMaybe<Scalars['URL']['input']>;
|
||||
name?: InputMaybe<Scalars['String']['input']>;
|
||||
type: URL_TYPE;
|
||||
};
|
||||
|
||||
export type AllowedOriginInput = {
|
||||
origins: Array<Scalars['String']['input']>;
|
||||
};
|
||||
@@ -64,10 +80,18 @@ export type ArrayType = {
|
||||
|
||||
export type ArrayCapacity = {
|
||||
__typename?: 'ArrayCapacity';
|
||||
bytes?: Maybe<ArrayCapacityBytes>;
|
||||
disks: Capacity;
|
||||
kilobytes: Capacity;
|
||||
};
|
||||
|
||||
export type ArrayCapacityBytes = {
|
||||
__typename?: 'ArrayCapacityBytes';
|
||||
free?: Maybe<Scalars['Long']['output']>;
|
||||
total?: Maybe<Scalars['Long']['output']>;
|
||||
used?: Maybe<Scalars['Long']['output']>;
|
||||
};
|
||||
|
||||
export type ArrayDisk = {
|
||||
__typename?: 'ArrayDisk';
|
||||
/** User comment on disk */
|
||||
@@ -294,6 +318,123 @@ export enum ContainerState {
|
||||
RUNNING = 'RUNNING'
|
||||
}
|
||||
|
||||
export type Dashboard = {
|
||||
__typename?: 'Dashboard';
|
||||
apps?: Maybe<DashboardApps>;
|
||||
array?: Maybe<DashboardArray>;
|
||||
config?: Maybe<DashboardConfig>;
|
||||
display?: Maybe<DashboardDisplay>;
|
||||
id: Scalars['ID']['output'];
|
||||
lastPublish?: Maybe<Scalars['DateTime']['output']>;
|
||||
network?: Maybe<Network>;
|
||||
online?: Maybe<Scalars['Boolean']['output']>;
|
||||
os?: Maybe<DashboardOs>;
|
||||
services?: Maybe<Array<Maybe<DashboardService>>>;
|
||||
twoFactor?: Maybe<DashboardTwoFactor>;
|
||||
vars?: Maybe<DashboardVars>;
|
||||
versions?: Maybe<DashboardVersions>;
|
||||
vms?: Maybe<DashboardVms>;
|
||||
};
|
||||
|
||||
export type DashboardApps = {
|
||||
__typename?: 'DashboardApps';
|
||||
installed?: Maybe<Scalars['Int']['output']>;
|
||||
started?: Maybe<Scalars['Int']['output']>;
|
||||
};
|
||||
|
||||
export type DashboardArray = {
|
||||
__typename?: 'DashboardArray';
|
||||
/** Current array capacity */
|
||||
capacity?: Maybe<ArrayCapacity>;
|
||||
/** Current array state */
|
||||
state?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
export type DashboardCase = {
|
||||
__typename?: 'DashboardCase';
|
||||
base64?: Maybe<Scalars['String']['output']>;
|
||||
error?: Maybe<Scalars['String']['output']>;
|
||||
icon?: Maybe<Scalars['String']['output']>;
|
||||
url?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
export type DashboardConfig = {
|
||||
__typename?: 'DashboardConfig';
|
||||
error?: Maybe<Scalars['String']['output']>;
|
||||
valid?: Maybe<Scalars['Boolean']['output']>;
|
||||
};
|
||||
|
||||
export type DashboardDisplay = {
|
||||
__typename?: 'DashboardDisplay';
|
||||
case?: Maybe<DashboardCase>;
|
||||
};
|
||||
|
||||
export type DashboardOs = {
|
||||
__typename?: 'DashboardOs';
|
||||
hostname?: Maybe<Scalars['String']['output']>;
|
||||
uptime?: Maybe<Scalars['DateTime']['output']>;
|
||||
};
|
||||
|
||||
export type DashboardService = {
|
||||
__typename?: 'DashboardService';
|
||||
name?: Maybe<Scalars['String']['output']>;
|
||||
online?: Maybe<Scalars['Boolean']['output']>;
|
||||
uptime?: Maybe<DashboardServiceUptime>;
|
||||
version?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
export type DashboardServiceInput = {
|
||||
name: Scalars['String']['input'];
|
||||
online: Scalars['Boolean']['input'];
|
||||
uptime?: InputMaybe<DashboardServiceUptimeInput>;
|
||||
version: Scalars['String']['input'];
|
||||
};
|
||||
|
||||
export type DashboardServiceUptime = {
|
||||
__typename?: 'DashboardServiceUptime';
|
||||
timestamp?: Maybe<Scalars['DateTime']['output']>;
|
||||
};
|
||||
|
||||
export type DashboardServiceUptimeInput = {
|
||||
timestamp: Scalars['DateTime']['input'];
|
||||
};
|
||||
|
||||
export type DashboardTwoFactor = {
|
||||
__typename?: 'DashboardTwoFactor';
|
||||
local?: Maybe<DashboardTwoFactorLocal>;
|
||||
remote?: Maybe<DashboardTwoFactorRemote>;
|
||||
};
|
||||
|
||||
export type DashboardTwoFactorLocal = {
|
||||
__typename?: 'DashboardTwoFactorLocal';
|
||||
enabled?: Maybe<Scalars['Boolean']['output']>;
|
||||
};
|
||||
|
||||
export type DashboardTwoFactorRemote = {
|
||||
__typename?: 'DashboardTwoFactorRemote';
|
||||
enabled?: Maybe<Scalars['Boolean']['output']>;
|
||||
};
|
||||
|
||||
export type DashboardVars = {
|
||||
__typename?: 'DashboardVars';
|
||||
flashGuid?: Maybe<Scalars['String']['output']>;
|
||||
regState?: Maybe<Scalars['String']['output']>;
|
||||
regTy?: Maybe<Scalars['String']['output']>;
|
||||
serverDescription?: Maybe<Scalars['String']['output']>;
|
||||
serverName?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
export type DashboardVersions = {
|
||||
__typename?: 'DashboardVersions';
|
||||
unraid?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
export type DashboardVms = {
|
||||
__typename?: 'DashboardVms';
|
||||
installed?: Maybe<Scalars['Int']['output']>;
|
||||
started?: Maybe<Scalars['Int']['output']>;
|
||||
};
|
||||
|
||||
export type Devices = {
|
||||
__typename?: 'Devices';
|
||||
gpu?: Maybe<Array<Maybe<Gpu>>>;
|
||||
@@ -588,7 +729,6 @@ export type Mutation = {
|
||||
removeDiskFromArray?: Maybe<ArrayType>;
|
||||
/** Resume parity check */
|
||||
resumeParityCheck?: Maybe<Scalars['JSON']['output']>;
|
||||
sendNotification?: Maybe<Notification>;
|
||||
setAdditionalAllowedOrigins: Array<Scalars['String']['output']>;
|
||||
setupRemoteAccess: Scalars['Boolean']['output'];
|
||||
shutdown?: Maybe<Scalars['String']['output']>;
|
||||
@@ -601,6 +741,7 @@ export type Mutation = {
|
||||
unmountArrayDisk?: Maybe<Disk>;
|
||||
/** Update an existing API key */
|
||||
updateApikey?: Maybe<ApiKey>;
|
||||
updateNetwork: Network;
|
||||
};
|
||||
|
||||
|
||||
@@ -657,11 +798,6 @@ export type MutationremoveDiskFromArrayArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationsendNotificationArgs = {
|
||||
notification: NotificationInput;
|
||||
};
|
||||
|
||||
|
||||
export type MutationsetAdditionalAllowedOriginsArgs = {
|
||||
input: AllowedOriginInput;
|
||||
};
|
||||
@@ -687,8 +823,14 @@ export type MutationupdateApikeyArgs = {
|
||||
name: Scalars['String']['input'];
|
||||
};
|
||||
|
||||
|
||||
export type MutationupdateNetworkArgs = {
|
||||
data: NetworkInput;
|
||||
};
|
||||
|
||||
export type Network = {
|
||||
__typename?: 'Network';
|
||||
accessUrls?: Maybe<Array<AccessUrl>>;
|
||||
carrierChanges?: Maybe<Scalars['String']['output']>;
|
||||
duplex?: Maybe<Scalars['String']['output']>;
|
||||
iface?: Maybe<Scalars['String']['output']>;
|
||||
@@ -703,6 +845,10 @@ export type Network = {
|
||||
type?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
export type NetworkInput = {
|
||||
accessUrls: Array<AccessUrlInput>;
|
||||
};
|
||||
|
||||
export type Notification = {
|
||||
__typename?: 'Notification';
|
||||
description: Scalars['String']['output'];
|
||||
@@ -886,6 +1032,8 @@ export type Query = {
|
||||
registration?: Maybe<Registration>;
|
||||
remoteAccess: RemoteAccess;
|
||||
server?: Maybe<Server>;
|
||||
/** Temporary Type to Enable Swapping Dashboard over in Connect without major changes */
|
||||
serverDashboard: Dashboard;
|
||||
servers: Array<Server>;
|
||||
/** Network Shares */
|
||||
shares?: Maybe<Array<Maybe<Share>>>;
|
||||
@@ -1133,6 +1281,14 @@ export enum Theme {
|
||||
WHITE = 'white'
|
||||
}
|
||||
|
||||
export enum URL_TYPE {
|
||||
DEFAULT = 'DEFAULT',
|
||||
LAN = 'LAN',
|
||||
MDNS = 'MDNS',
|
||||
WAN = 'WAN',
|
||||
WIREGUARD = 'WIREGUARD'
|
||||
}
|
||||
|
||||
export type UnassignedDevice = {
|
||||
__typename?: 'UnassignedDevice';
|
||||
devlinks?: Maybe<Scalars['String']['output']>;
|
||||
@@ -1582,11 +1738,14 @@ export type ResolversInterfaceTypes<RefType extends Record<string, unknown>> = R
|
||||
|
||||
/** Mapping between all available schema types and the resolvers types */
|
||||
export type ResolversTypes = ResolversObject<{
|
||||
AccessUrl: ResolverTypeWrapper<AccessUrl>;
|
||||
AccessUrlInput: AccessUrlInput;
|
||||
AllowedOriginInput: AllowedOriginInput;
|
||||
ApiKey: ResolverTypeWrapper<ApiKey>;
|
||||
ApiKeyResponse: ResolverTypeWrapper<ApiKeyResponse>;
|
||||
Array: ResolverTypeWrapper<ArrayType>;
|
||||
ArrayCapacity: ResolverTypeWrapper<ArrayCapacity>;
|
||||
ArrayCapacityBytes: ResolverTypeWrapper<ArrayCapacityBytes>;
|
||||
ArrayDisk: ResolverTypeWrapper<ArrayDisk>;
|
||||
ArrayDiskFsColor: ArrayDiskFsColor;
|
||||
ArrayDiskStatus: ArrayDiskStatus;
|
||||
@@ -1608,6 +1767,23 @@ export type ResolversTypes = ResolversObject<{
|
||||
ContainerPort: ResolverTypeWrapper<ContainerPort>;
|
||||
ContainerPortType: ContainerPortType;
|
||||
ContainerState: ContainerState;
|
||||
Dashboard: ResolverTypeWrapper<Dashboard>;
|
||||
DashboardApps: ResolverTypeWrapper<DashboardApps>;
|
||||
DashboardArray: ResolverTypeWrapper<DashboardArray>;
|
||||
DashboardCase: ResolverTypeWrapper<DashboardCase>;
|
||||
DashboardConfig: ResolverTypeWrapper<DashboardConfig>;
|
||||
DashboardDisplay: ResolverTypeWrapper<DashboardDisplay>;
|
||||
DashboardOs: ResolverTypeWrapper<DashboardOs>;
|
||||
DashboardService: ResolverTypeWrapper<DashboardService>;
|
||||
DashboardServiceInput: DashboardServiceInput;
|
||||
DashboardServiceUptime: ResolverTypeWrapper<DashboardServiceUptime>;
|
||||
DashboardServiceUptimeInput: DashboardServiceUptimeInput;
|
||||
DashboardTwoFactor: ResolverTypeWrapper<DashboardTwoFactor>;
|
||||
DashboardTwoFactorLocal: ResolverTypeWrapper<DashboardTwoFactorLocal>;
|
||||
DashboardTwoFactorRemote: ResolverTypeWrapper<DashboardTwoFactorRemote>;
|
||||
DashboardVars: ResolverTypeWrapper<DashboardVars>;
|
||||
DashboardVersions: ResolverTypeWrapper<DashboardVersions>;
|
||||
DashboardVms: ResolverTypeWrapper<DashboardVms>;
|
||||
DateTime: ResolverTypeWrapper<Scalars['DateTime']['output']>;
|
||||
Devices: ResolverTypeWrapper<Devices>;
|
||||
Disk: ResolverTypeWrapper<Disk>;
|
||||
@@ -1640,6 +1816,7 @@ export type ResolversTypes = ResolversObject<{
|
||||
Mount: ResolverTypeWrapper<Mount>;
|
||||
Mutation: ResolverTypeWrapper<{}>;
|
||||
Network: ResolverTypeWrapper<Network>;
|
||||
NetworkInput: NetworkInput;
|
||||
Notification: ResolverTypeWrapper<Notification>;
|
||||
NotificationFilter: NotificationFilter;
|
||||
NotificationInput: NotificationInput;
|
||||
@@ -1666,6 +1843,8 @@ export type ResolversTypes = ResolversObject<{
|
||||
System: ResolverTypeWrapper<System>;
|
||||
Temperature: Temperature;
|
||||
Theme: Theme;
|
||||
URL: ResolverTypeWrapper<Scalars['URL']['output']>;
|
||||
URL_TYPE: URL_TYPE;
|
||||
UUID: ResolverTypeWrapper<Scalars['UUID']['output']>;
|
||||
UnassignedDevice: ResolverTypeWrapper<UnassignedDevice>;
|
||||
Uptime: ResolverTypeWrapper<Uptime>;
|
||||
@@ -1693,11 +1872,14 @@ export type ResolversTypes = ResolversObject<{
|
||||
|
||||
/** Mapping between all available schema types and the resolvers parents */
|
||||
export type ResolversParentTypes = ResolversObject<{
|
||||
AccessUrl: AccessUrl;
|
||||
AccessUrlInput: AccessUrlInput;
|
||||
AllowedOriginInput: AllowedOriginInput;
|
||||
ApiKey: ApiKey;
|
||||
ApiKeyResponse: ApiKeyResponse;
|
||||
Array: ArrayType;
|
||||
ArrayCapacity: ArrayCapacity;
|
||||
ArrayCapacityBytes: ArrayCapacityBytes;
|
||||
ArrayDisk: ArrayDisk;
|
||||
Baseboard: Baseboard;
|
||||
Boolean: Scalars['Boolean']['output'];
|
||||
@@ -1711,6 +1893,23 @@ export type ResolversParentTypes = ResolversObject<{
|
||||
ContainerHostConfig: ContainerHostConfig;
|
||||
ContainerMount: ContainerMount;
|
||||
ContainerPort: ContainerPort;
|
||||
Dashboard: Dashboard;
|
||||
DashboardApps: DashboardApps;
|
||||
DashboardArray: DashboardArray;
|
||||
DashboardCase: DashboardCase;
|
||||
DashboardConfig: DashboardConfig;
|
||||
DashboardDisplay: DashboardDisplay;
|
||||
DashboardOs: DashboardOs;
|
||||
DashboardService: DashboardService;
|
||||
DashboardServiceInput: DashboardServiceInput;
|
||||
DashboardServiceUptime: DashboardServiceUptime;
|
||||
DashboardServiceUptimeInput: DashboardServiceUptimeInput;
|
||||
DashboardTwoFactor: DashboardTwoFactor;
|
||||
DashboardTwoFactorLocal: DashboardTwoFactorLocal;
|
||||
DashboardTwoFactorRemote: DashboardTwoFactorRemote;
|
||||
DashboardVars: DashboardVars;
|
||||
DashboardVersions: DashboardVersions;
|
||||
DashboardVms: DashboardVms;
|
||||
DateTime: Scalars['DateTime']['output'];
|
||||
Devices: Devices;
|
||||
Disk: Disk;
|
||||
@@ -1736,6 +1935,7 @@ export type ResolversParentTypes = ResolversObject<{
|
||||
Mount: Mount;
|
||||
Mutation: {};
|
||||
Network: Network;
|
||||
NetworkInput: NetworkInput;
|
||||
Notification: Notification;
|
||||
NotificationFilter: NotificationFilter;
|
||||
NotificationInput: NotificationInput;
|
||||
@@ -1757,6 +1957,7 @@ export type ResolversParentTypes = ResolversObject<{
|
||||
String: Scalars['String']['output'];
|
||||
Subscription: {};
|
||||
System: System;
|
||||
URL: Scalars['URL']['output'];
|
||||
UUID: Scalars['UUID']['output'];
|
||||
UnassignedDevice: UnassignedDevice;
|
||||
Uptime: Uptime;
|
||||
@@ -1777,6 +1978,14 @@ export type ResolversParentTypes = ResolversObject<{
|
||||
usersInput: usersInput;
|
||||
}>;
|
||||
|
||||
export type AccessUrlResolvers<ContextType = Context, ParentType extends ResolversParentTypes['AccessUrl'] = ResolversParentTypes['AccessUrl']> = ResolversObject<{
|
||||
ipv4?: Resolver<Maybe<ResolversTypes['URL']>, ParentType, ContextType>;
|
||||
ipv6?: Resolver<Maybe<ResolversTypes['URL']>, ParentType, ContextType>;
|
||||
name?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
type?: Resolver<ResolversTypes['URL_TYPE'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type ApiKeyResolvers<ContextType = Context, ParentType extends ResolversParentTypes['ApiKey'] = ResolversParentTypes['ApiKey']> = ResolversObject<{
|
||||
description?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
expiresAt?: Resolver<ResolversTypes['Long'], ParentType, ContextType>;
|
||||
@@ -1805,11 +2014,19 @@ export type ArrayResolvers<ContextType = Context, ParentType extends ResolversPa
|
||||
}>;
|
||||
|
||||
export type ArrayCapacityResolvers<ContextType = Context, ParentType extends ResolversParentTypes['ArrayCapacity'] = ResolversParentTypes['ArrayCapacity']> = ResolversObject<{
|
||||
bytes?: Resolver<Maybe<ResolversTypes['ArrayCapacityBytes']>, ParentType, ContextType>;
|
||||
disks?: Resolver<ResolversTypes['Capacity'], ParentType, ContextType>;
|
||||
kilobytes?: Resolver<ResolversTypes['Capacity'], ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type ArrayCapacityBytesResolvers<ContextType = Context, ParentType extends ResolversParentTypes['ArrayCapacityBytes'] = ResolversParentTypes['ArrayCapacityBytes']> = ResolversObject<{
|
||||
free?: Resolver<Maybe<ResolversTypes['Long']>, ParentType, ContextType>;
|
||||
total?: Resolver<Maybe<ResolversTypes['Long']>, ParentType, ContextType>;
|
||||
used?: Resolver<Maybe<ResolversTypes['Long']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type ArrayDiskResolvers<ContextType = Context, ParentType extends ResolversParentTypes['ArrayDisk'] = ResolversParentTypes['ArrayDisk']> = ResolversObject<{
|
||||
comment?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
critical?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
|
||||
@@ -1908,6 +2125,110 @@ export type ContainerPortResolvers<ContextType = Context, ParentType extends Res
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardResolvers<ContextType = Context, ParentType extends ResolversParentTypes['Dashboard'] = ResolversParentTypes['Dashboard']> = ResolversObject<{
|
||||
apps?: Resolver<Maybe<ResolversTypes['DashboardApps']>, ParentType, ContextType>;
|
||||
array?: Resolver<Maybe<ResolversTypes['DashboardArray']>, ParentType, ContextType>;
|
||||
config?: Resolver<Maybe<ResolversTypes['DashboardConfig']>, ParentType, ContextType>;
|
||||
display?: Resolver<Maybe<ResolversTypes['DashboardDisplay']>, ParentType, ContextType>;
|
||||
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
|
||||
lastPublish?: Resolver<Maybe<ResolversTypes['DateTime']>, ParentType, ContextType>;
|
||||
network?: Resolver<Maybe<ResolversTypes['Network']>, ParentType, ContextType>;
|
||||
online?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>;
|
||||
os?: Resolver<Maybe<ResolversTypes['DashboardOs']>, ParentType, ContextType>;
|
||||
services?: Resolver<Maybe<Array<Maybe<ResolversTypes['DashboardService']>>>, ParentType, ContextType>;
|
||||
twoFactor?: Resolver<Maybe<ResolversTypes['DashboardTwoFactor']>, ParentType, ContextType>;
|
||||
vars?: Resolver<Maybe<ResolversTypes['DashboardVars']>, ParentType, ContextType>;
|
||||
versions?: Resolver<Maybe<ResolversTypes['DashboardVersions']>, ParentType, ContextType>;
|
||||
vms?: Resolver<Maybe<ResolversTypes['DashboardVms']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardAppsResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardApps'] = ResolversParentTypes['DashboardApps']> = ResolversObject<{
|
||||
installed?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
|
||||
started?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardArrayResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardArray'] = ResolversParentTypes['DashboardArray']> = ResolversObject<{
|
||||
capacity?: Resolver<Maybe<ResolversTypes['ArrayCapacity']>, ParentType, ContextType>;
|
||||
state?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardCaseResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardCase'] = ResolversParentTypes['DashboardCase']> = ResolversObject<{
|
||||
base64?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
error?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
icon?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
url?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardConfigResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardConfig'] = ResolversParentTypes['DashboardConfig']> = ResolversObject<{
|
||||
error?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
valid?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardDisplayResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardDisplay'] = ResolversParentTypes['DashboardDisplay']> = ResolversObject<{
|
||||
case?: Resolver<Maybe<ResolversTypes['DashboardCase']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardOsResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardOs'] = ResolversParentTypes['DashboardOs']> = ResolversObject<{
|
||||
hostname?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
uptime?: Resolver<Maybe<ResolversTypes['DateTime']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardServiceResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardService'] = ResolversParentTypes['DashboardService']> = ResolversObject<{
|
||||
name?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
online?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>;
|
||||
uptime?: Resolver<Maybe<ResolversTypes['DashboardServiceUptime']>, ParentType, ContextType>;
|
||||
version?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardServiceUptimeResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardServiceUptime'] = ResolversParentTypes['DashboardServiceUptime']> = ResolversObject<{
|
||||
timestamp?: Resolver<Maybe<ResolversTypes['DateTime']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardTwoFactorResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardTwoFactor'] = ResolversParentTypes['DashboardTwoFactor']> = ResolversObject<{
|
||||
local?: Resolver<Maybe<ResolversTypes['DashboardTwoFactorLocal']>, ParentType, ContextType>;
|
||||
remote?: Resolver<Maybe<ResolversTypes['DashboardTwoFactorRemote']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardTwoFactorLocalResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardTwoFactorLocal'] = ResolversParentTypes['DashboardTwoFactorLocal']> = ResolversObject<{
|
||||
enabled?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardTwoFactorRemoteResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardTwoFactorRemote'] = ResolversParentTypes['DashboardTwoFactorRemote']> = ResolversObject<{
|
||||
enabled?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardVarsResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardVars'] = ResolversParentTypes['DashboardVars']> = ResolversObject<{
|
||||
flashGuid?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
regState?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
regTy?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
serverDescription?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
serverName?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardVersionsResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardVersions'] = ResolversParentTypes['DashboardVersions']> = ResolversObject<{
|
||||
unraid?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export type DashboardVmsResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DashboardVms'] = ResolversParentTypes['DashboardVms']> = ResolversObject<{
|
||||
installed?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
|
||||
started?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export interface DateTimeScalarConfig extends GraphQLScalarTypeConfig<ResolversTypes['DateTime'], any> {
|
||||
name: 'DateTime';
|
||||
}
|
||||
@@ -2154,7 +2475,6 @@ export type MutationResolvers<ContextType = Context, ParentType extends Resolver
|
||||
reboot?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
removeDiskFromArray?: Resolver<Maybe<ResolversTypes['Array']>, ParentType, ContextType, Partial<MutationremoveDiskFromArrayArgs>>;
|
||||
resumeParityCheck?: Resolver<Maybe<ResolversTypes['JSON']>, ParentType, ContextType>;
|
||||
sendNotification?: Resolver<Maybe<ResolversTypes['Notification']>, ParentType, ContextType, RequireFields<MutationsendNotificationArgs, 'notification'>>;
|
||||
setAdditionalAllowedOrigins?: Resolver<Array<ResolversTypes['String']>, ParentType, ContextType, RequireFields<MutationsetAdditionalAllowedOriginsArgs, 'input'>>;
|
||||
setupRemoteAccess?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType, RequireFields<MutationsetupRemoteAccessArgs, 'input'>>;
|
||||
shutdown?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
@@ -2163,9 +2483,11 @@ export type MutationResolvers<ContextType = Context, ParentType extends Resolver
|
||||
stopArray?: Resolver<Maybe<ResolversTypes['Array']>, ParentType, ContextType>;
|
||||
unmountArrayDisk?: Resolver<Maybe<ResolversTypes['Disk']>, ParentType, ContextType, RequireFields<MutationunmountArrayDiskArgs, 'id'>>;
|
||||
updateApikey?: Resolver<Maybe<ResolversTypes['ApiKey']>, ParentType, ContextType, RequireFields<MutationupdateApikeyArgs, 'name'>>;
|
||||
updateNetwork?: Resolver<ResolversTypes['Network'], ParentType, ContextType, RequireFields<MutationupdateNetworkArgs, 'data'>>;
|
||||
}>;
|
||||
|
||||
export type NetworkResolvers<ContextType = Context, ParentType extends ResolversParentTypes['Network'] = ResolversParentTypes['Network']> = ResolversObject<{
|
||||
accessUrls?: Resolver<Maybe<Array<ResolversTypes['AccessUrl']>>, ParentType, ContextType>;
|
||||
carrierChanges?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
duplex?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
iface?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
@@ -2334,6 +2656,7 @@ export type QueryResolvers<ContextType = Context, ParentType extends ResolversPa
|
||||
registration?: Resolver<Maybe<ResolversTypes['Registration']>, ParentType, ContextType>;
|
||||
remoteAccess?: Resolver<ResolversTypes['RemoteAccess'], ParentType, ContextType>;
|
||||
server?: Resolver<Maybe<ResolversTypes['Server']>, ParentType, ContextType>;
|
||||
serverDashboard?: Resolver<ResolversTypes['Dashboard'], ParentType, ContextType>;
|
||||
servers?: Resolver<Array<ResolversTypes['Server']>, ParentType, ContextType>;
|
||||
shares?: Resolver<Maybe<Array<Maybe<ResolversTypes['Share']>>>, ParentType, ContextType>;
|
||||
unassignedDevices?: Resolver<Maybe<Array<Maybe<ResolversTypes['UnassignedDevice']>>>, ParentType, ContextType>;
|
||||
@@ -2446,6 +2769,10 @@ export type SystemResolvers<ContextType = Context, ParentType extends ResolversP
|
||||
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
|
||||
}>;
|
||||
|
||||
export interface URLScalarConfig extends GraphQLScalarTypeConfig<ResolversTypes['URL'], any> {
|
||||
name: 'URL';
|
||||
}
|
||||
|
||||
export interface UUIDScalarConfig extends GraphQLScalarTypeConfig<ResolversTypes['UUID'], any> {
|
||||
name: 'UUID';
|
||||
}
|
||||
@@ -2728,10 +3055,12 @@ export type WelcomeResolvers<ContextType = Context, ParentType extends Resolvers
|
||||
}>;
|
||||
|
||||
export type Resolvers<ContextType = Context> = ResolversObject<{
|
||||
AccessUrl?: AccessUrlResolvers<ContextType>;
|
||||
ApiKey?: ApiKeyResolvers<ContextType>;
|
||||
ApiKeyResponse?: ApiKeyResponseResolvers<ContextType>;
|
||||
Array?: ArrayResolvers<ContextType>;
|
||||
ArrayCapacity?: ArrayCapacityResolvers<ContextType>;
|
||||
ArrayCapacityBytes?: ArrayCapacityBytesResolvers<ContextType>;
|
||||
ArrayDisk?: ArrayDiskResolvers<ContextType>;
|
||||
Baseboard?: BaseboardResolvers<ContextType>;
|
||||
Capacity?: CapacityResolvers<ContextType>;
|
||||
@@ -2742,6 +3071,21 @@ export type Resolvers<ContextType = Context> = ResolversObject<{
|
||||
ContainerHostConfig?: ContainerHostConfigResolvers<ContextType>;
|
||||
ContainerMount?: ContainerMountResolvers<ContextType>;
|
||||
ContainerPort?: ContainerPortResolvers<ContextType>;
|
||||
Dashboard?: DashboardResolvers<ContextType>;
|
||||
DashboardApps?: DashboardAppsResolvers<ContextType>;
|
||||
DashboardArray?: DashboardArrayResolvers<ContextType>;
|
||||
DashboardCase?: DashboardCaseResolvers<ContextType>;
|
||||
DashboardConfig?: DashboardConfigResolvers<ContextType>;
|
||||
DashboardDisplay?: DashboardDisplayResolvers<ContextType>;
|
||||
DashboardOs?: DashboardOsResolvers<ContextType>;
|
||||
DashboardService?: DashboardServiceResolvers<ContextType>;
|
||||
DashboardServiceUptime?: DashboardServiceUptimeResolvers<ContextType>;
|
||||
DashboardTwoFactor?: DashboardTwoFactorResolvers<ContextType>;
|
||||
DashboardTwoFactorLocal?: DashboardTwoFactorLocalResolvers<ContextType>;
|
||||
DashboardTwoFactorRemote?: DashboardTwoFactorRemoteResolvers<ContextType>;
|
||||
DashboardVars?: DashboardVarsResolvers<ContextType>;
|
||||
DashboardVersions?: DashboardVersionsResolvers<ContextType>;
|
||||
DashboardVms?: DashboardVmsResolvers<ContextType>;
|
||||
DateTime?: GraphQLScalarType;
|
||||
Devices?: DevicesResolvers<ContextType>;
|
||||
Disk?: DiskResolvers<ContextType>;
|
||||
@@ -2781,6 +3125,7 @@ export type Resolvers<ContextType = Context> = ResolversObject<{
|
||||
Share?: ShareResolvers<ContextType>;
|
||||
Subscription?: SubscriptionResolvers<ContextType>;
|
||||
System?: SystemResolvers<ContextType>;
|
||||
URL?: GraphQLScalarType;
|
||||
UUID?: GraphQLScalarType;
|
||||
UnassignedDevice?: UnassignedDeviceResolvers<ContextType>;
|
||||
Uptime?: UptimeResolvers<ContextType>;
|
||||
|
||||
62
api/src/graphql/generated/client/gql.ts
Normal file
62
api/src/graphql/generated/client/gql.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
/* eslint-disable */
|
||||
import * as types from './graphql.js';
|
||||
import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
|
||||
|
||||
/**
|
||||
* Map of all GraphQL operations in the project.
|
||||
*
|
||||
* This map has several performance disadvantages:
|
||||
* 1. It is not tree-shakeable, so it will include all operations in the project.
|
||||
* 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle.
|
||||
* 3. It does not support dead code elimination, so it will add unused operations.
|
||||
*
|
||||
* Therefore it is highly recommended to use the babel or swc plugin for production.
|
||||
*/
|
||||
const documents = {
|
||||
"\nmutation sendRemoteAccessMutation($remoteAccess: RemoteAccessInput!) {\n\tremoteSession(remoteAccess: $remoteAccess)\n}\n": types.sendRemoteAccessMutationDocument,
|
||||
"\n mutation sendRemoteGraphQLResponse($input: RemoteGraphQLServerInput!) {\n remoteGraphQLResponse(input: $input)\n }\n": types.sendRemoteGraphQLResponseDocument,
|
||||
"\n fragment RemoteGraphQLEventFragment on RemoteGraphQLEvent {\n remoteGraphQLEventData: data {\n type\n body\n sha256\n }\n }\n": types.RemoteGraphQLEventFragmentFragmentDoc,
|
||||
"\n fragment RemoteAccessEventFragment on RemoteAccessEvent {\n type\n data {\n type\n url {\n type\n name\n ipv4\n ipv6\n }\n apiKey\n }\n }\n": types.RemoteAccessEventFragmentFragmentDoc,
|
||||
"\n subscription events {\n events {\n __typename\n ... on ClientConnectedEvent {\n connectedData: data {\n type\n version\n apiKey\n }\n connectedEvent: type\n }\n ... on ClientDisconnectedEvent {\n disconnectedData: data {\n type\n version\n apiKey\n }\n disconnectedEvent: type\n }\n ...RemoteAccessEventFragment\n ...RemoteGraphQLEventFragment\n }\n }\n": types.eventsDocument,
|
||||
};
|
||||
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const query = graphql(`query GetUser($id: ID!) { user(id: $id) { name } }`);
|
||||
* ```
|
||||
*
|
||||
* The query argument is unknown!
|
||||
* Please regenerate the types.
|
||||
*/
|
||||
export function graphql(source: string): unknown;
|
||||
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\nmutation sendRemoteAccessMutation($remoteAccess: RemoteAccessInput!) {\n\tremoteSession(remoteAccess: $remoteAccess)\n}\n"): (typeof documents)["\nmutation sendRemoteAccessMutation($remoteAccess: RemoteAccessInput!) {\n\tremoteSession(remoteAccess: $remoteAccess)\n}\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n mutation sendRemoteGraphQLResponse($input: RemoteGraphQLServerInput!) {\n remoteGraphQLResponse(input: $input)\n }\n"): (typeof documents)["\n mutation sendRemoteGraphQLResponse($input: RemoteGraphQLServerInput!) {\n remoteGraphQLResponse(input: $input)\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment RemoteGraphQLEventFragment on RemoteGraphQLEvent {\n remoteGraphQLEventData: data {\n type\n body\n sha256\n }\n }\n"): (typeof documents)["\n fragment RemoteGraphQLEventFragment on RemoteGraphQLEvent {\n remoteGraphQLEventData: data {\n type\n body\n sha256\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment RemoteAccessEventFragment on RemoteAccessEvent {\n type\n data {\n type\n url {\n type\n name\n ipv4\n ipv6\n }\n apiKey\n }\n }\n"): (typeof documents)["\n fragment RemoteAccessEventFragment on RemoteAccessEvent {\n type\n data {\n type\n url {\n type\n name\n ipv4\n ipv6\n }\n apiKey\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n subscription events {\n events {\n __typename\n ... on ClientConnectedEvent {\n connectedData: data {\n type\n version\n apiKey\n }\n connectedEvent: type\n }\n ... on ClientDisconnectedEvent {\n disconnectedData: data {\n type\n version\n apiKey\n }\n disconnectedEvent: type\n }\n ...RemoteAccessEventFragment\n ...RemoteGraphQLEventFragment\n }\n }\n"): (typeof documents)["\n subscription events {\n events {\n __typename\n ... on ClientConnectedEvent {\n connectedData: data {\n type\n version\n apiKey\n }\n connectedEvent: type\n }\n ... on ClientDisconnectedEvent {\n disconnectedData: data {\n type\n version\n apiKey\n }\n disconnectedEvent: type\n }\n ...RemoteAccessEventFragment\n ...RemoteGraphQLEventFragment\n }\n }\n"];
|
||||
|
||||
export function graphql(source: string) {
|
||||
return (documents as any)[source] ?? {};
|
||||
}
|
||||
|
||||
export type DocumentType<TDocumentNode extends DocumentNode<any, any>> = TDocumentNode extends DocumentNode< infer TType, any> ? TType : never;
|
||||
@@ -709,30 +709,6 @@ export type Vars = {
|
||||
regTy?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
export type updateDashboardMutationVariables = Exact<{
|
||||
data: DashboardInput;
|
||||
apiKey: Scalars['String']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type updateDashboardMutation = { __typename?: 'Mutation', updateDashboard: { __typename?: 'Dashboard', apps?: { __typename?: 'DashboardApps', installed?: number | null } | null } };
|
||||
|
||||
export type sendNotificationMutationVariables = Exact<{
|
||||
notification: NotificationInput;
|
||||
apiKey: Scalars['String']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type sendNotificationMutation = { __typename?: 'Mutation', sendNotification?: { __typename?: 'Notification', title?: string | null, subject?: string | null, description?: string | null, importance?: Importance | null, link?: string | null, status: NotificationStatus } | null };
|
||||
|
||||
export type updateNetworkMutationVariables = Exact<{
|
||||
data: NetworkInput;
|
||||
apiKey: Scalars['String']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type updateNetworkMutation = { __typename?: 'Mutation', updateNetwork: { __typename?: 'Network', accessUrls?: Array<{ __typename?: 'AccessUrl', name?: string | null, type: URL_TYPE, ipv4?: URL | null, ipv6?: URL | null }> | null } };
|
||||
|
||||
export type sendRemoteAccessMutationMutationVariables = Exact<{
|
||||
remoteAccess: RemoteAccessInput;
|
||||
}>;
|
||||
@@ -764,9 +740,6 @@ export type eventsSubscription = { __typename?: 'Subscription', events?: Array<{
|
||||
|
||||
export const RemoteGraphQLEventFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteGraphQLEventFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteGraphQLEvent"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"remoteGraphQLEventData"},"name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"body"}},{"kind":"Field","name":{"kind":"Name","value":"sha256"}}]}}]}}]} as unknown as DocumentNode<RemoteGraphQLEventFragmentFragment, unknown>;
|
||||
export const RemoteAccessEventFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteAccessEventFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteAccessEvent"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"url"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"ipv4"}},{"kind":"Field","name":{"kind":"Name","value":"ipv6"}}]}},{"kind":"Field","name":{"kind":"Name","value":"apiKey"}}]}}]}}]} as unknown as DocumentNode<RemoteAccessEventFragmentFragment, unknown>;
|
||||
export const updateDashboardDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"updateDashboard"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DashboardInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"apiKey"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateDashboard"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"directives":[{"kind":"Directive","name":{"kind":"Name","value":"auth"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"apiKey"},"value":{"kind":"Variable","name":{"kind":"Name","value":"apiKey"}}}]}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"apps"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"installed"}}]}}]}}]}}]} as unknown as DocumentNode<updateDashboardMutation, updateDashboardMutationVariables>;
|
||||
export const sendNotificationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"sendNotification"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"notification"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"NotificationInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"apiKey"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"sendNotification"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"notification"},"value":{"kind":"Variable","name":{"kind":"Name","value":"notification"}}}],"directives":[{"kind":"Directive","name":{"kind":"Name","value":"auth"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"apiKey"},"value":{"kind":"Variable","name":{"kind":"Name","value":"apiKey"}}}]}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"subject"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"importance"}},{"kind":"Field","name":{"kind":"Name","value":"link"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]}}]} as unknown as DocumentNode<sendNotificationMutation, sendNotificationMutationVariables>;
|
||||
export const updateNetworkDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"updateNetwork"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"NetworkInput"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"apiKey"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateNetwork"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"directives":[{"kind":"Directive","name":{"kind":"Name","value":"auth"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"apiKey"},"value":{"kind":"Variable","name":{"kind":"Name","value":"apiKey"}}}]}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"accessUrls"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"ipv4"}},{"kind":"Field","name":{"kind":"Name","value":"ipv6"}}]}}]}}]}}]} as unknown as DocumentNode<updateNetworkMutation, updateNetworkMutationVariables>;
|
||||
export const sendRemoteAccessMutationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"sendRemoteAccessMutation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"remoteAccess"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteAccessInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"remoteSession"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"remoteAccess"},"value":{"kind":"Variable","name":{"kind":"Name","value":"remoteAccess"}}}]}]}}]} as unknown as DocumentNode<sendRemoteAccessMutationMutation, sendRemoteAccessMutationMutationVariables>;
|
||||
export const sendRemoteGraphQLResponseDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"sendRemoteGraphQLResponse"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteGraphQLServerInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"remoteGraphQLResponse"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode<sendRemoteGraphQLResponseMutation, sendRemoteGraphQLResponseMutationVariables>;
|
||||
export const eventsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"events"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"events"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ClientConnectedEvent"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"connectedData"},"name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"apiKey"}}]}},{"kind":"Field","alias":{"kind":"Name","value":"connectedEvent"},"name":{"kind":"Name","value":"type"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ClientDisconnectedEvent"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"disconnectedData"},"name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"apiKey"}}]}},{"kind":"Field","alias":{"kind":"Name","value":"disconnectedEvent"},"name":{"kind":"Name","value":"type"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"RemoteAccessEventFragment"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"RemoteGraphQLEventFragment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteAccessEventFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteAccessEvent"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"url"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"ipv4"}},{"kind":"Field","name":{"kind":"Name","value":"ipv6"}}]}},{"kind":"Field","name":{"kind":"Name","value":"apiKey"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"RemoteGraphQLEventFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"RemoteGraphQLEvent"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"remoteGraphQLEventData"},"name":{"kind":"Name","value":"data"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"body"}},{"kind":"Field","name":{"kind":"Name","value":"sha256"}}]}}]}}]} as unknown as DocumentNode<eventsSubscription, eventsSubscriptionVariables>;
|
||||
14
api/src/graphql/mothership/mutations.ts
Normal file
14
api/src/graphql/mothership/mutations.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { graphql } from '@app/graphql/generated/client/gql';
|
||||
|
||||
// This doesn't need auth directive, new mothership can handle clients with no auth directives
|
||||
export const SEND_DYNAMIC_REMOTE_ACCESS_MUTATION = graphql(/* GraphQL */ `
|
||||
mutation sendRemoteAccessMutation($remoteAccess: RemoteAccessInput!) {
|
||||
remoteSession(remoteAccess: $remoteAccess)
|
||||
}
|
||||
`);
|
||||
|
||||
export const SEND_REMOTE_QUERY_RESPONSE = graphql(/* GraphQL */ `
|
||||
mutation sendRemoteGraphQLResponse($input: RemoteGraphQLServerInput!) {
|
||||
remoteGraphQLResponse(input: $input)
|
||||
}
|
||||
`);
|
||||
@@ -1,91 +0,0 @@
|
||||
import { dashboardLogger } from '@app/core/log';
|
||||
import { generateData } from '@app/common/dashboard/generate-data';
|
||||
import { PUBSUB_CHANNEL, pubsub } from '@app/core/pubsub';
|
||||
import { getters, store } from '@app/store';
|
||||
import { saveDataPacket } from '@app/store/modules/dashboard';
|
||||
import { isEqual } from 'lodash';
|
||||
import { GraphQLClient } from '@app/mothership/graphql-client';
|
||||
import { SEND_DASHBOARD_PAYLOAD_MUTATION } from '../../mothership/mutations';
|
||||
import { type DashboardInput } from '../../generated/client/graphql';
|
||||
import { getDiff } from 'json-difference';
|
||||
import { DEBUG } from '@app/environment';
|
||||
import { isApolloError } from '@apollo/client/core';
|
||||
|
||||
const isNumberBetween = (min: number, max: number) => (num: number) => num > min && num < max;
|
||||
|
||||
const logAndReturn = <T>(returnValue: T, logLevel: 'info' | 'debug' | 'trace' | 'error', logLine: string, ...logParams: unknown[]): T => {
|
||||
dashboardLogger[logLevel](logLine, ...logParams);
|
||||
return returnValue;
|
||||
};
|
||||
|
||||
const ONE_MB = 1_024 * 1_024;
|
||||
const ONE_HUNDRED_MB = 100 * ONE_MB;
|
||||
|
||||
const canSendDataPacket = (dataPacket: DashboardInput | null) => {
|
||||
const { lastDataPacketTimestamp, lastDataPacket } = getters.dashboard();
|
||||
// Const { lastDataPacketTimestamp, lastDataPacketString, lastDataPacket } = dashboardStore;
|
||||
if (!dataPacket) return logAndReturn(false, 'error', 'Not sending update to dashboard becuase the data packet is empty');
|
||||
|
||||
// UPDATE - No data packet has been sent since boot
|
||||
if (!lastDataPacketTimestamp) return logAndReturn(true, 'debug', 'Sending update as none have been sent since the API started');
|
||||
|
||||
// NO_UPDATE - This is an exact copy of the last data packet
|
||||
if (isEqual(dataPacket, lastDataPacket)) return logAndReturn(false, 'trace', '[NETWORK] Skipping Update');
|
||||
|
||||
if (!lastDataPacket) return logAndReturn(true, 'debug', 'Sending update as no data packets have been stored in state yet');
|
||||
|
||||
const difference = getDiff(lastDataPacket, dataPacket);
|
||||
|
||||
const oldBytesFree = lastDataPacket.array?.capacity.bytes?.free;
|
||||
const newBytesFree = dataPacket.array?.capacity.bytes?.free;
|
||||
|
||||
if (oldBytesFree && newBytesFree && difference.added.length === 0 && difference.removed.length === 0 && difference.edited.length === 2) {
|
||||
// If size has changed less than 100 MB (and nothing else has changed), don't send an update
|
||||
|
||||
const numberBetweenCheck = isNumberBetween((Number(oldBytesFree) * ONE_MB) - ONE_HUNDRED_MB, (Number(oldBytesFree) * ONE_MB) + ONE_HUNDRED_MB);
|
||||
if (numberBetweenCheck(Number(newBytesFree) * ONE_MB)) {
|
||||
logAndReturn(false, 'info', 'Size has not changed enough to send a new dashboard payload');
|
||||
}
|
||||
}
|
||||
|
||||
return logAndReturn(true, 'trace', 'Sending update because the packets are not equal');
|
||||
};
|
||||
|
||||
export const publishToDashboard = async () => {
|
||||
try {
|
||||
const dataPacket = await generateData();
|
||||
// Only update data on change
|
||||
if (!canSendDataPacket(dataPacket)) return;
|
||||
|
||||
dashboardLogger.debug('New Data Packet Is: %o', dataPacket);
|
||||
|
||||
// Save new data packet
|
||||
store.dispatch(saveDataPacket({ lastDataPacket: dataPacket }));
|
||||
|
||||
// Publish the updated data
|
||||
dashboardLogger.trace({ dataPacket } , 'Publishing update');
|
||||
|
||||
// Update local clients
|
||||
await pubsub.publish(PUBSUB_CHANNEL.DASHBOARD, {
|
||||
dashboard: dataPacket,
|
||||
});
|
||||
if (dataPacket) {
|
||||
const client = GraphQLClient.getInstance();
|
||||
if (!client) {
|
||||
throw new Error('Invalid Client');
|
||||
}
|
||||
|
||||
// Update mothership
|
||||
await client.mutate({ mutation: SEND_DASHBOARD_PAYLOAD_MUTATION, variables: { apiKey: getters.config().remote.apikey, data: dataPacket } });
|
||||
} else {
|
||||
dashboardLogger.error('DataPacket Was Empty');
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error && isApolloError(error)) {
|
||||
dashboardLogger.error('Failed publishing with GQL Errors: %s, \nClient Errors: %s', error.graphQLErrors.map(error => error.message).join(','), error.clientErrors.join(', '));
|
||||
}
|
||||
|
||||
if (DEBUG) dashboardLogger.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
import { GraphQLClient } from '@app/mothership/graphql-client';
|
||||
import { type Nginx } from '@app/core/types/states/nginx';
|
||||
import { type RootState, store, getters } from '@app/store';
|
||||
import { type RootState, store } from '@app/store';
|
||||
import {
|
||||
type NetworkInput,
|
||||
URL_TYPE,
|
||||
type AccessUrlInput,
|
||||
} from '@app/graphql/generated/client/graphql';
|
||||
import { dashboardLogger, logger } from '@app/core';
|
||||
import { isEqual } from 'lodash';
|
||||
import { SEND_NETWORK_MUTATION } from '@app/graphql/mothership/mutations';
|
||||
import { saveNetworkPacket } from '@app/store/modules/dashboard';
|
||||
import { ApolloError } from '@apollo/client/core/core.cjs';
|
||||
import { logger } from '@app/core';
|
||||
import {
|
||||
AccessUrlInputSchema,
|
||||
NetworkInputSchema,
|
||||
} from '@app/graphql/generated/client/validators';
|
||||
import { ZodError } from 'zod';
|
||||
|
||||
interface UrlForFieldInput {
|
||||
url: string;
|
||||
@@ -271,66 +263,3 @@ export const getServerIps = (
|
||||
|
||||
return { urls: safeUrls, errors };
|
||||
};
|
||||
|
||||
export const publishNetwork = async () => {
|
||||
try {
|
||||
const client = GraphQLClient.getInstance();
|
||||
|
||||
const datapacket = getServerIps();
|
||||
if (datapacket.errors) {
|
||||
const zodErrors = datapacket.errors.filter(
|
||||
(error) => error instanceof ZodError
|
||||
);
|
||||
if (zodErrors.length) {
|
||||
dashboardLogger.warn(
|
||||
'Validation Errors Encountered with Network Payload: %s',
|
||||
zodErrors.map((error) => error.message).join(',')
|
||||
);
|
||||
}
|
||||
}
|
||||
const networkPacket: NetworkInput = { accessUrls: datapacket.urls };
|
||||
const validatedNetwork = NetworkInputSchema().parse(networkPacket);
|
||||
|
||||
const { lastNetworkPacket } = getters.dashboard();
|
||||
const { apikey: apiKey } = getters.config().remote;
|
||||
if (
|
||||
isEqual(
|
||||
JSON.stringify(lastNetworkPacket),
|
||||
JSON.stringify(validatedNetwork)
|
||||
)
|
||||
) {
|
||||
dashboardLogger.trace('[DASHBOARD] Skipping Update');
|
||||
} else if (client) {
|
||||
dashboardLogger.info(
|
||||
{ validatedNetwork },
|
||||
'Sending data packet for network'
|
||||
);
|
||||
const result = await client.mutate({
|
||||
mutation: SEND_NETWORK_MUTATION,
|
||||
variables: {
|
||||
apiKey,
|
||||
data: validatedNetwork,
|
||||
},
|
||||
});
|
||||
dashboardLogger.debug(
|
||||
{ result },
|
||||
'Sent network mutation with %s urls',
|
||||
datapacket.urls.length
|
||||
);
|
||||
store.dispatch(
|
||||
saveNetworkPacket({ lastNetworkPacket: validatedNetwork })
|
||||
);
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
dashboardLogger.trace('ERROR', error);
|
||||
if (error instanceof ApolloError) {
|
||||
dashboardLogger.error(
|
||||
'Failed publishing with GQL Errors: %s, \nClient Errors: %s',
|
||||
(error as ApolloError).graphQLErrors.map((error) => error.message).join(','),
|
||||
(error as ApolloError).clientErrors.join(', ')
|
||||
);
|
||||
} else {
|
||||
dashboardLogger.error(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ scalar Long
|
||||
scalar UUID
|
||||
scalar DateTime
|
||||
scalar Port
|
||||
scalar URL
|
||||
|
||||
type Welcome {
|
||||
message: String!
|
||||
@@ -16,7 +17,6 @@ type Query {
|
||||
|
||||
type Mutation {
|
||||
login(username: String!, password: String!): String
|
||||
sendNotification(notification: NotificationInput!): Notification
|
||||
shutdown: String
|
||||
reboot: String
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ input SetupRemoteAccessInput {
|
||||
type Query {
|
||||
remoteAccess: RemoteAccess!
|
||||
extraAllowedOrigins: [String!]!
|
||||
""" Temporary Type to Enable Swapping Dashboard over in Connect without major changes """
|
||||
serverDashboard: Dashboard!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
|
||||
93
api/src/graphql/schema/types/dashboard/dashboard.graphql
Normal file
93
api/src/graphql/schema/types/dashboard/dashboard.graphql
Normal file
@@ -0,0 +1,93 @@
|
||||
type DashboardApps {
|
||||
installed: Int
|
||||
started: Int
|
||||
}
|
||||
|
||||
type DashboardVersions {
|
||||
unraid: String
|
||||
}
|
||||
|
||||
type DashboardOs {
|
||||
hostname: String
|
||||
uptime: DateTime
|
||||
}
|
||||
|
||||
type DashboardVms {
|
||||
installed: Int
|
||||
started: Int
|
||||
}
|
||||
|
||||
type ArrayCapacityBytes {
|
||||
free: Long
|
||||
used: Long
|
||||
total: Long
|
||||
}
|
||||
|
||||
type ArrayCapacity {
|
||||
bytes: ArrayCapacityBytes
|
||||
}
|
||||
|
||||
type DashboardArray {
|
||||
"""
|
||||
Current array state
|
||||
"""
|
||||
state: String
|
||||
"""
|
||||
Current array capacity
|
||||
"""
|
||||
capacity: ArrayCapacity
|
||||
}
|
||||
|
||||
type DashboardCase {
|
||||
icon: String
|
||||
url: String
|
||||
error: String
|
||||
base64: String
|
||||
}
|
||||
|
||||
type DashboardDisplay {
|
||||
case: DashboardCase
|
||||
}
|
||||
|
||||
type DashboardConfig {
|
||||
valid: Boolean
|
||||
error: String
|
||||
}
|
||||
|
||||
type DashboardVars {
|
||||
regState: String
|
||||
regTy: String
|
||||
flashGuid: String
|
||||
serverName: String
|
||||
serverDescription: String
|
||||
}
|
||||
|
||||
type DashboardTwoFactorRemote {
|
||||
enabled: Boolean
|
||||
}
|
||||
|
||||
type DashboardTwoFactorLocal {
|
||||
enabled: Boolean
|
||||
}
|
||||
|
||||
type DashboardTwoFactor {
|
||||
remote: DashboardTwoFactorRemote
|
||||
local: DashboardTwoFactorLocal
|
||||
}
|
||||
|
||||
type Dashboard {
|
||||
id: ID!
|
||||
lastPublish: DateTime
|
||||
online: Boolean
|
||||
apps: DashboardApps
|
||||
versions: DashboardVersions
|
||||
os: DashboardOs
|
||||
vms: DashboardVms
|
||||
array: DashboardArray
|
||||
services: [DashboardService]
|
||||
display: DashboardDisplay
|
||||
config: DashboardConfig
|
||||
vars: DashboardVars
|
||||
twoFactor: DashboardTwoFactor
|
||||
network: Network
|
||||
}
|
||||
33
api/src/graphql/schema/types/dashboard/network.graphql
Normal file
33
api/src/graphql/schema/types/dashboard/network.graphql
Normal file
@@ -0,0 +1,33 @@
|
||||
enum URL_TYPE {
|
||||
LAN
|
||||
WIREGUARD
|
||||
WAN
|
||||
MDNS
|
||||
DEFAULT
|
||||
}
|
||||
|
||||
type AccessUrl {
|
||||
type: URL_TYPE!
|
||||
name: String
|
||||
ipv4: URL
|
||||
ipv6: URL
|
||||
}
|
||||
|
||||
type Network {
|
||||
accessUrls: [AccessUrl!]
|
||||
}
|
||||
|
||||
input AccessUrlInput {
|
||||
type: URL_TYPE!
|
||||
name: String
|
||||
ipv4: URL
|
||||
ipv6: URL
|
||||
}
|
||||
|
||||
input NetworkInput {
|
||||
accessUrls: [AccessUrlInput!]!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
updateNetwork(data: NetworkInput!): Network!
|
||||
}
|
||||
22
api/src/graphql/schema/types/dashboard/service.graphql
Normal file
22
api/src/graphql/schema/types/dashboard/service.graphql
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
type DashboardServiceUptime {
|
||||
timestamp: DateTime
|
||||
}
|
||||
|
||||
type DashboardService {
|
||||
name: String
|
||||
online: Boolean
|
||||
uptime: DashboardServiceUptime
|
||||
version: String
|
||||
}
|
||||
|
||||
input DashboardServiceUptimeInput {
|
||||
timestamp: DateTime!
|
||||
}
|
||||
|
||||
input DashboardServiceInput {
|
||||
name: String!
|
||||
online: Boolean!
|
||||
uptime: DashboardServiceUptimeInput
|
||||
version: String!
|
||||
}
|
||||
@@ -22,10 +22,6 @@ input NotificationFilter {
|
||||
limit: Int!
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
sendNotification(notification: NotificationInput!): Notification
|
||||
}
|
||||
|
||||
type Query {
|
||||
notifications(filter: NotificationFilter!): [Notification!]!
|
||||
}
|
||||
|
||||
@@ -2,10 +2,6 @@
|
||||
import { minigraphLogger, mothershipLogger } from '@app/core/log';
|
||||
import { GraphQLClient } from './graphql-client';
|
||||
import { store } from '@app/store';
|
||||
import {
|
||||
startDashboardProducer,
|
||||
stopDashboardProducer,
|
||||
} from '@app/store/modules/dashboard';
|
||||
|
||||
import {
|
||||
EVENTS_SUBSCRIPTION,
|
||||
@@ -57,15 +53,6 @@ export const subscribeToEvents = async (apiKey: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Dashboard Connected to Mothership
|
||||
|
||||
if (
|
||||
type === ClientType.DASHBOARD &&
|
||||
apiKey === eventApiKey
|
||||
) {
|
||||
store.dispatch(startDashboardProducer());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -80,15 +67,6 @@ export const subscribeToEvents = async (apiKey: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
// The dashboard was closed or went idle
|
||||
|
||||
if (
|
||||
type === ClientType.DASHBOARD &&
|
||||
apiKey === eventApiKey
|
||||
) {
|
||||
store.dispatch(stopDashboardProducer());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import { configReducer } from '@app/store/modules/config';
|
||||
import { emhttp } from '@app/store/modules/emhttp';
|
||||
import { registration } from '@app/store/modules/registration';
|
||||
import { cache } from '@app/store/modules/cache';
|
||||
import { dashboard } from '@app/store/modules/dashboard';
|
||||
import { docker } from '@app/store/modules/docker';
|
||||
import { upnp } from '@app/store/modules/upnp';
|
||||
import { listenerMiddleware } from '@app/store/listeners/listener-middleware';
|
||||
@@ -27,7 +26,6 @@ export const store = configureStore({
|
||||
remoteGraphQL: remoteGraphQLReducer,
|
||||
notifications: notificationReducer,
|
||||
cache: cache.reducer,
|
||||
dashboard: dashboard.reducer,
|
||||
docker: docker.reducer,
|
||||
upnp: upnp.reducer,
|
||||
dynamix: dynamix.reducer,
|
||||
@@ -45,7 +43,6 @@ export const getters = {
|
||||
apiKey: () => store.getState().apiKey,
|
||||
cache: () => store.getState().cache,
|
||||
config: () => store.getState().config,
|
||||
dashboard: () => store.getState().dashboard,
|
||||
docker: () => store.getState().docker,
|
||||
dynamix: () => store.getState().dynamix,
|
||||
emhttp: () => store.getState().emhttp,
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
DateTimeResolver,
|
||||
JSONResolver,
|
||||
PortResolver,
|
||||
URLResolver,
|
||||
UUIDResolver,
|
||||
} from 'graphql-scalars';
|
||||
import { GraphQLLong } from '@app/graphql/resolvers/graphql-type-long';
|
||||
@@ -42,6 +43,7 @@ import { print } from 'graphql';
|
||||
UUID: UUIDResolver,
|
||||
DateTime: DateTimeResolver,
|
||||
Port: PortResolver,
|
||||
URL: URLResolver
|
||||
},
|
||||
// schema: schema
|
||||
}),
|
||||
|
||||
@@ -130,4 +130,5 @@ export class CloudResolver {
|
||||
await store.dispatch(setupRemoteAccessThunk(input)).unwrap();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { DashboardResolver } from './dashboard.resolver';
|
||||
|
||||
describe('DashboardResolver', () => {
|
||||
let resolver: DashboardResolver;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [DashboardResolver],
|
||||
}).compile();
|
||||
|
||||
resolver = module.get<DashboardResolver>(DashboardResolver);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(resolver).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import { dashboardDataServer } from '@app/common/dashboard/generate-server-data';
|
||||
import { Dashboard } from '@app/graphql/generated/api/types';
|
||||
import { getServerIps } from '@app/graphql/resolvers/subscription/network';
|
||||
import { Query, ResolveField, Resolver } from '@nestjs/graphql';
|
||||
import { UseRoles } from 'nest-access-control';
|
||||
import { ZodError } from 'zod';
|
||||
|
||||
@Resolver('Dashboard')
|
||||
@UseRoles({
|
||||
resource: 'connect',
|
||||
action: 'read',
|
||||
possession: 'own',
|
||||
})
|
||||
export class DashboardResolver {
|
||||
@Query('serverDashboard')
|
||||
public async serverDashboard(): Promise<Dashboard> {
|
||||
console.log('Dashboard is', await dashboardDataServer());
|
||||
return await dashboardDataServer();
|
||||
}
|
||||
@ResolveField()
|
||||
public network(): Dashboard['network'] {
|
||||
const datapacket = getServerIps();
|
||||
if (datapacket.errors) {
|
||||
const zodErrors = datapacket.errors.filter(
|
||||
(error) => error instanceof ZodError
|
||||
);
|
||||
if (zodErrors.length) {
|
||||
console.warn(
|
||||
'Validation Errors Encountered with Network Payload: %s',
|
||||
zodErrors.map((error) => error.message).join(',')
|
||||
);
|
||||
}
|
||||
}
|
||||
const networkPacket: Dashboard['network'] = { accessUrls: datapacket.urls };
|
||||
|
||||
return networkPacket;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import { UseRoles } from 'nest-access-control';
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { type NotificationInput } from '@app/graphql/generated/client/graphql';
|
||||
import { GraphQLClient } from '@app/mothership/graphql-client';
|
||||
import { SEND_NOTIFICATION_MUTATION } from '@app/graphql/mothership/mutations';
|
||||
import { PUBSUB_CHANNEL, createSubscription } from '@app/core/pubsub';
|
||||
|
||||
@Resolver()
|
||||
@@ -44,49 +43,6 @@ export class NotificationsResolver {
|
||||
.slice(offset, limit + offset);
|
||||
}
|
||||
|
||||
@Mutation('sendNotification')
|
||||
@UseRoles({
|
||||
resource: 'notifications',
|
||||
action: 'create',
|
||||
possession: 'own',
|
||||
})
|
||||
public async sendNotification(
|
||||
@Args('notification') notification: NotificationInput
|
||||
) {
|
||||
this.logger.log('Sending notification', JSON.stringify(notification));
|
||||
const promise = new Promise((res, rej) => {
|
||||
setTimeout(async () => {
|
||||
rej(new GraphQLError('Sending Notification Timeout'));
|
||||
}, 5_000);
|
||||
const client = GraphQLClient.getInstance();
|
||||
// If there's no mothership connection then bail
|
||||
if (!client) {
|
||||
this.logger.error('Mothership is not working');
|
||||
throw new GraphQLError('Mothership is down');
|
||||
}
|
||||
client
|
||||
.query({
|
||||
query: SEND_NOTIFICATION_MUTATION,
|
||||
variables: {
|
||||
notification: notification,
|
||||
apiKey: getters.config().remote.apikey,
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
this.logger.debug(
|
||||
'Query Result from Notifications.ts',
|
||||
result
|
||||
);
|
||||
res(notification);
|
||||
})
|
||||
.catch((err) => {
|
||||
rej(err);
|
||||
});
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
@Subscription('notificationAdded')
|
||||
@UseRoles({
|
||||
resource: 'notifications',
|
||||
|
||||
@@ -14,12 +14,14 @@ import { OwnerResolver } from './owner/owner.resolver';
|
||||
import { RegistrationResolver } from './registration/registration.resolver';
|
||||
import { ServerResolver } from './servers/server.resolver';
|
||||
import { VarsResolver } from './vars/vars.resolver';
|
||||
import { DashboardResolver } from './dashboard/dashboard.resolver';
|
||||
|
||||
@Module({
|
||||
providers: [
|
||||
ArrayResolver,
|
||||
CloudResolver,
|
||||
ConfigResolver,
|
||||
DashboardResolver,
|
||||
DisksResolver,
|
||||
DockerContainersResolver,
|
||||
DisplayResolver,
|
||||
|
||||
Reference in New Issue
Block a user