diff --git a/codegen.ts b/codegen.ts index ec151d9..13c3a2a 100644 --- a/codegen.ts +++ b/codegen.ts @@ -2,16 +2,16 @@ import type {CodegenConfig} from '@graphql-codegen/cli'; const config: CodegenConfig = { overwrite: true, - schema: './schema.graphql', + schema: 'src/schema/*.graphql', generates: { - "src/generated/graphql.ts": { + "src/schema/generated/graphql.ts": { plugins: ["typescript", "typescript-resolvers"], config: { enumValues: { - DeviceCommunicationType: "../model/model_enum_values.js#DeviceCommunicationType", - StorageItemType: "../model/model_enum_values.js#StorageItemType", - DeviceStatus: "../model/model_enum_values.js#DeviceStatus", - Permission: "../model/model_enum_values.js#Permission", + DeviceCommunicationType: "../../model/model_enum_values.js#DeviceCommunicationType", + StorageItemType: "../../model/model_enum_values.js#StorageItemType", + DeviceStatus: "../../model/model_enum_values.js#DeviceStatus", + Permission: "../../model/model_enum_values.js#Permission", }, declarationKind: 'interface' } diff --git a/schema.graphql b/schema.graphql deleted file mode 100644 index b51c5a0..0000000 --- a/schema.graphql +++ /dev/null @@ -1,624 +0,0 @@ -# Scalars resolved by package "graphql-scalars" -scalar DateTime -scalar Time -scalar JSONObject - -# Schema definitions go here -type Query { - "Get api (build) version" - apiVersion: String! - "Get zabbix version" - zabbixVersion: String - """ - Login to zabbix - provided for debugging and testing purpose. The result of the login operation is - authentication token returned may be passed as - header 'zabbix-auth-token' for authenticating future API requests. - As an alternative to the cookie 'zbx_session' may be set which is automatically set after login to - the cockpit - this is the standard way to authenticate api calls initiated by the cockpit frontend - because the frontend is always embedded into the Zabbix portal which is only accessible after logging in and - obtainind the zbx_session - cookie. - """ - login(username: String!, password: String!): String - - """ - Logout from zabbix - provided for debugging and testing purpose. This invalidates the token received by the login - operation. Returns true on success - """ - logout: Boolean - - """ - Get all hosts + corresponding items. If with_items==true only hosts with attached items are delivered - name_pattern: If provided this will perform a LIKE "%…%" search on the name attribute within the database. - - Authentication: By zbx_session - cookie or zabbix-auth-token - header - """ - allHosts(name_pattern: String = "", filter_host: String = null, hostids: Int, - groupids:[Int!] = null, with_items: Boolean = false, tag_deviceType:[String]=[], tag_hostType:[String!]): [Host] - - """ - Get all host groups. - If with_hosts==true only groups with attached hosts are delivered. - - Authentication: By zbx_session - cookie or zabbix-auth-token - header - """ - allHostGroups(search_name: String, with_hosts: Boolean = true): [HostGroup] - - - """ - Get all locations used by hosts. - distinct_by_name=true means that the result is filtered for distinct names (default) - name_pattern: If provided this will perform a Regex search on the name attribute within the database. - - Authentication: By zbx_session - cookie or zabbix-auth-token - header - """ - locations(name_pattern: String = "", distinct_by_name: Boolean = true, templateids:[String] = null): [Location] - - """ - Export history from Zabbix items - - Authentication: By zbx_session - cookie or zabbix-auth-token - header - """ - exportHostValueHistory( - "(Optional) list of hostnames to be included in the result" - host_filter: [String!], - "(Optional) list of item keys to be included in the result" - itemKey_filter: [String!], - """ - (Optional) timestamp of earliest value""" - time_from: DateTime, - """(Optional) timestamp of last value """ - time_until: DateTime, - """Results are sorted by timestamps - ascending or descending order may be specified - using this parameter""" - sortOrder: SortOrder=desc, - """ - Maximum number of records to be delivered. Hint: This might be useful, because the - current version of Zabbix delivers a 500 - error in case of requesting too much data - """ - limit: Int - """ - As values are stored in different data structures depending on their type - the type information must be specified in advance, although - each value (also if number) is converted into a string afterwards - """ - type: StorageItemType = FLOAT - - ):HistoryExportResponse - - """ - Return all user permissions. If objectNames is provided return only the permissions related to the objects within - the objectNames - list - """ - userPermissions(objectNames: [String!]): [UserPermission!] - - """ - Return true if and only if the current user (identified by token / cookie) - has all requested permissions (minimum - if READ is requested and the user has READ_WRITE - the response will be true) - """ - hasPermissions(permissions: [PermissionRequest!]!): Boolean - - - """ - name_pattern: If provided this will perform a LIKE "%…%" search on the name attribute within the database. - exclude_groups_pattern: Regex allowing to exclude all matching hostgroups from group permissions - """ - exportUserRights(name_pattern: String = "" exclude_hostgroups_pattern: String = ""): UserRights -} - -type UserRights { - userGroups: [UserGroup!] - userRoles: [UserRole!] -} - -type UserRole { - roleid: Int! - name: String - type: Int - readonly: Int - rules: UserRoleRules -} - -type UserRoleRules { - ui: [UserRoleRule!] - ui_default_access: Int - modules:[UserRoleModule!] - modules_default_access: Int - api_access: Int - api_mode: Int - api: [String!] - actions: [UserRoleRule!] - actions_default_access: Int -} - -type UserRoleRule { - name: String - status: Int -} -type UserRoleModule { - moduleid: String - status: Int - id: String - relative_path: String -} - -type UserGroup { - usrgrpid: Int! - name: String! - gui_access: Int - users_status: Int - hostgroup_rights: [ZabbixGroupRight!] - templategroup_rights: [ZabbixGroupRight!] -} - -type ZabbixGroupRight { - id: Int! - uuid: String - name: String - permission: Permission -} - -######################################################## -# User permissions -######################################################## - -input PermissionRequest { - permission: Permission!, - """ - objectName maps to name / path suffix of the template group representing the permission in Zabbix: - Permissions/{objectName} - """ - objectName: String! -} - -""" -READ, READ_WRITE or DENY: -describes the rights related to an objectName -There is no EXECUTE or anything else in Zabbix, -i.e. objectName - Tree has to be designed accordingly in order to represent the perform actions. - -E.g. - -Let's assume a button called "button1", used in application "app1", having a label which shows "do something". Instead of model the action "do something" the idea is -to model the effect of this action - do something will result in a status change. Let's further assume that the button will only -be displayed if the user is allowed to see the current status. - -Permissions/app1/button1/status - -The following PermissionRequests would be used by the frontend: - -1. Should the button (and its status) be displayed at all? -button1.displayed = hasPermissions( -{ -objectName: "app1/button1/status" -permission: READ -}) -2. Should the user be able to press the button (enabled)? -button1.displayed = hasPermissions( -{ -objectName: "app1/button1/status" -permission: READ_WRITE -}) - - -Usage Example for this pattern: Activation/Deactivation of a control program - the button -shows the possible action. If the program is active it shows "Deactivate". If the program is inactive it shows "Activate". -From this label the user learns something about the current state - therefore the status - read - permission is needed in order -to display the button at all. The status write permission is needed in order to enable the button (i.e. allow the user to press it). -in order to model the permissions to press / see a button "button1" belonging to application "app1" -the following template group could be modelled in Zabbix -""" -enum Permission { - """ - DENY superseeds anything else - i.e. if in Zabbix there is a DENY and READ at the same time the result will be DENY - """ - DENY - """ - READ superseeds READ_WRITE - i.e. if in Zabbix there is a READ_WRITE and READ at the same time the resulting permission - level will be READ - """ - READ - """ - READ_WRITE implies the READ permission. Do not set both READ and READ_WRITE at the same time if you want to achieve - READ + WRITE permission, because in this case READ will superseed the READ_WRITE and the resulting permission level will be READ - """ - READ_WRITE -} - -type UserPermission { - permission: Permission!, - """ - objectName maps to name / path suffix of the template group representing the permission in Zabbix: - Permissions/{objectName} - """ - objectName: String! -} -######################################################## -# Values -######################################################## - -enum StorageItemType { - FLOAT - INT - TEXT -} - -type HistoryExportResponse { - result: [JSONObject!] - error: ApiError -} - -############################################################################ -type Mutation { - - """ - Authentication: By zbx_session - cookie or zabbix-auth-token - header - """ - createHost(host: String!, hostgroupids:[Int!]!, templateids: [Int!]!, - location: LocationInput): ZabbixCreateResponse - - """ - (Mass) Import zabbix groups - and assign them to the corresponding hosts by groupid or groupName. - - Return value: If no error occurs a groupid be returned for each created group, - otherwise the return object will contain an error message - - Authentication: By zbx_session - cookie or zabbix-auth-token - header - """ - importHostGroups(hostGroups: [CreateHostGroup!]!):[CreateHostGroupResponse!] - - - """ - (Mass) Import hosts and assign them to host groups by groupid or groupName. - - Return value: If no error occurs a hostid will be returned for each created host, - otherwise the return object will contain an error message. - - Authentication: By zbx_session - cookie or zabbix-auth-token - header - """ - importHosts(hosts: [CreateHost!]!):[CreateHostResponse!] - - importUserRights(input: UserRightsInput!, dryRun: Boolean! = true): ImportUserRightsResult -} - -input UserRightsInput { - userRoles: [UserRoleInput!] - userGroups: [UserGroupInput!] -} - -input UserRoleInput { - name: String - type: Int - readonly: Int - rules: UserRoleRulesInput -} - -input UserRoleRulesInput { - ui: [UserRoleRuleInput!] - ui_default_access: Int - modules:[UserRoleModuleInput!] - modules_default_access: Int - api_access: Int - api_mode: Int - api: [String!] - actions: [UserRoleRuleInput!] - actions_default_access: Int -} - -input UserRoleRuleInput { - name: String - status: Int -} -input UserRoleModuleInput { - moduleid: String - status: Int - id: String -} - - -input UserGroupInput { - name: String! - gui_access: Int - users_status: Int - hostgroup_rights: [ZabbixGroupRightInput!] - templategroup_rights: [ZabbixGroupRightInput!] -} - - -input ZabbixGroupRightInput { - uuid: String - """ - name may optionally be specified for documentation purpose, - but the master for setting the user right is the uuid. - If a uuid is found and the corresponding group - has a deviating name this will be documented within a message - with errorcode = 0 (OK) but the permission will be set ( - the reason is that names for groups may deviate between several - instances of the control center although the semantic is the same - - while the semantic is identified by uuid. - """ - name: String - permission: Permission -} - -type ImportUserRightsResult { - userRoles: [ImportUserRightResult!] - userGroups: [ImportUserRightResult!] -} -type ImportUserRightResult { - id: String - name: String - message: String - errors: [ApiError!] -} - - -""" -Hint: WGS84[dd.ddddd] coordinates are used -""" -interface GpsPosition { - latitude: Float - longitude: Float -} -######################################### - -type HostGroup { - groupid: ID! - name: String -} - -interface Host { - hostid: ID! - """ - The host field contains the "hostname" in Zabbix - """ - host: String! - deviceType: String - hostgroups: [HostGroup!] - name: String - tags: JSONObject -} - -type ZabbixItem { - itemid: Int! - name: String! - key_: String! - hostid: Int - lastclock: Int - lastvalue: String - value_type: Int! - attributeName: String - deviceType: String - topicType:String - status: DeviceStatus - type: DeviceCommunicationType - hosts: [Host] -} - -type ZabbixHost implements Host { - hostid: ID! - host: String! - deviceType: String - hostgroups: [HostGroup!] - name: String - tags: JSONObject - - - items: [ZabbixItem!] - inventory: Inventory - parentTemplates: [Template!] -} - - -""" -(IoT / Edge - ) Devices are hosts having a state containing the "output" / the business data which is exposed -besides monitoring information. -""" -interface Device implements Host { - hostid: ID! - """ - Per convention a uuid is used as hostname to identify devices if they do not have a unique hostname - """ - host: String! - deviceType: String - hostgroups: [HostGroup!] - name: String - tags: JSONObject - state: DeviceState -} -type OperationalDeviceData { - temperature: Float - voltage: Float - signalstrength: Float - location: Location - timestamp: DateTime - error: [ErrorPayload!] -} -interface DeviceState { - operational: OperationalDeviceData -} - -# Generic IoT devices with "generic" current state - mapping all "values" -type GenericDeviceState implements DeviceState { - operational: OperationalDeviceData - current: JSONObject -} - - -""" -Device represents generic IoT / Edge - devices providing their state as generic "state.current" - JSON Object -""" -type GenericDevice implements Host & Device { - hostid: ID! - """ - Per convention a uuid is used as hostname to identify devices if they do not have a unique hostname - """ - host: String! - deviceType: String - hostgroups: [HostGroup!] - name: String - tags: JSONObject - state: GenericDeviceState -} - -type ErrorPayload { - code: Int! - message: String - additionalInfo: JSONObject -} - -enum SensorValueType { - NUMERIC # 0 - numeric float; - CHARACTER # 1 - character; - LOG # 2 - log; - NUMERIC_UNSIGNED # 3 - numeric unsigned; - TEXT # 4 - text; -} - -type ZabbixCreateResponse { - hostids: [Int] - itemids: [Int] - error: ApiError -} - -input LocationInput { - name: String - location_lat: String - location_lon: String -} - -type Template { - templateid: String! - name: String -} - -type Inventory { - location: Location -} - -type Location implements GpsPosition { - name: String - latitude: Float - longitude: Float -} - -enum DeviceStatus { - ENABLED - DISABLED -} - -enum DeviceCommunicationType { - ZABBIX_AGENT - ZABBIX_AGENT_ACTIVE - ZABBIX_TRAP - ZABBIX_INTERNAL_ITEM - SIMPLE_CHECK - DEPENDANT_ITEM - SIMULATOR_CALCULATED - SIMULATOR_JAVASCRIPT - HTTP_AGENT - IPMI_AGENT - JMX_AGENT - SNMP_AGENT - SNMP_TRAP - DATABASE_MONITOR -} - -type Item { - itemid: Int - hostid: Int - name: String! - key_: String - attributeName: String - deviceType: String - topicType:String - status: DeviceStatus - type: DeviceCommunicationType - hosts: [Host] -} - - -#################################################################### -# Input types used for importXXX - and storeXXX - Mutations -#################################################################### - -input CreateHostGroup { - """ - Name of the host group - """ - groupName: String! - """ - Internally used unique id - (will be assigned by Zabbix if empty) - """ - uuid: String -} - -type CreateHostGroupResponse { - groupName: String! - groupid: Int - message: String - error: ApiError -} - -type HostTypeMeta { - deviceType: String - deviceTypeDescription: String -} - -input CreateHost { - deviceKey: String! - """ - Optional display name of the device (must be unique if provided - default is to set display name to deviceKey) - """ - name: String - deviceType: String! - """ - groupNames is used to assign the created object - to a host group. It is mandatory but - can also be blank. This is usefull in case of - passing a groupid instead which is - the zabbix internal key for storing the group. - If a groupid is provided the passed groupName is ignored - """ - groupNames: [String!]! - """ - Optionally the internal groupids can be passed - in this case the - groupName is ignored - """ - groupids: [Int] - location: LocationInput -} -type CreateHostResponse { - deviceKey: String! - hostid: String - message: String - error: ApiError -} - -interface Error { - code: Int - message: String - data: JSONObject -} - -type ApiError implements Error { - code: Int - message: String - data: JSONObject - path: String - args: JSONObject -} - -############################################################################ -# General purpose types + enums -############################################################################ -enum SortOrder { - "Deliver values in ascending order" - asc - "Deliver values in descending order" - desc -} - - diff --git a/src/api/resolver_helpers.ts b/src/api/resolver_helpers.ts index 30d2fbb..a462cc0 100644 --- a/src/api/resolver_helpers.ts +++ b/src/api/resolver_helpers.ts @@ -1,5 +1,8 @@ import {isObjectType} from "graphql"; import {logger} from "../logging/logger.js"; +import {Device, Host} from "../schema/generated/graphql"; + +export const isDevice = (value: Host): value is Device => !!(value as Device).deviceType; /* As a default all . - seperators within a key shall be replaced by a Capital letter of the following word diff --git a/src/api/resolvers.ts b/src/api/resolvers.ts index b2133a7..fb3c79a 100644 --- a/src/api/resolvers.ts +++ b/src/api/resolvers.ts @@ -12,8 +12,8 @@ import { QueryHasPermissionsArgs, QueryUserPermissionsArgs, Resolvers, - StorageItemType, Host, QueryExportHostValueHistoryArgs, -} from "../generated/graphql.js"; + StorageItemType, Host, QueryExportHostValueHistoryArgs, Device, +} from "../schema/generated/graphql.js"; import {HostImporter} from "../execution/host_importer"; import {HostValueExporter} from "../execution/host_exporter"; @@ -34,6 +34,7 @@ import { } from "../datasources/zabbix-userroles.js"; import {ZABBIX_EDGE_DEVICE_BASE_GROUP, zabbixAPI} from "../datasources/zabbix-api"; import {GraphQLInterfaceType, GraphQLList} from "graphql/type"; +import {isDevice} from "./resolver_helpers"; export function createResolvers(): Resolvers { @@ -160,23 +161,20 @@ export function createResolvers(): Resolvers { // @ts-ignore __resolveType: function (host: Host, _context, info ): string { - const deviceType = host.deviceType ?? ""; + if (!isDevice(host)) { + logger.info(`checking host ${host.name} for deviceType - no device type found, returning as ZabbixHost`); - if (deviceType) { - logger.info(`checking host ${host.name} for deviceType - found ${deviceType}`); - let interfaceType: GraphQLInterfaceType = (info.returnType instanceof GraphQLList ? - info.returnType.ofType : info.returnType) as GraphQLInterfaceType - if (info.schema.getImplementations(interfaceType).objects.some((impl: { name: string; }) => impl.name === deviceType)) { - return deviceType; - } - return "GenericDevice" + return "ZabbixHost"; } - - logger.info(`checking host ${host.name} for deviceType - no device type found, returning as ZabbixHost`); - return "ZabbixHost"; // Return "generic" device host as a default if no templates are assigned + const deviceType = host.deviceType!; + logger.info(`checking host ${host.name} for deviceType - found ${deviceType}`); + let interfaceType: GraphQLInterfaceType = (info.returnType instanceof GraphQLList ? + info.returnType.ofType : info.returnType) as GraphQLInterfaceType + if (info.schema.getImplementations(interfaceType).objects.some((impl: { name: string; }) => impl.name === deviceType)) { + return deviceType; + } + return "GenericDevice" } - - }, Inventory: { @@ -239,13 +237,6 @@ export function createResolvers(): Resolvers { DISABLED: DeviceStatus.DISABLED }, - SensorValueType: { - NUMERIC: 0, - CHARACTER: 1, - LOG: 2, - NUMERIC_UNSIGNED: 3, - TEXT: 4 - }, StorageItemType: { TEXT: StorageItemType.Text, FLOAT: StorageItemType.Float, diff --git a/src/datasources/zabbix-history.ts b/src/datasources/zabbix-history.ts index d01e246..8f6347e 100644 --- a/src/datasources/zabbix-history.ts +++ b/src/datasources/zabbix-history.ts @@ -1,5 +1,5 @@ import {ZabbixAPI} from "./zabbix-api.js"; -import {ApiError, SortOrder, StorageItemType} from "../generated/graphql.js"; +import {ApiError, SortOrder, StorageItemType} from "../schema/generated/graphql.js"; import {ZabbixCreateOrUpdateStorageItemRequest} from "./zabbix-items.js"; import {ZabbixForceCacheReloadRequest} from "./zabbix-script.js"; import {logger} from "../logging/logger.js"; diff --git a/src/datasources/zabbix-hostgroups.ts b/src/datasources/zabbix-hostgroups.ts index 42e38c6..bc15626 100644 --- a/src/datasources/zabbix-hostgroups.ts +++ b/src/datasources/zabbix-hostgroups.ts @@ -1,5 +1,5 @@ import {isZabbixErrorResult, ParsedArgs, ZabbixParams, ZabbixRequest} from "./zabbix-request.js"; -import {Permission} from "../generated/graphql.js"; +import {Permission} from "../schema/generated/graphql.js"; import { FIND_ZABBIX_EDGE_DEVICE_BASE_GROUP_PREFIX, ZABBIX_EDGE_DEVICE_BASE_GROUP, diff --git a/src/datasources/zabbix-hosts.ts b/src/datasources/zabbix-hosts.ts index df78075..b1c60af 100644 --- a/src/datasources/zabbix-hosts.ts +++ b/src/datasources/zabbix-hosts.ts @@ -1,4 +1,4 @@ -import {Host, ZabbixHost} from "../generated/graphql.js"; +import {CreateHostResponse, Host, ZabbixHost} from "../schema/generated/graphql.js"; import {ZabbixAPI} from "./zabbix-api.js"; import { isZabbixErrorResult, @@ -8,8 +8,7 @@ import { ZabbixRequest, ZabbixResult } from "./zabbix-request.js"; -import {QueryZabbixItemResponse} from "./zabbix-items.js"; -import {ZabbixExportValue, ZabbixHistoryGetParams, ZabbixQueryHistoryRequest} from "./zabbix-history.js"; +import {ZabbixHistoryGetParams, ZabbixQueryHistoryRequest} from "./zabbix-history.js"; export class ZabbixQueryHostsGenericRequest extends ZabbixRequest { @@ -244,9 +243,7 @@ class ZabbixCreateHostParams implements ZabbixParams { } -export class ZabbixCreateHostRequest extends ZabbixRequest<{ - hostids: number[] -}> { +export class ZabbixCreateHostRequest extends ZabbixRequest { constructor(authToken?: string | null, cookie?: string) { super("host.create", authToken, cookie); } diff --git a/src/datasources/zabbix-items.ts b/src/datasources/zabbix-items.ts index 25f3ac0..3a148f4 100644 --- a/src/datasources/zabbix-items.ts +++ b/src/datasources/zabbix-items.ts @@ -1,4 +1,5 @@ import {ParsedArgs, ZabbixParams, ZabbixRequest, ZabbixResult, ZabbixValueType} from "./zabbix-request.js"; +import {ZabbixItem} from "../schema/generated/graphql"; export class ZabbixQueryItemsMetaRequest extends ZabbixRequest { createZabbixParams(args?: ParsedArgs) { @@ -13,27 +14,8 @@ export class ZabbixQueryItemsMetaRequest extends ZabbixRequest { } } -export type QueryZabbixItemResponse = { - value_type: string; - itemid: string, - name: string, - status?: string, - key_?: string, - lastvalue: string | null - lastclock: string | null - tags?: { - tag: string, - value: string - }[] - hosts?: { - hostid: number, - host: string, - templateid?: number, - name: string - }[] -} -export class ZabbixQueryItemsRequest extends ZabbixRequest { +export class ZabbixQueryItemsRequest extends ZabbixRequest { constructor(authToken?: string | null, cookie?: string) { super("item.get", authToken, cookie); } @@ -66,7 +48,7 @@ export class ZabbixQueryItemsRequest extends ZabbixRequest { +export class ZabbixQueryItemsByIdRequest extends ZabbixRequest { constructor(authToken?: string | null, cookie?: string) { super("item.get.itembyid", authToken, cookie); } diff --git a/src/datasources/zabbix-module.ts b/src/datasources/zabbix-module.ts index 99a8532..b1b950c 100644 --- a/src/datasources/zabbix-module.ts +++ b/src/datasources/zabbix-module.ts @@ -1,5 +1,5 @@ import {ParsedArgs, ZabbixParams, ZabbixRequest} from "./zabbix-request.js"; -import {UserRoleModule} from "../generated/graphql.js"; +import {UserRoleModule} from "../schema/generated/graphql.js"; export class ZabbixQueryModulesRequest extends ZabbixRequest { constructor(authToken?: string | null, cookie?: string | null) { diff --git a/src/datasources/zabbix-request.ts b/src/datasources/zabbix-request.ts index 7b5fae2..adc5aad 100644 --- a/src/datasources/zabbix-request.ts +++ b/src/datasources/zabbix-request.ts @@ -1,4 +1,4 @@ -import {ApiError, InputMaybe, QueryHasPermissionsArgs, UserPermission} from "../generated/graphql.js"; +import {ApiError, InputMaybe, QueryHasPermissionsArgs, UserPermission} from "../schema/generated/graphql.js"; import {ZabbixAPI} from "./zabbix-api.js"; import {ApiErrorCode, Permission, PermissionNumber} from "../model/model_enum_values.js"; import {logger} from "../logging/logger.js"; diff --git a/src/datasources/zabbix-usergroups.ts b/src/datasources/zabbix-usergroups.ts index 497fd35..d728298 100644 --- a/src/datasources/zabbix-usergroups.ts +++ b/src/datasources/zabbix-usergroups.ts @@ -15,7 +15,7 @@ import { UserGroupInput, ZabbixGroupRight, ZabbixGroupRightInput -} from "../generated/graphql.js"; +} from "../schema/generated/graphql.js"; import {ZabbixAPI} from "./zabbix-api.js"; import {ZabbixQueryTemplateGroupRequest, ZabbixQueryTemplateGroupResponse} from "./zabbix-templates.js"; import {ZabbixQueryHostgroupsRequest, ZabbixQueryHostgroupsResult} from "./zabbix-hostgroups.js"; diff --git a/src/datasources/zabbix-userroles.ts b/src/datasources/zabbix-userroles.ts index 763a164..5095f01 100644 --- a/src/datasources/zabbix-userroles.ts +++ b/src/datasources/zabbix-userroles.ts @@ -8,7 +8,7 @@ import { ZabbixRequest, ZabbixResult } from "./zabbix-request.js"; -import {ApiError, ImportUserRightResult, UserRole, UserRoleInput, UserRoleModule} from "../generated/graphql.js"; +import {ApiError, ImportUserRightResult, UserRole, UserRoleInput, UserRoleModule} from "../schema/generated/graphql.js"; import {ZabbixAPI} from "./zabbix-api.js"; import {ZabbixQueryModulesRequest} from "./zabbix-module.js"; import {ApiErrorCode} from "../model/model_enum_values.js"; diff --git a/src/execution/host_exporter.ts b/src/execution/host_exporter.ts index f1d5905..4606e77 100644 --- a/src/execution/host_exporter.ts +++ b/src/execution/host_exporter.ts @@ -1,11 +1,11 @@ import { ApiError, - HistoryExportResponse, QueryExportHostValueHistoryArgs, - StorageItemType -} from "../generated/graphql.js"; + GenericResponse, QueryExportHostValueHistoryArgs, + StorageItemType, ZabbixItem +} from "../schema/generated/graphql.js"; import {ApiErrorCode, ApiErrorMessage} from "../model/model_enum_values.js"; -import {QueryZabbixItemResponse, ZabbixQueryItemsRequest} from "../datasources/zabbix-items.js"; +import {ZabbixQueryItemsRequest} from "../datasources/zabbix-items.js"; import {isZabbixErrorResult, ParsedArgs, ZabbixErrorResult} from "../datasources/zabbix-request.js"; import {ZabbixHistoryGetParams, ZabbixQueryHistoryRequest} from "../datasources/zabbix-history.js"; import {zabbixAPI} from "../datasources/zabbix-api"; @@ -20,7 +20,7 @@ type ItemMapResponse = { } export class HostValueExporter { - static async exportHistory(args: QueryExportHostValueHistoryArgs, zabbixAuthToken?: string, cookie?: string): Promise { + static async exportHistory(args: QueryExportHostValueHistoryArgs, zabbixAuthToken?: string, cookie?: string): Promise { let itemMapResponse: ItemMapResponse = await HostValueExporter.queryItemsForFilterArgs(args, zabbixAuthToken, cookie); if (itemMapResponse.error || !itemMapResponse.items) { return { @@ -77,7 +77,7 @@ export class HostValueExporter { let hostFilter = args.host_filter let itemKeyFilter = args.itemKey_filter - let items: QueryZabbixItemResponse[] | ZabbixErrorResult = await new ZabbixQueryItemsRequest(zabbixAuthToken, cookie) + let items: ZabbixItem[] | ZabbixErrorResult = await new ZabbixQueryItemsRequest(zabbixAuthToken, cookie) .executeRequestReturnError(zabbixAPI, new ParsedArgs( { filter: { diff --git a/src/execution/host_importer.ts b/src/execution/host_importer.ts index 0c2f0bf..1439292 100644 --- a/src/execution/host_importer.ts +++ b/src/execution/host_importer.ts @@ -1,9 +1,10 @@ import { CreateHost, - CreateHostResponse, + CreateHostGroup, CreateHostGroupResponse, - InputMaybe,CreateHostGroup -} from "../generated/graphql.js"; + ImportHostResponse, + InputMaybe +} from "../schema/generated/graphql.js"; import {logger} from "../logging/logger.js"; import {ZabbixQueryTemplatesRequest} from "../datasources/zabbix-templates.js"; import {isZabbixErrorResult, ParsedArgs, ZabbixErrorResult} from "../datasources/zabbix-request.js"; @@ -89,7 +90,7 @@ export class HostImporter { if (!hosts) { return null } - let result: CreateHostResponse[] = [] + let result: ImportHostResponse[] = [] for (let device of hosts) { let groupids = device.groupids if (!groupids) { diff --git a/src/generated/graphql.ts b/src/generated/graphql.ts deleted file mode 100644 index fc63c22..0000000 --- a/src/generated/graphql.ts +++ /dev/null @@ -1,1150 +0,0 @@ -import { DeviceCommunicationType } from '../model/model_enum_values.js'; -import { StorageItemType } from '../model/model_enum_values.js'; -import { DeviceStatus } from '../model/model_enum_values.js'; -import { Permission } from '../model/model_enum_values.js'; -import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql'; -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { [_ in K]?: never }; -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -export type Omit = Pick>; -export type EnumResolverSignature = { [key in keyof T]?: AllowedValues }; -export type RequireFields = Omit & { [P in K]-?: NonNullable }; -/** All built-in and custom scalars, mapped to their actual values */ -export interface Scalars { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - DateTime: { input: any; output: any; } - JSONObject: { input: any; output: any; } - Time: { input: any; output: any; } -} - -export interface ApiError extends Error { - __typename?: 'ApiError'; - args?: Maybe; - code?: Maybe; - data?: Maybe; - message?: Maybe; - path?: Maybe; -} - -export interface CreateHost { - deviceKey: Scalars['String']['input']; - deviceType: Scalars['String']['input']; - /** - * groupNames is used to assign the created object - * to a host group. It is mandatory but - * can also be blank. This is usefull in case of - * passing a groupid instead which is - * the zabbix internal key for storing the group. - * If a groupid is provided the passed groupName is ignored - */ - groupNames: Array; - /** - * Optionally the internal groupids can be passed - in this case the - * groupName is ignored - */ - groupids?: InputMaybe>>; - location?: InputMaybe; - /** Optional display name of the device (must be unique if provided - default is to set display name to deviceKey) */ - name?: InputMaybe; -} - -export interface CreateHostGroup { - /** Name of the host group */ - groupName: Scalars['String']['input']; - /** - * Internally used unique id - * (will be assigned by Zabbix if empty) - */ - uuid?: InputMaybe; -} - -export interface CreateHostGroupResponse { - __typename?: 'CreateHostGroupResponse'; - error?: Maybe; - groupName: Scalars['String']['output']; - groupid?: Maybe; - message?: Maybe; -} - -export interface CreateHostResponse { - __typename?: 'CreateHostResponse'; - deviceKey: Scalars['String']['output']; - error?: Maybe; - hostid?: Maybe; - message?: Maybe; -} - -/** - * (IoT / Edge - ) Devices are hosts having a state containing the "output" / the business data which is exposed - * besides monitoring information. - */ -export interface Device { - deviceType?: Maybe; - /** Per convention a uuid is used as hostname to identify devices if they do not have a unique hostname */ - host: Scalars['String']['output']; - hostgroups?: Maybe>; - hostid: Scalars['ID']['output']; - name?: Maybe; - state?: Maybe; - tags?: Maybe; -} - -export { DeviceCommunicationType }; - -export interface DeviceState { - operational?: Maybe; -} - -export { DeviceStatus }; - -export interface Error { - code?: Maybe; - data?: Maybe; - message?: Maybe; -} - -export interface ErrorPayload { - __typename?: 'ErrorPayload'; - additionalInfo?: Maybe; - code: Scalars['Int']['output']; - message?: Maybe; -} - -/** Device represents generic IoT / Edge - devices providing their state as generic "state.current" - JSON Object */ -export interface GenericDevice extends Device, Host { - __typename?: 'GenericDevice'; - deviceType?: Maybe; - /** Per convention a uuid is used as hostname to identify devices if they do not have a unique hostname */ - host: Scalars['String']['output']; - hostgroups?: Maybe>; - hostid: Scalars['ID']['output']; - name?: Maybe; - state?: Maybe; - tags?: Maybe; -} - -export interface GenericDeviceState extends DeviceState { - __typename?: 'GenericDeviceState'; - current?: Maybe; - operational?: Maybe; -} - -/** Hint: WGS84[dd.ddddd] coordinates are used */ -export interface GpsPosition { - latitude?: Maybe; - longitude?: Maybe; -} - -export interface HistoryExportResponse { - __typename?: 'HistoryExportResponse'; - error?: Maybe; - result?: Maybe>; -} - -export interface Host { - deviceType?: Maybe; - /** The host field contains the "hostname" in Zabbix */ - host: Scalars['String']['output']; - hostgroups?: Maybe>; - hostid: Scalars['ID']['output']; - name?: Maybe; - tags?: Maybe; -} - -export interface HostGroup { - __typename?: 'HostGroup'; - groupid: Scalars['ID']['output']; - name?: Maybe; -} - -export interface HostTypeMeta { - __typename?: 'HostTypeMeta'; - deviceType?: Maybe; - deviceTypeDescription?: Maybe; -} - -export interface ImportUserRightResult { - __typename?: 'ImportUserRightResult'; - errors?: Maybe>; - id?: Maybe; - message?: Maybe; - name?: Maybe; -} - -export interface ImportUserRightsResult { - __typename?: 'ImportUserRightsResult'; - userGroups?: Maybe>; - userRoles?: Maybe>; -} - -export interface Inventory { - __typename?: 'Inventory'; - location?: Maybe; -} - -export interface Item { - __typename?: 'Item'; - attributeName?: Maybe; - deviceType?: Maybe; - hostid?: Maybe; - hosts?: Maybe>>; - itemid?: Maybe; - key_?: Maybe; - name: Scalars['String']['output']; - status?: Maybe; - topicType?: Maybe; - type?: Maybe; -} - -export interface Location extends GpsPosition { - __typename?: 'Location'; - latitude?: Maybe; - longitude?: Maybe; - name?: Maybe; -} - -export interface LocationInput { - location_lat?: InputMaybe; - location_lon?: InputMaybe; - name?: InputMaybe; -} - -export interface Mutation { - __typename?: 'Mutation'; - /** Authentication: By zbx_session - cookie or zabbix-auth-token - header */ - createHost?: Maybe; - /** - * (Mass) Import zabbix groups - * and assign them to the corresponding hosts by groupid or groupName. - * - * Return value: If no error occurs a groupid be returned for each created group, - * otherwise the return object will contain an error message - * - * Authentication: By zbx_session - cookie or zabbix-auth-token - header - */ - importHostGroups?: Maybe>; - /** - * (Mass) Import hosts and assign them to host groups by groupid or groupName. - * - * Return value: If no error occurs a hostid will be returned for each created host, - * otherwise the return object will contain an error message. - * - * Authentication: By zbx_session - cookie or zabbix-auth-token - header - */ - importHosts?: Maybe>; - importUserRights?: Maybe; -} - - -export interface MutationCreateHostArgs { - host: Scalars['String']['input']; - hostgroupids: Array; - location?: InputMaybe; - templateids: Array; -} - - -export interface MutationImportHostGroupsArgs { - hostGroups: Array; -} - - -export interface MutationImportHostsArgs { - hosts: Array; -} - - -export interface MutationImportUserRightsArgs { - dryRun?: Scalars['Boolean']['input']; - input: UserRightsInput; -} - -export interface OperationalDeviceData { - __typename?: 'OperationalDeviceData'; - error?: Maybe>; - location?: Maybe; - signalstrength?: Maybe; - temperature?: Maybe; - timestamp?: Maybe; - voltage?: Maybe; -} - -export { Permission }; - -export interface PermissionRequest { - /** - * objectName maps to name / path suffix of the template group representing the permission in Zabbix: - * Permissions/{objectName} - */ - objectName: Scalars['String']['input']; - permission: Permission; -} - -export interface Query { - __typename?: 'Query'; - /** - * Get all host groups. - * If with_hosts==true only groups with attached hosts are delivered. - * - * Authentication: By zbx_session - cookie or zabbix-auth-token - header - */ - allHostGroups?: Maybe>>; - /** - * Get all hosts + corresponding items. If with_items==true only hosts with attached items are delivered - * name_pattern: If provided this will perform a LIKE "%…%" search on the name attribute within the database. - * - * Authentication: By zbx_session - cookie or zabbix-auth-token - header - */ - allHosts?: Maybe>>; - /** Get api (build) version */ - apiVersion: Scalars['String']['output']; - /** - * Export history from Zabbix items - * - * Authentication: By zbx_session - cookie or zabbix-auth-token - header - */ - exportHostValueHistory?: Maybe; - /** - * name_pattern: If provided this will perform a LIKE "%…%" search on the name attribute within the database. - * exclude_groups_pattern: Regex allowing to exclude all matching hostgroups from group permissions - */ - exportUserRights?: Maybe; - /** - * Return true if and only if the current user (identified by token / cookie) - * has all requested permissions (minimum - if READ is requested and the user has READ_WRITE - * the response will be true) - */ - hasPermissions?: Maybe; - /** - * Get all locations used by hosts. - * distinct_by_name=true means that the result is filtered for distinct names (default) - * name_pattern: If provided this will perform a Regex search on the name attribute within the database. - * - * Authentication: By zbx_session - cookie or zabbix-auth-token - header - */ - locations?: Maybe>>; - /** - * Login to zabbix - provided for debugging and testing purpose. The result of the login operation is - * authentication token returned may be passed as - * header 'zabbix-auth-token' for authenticating future API requests. - * As an alternative to the cookie 'zbx_session' may be set which is automatically set after login to - * the cockpit - this is the standard way to authenticate api calls initiated by the cockpit frontend - * because the frontend is always embedded into the Zabbix portal which is only accessible after logging in and - * obtainind the zbx_session - cookie. - */ - login?: Maybe; - /** - * Logout from zabbix - provided for debugging and testing purpose. This invalidates the token received by the login - * operation. Returns true on success - */ - logout?: Maybe; - /** - * Return all user permissions. If objectNames is provided return only the permissions related to the objects within - * the objectNames - list - */ - userPermissions?: Maybe>; - /** Get zabbix version */ - zabbixVersion?: Maybe; -} - - -export interface QueryAllHostGroupsArgs { - search_name?: InputMaybe; - with_hosts?: InputMaybe; -} - - -export interface QueryAllHostsArgs { - filter_host?: InputMaybe; - groupids?: InputMaybe>; - hostids?: InputMaybe; - name_pattern?: InputMaybe; - tag_deviceType?: InputMaybe>>; - tag_hostType?: InputMaybe>; - with_items?: InputMaybe; -} - - -export interface QueryExportHostValueHistoryArgs { - host_filter?: InputMaybe>; - itemKey_filter?: InputMaybe>; - limit?: InputMaybe; - sortOrder?: InputMaybe; - time_from?: InputMaybe; - time_until?: InputMaybe; - type?: InputMaybe; -} - - -export interface QueryExportUserRightsArgs { - exclude_hostgroups_pattern?: InputMaybe; - name_pattern?: InputMaybe; -} - - -export interface QueryHasPermissionsArgs { - permissions: Array; -} - - -export interface QueryLocationsArgs { - distinct_by_name?: InputMaybe; - name_pattern?: InputMaybe; - templateids?: InputMaybe>>; -} - - -export interface QueryLoginArgs { - password: Scalars['String']['input']; - username: Scalars['String']['input']; -} - - -export interface QueryUserPermissionsArgs { - objectNames?: InputMaybe>; -} - -export enum SensorValueType { - Character = 'CHARACTER', - Log = 'LOG', - Numeric = 'NUMERIC', - NumericUnsigned = 'NUMERIC_UNSIGNED', - Text = 'TEXT' -} - -export enum SortOrder { - /** Deliver values in ascending order */ - Asc = 'asc', - /** Deliver values in descending order */ - Desc = 'desc' -} - -export { StorageItemType }; - -export interface Template { - __typename?: 'Template'; - name?: Maybe; - templateid: Scalars['String']['output']; -} - -export interface UserGroup { - __typename?: 'UserGroup'; - gui_access?: Maybe; - hostgroup_rights?: Maybe>; - name: Scalars['String']['output']; - templategroup_rights?: Maybe>; - users_status?: Maybe; - usrgrpid: Scalars['Int']['output']; -} - -export interface UserGroupInput { - gui_access?: InputMaybe; - hostgroup_rights?: InputMaybe>; - name: Scalars['String']['input']; - templategroup_rights?: InputMaybe>; - users_status?: InputMaybe; -} - -export interface UserPermission { - __typename?: 'UserPermission'; - /** - * objectName maps to name / path suffix of the template group representing the permission in Zabbix: - * Permissions/{objectName} - */ - objectName: Scalars['String']['output']; - permission: Permission; -} - -export interface UserRights { - __typename?: 'UserRights'; - userGroups?: Maybe>; - userRoles?: Maybe>; -} - -export interface UserRightsInput { - userGroups?: InputMaybe>; - userRoles?: InputMaybe>; -} - -export interface UserRole { - __typename?: 'UserRole'; - name?: Maybe; - readonly?: Maybe; - roleid: Scalars['Int']['output']; - rules?: Maybe; - type?: Maybe; -} - -export interface UserRoleInput { - name?: InputMaybe; - readonly?: InputMaybe; - rules?: InputMaybe; - type?: InputMaybe; -} - -export interface UserRoleModule { - __typename?: 'UserRoleModule'; - id?: Maybe; - moduleid?: Maybe; - relative_path?: Maybe; - status?: Maybe; -} - -export interface UserRoleModuleInput { - id?: InputMaybe; - moduleid?: InputMaybe; - status?: InputMaybe; -} - -export interface UserRoleRule { - __typename?: 'UserRoleRule'; - name?: Maybe; - status?: Maybe; -} - -export interface UserRoleRuleInput { - name?: InputMaybe; - status?: InputMaybe; -} - -export interface UserRoleRules { - __typename?: 'UserRoleRules'; - actions?: Maybe>; - actions_default_access?: Maybe; - api?: Maybe>; - api_access?: Maybe; - api_mode?: Maybe; - modules?: Maybe>; - modules_default_access?: Maybe; - ui?: Maybe>; - ui_default_access?: Maybe; -} - -export interface UserRoleRulesInput { - actions?: InputMaybe>; - actions_default_access?: InputMaybe; - api?: InputMaybe>; - api_access?: InputMaybe; - api_mode?: InputMaybe; - modules?: InputMaybe>; - modules_default_access?: InputMaybe; - ui?: InputMaybe>; - ui_default_access?: InputMaybe; -} - -export interface ZabbixCreateResponse { - __typename?: 'ZabbixCreateResponse'; - error?: Maybe; - hostids?: Maybe>>; - itemids?: Maybe>>; -} - -export interface ZabbixGroupRight { - __typename?: 'ZabbixGroupRight'; - id: Scalars['Int']['output']; - name?: Maybe; - permission?: Maybe; - uuid?: Maybe; -} - -export interface ZabbixGroupRightInput { - /** - * name may optionally be specified for documentation purpose, - * but the master for setting the user right is the uuid. - * If a uuid is found and the corresponding group - * has a deviating name this will be documented within a message - * with errorcode = 0 (OK) but the permission will be set ( - * the reason is that names for groups may deviate between several - * instances of the control center although the semantic is the same - - * while the semantic is identified by uuid. - */ - name?: InputMaybe; - permission?: InputMaybe; - uuid?: InputMaybe; -} - -export interface ZabbixHost extends Host { - __typename?: 'ZabbixHost'; - deviceType?: Maybe; - host: Scalars['String']['output']; - hostgroups?: Maybe>; - hostid: Scalars['ID']['output']; - inventory?: Maybe; - items?: Maybe>; - name?: Maybe; - parentTemplates?: Maybe>; - tags?: Maybe; -} - -export interface ZabbixItem { - __typename?: 'ZabbixItem'; - attributeName?: Maybe; - deviceType?: Maybe; - hostid?: Maybe; - hosts?: Maybe>>; - itemid: Scalars['Int']['output']; - key_: Scalars['String']['output']; - lastclock?: Maybe; - lastvalue?: Maybe; - name: Scalars['String']['output']; - status?: Maybe; - topicType?: Maybe; - type?: Maybe; - value_type: Scalars['Int']['output']; -} - - - -export type ResolverTypeWrapper = Promise | T; - - -export type ResolverWithResolve = { - resolve: ResolverFn; -}; -export type Resolver = ResolverFn | ResolverWithResolve; - -export type ResolverFn = ( - parent: TParent, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo -) => Promise | TResult; - -export type SubscriptionSubscribeFn = ( - parent: TParent, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo -) => AsyncIterable | Promise>; - -export type SubscriptionResolveFn = ( - parent: TParent, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo -) => TResult | Promise; - -export interface SubscriptionSubscriberObject { - subscribe: SubscriptionSubscribeFn<{ [key in TKey]: TResult }, TParent, TContext, TArgs>; - resolve?: SubscriptionResolveFn; -} - -export interface SubscriptionResolverObject { - subscribe: SubscriptionSubscribeFn; - resolve: SubscriptionResolveFn; -} - -export type SubscriptionObject = - | SubscriptionSubscriberObject - | SubscriptionResolverObject; - -export type SubscriptionResolver = - | ((...args: any[]) => SubscriptionObject) - | SubscriptionObject; - -export type TypeResolveFn = ( - parent: TParent, - context: TContext, - info: GraphQLResolveInfo -) => Maybe | Promise>; - -export type IsTypeOfResolverFn = (obj: T, context: TContext, info: GraphQLResolveInfo) => boolean | Promise; - -export type NextResolverFn = () => Promise; - -export type DirectiveResolverFn = ( - next: NextResolverFn, - parent: TParent, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo -) => TResult | Promise; - - -/** Mapping of interface types */ -export type ResolversInterfaceTypes<_RefType extends Record> = { - Device: ( GenericDevice ); - DeviceState: ( GenericDeviceState ); - Error: ( ApiError ); - GpsPosition: ( Location ); - Host: ( GenericDevice ) | ( Omit & { items?: Maybe> } ); -}; - -/** Mapping between all available schema types and the resolvers types */ -export type ResolversTypes = { - ApiError: ResolverTypeWrapper; - Boolean: ResolverTypeWrapper; - CreateHost: CreateHost; - CreateHostGroup: CreateHostGroup; - CreateHostGroupResponse: ResolverTypeWrapper; - CreateHostResponse: ResolverTypeWrapper; - DateTime: ResolverTypeWrapper; - Device: ResolverTypeWrapper['Device']>; - DeviceCommunicationType: DeviceCommunicationType; - DeviceState: ResolverTypeWrapper['DeviceState']>; - DeviceStatus: DeviceStatus; - Error: ResolverTypeWrapper['Error']>; - ErrorPayload: ResolverTypeWrapper; - Float: ResolverTypeWrapper; - GenericDevice: ResolverTypeWrapper; - GenericDeviceState: ResolverTypeWrapper; - GpsPosition: ResolverTypeWrapper['GpsPosition']>; - HistoryExportResponse: ResolverTypeWrapper; - Host: ResolverTypeWrapper['Host']>; - HostGroup: ResolverTypeWrapper; - HostTypeMeta: ResolverTypeWrapper; - ID: ResolverTypeWrapper; - ImportUserRightResult: ResolverTypeWrapper; - ImportUserRightsResult: ResolverTypeWrapper; - Int: ResolverTypeWrapper; - Inventory: ResolverTypeWrapper; - Item: ResolverTypeWrapper & { hosts?: Maybe>> }>; - JSONObject: ResolverTypeWrapper; - Location: ResolverTypeWrapper; - LocationInput: LocationInput; - Mutation: ResolverTypeWrapper<{}>; - OperationalDeviceData: ResolverTypeWrapper; - Permission: Permission; - PermissionRequest: PermissionRequest; - Query: ResolverTypeWrapper<{}>; - SensorValueType: SensorValueType; - SortOrder: SortOrder; - StorageItemType: StorageItemType; - String: ResolverTypeWrapper; - Template: ResolverTypeWrapper