From ae0ff334068c33cce342ab4b1abe31971aa238de Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Tue, 21 Mar 2023 14:31:17 +0100 Subject: [PATCH 01/69] FD-495 definition list query (#262) * workflow query definitions * add missing files * better typing of metadata api * schema changes * return tasks as stringified json * workflow node query added --- .env.example | 1 + src/config.ts | 1 + src/context.ts | 4 +- src/external-api/conductor-network-types.ts | 87 +++++++++++++++++++++ src/external-api/conductor.ts | 27 +++++++ src/helpers/id-helper.ts | 12 ++- src/schema/api.graphql | 22 ++++++ src/schema/global-types.ts | 10 +++ src/schema/index.ts | 3 +- src/schema/nexus-typegen.ts | 67 +++++++++++++++- src/schema/source-types.ts | 3 + src/schema/workflow.ts | 70 +++++++++++++++++ 12 files changed, 303 insertions(+), 4 deletions(-) create mode 100644 src/external-api/conductor-network-types.ts create mode 100644 src/external-api/conductor.ts create mode 100644 src/schema/workflow.ts diff --git a/.env.example b/.env.example index 244d7bd1..6ce4cbf8 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,7 @@ DATABASE_URL="postgresql://postgres:postgres@localhost:5432/frinx" UNICONFIG_API_PROTOCOL=http UNICONFIG_API_PORT=4000 UNICONFIG_LIST_URL=http://localhost:4000/static/list/uniconfig +CONDUCTOR_API_URL="http:/10.19.0.7:8080/api" SHELL_HOST=10.19.0.12 X_TENANT_ID="frinx" TOPOLOGY_ENABLED=true diff --git a/src/config.ts b/src/config.ts index 191408f5..ba123eec 100644 --- a/src/config.ts +++ b/src/config.ts @@ -67,6 +67,7 @@ const config = { uniconfigApiProtocol: envString('UNICONFIG_API_PROTOCOL'), uniconfigApiPort: envString('UNICONFIG_API_PORT'), uniconfigListURL: envString('UNICONFIG_LIST_URL'), + conductorApiURL: envString('CONDUCTOR_API_URL'), defaultTenantId: envString('X_TENANT_ID'), shellHost: envString('SHELL_HOST'), ...getTopologyConfig(), diff --git a/src/context.ts b/src/context.ts index b62ae712..e5959c1d 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,6 +1,7 @@ import { PrismaClient } from '@prisma/client'; import { ExpressContext } from 'apollo-server-express'; import topologyDiscoveryAPI, { TopologyDiscoveryAPI } from './external-api/topology-discovery'; +import conductorAPI, { ConductorAPI } from './external-api/conductor'; import uniconfigAPI, { UniConfigAPI } from './external-api/uniconfig'; import prismaClient from './prisma-client'; @@ -9,6 +10,7 @@ export type Context = { tenantId: string; uniconfigAPI: UniConfigAPI; topologyDiscoveryAPI: TopologyDiscoveryAPI; + conductorAPI: ConductorAPI; }; export default function createContext(context: ExpressContext): Context { @@ -22,5 +24,5 @@ export default function createContext(context: ExpressContext): Context { tenantId = headers['x-tenant-id'] as string; } - return { prisma: prismaClient, tenantId, uniconfigAPI, topologyDiscoveryAPI }; + return { prisma: prismaClient, tenantId, uniconfigAPI, topologyDiscoveryAPI, conductorAPI }; } diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts new file mode 100644 index 00000000..49dd5cd4 --- /dev/null +++ b/src/external-api/conductor-network-types.ts @@ -0,0 +1,87 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import { Either, fold } from 'fp-ts/lib/Either'; +import * as t from 'io-ts'; +import { PathReporter } from 'io-ts/lib/PathReporter'; + +export function optional(type: t.Type) { + return t.union([type, t.void]); +} + +export function extractResult(result: Either): A { + return fold( + () => { + const errorMessages = PathReporter.report(result); + throw new Error(`BAD_REQUEST: ${errorMessages.join(',')}`); + }, + (data: A) => data, + )(result); +} + +const ApiBaseTask = t.type({ + name: t.string, + taskReferenceName: t.string, + description: optional(t.string), + inputParameters: optional(t.record(t.string, t.any)), + type: optional(t.string), + dynamicTaskNameParam: optional(t.string), + scriptExpression: optional(t.string), + dynamicForkTasksParam: optional(t.string), + dynamicForkTasksInputParamName: optional(t.string), + forkTasks: optional(t.UnknownArray), +}); + +export type BaseTask = t.TypeOf; + +export type NestedTask = BaseTask & { + decisionCases: Record | void; + defaultCase: NestedTask[] | void; +}; + +// TODO: this is properly typed nested workflow but is not used in graphql schema as +// we are not able to get whole deeply nested object in graphql +const WorkflowTask: t.Type = t.recursion('NestedTask', () => + t.intersection([ + ApiBaseTask, + t.type({ + decisionCases: optional(t.record(t.string, t.array(WorkflowTask))), + defaultCase: optional(t.array(WorkflowTask)), + }), + ]), +); + +const WorkflowMetadata = t.type({ + createTime: optional(t.number), + updateTime: optional(t.number), + createdBy: optional(t.string), + updatedBy: optional(t.string), + name: t.string, + description: optional(t.string), + version: optional(t.number), + tasks: t.UnknownArray, // TODO: we are passing task as stringified json for now (can we switch to WorkflowTask somehow?) + timeoutSeconds: t.number, + inputParameters: optional(t.array(t.string)), + outputParameters: optional(t.record(t.string, t.string)), + failureWorkflow: optional(t.string), + schemaVersion: optional(t.number), + restartable: optional(t.boolean), + workflowStatusListenerEnabled: optional(t.boolean), + ownerEmail: optional(t.string), + timeoutPolicy: optional(t.union([t.literal('TIME_OUT_WF'), t.literal('ALERT_ONLY')])), + variables: optional(t.record(t.string, t.UnknownRecord)), + inputTemplate: optional(t.record(t.string, t.UnknownRecord)), +}); + +const WorkflowMetadataValidator = t.array(WorkflowMetadata); + +export type WorfklowMetadataOutput = t.TypeOf; +export type ApiWorkflow = t.TypeOf; + +export function decodeWorkflowMetadataOutput(value: unknown): WorfklowMetadataOutput { + return extractResult(WorkflowMetadataValidator.decode(value)); +} + +export type WorkflowDetailOutput = t.TypeOf; + +export function decodeWorkflowDetailOutput(value: unknown): WorkflowDetailOutput { + return extractResult(WorkflowMetadata.decode(value)); +} diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts new file mode 100644 index 00000000..b3f0c9fe --- /dev/null +++ b/src/external-api/conductor.ts @@ -0,0 +1,27 @@ +import { + decodeWorkflowDetailOutput, + decodeWorkflowMetadataOutput, + WorfklowMetadataOutput, + WorkflowDetailOutput, +} from './conductor-network-types'; +import { sendGetRequest } from './helpers'; + +async function getWorkflowMetadata(baseURL: string): Promise { + const json = await sendGetRequest([baseURL, 'metadata/workflow']); + const data = decodeWorkflowMetadataOutput(json); + return data; +} + +async function getWorkflowDetail(baseURL: string, workflowName: string): Promise { + const json = await sendGetRequest([baseURL, `metadata/workflow/${workflowName}`]); + const data = decodeWorkflowDetailOutput(json); + return data; +} + +const conductorAPI = { + getWorkflowMetadata, + getWorkflowDetail, +}; + +export type ConductorAPI = typeof conductorAPI; +export default conductorAPI; diff --git a/src/helpers/id-helper.ts b/src/helpers/id-helper.ts index 77698cf5..740adefb 100644 --- a/src/helpers/id-helper.ts +++ b/src/helpers/id-helper.ts @@ -1,11 +1,21 @@ import base64url from 'base64url'; -export type DataType = 'Zone' | 'Device' | 'Label' | 'Location' | 'Country' | 'Blueprint' | 'GraphNode' | 'GraphEdge'; +export type DataType = + | 'Zone' + | 'Device' + | 'Workflow' + | 'Label' + | 'Location' + | 'Country' + | 'Blueprint' + | 'GraphNode' + | 'GraphEdge'; function isDataType(value: string): value is DataType { return ( value === 'Zone' || value === 'Device' || + value === 'Workflow' || value === 'Label' || value === 'Location' || value === 'Country' || diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 7eac53f5..b0b502d0 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -421,6 +421,7 @@ type Query { topologyVersions: [String!] transactions: [Transaction!]! uniconfigShellSession: String + worfklows(after: String, before: String, first: Int, last: Int): WorkflowConnection! zones(after: String, before: String, first: Int, last: Int): ZonesConnection! } @@ -541,6 +542,27 @@ The `Upload` scalar type represents a file upload. """ scalar Upload +type Workflow implements Node { + createdAt: String + createdBy: String + id: ID! + name: String! + tasks: String + updatedAt: String + updatedBy: String +} + +type WorkflowConnection { + edges: [WorkflowEdge!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type WorkflowEdge { + cursor: String! + node: Workflow! +} + type Zone implements Node { createdAt: String! id: ID! diff --git a/src/schema/global-types.ts b/src/schema/global-types.ts index 6034ff6c..52be1269 100644 --- a/src/schema/global-types.ts +++ b/src/schema/global-types.ts @@ -1,6 +1,8 @@ import countries from 'i18n-iso-countries'; import { extendType, idArg, intArg, interfaceType, nonNull, objectType, stringArg } from 'nexus'; import { fromGraphId, getType } from '../helpers/id-helper'; +import conductorAPI from '../external-api/conductor'; +import config from '../config'; export const Node = interfaceType({ name: 'Node', @@ -95,6 +97,14 @@ export const NodeQuery = extendType({ } return { ...blueprint, __typename: 'Blueprint' }; } + case 'Workflow': { + const id = fromGraphId('Workflow', args.id); + const workflow = await conductorAPI.getWorkflowDetail(config.conductorApiURL, id); + if (workflow == null) { + return null; + } + return { ...workflow, id: args.id, __typename: 'Workflow' }; + } /* eslint-enable */ default: return null; diff --git a/src/schema/index.ts b/src/schema/index.ts index 08c3f37d..b9c69eea 100644 --- a/src/schema/index.ts +++ b/src/schema/index.ts @@ -9,6 +9,7 @@ import * as location from './location'; import * as zone from './zone'; import * as transaction from './transaction'; import * as topology from './topology'; +import * as workflow from './workflow'; export default makeSchema({ features: { @@ -26,7 +27,7 @@ export default makeSchema({ schema: join(__dirname, './api.graphql'), }, shouldExitAfterGenerateArtifacts: Boolean(process.env.NEXUS_SHOULD_EXIT_AFTER_REFLECTION), - types: [globalTypes, device, zone, dataStore, label, location, blueprint, transaction, topology], + types: [globalTypes, device, zone, dataStore, label, location, blueprint, transaction, topology, workflow], sourceTypes: { modules: [ { diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index beb05958..70cb43d3 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -441,6 +441,18 @@ export interface NexusGenObjects { // root type deviceNames: string[]; // [String!]! }; + Workflow: SourceTypes.Workflow; + WorkflowConnection: { + // root type + edges: NexusGenRootTypes['WorkflowEdge'][]; // [WorkflowEdge!]! + pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! + totalCount: number; // Int! + }; + WorkflowEdge: { + // root type + cursor: string; // String! + node: NexusGenRootTypes['Workflow']; // Workflow! + }; Zone: SourceTypes.Zone; ZoneEdge: { // root type @@ -463,6 +475,7 @@ export interface NexusGenInterfaces { | core.Discriminate<'Device', 'required'> | core.Discriminate<'Label', 'required'> | core.Discriminate<'Location', 'required'> + | core.Discriminate<'Workflow', 'required'> | core.Discriminate<'Zone', 'required'>; } @@ -770,6 +783,7 @@ export interface NexusGenFieldTypes { topologyVersions: string[] | null; // [String!] transactions: NexusGenRootTypes['Transaction'][]; // [Transaction!]! uniconfigShellSession: string | null; // String + worfklows: NexusGenRootTypes['WorkflowConnection']; // WorkflowConnection! zones: NexusGenRootTypes['ZonesConnection']; // ZonesConnection! }; ResetConfigPayload: { @@ -848,6 +862,27 @@ export interface NexusGenFieldTypes { // field return type deviceNames: string[]; // [String!]! }; + Workflow: { + // field return type + createdAt: string | null; // String + createdBy: string | null; // String + id: string; // ID! + name: string; // String! + tasks: string | null; // String + updatedAt: string | null; // String + updatedBy: string | null; // String + }; + WorkflowConnection: { + // field return type + edges: NexusGenRootTypes['WorkflowEdge'][]; // [WorkflowEdge!]! + pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! + totalCount: number; // Int! + }; + WorkflowEdge: { + // field return type + cursor: string; // String! + node: NexusGenRootTypes['Workflow']; // Workflow! + }; Zone: { // field return type createdAt: string; // String! @@ -1178,6 +1213,7 @@ export interface NexusGenFieldTypeNames { topologyVersions: 'String'; transactions: 'Transaction'; uniconfigShellSession: 'String'; + worfklows: 'WorkflowConnection'; zones: 'ZonesConnection'; }; ResetConfigPayload: { @@ -1256,6 +1292,27 @@ export interface NexusGenFieldTypeNames { // field return type name deviceNames: 'String'; }; + Workflow: { + // field return type name + createdAt: 'String'; + createdBy: 'String'; + id: 'ID'; + name: 'String'; + tasks: 'String'; + updatedAt: 'String'; + updatedBy: 'String'; + }; + WorkflowConnection: { + // field return type name + edges: 'WorkflowEdge'; + pageInfo: 'PageInfo'; + totalCount: 'Int'; + }; + WorkflowEdge: { + // field return type name + cursor: 'String'; + node: 'Workflow'; + }; Zone: { // field return type name createdAt: 'String'; @@ -1470,6 +1527,13 @@ export interface NexusGenArgTypes { // args version: string; // String! }; + worfklows: { + // args + after?: string | null; // String + before?: string | null; // String + first?: number | null; // Int + last?: number | null; // Int + }; zones: { // args after?: string | null; // String @@ -1490,7 +1554,7 @@ export interface NexusGenArgTypes { export interface NexusGenAbstractTypeMembers { BaseGraphNode: 'GraphNode' | 'GraphVersionNode'; - Node: 'Blueprint' | 'Country' | 'Device' | 'Label' | 'Location' | 'Zone'; + Node: 'Blueprint' | 'Country' | 'Device' | 'Label' | 'Location' | 'Workflow' | 'Zone'; } export interface NexusGenTypeInterfaces { @@ -1501,6 +1565,7 @@ export interface NexusGenTypeInterfaces { GraphVersionNode: 'BaseGraphNode'; Label: 'Node'; Location: 'Node'; + Workflow: 'Node'; Zone: 'Node'; } diff --git a/src/schema/source-types.ts b/src/schema/source-types.ts index e305eae1..fd33f657 100644 --- a/src/schema/source-types.ts +++ b/src/schema/source-types.ts @@ -1,4 +1,5 @@ import { blueprint, device, label, location, uniconfigZone } from '@prisma/client'; +import { ApiWorkflow, NestedTask } from '../external-api/conductor-network-types'; export type Label = label; export type Device = device; @@ -15,3 +16,5 @@ export type Country = { code: string; }; export type Blueprint = blueprint; +export type Workflow = ApiWorkflow & { id: string }; +export type WorkflowTask = NestedTask; diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts new file mode 100644 index 00000000..9fc611da --- /dev/null +++ b/src/schema/workflow.ts @@ -0,0 +1,70 @@ +import { connectionFromArray } from 'graphql-relay'; +import { extendType, objectType } from 'nexus'; +import config from '../config'; +import { toGraphId } from '../helpers/id-helper'; +import { Node, PageInfo, PaginationConnectionArgs } from './global-types'; + +export const Workflow = objectType({ + name: 'Workflow', + definition: (t) => { + t.implements(Node); + t.nonNull.id('id', { + resolve: (workflow) => toGraphId('Workflow', workflow.name), + }); + t.nonNull.string('name'); + t.string('createdBy', { resolve: (workflow) => workflow.createdBy ?? null }); + t.string('updatedBy', { resolve: (workflow) => workflow.updatedBy ?? null }); + t.string('createdAt', { + resolve: (workflow) => (workflow.createTime ? new Date(workflow.createTime).toISOString() : null), + }); + t.string('updatedAt', { + resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), + }); + t.string('tasks', { resolve: (workflow) => JSON.stringify(workflow.tasks) }); + }, +}); + +export const WorkflowEdge = objectType({ + name: 'WorkflowEdge', + definition: (t) => { + t.nonNull.field('node', { + type: Workflow, + }); + t.nonNull.string('cursor'); + }, +}); + +export const WorkflowConnection = objectType({ + name: 'WorkflowConnection', + definition: (t) => { + t.nonNull.list.nonNull.field('edges', { + type: WorkflowEdge, + }); + t.nonNull.field('pageInfo', { + type: PageInfo, + }); + t.nonNull.int('totalCount'); + }, +}); + +export const WorkflowsQuery = extendType({ + type: 'Query', + definition: (t) => { + t.nonNull.field('worfklows', { + type: WorkflowConnection, + args: PaginationConnectionArgs, + resolve: async (_, args, { conductorAPI }) => { + const workflows = await conductorAPI.getWorkflowMetadata(config.conductorApiURL); + + const workflowsWithId = workflows.map((w) => ({ + ...w, + id: w.name, + })); + return { + ...connectionFromArray(workflowsWithId, args), + totalCount: workflows.length, + }; + }, + }); + }, +}); From 3895c6bc9641400c31a16f41d4621b77d6b7a201 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Thu, 23 Mar 2023 15:41:33 +0100 Subject: [PATCH 02/69] Executed workflow query (#264) * workflow query definitions * add missing files * better typing of metadata api * schema changes * return tasks as stringified json * workflow node query added * create graphql and io-ts schemas for executed workflow and executed workflow tasks * add filter and pagination query * update calculation of relay specific pagination * add executed workflow detail query * resolve wanted changes to make codebase more readable * remove as type * add tests for conductor helpers (#266) --------- Co-authored-by: Martin Sottnik --- src/external-api/conductor-network-types.ts | 108 +++++++++ src/external-api/conductor.ts | 26 +++ src/helpers/conductor.helpers.spec.ts | 242 ++++++++++++++++++++ src/helpers/conductor.helpers.ts | 103 +++++++++ src/helpers/id-helper.ts | 4 + src/helpers/omit-null-value.ts | 10 - src/helpers/topology.helpers.ts | 2 +- src/helpers/unwrap.ts | 6 - src/helpers/utils.helpers.ts | 25 ++ src/helpers/workflow.helpers.ts | 38 +++ src/schema/api.graphql | 99 ++++++++ src/schema/executed-workflow.ts | 148 ++++++++++++ src/schema/global-types.ts | 12 +- src/schema/index.ts | 17 +- src/schema/nexus-typegen.ts | 178 +++++++++++++- src/schema/source-types.ts | 9 +- src/schema/task.ts | 52 +++++ src/schema/topology.ts | 3 +- src/schema/transaction.ts | 2 +- 19 files changed, 1059 insertions(+), 25 deletions(-) create mode 100644 src/helpers/conductor.helpers.spec.ts create mode 100644 src/helpers/conductor.helpers.ts delete mode 100644 src/helpers/omit-null-value.ts delete mode 100644 src/helpers/unwrap.ts create mode 100644 src/helpers/utils.helpers.ts create mode 100644 src/helpers/workflow.helpers.ts create mode 100644 src/schema/executed-workflow.ts create mode 100644 src/schema/task.ts diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index 49dd5cd4..501fffdc 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -73,8 +73,108 @@ const WorkflowMetadata = t.type({ const WorkflowMetadataValidator = t.array(WorkflowMetadata); +const ExecutedWorkflowTaskStatus = t.union([ + t.literal('IN_PROGRESS'), + t.literal('COMPLETED'), + t.literal('FAILED'), + t.literal('TIMED_OUT'), + t.literal('SCHEDULED'), + t.literal('CANCELED'), + t.literal('SKIPPED'), + t.literal('FAILED_WITH_TERMINAL_ERROR'), + t.literal('COMPLETED_WITH_ERROR'), +]); + +const ExecutedWorkflowStatus = t.union([ + t.literal('RUNNING'), + t.literal('COMPLETED'), + t.literal('FAILED'), + t.literal('TERMINATED'), + t.literal('TIMED_OUT'), + t.literal('PAUSED'), +]); + +const ExecutedWorkflowTask = t.type({ + taskType: optional(t.string), + status: optional(ExecutedWorkflowTaskStatus), + referenceTaskName: optional(t.string), + retryCount: optional(t.number), + seq: optional(t.number), + pollCount: optional(t.number), + startTime: optional(t.number), + endTime: optional(t.number), + updateTime: optional(t.number), + correlationId: optional(t.string), + taskDefName: optional(t.string), + scheduledTime: optional(t.number), + callbackAfterSeconds: optional(t.number), + startDelayInSeconds: optional(t.number), + retried: optional(t.boolean), + responseTimeoutSeconds: optional(t.number), + executionNameSpace: optional(t.string), + workflowInstanceId: optional(t.string), + workflowType: optional(t.string), + executed: optional(t.boolean), + callbackFromWorker: optional(t.boolean), + workerId: optional(t.string), + taskId: optional(t.string), + reasonForIncompletion: optional(t.string), + domain: optional(t.string), + rateLimitPerFrequency: optional(t.number), + rateLimitFrequencyInSeconds: optional(t.number), + externalInputPayloadStoragePath: optional(t.string), + externalOutputPayloadStoragePath: optional(t.string), + workflowPriority: optional(t.number), + isolationGroupId: optional(t.string), + taskDefinition: t.union([optional(t.UnknownRecord), t.null]), + iteration: optional(t.number), + subWorkflowId: optional(t.string), + subWorkflowChanged: optional(t.boolean), + queueWaitTime: optional(t.number), + loopOverTask: optional(t.boolean), +}); + +const ExecutedWorkflow = t.type({ + ownerApp: optional(t.string), + createTime: optional(t.number), + updateTime: optional(t.number), + createdBy: optional(t.string), + updatedBy: optional(t.string), + status: ExecutedWorkflowStatus, + endTime: optional(t.number), + workflowId: optional(t.string), + parentWorkflowId: optional(t.string), + parentWorkflowTaskId: optional(t.string), + tasks: t.array(optional(ExecutedWorkflowTask)), + input: optional(t.UnknownRecord), + output: optional(t.UnknownRecord), + correlationId: optional(t.string), + reRunFromWorkflowId: optional(t.string), + reasonForIncompletion: optional(t.string), + event: optional(t.string), + taskToDomain: optional(t.record(t.string, t.string)), + failedReferenceTaskNames: optional(t.array(t.string)), + workflowDefinition: optional(WorkflowMetadata), + externalInputPayloadStoragePath: optional(t.string), + externalOutputPayloadStoragePath: optional(t.string), + priority: optional(t.number), + variables: optional(t.record(t.string, t.UnknownRecord)), + lastRetriedTime: optional(t.number), + failedTaskNames: optional(t.array(t.string)), + startTime: optional(t.number), + workflowVersion: optional(t.number), + workflowName: optional(t.string), +}); + +const ExecutedWorkflowsValidator = t.type({ + results: t.array(ExecutedWorkflow), +}); + +export type ExecutedWorkflowsOutput = t.TypeOf; export type WorfklowMetadataOutput = t.TypeOf; export type ApiWorkflow = t.TypeOf; +export type ApiExecutedWorkflow = t.TypeOf; +export type ApiExecutedWorkflowTask = t.TypeOf; export function decodeWorkflowMetadataOutput(value: unknown): WorfklowMetadataOutput { return extractResult(WorkflowMetadataValidator.decode(value)); @@ -85,3 +185,11 @@ export type WorkflowDetailOutput = t.TypeOf; export function decodeWorkflowDetailOutput(value: unknown): WorkflowDetailOutput { return extractResult(WorkflowMetadata.decode(value)); } + +export function decodeExecutedWorkflowsOutput(value: unknown): ExecutedWorkflowsOutput { + return extractResult(ExecutedWorkflowsValidator.decode(value)); +} + +export function decodeExecutedWorkflowDetailOutput(value: unknown): ApiExecutedWorkflow { + return extractResult(ExecutedWorkflow.decode(value)); +} diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts index b3f0c9fe..e4d6b835 100644 --- a/src/external-api/conductor.ts +++ b/src/external-api/conductor.ts @@ -1,6 +1,11 @@ +import { makeStringQueryFromSearchQueryObject, PaginationArgs, SearchQuery } from '../helpers/conductor.helpers'; import { + ApiExecutedWorkflow, + decodeExecutedWorkflowDetailOutput, + decodeExecutedWorkflowsOutput, decodeWorkflowDetailOutput, decodeWorkflowMetadataOutput, + ExecutedWorkflowsOutput, WorfklowMetadataOutput, WorkflowDetailOutput, } from './conductor-network-types'; @@ -18,9 +23,30 @@ async function getWorkflowDetail(baseURL: string, workflowName: string): Promise return data; } +async function getExecutedWorkflows( + baseURL: string, + query?: SearchQuery | null, + paginationArgs?: PaginationArgs | null, +): Promise { + const formattedQuery = makeStringQueryFromSearchQueryObject(query, paginationArgs); + const json = await sendGetRequest([baseURL, `workflow/search-v2?${formattedQuery}`]); + const data = decodeExecutedWorkflowsOutput(json); + + return data; +} + +async function getExecutedWorkflowDetail(baseURL: string, workflowId: string): Promise { + const json = await sendGetRequest([baseURL, `workflow/${workflowId}`]); + const data = decodeExecutedWorkflowDetailOutput(json); + + return data; +} + const conductorAPI = { getWorkflowMetadata, getWorkflowDetail, + getExecutedWorkflows, + getExecutedWorkflowDetail, }; export type ConductorAPI = typeof conductorAPI; diff --git a/src/helpers/conductor.helpers.spec.ts b/src/helpers/conductor.helpers.spec.ts new file mode 100644 index 00000000..603dbe3f --- /dev/null +++ b/src/helpers/conductor.helpers.spec.ts @@ -0,0 +1,242 @@ +import { + ConductorQuery, + ConductorQuerySearchTime, + PaginationArgs, + SearchQuery, + makeStringFromIsRootWorkflow, + makeStringFromPagination, + makeStringFromQuery, + makeStringQueryFromSearchQueryObject, + makeStringQueryFromSearchTime, +} from './conductor.helpers'; + +/* eslint-env jest */ +test('Make string from Search Time Conductor Query Object', () => { + const searchTime: ConductorQuerySearchTime = { + from: 123, + to: 456, + }; + const result = makeStringQueryFromSearchTime(searchTime); + expect(result).toBe('startTime > 123 AND startTime < 456'); +}); + +test('Make string from Search Time Conductor Query Object with only from', () => { + const searchTime: ConductorQuerySearchTime = { + from: 123, + }; + const result = makeStringQueryFromSearchTime(searchTime); + expect(result).toBe('startTime > 123'); +}); + +test('Make string from isRootWorkflow when true', () => { + const result = makeStringFromIsRootWorkflow(true); + expect(result).toBe('freeText=root_wf'); +}); + +test('Make string from isRootWorkflow with false', () => { + const result = makeStringFromIsRootWorkflow(false); + expect(result).toBe('freeText=*'); +}); + +test('Make string from isRootWorkflow with null', () => { + const result = makeStringFromIsRootWorkflow(null); + expect(result).toBe('freeText=*'); +}); + +test('Make string from isRootWorkflow with undefined', () => { + const result = makeStringFromIsRootWorkflow(undefined); + expect(result).toBe('freeText=*'); +}); + +test('Make string from pagination', () => { + const paginationArgs: PaginationArgs = { + size: 10, + start: 0, + }; + const result = makeStringFromPagination(paginationArgs); + expect(result).toBe('size=10&start=0'); +}); + +test('Make string from Conductor Query object only with start time', () => { + const query: ConductorQuery = { + startTime: { + from: 123, + to: 456, + }, + }; + + const result = makeStringFromQuery(query); + expect(result).toBe('startTime > 123 AND startTime < 456'); +}); + +test('Make string from Conductor Query object only with start time and status', () => { + const query: ConductorQuery = { + startTime: { + from: 123, + to: 456, + }, + status: ['COMPLETED'], + }; + + const result = makeStringFromQuery(query); + expect(result).toBe('startTime > 123 AND startTime < 456 AND status IN (COMPLETED)'); +}); + +test('Make string from Conductor Query object only with start time and status and workflowId', () => { + const query: ConductorQuery = { + startTime: { + from: 123, + to: 456, + }, + status: ['COMPLETED'], + workflowId: ['123'], + }; + + const result = makeStringFromQuery(query); + expect(result).toBe('startTime > 123 AND startTime < 456 AND status IN (COMPLETED) AND workflowId IN (123)'); +}); + +test('Make string from Conductor Query with multiple statuses', () => { + const query: ConductorQuery = { + status: ['COMPLETED', 'FAILED'], + }; + + const result = makeStringFromQuery(query); + expect(result).toBe('status IN (COMPLETED,FAILED)'); +}); + +test('Make string from Conductor Query with multiple workflowIds', () => { + const query: ConductorQuery = { + workflowId: ['123', '456'], + }; + + const result = makeStringFromQuery(query); + expect(result).toBe('workflowId IN (123,456)'); +}); + +test('Make string from Conductor Query with multiple workflowTypes', () => { + const query: ConductorQuery = { + workflowType: ['123', '456'], + }; + + const result = makeStringFromQuery(query); + expect(result).toBe('workflowType IN (123,456)'); +}); + +test('Make string from Conductor Query with multiple workflowTypes and workflowIds', () => { + const query: ConductorQuery = { + workflowType: ['123', '456'], + workflowId: ['123', '456'], + }; + + const result = makeStringFromQuery(query); + expect(result).toBe('workflowType IN (123,456) AND workflowId IN (123,456)'); +}); + +test('Make string from Conductor Query with multiple workflowTypes, workflowIds, start time and statuses', () => { + const query: ConductorQuery = { + workflowType: ['123', '456'], + workflowId: ['123', '456'], + startTime: { + from: 123, + to: 456, + }, + status: ['COMPLETED', 'FAILED'], + }; + + const result = makeStringFromQuery(query); + expect(result).toBe( + 'workflowType IN (123,456) AND workflowId IN (123,456) AND startTime > 123 AND startTime < 456 AND status IN (COMPLETED,FAILED)', + ); +}); + +test('Make string from Search Query object and Pagination object', () => { + const query: SearchQuery = { + isRootWorkflow: true, + query: { + workflowType: ['123', '456'], + workflowId: ['123', '456'], + startTime: { + from: 123, + to: 456, + }, + status: ['COMPLETED', 'FAILED'], + }, + }; + + const pagination: PaginationArgs = { + size: 10, + start: 0, + }; + + const result = makeStringQueryFromSearchQueryObject(query, pagination); + expect(result).toBe( + 'query=workflowType IN (123,456) AND workflowId IN (123,456) AND startTime > 123 AND startTime < 456 AND status IN (COMPLETED,FAILED)&freeText=root_wf&size=10&start=0', + ); +}); + +test('Make string from Pagination', () => { + const pagination: PaginationArgs = { + size: 10, + start: 0, + }; + + const result = makeStringQueryFromSearchQueryObject(null, pagination); + expect(result).toBe('freeText=*&size=10&start=0'); +}); + +test('Make string from Search Query object (isRootWorkflow = false) and pagination is null', () => { + const query: SearchQuery = { + isRootWorkflow: false, + query: { + workflowType: ['123', '456'], + workflowId: ['123'], + startTime: { + from: 123, + }, + status: ['COMPLETED', 'FAILED'], + }, + }; + + const result = makeStringQueryFromSearchQueryObject(query, null); + expect(result).toBe( + 'query=workflowType IN (123,456) AND workflowId IN (123) AND startTime > 123 AND status IN (COMPLETED,FAILED)&freeText=*', + ); +}); + +test('Make string from Search Query object (isRootWorkflow = false) and pagination is undefined', () => { + const query: SearchQuery = { + isRootWorkflow: false, + query: { + workflowType: ['123'], + workflowId: ['123'], + startTime: { + from: 123, + }, + status: ['COMPLETED'], + }, + }; + + const result = makeStringQueryFromSearchQueryObject(query, undefined); + expect(result).toBe( + 'query=workflowType IN (123) AND workflowId IN (123) AND startTime > 123 AND status IN (COMPLETED)&freeText=*', + ); +}); + +test('Make string query when SearchQuery object and Pagination object are null', () => { + const result = makeStringQueryFromSearchQueryObject(null, null); + expect(result).toBe('freeText=*'); +}); + +test('Make string query when SearchQuery object and Pagination object are undefined', () => { + const result = makeStringQueryFromSearchQueryObject(undefined, undefined); + expect(result).toBe('freeText=*'); +}); + +test('Make string query when SearchQuery object is null and Pagination object is undefined and (isRootWorkflow = true)', () => { + const query: SearchQuery = { + isRootWorkflow: true, + }; + const result = makeStringQueryFromSearchQueryObject(query, undefined); + expect(result).toBe('freeText=root_wf'); +}); diff --git a/src/helpers/conductor.helpers.ts b/src/helpers/conductor.helpers.ts new file mode 100644 index 00000000..93bd4488 --- /dev/null +++ b/src/helpers/conductor.helpers.ts @@ -0,0 +1,103 @@ +import { isValidType } from './utils.helpers'; + +export type ExecutedWorkflowResult = { + results: unknown[]; + totalHits: number; +}; + +export type ConductorQuerySearchTime = { + from: number; + to?: number | null; +}; + +export type ConductorQueryStatus = 'RUNNING' | 'COMPLETED' | 'FAILED' | 'TERMINATED' | 'TIMED_OUT' | 'PAUSED'; + +export type ConductorQuery = { + status?: ConductorQueryStatus[] | null; + startTime?: ConductorQuerySearchTime | null; + workflowId?: string[] | null; + workflowType?: string[] | null; +}; + +export type SearchQuery = { + isRootWorkflow?: boolean | null; + query?: ConductorQuery | null; +}; + +export type PaginationArgs = { + size: number; + start: number; +}; + +export function makeStringQueryFromSearchTime(searchTime: ConductorQuerySearchTime): string { + const { from, to } = searchTime; + + if (from != null && to != null) { + return `startTime > ${from} AND startTime < ${to}`; + } else { + return `startTime > ${from}`; + } +} + +export function makeStringFromQuery(query: ConductorQuery): string { + const entries = Object.entries(query); + + return entries + .map(([key, value]) => { + if (value == null) { + return ''; + } else { + if (Array.isArray(value)) { + if (value.every((v) => typeof v === 'string')) { + return `${key} IN (${value.map((v) => `${v}`).join(',')})`; + } + } + + if (isValidType('from', value)) { + return makeStringQueryFromSearchTime(value); + } + + return `${key}=${value}`; + } + }) + .join(' AND '); +} + +export function makeStringFromIsRootWorkflow(isRootWorkflow?: boolean | null): string { + if (isRootWorkflow) { + return 'freeText=root_wf'; + } + + return 'freeText=*'; +} + +export function makeStringFromPagination(paginationArgs: PaginationArgs): string { + const { size, start } = paginationArgs; + + return `size=${size ?? 100}&start=${start ?? 0}`; +} + +export function makeStringQueryFromSearchQueryObject( + searchQuery?: SearchQuery | null, + paginationArgs?: PaginationArgs | null, +): string { + const result = []; + + if (searchQuery) { + const { isRootWorkflow, query } = searchQuery; + + if (query) { + result.push(`query=${makeStringFromQuery(query)}`); + } + + result.push(makeStringFromIsRootWorkflow(isRootWorkflow)); + } else { + result.push('freeText=*'); + } + + if (paginationArgs) { + result.push(makeStringFromPagination(paginationArgs)); + } + + return result.join('&'); +} diff --git a/src/helpers/id-helper.ts b/src/helpers/id-helper.ts index 740adefb..6d40d489 100644 --- a/src/helpers/id-helper.ts +++ b/src/helpers/id-helper.ts @@ -4,6 +4,8 @@ export type DataType = | 'Zone' | 'Device' | 'Workflow' + | 'ExecutedWorkflow' + | 'ExecutedWorkflowTask' | 'Label' | 'Location' | 'Country' @@ -16,6 +18,8 @@ function isDataType(value: string): value is DataType { value === 'Zone' || value === 'Device' || value === 'Workflow' || + value === 'ExecutedWorkflow' || + value === 'ExecutedWorkflowTask' || value === 'Label' || value === 'Location' || value === 'Country' || diff --git a/src/helpers/omit-null-value.ts b/src/helpers/omit-null-value.ts deleted file mode 100644 index 3d419040..00000000 --- a/src/helpers/omit-null-value.ts +++ /dev/null @@ -1,10 +0,0 @@ -export function omitNullValue(item: T | null | undefined): item is T { - return !!item; -} - -export function omitMaybeType(item: T | null | undefined): T | null { - if (item == null) { - return null; - } - return item; -} diff --git a/src/helpers/topology.helpers.ts b/src/helpers/topology.helpers.ts index 3a350734..917c18a5 100644 --- a/src/helpers/topology.helpers.ts +++ b/src/helpers/topology.helpers.ts @@ -7,7 +7,7 @@ import { Status, TopologyDiffOutput, } from '../external-api/topology-network-types'; -import unwrap from './unwrap'; +import { unwrap } from './utils.helpers'; type FilterInput = { labelIds?: string[] | null; diff --git a/src/helpers/unwrap.ts b/src/helpers/unwrap.ts deleted file mode 100644 index 8c49a586..00000000 --- a/src/helpers/unwrap.ts +++ /dev/null @@ -1,6 +0,0 @@ -export default function unwrap(value: T | null | undefined): T { - if (value == null) { - throw new Error(`value is of type ${typeof value}`); - } - return value; -} diff --git a/src/helpers/utils.helpers.ts b/src/helpers/utils.helpers.ts new file mode 100644 index 00000000..59d4d7eb --- /dev/null +++ b/src/helpers/utils.helpers.ts @@ -0,0 +1,25 @@ +export function unwrap(value: T | null | undefined): T { + if (value == null) { + throw new Error(`value is of type ${typeof value}`); + } + return value; +} + +export function omitNullValue(item: T | null | undefined): item is T { + return !!item; +} + +export function omitMaybeType(item: T | null | undefined): T | null { + if (item == null) { + return null; + } + return item; +} + +export function isValidType(key: string, obj: unknown): obj is T { + if (typeof obj !== 'object' || obj == null) { + return false; + } + + return key in obj; +} diff --git a/src/helpers/workflow.helpers.ts b/src/helpers/workflow.helpers.ts new file mode 100644 index 00000000..73b1fb4d --- /dev/null +++ b/src/helpers/workflow.helpers.ts @@ -0,0 +1,38 @@ +import { PaginationArgs, SearchQuery } from './conductor.helpers'; + +type GraphQLSearchQuery = { + isRootWorkflow?: boolean | null; + query?: { + freeText?: string | null; + startTime?: { + from: string; + to?: string | null; + } | null; + workflowId?: string[] | null; + workflowType?: string[] | null; + } | null; +}; + +export function makeSearchQueryFromArgs(searchQuery?: GraphQLSearchQuery | null): SearchQuery { + return { + ...searchQuery, + query: { + ...searchQuery?.query, + startTime: searchQuery?.query?.startTime + ? { + from: Date.parse(searchQuery.query.startTime.from), + to: searchQuery.query.startTime.to ? Date.parse(searchQuery.query.startTime.to) : undefined, + } + : undefined, + }, + }; +} + +export function makePaginationFromArgs(pagination?: PaginationArgs | null) { + return pagination != null + ? { + size: pagination.size + 1, + start: pagination.start, + } + : null; +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index b0b502d0..9b847548 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -259,6 +259,99 @@ type EdgeSourceTarget { nodeId: String! } +type ExecutedWorkflow implements Node { + createdAt: String + createdBy: String + endTime: String + failedReferenceTaskNames: [String] + id: ID! + input: String + lastRetriedTime: String + output: String + ownerApp: String + parentWorkflowId: String + reasonForIncompletion: String + startTime: String + status: ExecutedWorkflowStatus + tasks: [ExecutedWorkflowTask] + updatedAt: String + updatedBy: String + variables: String + workflowDefinition: Workflow + workflowId: String + workflowName: String + workflowVersion: Int +} + +type ExecutedWorkflowConnection { + edges: [ExecutedWorkflowEdge!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type ExecutedWorkflowEdge { + cursor: String! + node: ExecutedWorkflow! +} + +input ExecutedWorkflowFilterInput { + startTime: ExecutedWorkflowStartTimeRange + status: [ExecutedWorkflowStatus!] + workflowId: [String!] + workflowType: [String!] +} + +input ExecutedWorkflowSearchInput { + isRootWorkflow: Boolean + query: ExecutedWorkflowFilterInput +} + +input ExecutedWorkflowStartTimeRange { + from: String! + to: String +} + +enum ExecutedWorkflowStatus { + COMPLETED + FAILED + PAUSED + RUNNING + TERMINATED + TIMED_OUT +} + +type ExecutedWorkflowTask implements Node { + endTime: String + executed: Boolean + id: ID! + reasonForIncompletion: String + retried: Boolean + retryCount: Int + scheduledTime: String + startTime: String + status: ExecutedWorkflowTaskStatus + subWorkflowId: String + taskDefName: String + taskDefinition: String + taskId: String + taskReferenceName: String + taskType: String + updateTime: String + workflowType: String +} + +enum ExecutedWorkflowTaskStatus { + CANCELED + COMPLETED + COMPLETED_WITH_ERROR + FAILED + FAILED_WITH_TERMINAL_ERROR + IN_PROGRESS + SCHEDULED + SKIPPED + TIMED_OUT +} + input FilterDevicesInput { deviceName: String labels: [String!] @@ -399,6 +492,11 @@ type PageInfo { startCursor: String } +input PaginationArgs { + size: Int! + start: Int! +} + type Query { blueprints(after: String, before: String, first: Int, last: Int): BlueprintConnection! calculatedDiff(deviceId: String!, transactionId: String!): CalculatedDiffPayload! @@ -412,6 +510,7 @@ type Query { last: Int orderBy: DeviceOrderByInput ): DeviceConnection! + executedWorkflows(pagination: PaginationArgs, searchQuery: ExecutedWorkflowSearchInput): ExecutedWorkflowConnection labels(after: String, before: String, first: Int, last: Int): LabelConnection! locations(after: String, before: String, first: Int, last: Int): LocationConnection! node(id: ID!): Node diff --git a/src/schema/executed-workflow.ts b/src/schema/executed-workflow.ts new file mode 100644 index 00000000..1e87a7cc --- /dev/null +++ b/src/schema/executed-workflow.ts @@ -0,0 +1,148 @@ +import { arg, enumType, inputObjectType, objectType, queryField } from 'nexus'; +import { v4 as uuid } from 'uuid'; +import config from '../config'; +import { toGraphId } from '../helpers/id-helper'; +import { makePaginationFromArgs, makeSearchQueryFromArgs } from '../helpers/workflow.helpers'; +import { Node, PageInfo } from './global-types'; +import { ExecutedWorkflowTask } from './task'; +import { Workflow } from './workflow'; + +export const ExecutedWorkflowStatus = enumType({ + name: 'ExecutedWorkflowStatus', + members: ['RUNNING', 'COMPLETED', 'FAILED', 'TERMINATED', 'TIMED_OUT', 'PAUSED'], +}); + +export const ExecutedWorkflow = objectType({ + name: 'ExecutedWorkflow', + definition(t) { + t.implements(Node); + t.nonNull.id('id', { + resolve: (executedWorkflow) => toGraphId('ExecutedWorkflow', executedWorkflow.workflowId ?? uuid()), + }); + t.string('createdBy', { resolve: (executedWorkflow) => executedWorkflow.createdBy ?? null }); + t.string('updatedBy', { resolve: (workflow) => workflow.updatedBy ?? null }); + t.string('createdAt', { + resolve: (workflow) => (workflow.createTime ? new Date(workflow.createTime).toISOString() : null), + }); + t.string('updatedAt', { + resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), + }); + t.field('status', { type: ExecutedWorkflowStatus }); + t.string('parentWorkflowId'); + t.string('ownerApp'); + t.string('input', { resolve: (workflow) => JSON.stringify(workflow.input) }); + t.string('output', { resolve: (workflow) => JSON.stringify(workflow.output) }); + t.string('reasonForIncompletion'); + t.list.string('failedReferenceTaskNames'); + t.field('workflowDefinition', { type: Workflow }); + t.string('variables', { resolve: (workflow) => JSON.stringify(workflow.variables) }); + t.string('lastRetriedTime', { + resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), + }); + t.string('startTime', { + resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), + }); + t.string('endTime', { + resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), + }); + t.int('workflowVersion'); + t.string('workflowName'); + t.string('workflowId'); + t.list.field('tasks', { + type: ExecutedWorkflowTask, + }); + }, +}); + +export const ExecutedWorkflowEdge = objectType({ + name: 'ExecutedWorkflowEdge', + definition: (t) => { + t.nonNull.field('node', { + type: ExecutedWorkflow, + }); + t.nonNull.string('cursor'); + }, +}); + +export const ExecutedWorkflowConnection = objectType({ + name: 'ExecutedWorkflowConnection', + definition: (t) => { + t.nonNull.list.nonNull.field('edges', { + type: ExecutedWorkflowEdge, + }); + t.nonNull.field('pageInfo', { + type: PageInfo, + }); + t.nonNull.int('totalCount'); + }, +}); + +export const ExecutedWorkflowStartTimeRange = inputObjectType({ + name: 'ExecutedWorkflowStartTimeRange', + definition: (t) => { + t.nonNull.string('from'); + t.string('to'); + }, +}); + +export const ExecutedWorkflowFilterInput = inputObjectType({ + name: 'ExecutedWorkflowFilterInput', + definition: (t) => { + t.list.nonNull.string('workflowId'); + t.list.nonNull.string('workflowType'); + t.list.nonNull.field('status', { type: ExecutedWorkflowStatus }); + t.field('startTime', { type: ExecutedWorkflowStartTimeRange }); + }, +}); + +export const ExecutedWorkflowSearchInput = inputObjectType({ + name: 'ExecutedWorkflowSearchInput', + definition: (t) => { + t.boolean('isRootWorkflow'); + t.field('query', { type: ExecutedWorkflowFilterInput }); + }, +}); + +export const PaginationArgs = inputObjectType({ + name: 'PaginationArgs', + definition: (t) => { + t.nonNull.int('size'); + t.nonNull.int('start'); + }, +}); + +export const ExecutedWorkflowsQuery = queryField('executedWorkflows', { + type: ExecutedWorkflowConnection, + args: { + pagination: arg({ type: PaginationArgs }), + searchQuery: arg({ type: ExecutedWorkflowSearchInput }), + }, + resolve: async (_, args, { conductorAPI }) => { + const { results: executedWorkflows } = await conductorAPI.getExecutedWorkflows( + config.conductorApiURL, + makeSearchQueryFromArgs(args.searchQuery), + makePaginationFromArgs(args.pagination), + ); + + const executedWorkflowsWithId = executedWorkflows + .map((w) => ({ + ...w, + id: toGraphId('ExecutedWorkflow', w.workflowId || uuid()), + })) + .slice(0, args.pagination?.size ?? 0 - 1); + + return { + edges: executedWorkflowsWithId.map((w) => ({ + node: w, + cursor: w.id, + })), + pageInfo: { + hasNextPage: args.pagination ? executedWorkflowsWithId.length < executedWorkflows.length : false, + hasPreviousPage: args.pagination ? args.pagination.start >= args.pagination.size : false, + endCursor: executedWorkflowsWithId[executedWorkflowsWithId.length - 1]?.id, + startCursor: executedWorkflowsWithId[0]?.id, + }, + totalCount: executedWorkflows.length, + }; + }, +}); diff --git a/src/schema/global-types.ts b/src/schema/global-types.ts index 52be1269..41b11f4e 100644 --- a/src/schema/global-types.ts +++ b/src/schema/global-types.ts @@ -1,8 +1,8 @@ import countries from 'i18n-iso-countries'; import { extendType, idArg, intArg, interfaceType, nonNull, objectType, stringArg } from 'nexus'; -import { fromGraphId, getType } from '../helpers/id-helper'; -import conductorAPI from '../external-api/conductor'; import config from '../config'; +import conductorAPI from '../external-api/conductor'; +import { fromGraphId, getType } from '../helpers/id-helper'; export const Node = interfaceType({ name: 'Node', @@ -105,6 +105,14 @@ export const NodeQuery = extendType({ } return { ...workflow, id: args.id, __typename: 'Workflow' }; } + case 'ExecutedWorkflow': { + const id = fromGraphId('ExecutedWorkflow', args.id); + const workflow = await conductorAPI.getExecutedWorkflowDetail(config.conductorApiURL, id); + if (workflow == null) { + return null; + } + return { ...workflow, id: args.id, __typename: 'ExecutedWorkflow' }; + } /* eslint-enable */ default: return null; diff --git a/src/schema/index.ts b/src/schema/index.ts index b9c69eea..1da56472 100644 --- a/src/schema/index.ts +++ b/src/schema/index.ts @@ -10,6 +10,8 @@ import * as zone from './zone'; import * as transaction from './transaction'; import * as topology from './topology'; import * as workflow from './workflow'; +import * as executedWorkflow from './executed-workflow'; +import * as executedWorkflowTask from './task'; export default makeSchema({ features: { @@ -27,7 +29,20 @@ export default makeSchema({ schema: join(__dirname, './api.graphql'), }, shouldExitAfterGenerateArtifacts: Boolean(process.env.NEXUS_SHOULD_EXIT_AFTER_REFLECTION), - types: [globalTypes, device, zone, dataStore, label, location, blueprint, transaction, topology, workflow], + types: [ + globalTypes, + device, + zone, + dataStore, + label, + location, + blueprint, + transaction, + topology, + workflow, + executedWorkflow, + executedWorkflowTask, + ], sourceTypes: { modules: [ { diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 70cb43d3..761c9175 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -98,6 +98,23 @@ export interface NexusGenInputs { direction: NexusGenEnums['SortDirection']; // SortDirection! sortKey: NexusGenEnums['SortDeviceBy']; // SortDeviceBy! }; + ExecutedWorkflowFilterInput: { + // input type + startTime?: NexusGenInputs['ExecutedWorkflowStartTimeRange'] | null; // ExecutedWorkflowStartTimeRange + status?: NexusGenEnums['ExecutedWorkflowStatus'][] | null; // [ExecutedWorkflowStatus!] + workflowId?: string[] | null; // [String!] + workflowType?: string[] | null; // [String!] + }; + ExecutedWorkflowSearchInput: { + // input type + isRootWorkflow?: boolean | null; // Boolean + query?: NexusGenInputs['ExecutedWorkflowFilterInput'] | null; // ExecutedWorkflowFilterInput + }; + ExecutedWorkflowStartTimeRange: { + // input type + from: string; // String! + to?: string | null; // String + }; FilterDevicesInput: { // input type deviceName?: string | null; // String @@ -113,6 +130,11 @@ export interface NexusGenInputs { x: number; // Float! y: number; // Float! }; + PaginationArgs: { + // input type + size: number; // Int! + start: number; // Int! + }; UpdateBlueprintInput: { // input type name?: string | null; // String @@ -145,6 +167,17 @@ export interface NexusGenEnums { DeviceServiceState: 'IN_SERVICE' | 'OUT_OF_SERVICE' | 'PLANNING'; DeviceSize: 'LARGE' | 'MEDIUM' | 'SMALL'; DeviceSource: 'DISCOVERED' | 'IMPORTED' | 'MANUAL'; + ExecutedWorkflowStatus: 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT'; + ExecutedWorkflowTaskStatus: + | 'CANCELED' + | 'COMPLETED' + | 'COMPLETED_WITH_ERROR' + | 'FAILED' + | 'FAILED_WITH_TERMINAL_ERROR' + | 'IN_PROGRESS' + | 'SCHEDULED' + | 'SKIPPED' + | 'TIMED_OUT'; GraphEdgeStatus: 'ok' | 'unknown'; SortDeviceBy: 'CREATED_AT' | 'NAME'; SortDirection: 'ASC' | 'DESC'; @@ -290,6 +323,19 @@ export interface NexusGenObjects { interface: string; // String! nodeId: string; // String! }; + ExecutedWorkflow: SourceTypes.ExecutedWorkflow; + ExecutedWorkflowConnection: { + // root type + edges: NexusGenRootTypes['ExecutedWorkflowEdge'][]; // [ExecutedWorkflowEdge!]! + pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! + totalCount: number; // Int! + }; + ExecutedWorkflowEdge: { + // root type + cursor: string; // String! + node: NexusGenRootTypes['ExecutedWorkflow']; // ExecutedWorkflow! + }; + ExecutedWorkflowTask: SourceTypes.ExecutedWorkflowTask; GraphEdge: { // root type id: string; // ID! @@ -473,6 +519,8 @@ export interface NexusGenInterfaces { | core.Discriminate<'Blueprint', 'required'> | core.Discriminate<'Country', 'required'> | core.Discriminate<'Device', 'required'> + | core.Discriminate<'ExecutedWorkflow', 'required'> + | core.Discriminate<'ExecutedWorkflowTask', 'required'> | core.Discriminate<'Label', 'required'> | core.Discriminate<'Location', 'required'> | core.Discriminate<'Workflow', 'required'> @@ -651,6 +699,61 @@ export interface NexusGenFieldTypes { interface: string; // String! nodeId: string; // String! }; + ExecutedWorkflow: { + // field return type + createdAt: string | null; // String + createdBy: string | null; // String + endTime: string | null; // String + failedReferenceTaskNames: Array | null; // [String] + id: string; // ID! + input: string | null; // String + lastRetriedTime: string | null; // String + output: string | null; // String + ownerApp: string | null; // String + parentWorkflowId: string | null; // String + reasonForIncompletion: string | null; // String + startTime: string | null; // String + status: NexusGenEnums['ExecutedWorkflowStatus'] | null; // ExecutedWorkflowStatus + tasks: Array | null; // [ExecutedWorkflowTask] + updatedAt: string | null; // String + updatedBy: string | null; // String + variables: string | null; // String + workflowDefinition: NexusGenRootTypes['Workflow'] | null; // Workflow + workflowId: string | null; // String + workflowName: string | null; // String + workflowVersion: number | null; // Int + }; + ExecutedWorkflowConnection: { + // field return type + edges: NexusGenRootTypes['ExecutedWorkflowEdge'][]; // [ExecutedWorkflowEdge!]! + pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! + totalCount: number; // Int! + }; + ExecutedWorkflowEdge: { + // field return type + cursor: string; // String! + node: NexusGenRootTypes['ExecutedWorkflow']; // ExecutedWorkflow! + }; + ExecutedWorkflowTask: { + // field return type + endTime: string | null; // String + executed: boolean | null; // Boolean + id: string; // ID! + reasonForIncompletion: string | null; // String + retried: boolean | null; // Boolean + retryCount: number | null; // Int + scheduledTime: string | null; // String + startTime: string | null; // String + status: NexusGenEnums['ExecutedWorkflowTaskStatus'] | null; // ExecutedWorkflowTaskStatus + subWorkflowId: string | null; // String + taskDefName: string | null; // String + taskDefinition: string | null; // String + taskId: string | null; // String + taskReferenceName: string | null; // String + taskType: string | null; // String + updateTime: string | null; // String + workflowType: string | null; // String + }; GraphEdge: { // field return type id: string; // ID! @@ -774,6 +877,7 @@ export interface NexusGenFieldTypes { countries: NexusGenRootTypes['CountryConnection']; // CountryConnection! dataStore: NexusGenRootTypes['DataStore'] | null; // DataStore devices: NexusGenRootTypes['DeviceConnection']; // DeviceConnection! + executedWorkflows: NexusGenRootTypes['ExecutedWorkflowConnection'] | null; // ExecutedWorkflowConnection labels: NexusGenRootTypes['LabelConnection']; // LabelConnection! locations: NexusGenRootTypes['LocationConnection']; // LocationConnection! node: NexusGenRootTypes['Node'] | null; // Node @@ -1081,6 +1185,61 @@ export interface NexusGenFieldTypeNames { interface: 'String'; nodeId: 'String'; }; + ExecutedWorkflow: { + // field return type name + createdAt: 'String'; + createdBy: 'String'; + endTime: 'String'; + failedReferenceTaskNames: 'String'; + id: 'ID'; + input: 'String'; + lastRetriedTime: 'String'; + output: 'String'; + ownerApp: 'String'; + parentWorkflowId: 'String'; + reasonForIncompletion: 'String'; + startTime: 'String'; + status: 'ExecutedWorkflowStatus'; + tasks: 'ExecutedWorkflowTask'; + updatedAt: 'String'; + updatedBy: 'String'; + variables: 'String'; + workflowDefinition: 'Workflow'; + workflowId: 'String'; + workflowName: 'String'; + workflowVersion: 'Int'; + }; + ExecutedWorkflowConnection: { + // field return type name + edges: 'ExecutedWorkflowEdge'; + pageInfo: 'PageInfo'; + totalCount: 'Int'; + }; + ExecutedWorkflowEdge: { + // field return type name + cursor: 'String'; + node: 'ExecutedWorkflow'; + }; + ExecutedWorkflowTask: { + // field return type name + endTime: 'String'; + executed: 'Boolean'; + id: 'ID'; + reasonForIncompletion: 'String'; + retried: 'Boolean'; + retryCount: 'Int'; + scheduledTime: 'String'; + startTime: 'String'; + status: 'ExecutedWorkflowTaskStatus'; + subWorkflowId: 'String'; + taskDefName: 'String'; + taskDefinition: 'String'; + taskId: 'String'; + taskReferenceName: 'String'; + taskType: 'String'; + updateTime: 'String'; + workflowType: 'String'; + }; GraphEdge: { // field return type name id: 'ID'; @@ -1204,6 +1363,7 @@ export interface NexusGenFieldTypeNames { countries: 'CountryConnection'; dataStore: 'DataStore'; devices: 'DeviceConnection'; + executedWorkflows: 'ExecutedWorkflowConnection'; labels: 'LabelConnection'; locations: 'LocationConnection'; node: 'Node'; @@ -1497,6 +1657,11 @@ export interface NexusGenArgTypes { last?: number | null; // Int orderBy?: NexusGenInputs['DeviceOrderByInput'] | null; // DeviceOrderByInput }; + executedWorkflows: { + // args + pagination?: NexusGenInputs['PaginationArgs'] | null; // PaginationArgs + searchQuery?: NexusGenInputs['ExecutedWorkflowSearchInput'] | null; // ExecutedWorkflowSearchInput + }; labels: { // args after?: string | null; // String @@ -1554,13 +1719,24 @@ export interface NexusGenArgTypes { export interface NexusGenAbstractTypeMembers { BaseGraphNode: 'GraphNode' | 'GraphVersionNode'; - Node: 'Blueprint' | 'Country' | 'Device' | 'Label' | 'Location' | 'Workflow' | 'Zone'; + Node: + | 'Blueprint' + | 'Country' + | 'Device' + | 'ExecutedWorkflow' + | 'ExecutedWorkflowTask' + | 'Label' + | 'Location' + | 'Workflow' + | 'Zone'; } export interface NexusGenTypeInterfaces { Blueprint: 'Node'; Country: 'Node'; Device: 'Node'; + ExecutedWorkflow: 'Node'; + ExecutedWorkflowTask: 'Node'; GraphNode: 'BaseGraphNode'; GraphVersionNode: 'BaseGraphNode'; Label: 'Node'; diff --git a/src/schema/source-types.ts b/src/schema/source-types.ts index fd33f657..43b6eb63 100644 --- a/src/schema/source-types.ts +++ b/src/schema/source-types.ts @@ -1,5 +1,10 @@ import { blueprint, device, label, location, uniconfigZone } from '@prisma/client'; -import { ApiWorkflow, NestedTask } from '../external-api/conductor-network-types'; +import { + ApiExecutedWorkflow, + ApiExecutedWorkflowTask, + ApiWorkflow, + NestedTask, +} from '../external-api/conductor-network-types'; export type Label = label; export type Device = device; @@ -17,4 +22,6 @@ export type Country = { }; export type Blueprint = blueprint; export type Workflow = ApiWorkflow & { id: string }; +export type ExecutedWorkflow = ApiExecutedWorkflow & { id: string }; +export type ExecutedWorkflowTask = ApiExecutedWorkflowTask & { id: string }; export type WorkflowTask = NestedTask; diff --git a/src/schema/task.ts b/src/schema/task.ts new file mode 100644 index 00000000..0d727670 --- /dev/null +++ b/src/schema/task.ts @@ -0,0 +1,52 @@ +import { enumType, objectType } from 'nexus'; +import { v4 as uuid } from 'uuid'; +import { toGraphId } from '../helpers/id-helper'; + +export const ExecutedWorkflowTaskStatus = enumType({ + name: 'ExecutedWorkflowTaskStatus', + members: [ + 'IN_PROGRESS', + 'COMPLETED', + 'FAILED', + 'TIMED_OUT', + 'CANCELED', + 'SCHEDULED', + 'SKIPPED', + 'FAILED_WITH_TERMINAL_ERROR', + 'COMPLETED_WITH_ERROR', + ], +}); + +export const ExecutedWorkflowTask = objectType({ + name: 'ExecutedWorkflowTask', + definition: (t) => { + t.implements('Node'); + t.nonNull.id('id', { + resolve: (executedWorkflowTask) => toGraphId('ExecutedWorkflowTask', executedWorkflowTask.taskId ?? uuid()), + }); + t.string('taskType'); + t.string('taskReferenceName'); + t.field('status', { type: ExecutedWorkflowTaskStatus }); + t.int('retryCount'); + t.string('startTime', { + resolve: (task) => (task.startTime ? new Date(task.startTime).toISOString() : null), + }); + t.string('endTime', { + resolve: (task) => (task.endTime ? new Date(task.endTime).toISOString() : null), + }); + t.string('updateTime', { + resolve: (task) => (task.updateTime ? new Date(task.updateTime).toISOString() : null), + }); + t.string('scheduledTime', { + resolve: (task) => (task.scheduledTime ? new Date(task.scheduledTime).toISOString() : null), + }); + t.string('taskDefName'); + t.string('workflowType'); + t.boolean('retried'); + t.boolean('executed'); + t.string('taskId'); + t.string('reasonForIncompletion'); + t.string('taskDefinition', { resolve: (task) => JSON.stringify(task.taskDefinition) }); + t.string('subWorkflowId'); + }, +}); diff --git a/src/schema/topology.ts b/src/schema/topology.ts index eb98ee7b..8e2ad294 100644 --- a/src/schema/topology.ts +++ b/src/schema/topology.ts @@ -1,7 +1,6 @@ import { extendType, inputObjectType, nonNull, list, objectType, stringArg, enumType, arg, interfaceType } from 'nexus'; import config from '../config'; import { toGraphId } from '../helpers/id-helper'; -import { omitNullValue } from '../helpers/omit-null-value'; import { getFilterQuery, getOldTopologyConnectedEdges, @@ -12,7 +11,7 @@ import { makeInterfaceNameMap, makeNodesMap, } from '../helpers/topology.helpers'; -import unwrap from '../helpers/unwrap'; +import { unwrap, omitNullValue } from '../helpers/utils.helpers'; export const FilterTopologyInput = inputObjectType({ name: 'FilterTopologyInput', diff --git a/src/schema/transaction.ts b/src/schema/transaction.ts index 0a340f3d..955b8c4e 100644 --- a/src/schema/transaction.ts +++ b/src/schema/transaction.ts @@ -1,7 +1,7 @@ import { extendType, list, nonNull, objectType, stringArg } from 'nexus'; import { SuccessTransactionType, TransactionType } from '../external-api/network-types'; import { fromGraphId } from '../helpers/id-helper'; -import unwrap from '../helpers/unwrap'; +import { unwrap } from '../helpers/utils.helpers'; import { getUniconfigURL, makeUniconfigURL } from '../helpers/zone.helpers'; import { Device } from './device'; From 9ff7af053892d1863229a7aaf28991e74e44b3f2 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Mon, 27 Mar 2023 11:14:57 +0200 Subject: [PATCH 03/69] Pause resume wf mutations (#265) * bump version 1.8.3 (#263) * create pause and resume mutation with bulk ones * add env variable for github action --------- Co-authored-by: Martin Sottnik --- .github/workflows/pr-check.yml | 1 + package.json | 2 +- src/external-api/conductor-network-types.ts | 11 +++ src/external-api/conductor.ts | 56 +++++++++++++-- src/schema/api.graphql | 9 +++ src/schema/nexus-typegen.ts | 38 +++++++++++ src/schema/workflow.ts | 76 ++++++++++++++++++++- 7 files changed, 187 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index fbed3930..82031f73 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -42,6 +42,7 @@ jobs: X_TENANT_ID: frinx TOPOLOGY_ENABLED: false SHELL_HOST: 10.19.0.12 + CONDUCTOR_API_URL: 10.19.0.7 - name: Check code formatting run: yarn run formatter:check - name: Run eslint check diff --git a/package.json b/package.json index 736aa46c..ae4d508a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@frinx/inventory-server", - "version": "1.8.2", + "version": "1.8.3", "engines": { "node": "18" }, diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index 501fffdc..743d7d1b 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -73,6 +73,11 @@ const WorkflowMetadata = t.type({ const WorkflowMetadataValidator = t.array(WorkflowMetadata); +const BulkOperation = t.type({ + bulkErrorResults: t.record(t.string, t.string), + bulkSuccessfulResults: t.array(t.string), +}); + const ExecutedWorkflowTaskStatus = t.union([ t.literal('IN_PROGRESS'), t.literal('COMPLETED'), @@ -186,6 +191,12 @@ export function decodeWorkflowDetailOutput(value: unknown): WorkflowDetailOutput return extractResult(WorkflowMetadata.decode(value)); } +export type BulkOperationOutput = t.TypeOf; + +export function decodeBulkOperationOutput(value: unknown): BulkOperationOutput { + return extractResult(BulkOperation.decode(value)); +} + export function decodeExecutedWorkflowsOutput(value: unknown): ExecutedWorkflowsOutput { return extractResult(ExecutedWorkflowsValidator.decode(value)); } diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts index e4d6b835..b1af77a3 100644 --- a/src/external-api/conductor.ts +++ b/src/external-api/conductor.ts @@ -1,15 +1,17 @@ import { makeStringQueryFromSearchQueryObject, PaginationArgs, SearchQuery } from '../helpers/conductor.helpers'; import { + BulkOperationOutput, + decodeBulkOperationOutput, ApiExecutedWorkflow, - decodeExecutedWorkflowDetailOutput, - decodeExecutedWorkflowsOutput, decodeWorkflowDetailOutput, decodeWorkflowMetadataOutput, - ExecutedWorkflowsOutput, WorfklowMetadataOutput, WorkflowDetailOutput, + decodeExecutedWorkflowDetailOutput, + decodeExecutedWorkflowsOutput, + ExecutedWorkflowsOutput, } from './conductor-network-types'; -import { sendGetRequest } from './helpers'; +import { sendGetRequest, sendPutRequest } from './helpers'; async function getWorkflowMetadata(baseURL: string): Promise { const json = await sendGetRequest([baseURL, 'metadata/workflow']); @@ -23,6 +25,48 @@ async function getWorkflowDetail(baseURL: string, workflowName: string): Promise return data; } +async function pauseWorkflow(baseURL: string, workflowId: string): Promise { + try { + const json = await sendPutRequest([baseURL, `workflow/${workflowId}/pause`]); + + return String(json); + } catch (error) { + throw new Error("Workflow couldn't be paused"); + } +} + +async function resumeWorkflow(baseURL: string, workflowId: string): Promise { + try { + const json = await sendPutRequest([baseURL, `workflow/${workflowId}/resume`]); + + return String(json); + } catch (error) { + throw new Error("Workflow couldn't be resumed"); + } +} + +async function bulkResumeWorkflow(baseURL: string, workflowIds: string[]): Promise { + try { + const json = await sendPutRequest([baseURL, `workflow/bulk/resume`], workflowIds); + const data = decodeBulkOperationOutput(json); + + return data; + } catch (error) { + throw new Error('Bulk resume of workflows was not successful'); + } +} + +async function bulkPauseWorkflow(baseURL: string, workflowIds: string[]): Promise { + try { + const json = await sendPutRequest([baseURL, `workflow/bulk/pause`], workflowIds); + const data = decodeBulkOperationOutput(json); + + return data; + } catch (error) { + throw new Error('Bulk pause of workflows was not successful'); + } +} + async function getExecutedWorkflows( baseURL: string, query?: SearchQuery | null, @@ -45,6 +89,10 @@ async function getExecutedWorkflowDetail(baseURL: string, workflowId: string): P const conductorAPI = { getWorkflowMetadata, getWorkflowDetail, + pauseWorkflow, + resumeWorkflow, + bulkResumeWorkflow, + bulkPauseWorkflow, getExecutedWorkflows, getExecutedWorkflowDetail, }; diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 9b847548..3ca9a299 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -95,6 +95,11 @@ type BlueprintEdge { node: Blueprint! } +type BulkOperationResponse { + bulkErrorResults: String + bulkSuccessfulResults: [String!] +} + type CSVImport { isOk: Boolean } @@ -461,6 +466,8 @@ type Mutation { addSnapshot(input: AddSnapshotInput!, transactionId: String!): AddSnapshotPayload addZone(input: AddZoneInput!): AddZonePayload! applySnapshot(input: ApplySnapshotInput!, transactionId: String!): ApplySnapshotPayload! + bulkPauseWorkflow(workflowIds: [String!]!): BulkOperationResponse + bulkResumeWorkflow(workflowIds: [String!]!): BulkOperationResponse closeTransaction(deviceId: String!, transactionId: String!): CloseTransactionPayload! commitConfig(input: CommitConfigInput!, transactionId: String!): CommitConfigPayload! createLabel(input: CreateLabelInput!): CreateLabelPayload! @@ -471,7 +478,9 @@ type Mutation { deleteSnapshot(input: DeleteSnapshotInput!): DeleteSnapshotPayload importCSV(input: CSVImportInput!): CSVImport installDevice(id: String!): InstallDevicePayload! + pauseWorkflow(workflowId: String!): String resetConfig(deviceId: String!, transactionId: String!): ResetConfigPayload! + resumeWorkflow(workflowId: String!): String revertChanges(transactionId: String!): RevertChangesPayload! syncFromNetwork(deviceId: String!, transactionId: String!): SyncFromNetworkPayload! uninstallDevice(id: String!): UninstallDevicePayload! diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 761c9175..e10d12d3 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -230,6 +230,10 @@ export interface NexusGenObjects { cursor: string; // String! node: NexusGenRootTypes['Blueprint']; // Blueprint! }; + BulkOperationResponse: { + // root type + bulkSuccessfulResults?: string[] | null; // [String!] + }; CSVImport: { // root type isOk?: boolean | null; // Boolean @@ -578,6 +582,11 @@ export interface NexusGenFieldTypes { cursor: string; // String! node: NexusGenRootTypes['Blueprint']; // Blueprint! }; + BulkOperationResponse: { + // field return type + bulkErrorResults: string | null; // String + bulkSuccessfulResults: string[] | null; // [String!] + }; CSVImport: { // field return type isOk: boolean | null; // Boolean @@ -844,6 +853,8 @@ export interface NexusGenFieldTypes { addSnapshot: NexusGenRootTypes['AddSnapshotPayload'] | null; // AddSnapshotPayload addZone: NexusGenRootTypes['AddZonePayload']; // AddZonePayload! applySnapshot: NexusGenRootTypes['ApplySnapshotPayload']; // ApplySnapshotPayload! + bulkPauseWorkflow: NexusGenRootTypes['BulkOperationResponse'] | null; // BulkOperationResponse + bulkResumeWorkflow: NexusGenRootTypes['BulkOperationResponse'] | null; // BulkOperationResponse closeTransaction: NexusGenRootTypes['CloseTransactionPayload']; // CloseTransactionPayload! commitConfig: NexusGenRootTypes['CommitConfigPayload']; // CommitConfigPayload! createLabel: NexusGenRootTypes['CreateLabelPayload']; // CreateLabelPayload! @@ -854,7 +865,9 @@ export interface NexusGenFieldTypes { deleteSnapshot: NexusGenRootTypes['DeleteSnapshotPayload'] | null; // DeleteSnapshotPayload importCSV: NexusGenRootTypes['CSVImport'] | null; // CSVImport installDevice: NexusGenRootTypes['InstallDevicePayload']; // InstallDevicePayload! + pauseWorkflow: string | null; // String resetConfig: NexusGenRootTypes['ResetConfigPayload']; // ResetConfigPayload! + resumeWorkflow: string | null; // String revertChanges: NexusGenRootTypes['RevertChangesPayload']; // RevertChangesPayload! syncFromNetwork: NexusGenRootTypes['SyncFromNetworkPayload']; // SyncFromNetworkPayload! uninstallDevice: NexusGenRootTypes['UninstallDevicePayload']; // UninstallDevicePayload! @@ -1064,6 +1077,11 @@ export interface NexusGenFieldTypeNames { cursor: 'String'; node: 'Blueprint'; }; + BulkOperationResponse: { + // field return type name + bulkErrorResults: 'String'; + bulkSuccessfulResults: 'String'; + }; CSVImport: { // field return type name isOk: 'Boolean'; @@ -1330,6 +1348,8 @@ export interface NexusGenFieldTypeNames { addSnapshot: 'AddSnapshotPayload'; addZone: 'AddZonePayload'; applySnapshot: 'ApplySnapshotPayload'; + bulkPauseWorkflow: 'BulkOperationResponse'; + bulkResumeWorkflow: 'BulkOperationResponse'; closeTransaction: 'CloseTransactionPayload'; commitConfig: 'CommitConfigPayload'; createLabel: 'CreateLabelPayload'; @@ -1340,7 +1360,9 @@ export interface NexusGenFieldTypeNames { deleteSnapshot: 'DeleteSnapshotPayload'; importCSV: 'CSVImport'; installDevice: 'InstallDevicePayload'; + pauseWorkflow: 'String'; resetConfig: 'ResetConfigPayload'; + resumeWorkflow: 'String'; revertChanges: 'RevertChangesPayload'; syncFromNetwork: 'SyncFromNetworkPayload'; uninstallDevice: 'UninstallDevicePayload'; @@ -1542,6 +1564,14 @@ export interface NexusGenArgTypes { input: NexusGenInputs['ApplySnapshotInput']; // ApplySnapshotInput! transactionId: string; // String! }; + bulkPauseWorkflow: { + // args + workflowIds: string[]; // [String!]! + }; + bulkResumeWorkflow: { + // args + workflowIds: string[]; // [String!]! + }; closeTransaction: { // args deviceId: string; // String! @@ -1584,11 +1614,19 @@ export interface NexusGenArgTypes { // args id: string; // String! }; + pauseWorkflow: { + // args + workflowId: string; // String! + }; resetConfig: { // args deviceId: string; // String! transactionId: string; // String! }; + resumeWorkflow: { + // args + workflowId: string; // String! + }; revertChanges: { // args transactionId: string; // String! diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 9fc611da..931ed5a2 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -1,5 +1,5 @@ import { connectionFromArray } from 'graphql-relay'; -import { extendType, objectType } from 'nexus'; +import { extendType, list, mutationField, nonNull, objectType, stringArg } from 'nexus'; import config from '../config'; import { toGraphId } from '../helpers/id-helper'; import { Node, PageInfo, PaginationConnectionArgs } from './global-types'; @@ -68,3 +68,77 @@ export const WorkflowsQuery = extendType({ }); }, }); + +export const PauseWorkflowMutation = mutationField('pauseWorkflow', { + type: 'String', + args: { + workflowId: nonNull(stringArg()), + }, + resolve: async (_, { workflowId }, { conductorAPI }) => { + try { + await conductorAPI.pauseWorkflow(config.conductorApiURL, workflowId); + + return 'Workflow paused'; + } catch (error) { + throw new Error("Workflow couldn't be paused"); + } + }, +}); + +export const ResumeWorkflowMutation = mutationField('resumeWorkflow', { + type: 'String', + args: { + workflowId: nonNull(stringArg()), + }, + resolve: async (_, { workflowId }, { conductorAPI }) => { + try { + await conductorAPI.resumeWorkflow(config.conductorApiURL, workflowId); + + return 'Workflow resumed'; + } catch (error) { + throw new Error("Workflow couldn't be resumed"); + } + }, +}); + +export const BulkOperationResponse = objectType({ + name: 'BulkOperationResponse', + definition: (t) => { + t.string('bulkErrorResults', { + resolve: (response) => JSON.stringify(response.bulkErrorResults ?? null), + }); + t.list.nonNull.string('bulkSuccessfulResults'); + }, +}); + +export const BulkResumeWorkflowMutation = mutationField('bulkResumeWorkflow', { + type: BulkOperationResponse, + args: { + workflowIds: nonNull(list(nonNull(stringArg()))), + }, + resolve: async (_, { workflowIds }, { conductorAPI }) => { + try { + const data = await conductorAPI.bulkResumeWorkflow(config.conductorApiURL, workflowIds); + + return data; + } catch (error) { + throw new Error('Bulk resume of workflows was not successful'); + } + }, +}); + +export const BulkPauseWorkflowMutation = mutationField('bulkPauseWorkflow', { + type: BulkOperationResponse, + args: { + workflowIds: nonNull(list(nonNull(stringArg()))), + }, + resolve: async (_, { workflowIds }, { conductorAPI }) => { + try { + const data = await conductorAPI.bulkPauseWorkflow(config.conductorApiURL, workflowIds); + + return data; + } catch (error) { + throw new Error('Bulk pause of workflows was not successful'); + } + }, +}); From ea3582a2d38b610f623ff88d1b5d524e500d477b Mon Sep 17 00:00:00 2001 From: "marco.mruz" Date: Mon, 27 Mar 2023 12:15:23 +0200 Subject: [PATCH 04/69] fix typescript error of nonexisting property --- src/schema/nexus-typegen.ts | 1 + src/schema/workflow.ts | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index e10d12d3..b23b1e27 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -232,6 +232,7 @@ export interface NexusGenObjects { }; BulkOperationResponse: { // root type + bulkErrorResults?: string | null; // String bulkSuccessfulResults?: string[] | null; // [String!] }; CSVImport: { diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 931ed5a2..2583310f 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -104,9 +104,7 @@ export const ResumeWorkflowMutation = mutationField('resumeWorkflow', { export const BulkOperationResponse = objectType({ name: 'BulkOperationResponse', definition: (t) => { - t.string('bulkErrorResults', { - resolve: (response) => JSON.stringify(response.bulkErrorResults ?? null), - }); + t.string('bulkErrorResults'); t.list.nonNull.string('bulkSuccessfulResults'); }, }); @@ -120,7 +118,10 @@ export const BulkResumeWorkflowMutation = mutationField('bulkResumeWorkflow', { try { const data = await conductorAPI.bulkResumeWorkflow(config.conductorApiURL, workflowIds); - return data; + return { + bulkErrorResults: JSON.stringify(data.bulkErrorResults), + bulkSuccessfulResults: data.bulkSuccessfulResults, + }; } catch (error) { throw new Error('Bulk resume of workflows was not successful'); } @@ -136,7 +137,10 @@ export const BulkPauseWorkflowMutation = mutationField('bulkPauseWorkflow', { try { const data = await conductorAPI.bulkPauseWorkflow(config.conductorApiURL, workflowIds); - return data; + return { + bulkErrorResults: JSON.stringify(data.bulkErrorResults), + bulkSuccessfulResults: data.bulkSuccessfulResults, + }; } catch (error) { throw new Error('Bulk pause of workflows was not successful'); } From 47cba94c55a6c2dd9f66812800a5507e43665c2d Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Mon, 27 Mar 2023 15:43:11 +0200 Subject: [PATCH 05/69] FD-496 workflow definition mutations (#267) * workflow defintion mutations added * typo fixes; add missing fields * handling bulk result on update workflow * add CONDUCTOR_API_URL to env variables * addWorkflow renamed to createWorkflow --- src/external-api/conductor-network-types.ts | 67 ++++++--- src/external-api/conductor.ts | 33 +++- src/external-api/helpers.ts | 25 +++- src/helpers/workflow-helpers.ts | 11 ++ src/schema/api.graphql | 35 ++++- src/schema/nexus-typegen.ts | 82 +++++++++- src/schema/workflow.ts | 158 +++++++++++++++++++- 7 files changed, 377 insertions(+), 34 deletions(-) create mode 100644 src/helpers/workflow-helpers.ts diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index 743d7d1b..fd5ac8b3 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -17,48 +17,61 @@ export function extractResult(result: Either): A { )(result); } -const ApiBaseTask = t.type({ +export const ApiBaseTask = t.type({ name: t.string, taskReferenceName: t.string, - description: optional(t.string), - inputParameters: optional(t.record(t.string, t.any)), - type: optional(t.string), - dynamicTaskNameParam: optional(t.string), - scriptExpression: optional(t.string), - dynamicForkTasksParam: optional(t.string), - dynamicForkTasksInputParamName: optional(t.string), - forkTasks: optional(t.UnknownArray), + // description: optional(t.string), + // inputParameters: optional(t.record(t.string, t.any)), + // type: optional(t.string), + // dynamicTaskNameParam: optional(t.string), + // scriptExpression: optional(t.string), + // dynamicForkTasksParam: optional(t.string), + // dynamicForkTasksInputParamName: optional(t.string), + // forkTasks: optional(t.UnknownArray), }); export type BaseTask = t.TypeOf; -export type NestedTask = BaseTask & { - decisionCases: Record | void; - defaultCase: NestedTask[] | void; -}; +export type NestedTask = BaseTask & + Partial<{ + decisionCases: Record | void; + defaultCase: NestedTask[] | void; + }>; // TODO: this is properly typed nested workflow but is not used in graphql schema as // we are not able to get whole deeply nested object in graphql -const WorkflowTask: t.Type = t.recursion('NestedTask', () => +export const WorkflowTask: t.Type = t.recursion('NestedTask', () => t.intersection([ ApiBaseTask, - t.type({ + t.partial({ decisionCases: optional(t.record(t.string, t.array(WorkflowTask))), defaultCase: optional(t.array(WorkflowTask)), }), ]), ); -const WorkflowMetadata = t.type({ +// const WorkflowTask = ApiBaseTask; +const WorkflowTasksValidator = t.array(WorkflowTask); + +type WorkflowTaskInput = t.TypeOf; + +export function decodeWorkflowTaskInput(value: unknown): WorkflowTaskInput { + return extractResult(WorkflowTasksValidator.decode(value)); +} + +const WorkflowMetadataRequired = t.type({ + name: t.string, + timeoutSeconds: t.number, + tasks: t.UnknownArray, // TODO: we are passing task as stringified json for now (can we switch to WorkflowTask somehow?) +}); + +const WorkflowMetadataOptional = t.partial({ createTime: optional(t.number), updateTime: optional(t.number), createdBy: optional(t.string), updatedBy: optional(t.string), - name: t.string, description: optional(t.string), version: optional(t.number), - tasks: t.UnknownArray, // TODO: we are passing task as stringified json for now (can we switch to WorkflowTask somehow?) - timeoutSeconds: t.number, inputParameters: optional(t.array(t.string)), outputParameters: optional(t.record(t.string, t.string)), failureWorkflow: optional(t.string), @@ -71,6 +84,8 @@ const WorkflowMetadata = t.type({ inputTemplate: optional(t.record(t.string, t.UnknownRecord)), }); +const WorkflowMetadata = t.intersection([WorkflowMetadataRequired, WorkflowMetadataOptional]); + const WorkflowMetadataValidator = t.array(WorkflowMetadata); const BulkOperation = t.type({ @@ -177,20 +192,32 @@ const ExecutedWorkflowsValidator = t.type({ export type ExecutedWorkflowsOutput = t.TypeOf; export type WorfklowMetadataOutput = t.TypeOf; +export type WorkflowMetadataOutput = t.TypeOf; export type ApiWorkflow = t.TypeOf; export type ApiExecutedWorkflow = t.TypeOf; export type ApiExecutedWorkflowTask = t.TypeOf; -export function decodeWorkflowMetadataOutput(value: unknown): WorfklowMetadataOutput { +export function decodeWorkflowMetadataOutput(value: unknown): WorkflowMetadataOutput { return extractResult(WorkflowMetadataValidator.decode(value)); } export type WorkflowDetailOutput = t.TypeOf; +export type WorkflowDetailInput = t.TypeOf; export function decodeWorkflowDetailOutput(value: unknown): WorkflowDetailOutput { return extractResult(WorkflowMetadata.decode(value)); } +const WorkflowEditValidator = t.type({ + bulkErrorResults: t.record(t.string, t.string), + bulkSuccessfulResults: t.array(t.string), +}); + +export type WorkflowEditOutput = t.TypeOf; + +export function decodeWorkflowEditOutput(value: unknown): WorkflowEditOutput { + return extractResult(WorkflowEditValidator.decode(value)); +} export type BulkOperationOutput = t.TypeOf; export function decodeBulkOperationOutput(value: unknown): BulkOperationOutput { diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts index b1af77a3..bf50ad88 100644 --- a/src/external-api/conductor.ts +++ b/src/external-api/conductor.ts @@ -1,19 +1,22 @@ import { makeStringQueryFromSearchQueryObject, PaginationArgs, SearchQuery } from '../helpers/conductor.helpers'; import { BulkOperationOutput, - decodeBulkOperationOutput, ApiExecutedWorkflow, - decodeWorkflowDetailOutput, - decodeWorkflowMetadataOutput, - WorfklowMetadataOutput, - WorkflowDetailOutput, + decodeBulkOperationOutput, decodeExecutedWorkflowDetailOutput, decodeExecutedWorkflowsOutput, + decodeWorkflowDetailOutput, + decodeWorkflowEditOutput, + decodeWorkflowMetadataOutput, + WorkflowMetadataOutput, + WorkflowDetailInput, ExecutedWorkflowsOutput, + WorkflowDetailOutput, + WorkflowEditOutput, } from './conductor-network-types'; -import { sendGetRequest, sendPutRequest } from './helpers'; +import { sendDeleteRequest, sendGetRequest, sendPostRequest, sendPutRequest } from './helpers'; -async function getWorkflowMetadata(baseURL: string): Promise { +async function getWorkflowMetadata(baseURL: string): Promise { const json = await sendGetRequest([baseURL, 'metadata/workflow']); const data = decodeWorkflowMetadataOutput(json); return data; @@ -25,6 +28,19 @@ async function getWorkflowDetail(baseURL: string, workflowName: string): Promise return data; } +async function createWorkflow(baseURL: string, workflow: WorkflowDetailInput): Promise { + await sendPostRequest([baseURL, 'metadata/workflow'], workflow); +} + +async function editWorkflow(baseURL: string, workflow: WorkflowDetailInput): Promise { + const json = await sendPutRequest([baseURL, 'metadata/workflow'], [workflow]); + const data = decodeWorkflowEditOutput(json); + return data; +} + +async function deleteWorkflow(baseURL: string, name: string, version: number): Promise { + await sendDeleteRequest([baseURL, `metadata/workflow/${name}/${version}`]); +} async function pauseWorkflow(baseURL: string, workflowId: string): Promise { try { const json = await sendPutRequest([baseURL, `workflow/${workflowId}/pause`]); @@ -89,6 +105,9 @@ async function getExecutedWorkflowDetail(baseURL: string, workflowId: string): P const conductorAPI = { getWorkflowMetadata, getWorkflowDetail, + createWorkflow, + editWorkflow, + deleteWorkflow, pauseWorkflow, resumeWorkflow, bulkResumeWorkflow, diff --git a/src/external-api/helpers.ts b/src/external-api/helpers.ts index 265c6d77..7e0c53a9 100644 --- a/src/external-api/helpers.ts +++ b/src/external-api/helpers.ts @@ -78,7 +78,18 @@ async function apiFetch(path: APIPath, options: RequestInit): Promise { return response; } - const json = await response.json(); + // TODO: + // this is stupid hack because of how conductor API is working + // it always response with 200 even if it has empty body + // the change was requested (it should use 201/204 status codes) and once implemented in conductor API + // we can revert this changes to previous state + const text = await response.text(); + + if (!text.length) { + return response; + } + + const json = JSON.parse(text); logResponse(requestId, json); return json; @@ -134,3 +145,15 @@ export async function sendPatchRequest(path: APIPath, body?: unknown, cookie?: s }; return apiFetch(path, options); } + +export async function sendDeleteRequest(path: APIPath, cookie?: string): Promise { + const options = { + method: 'DELETE', + headers: { + // eslint-disable-next-line @typescript-eslint/naming-convention + 'Content-Type': 'application/json', + ...(cookie != null ? { cookie } : {}), + }, + }; + return apiFetch(path, options); +} diff --git a/src/helpers/workflow-helpers.ts b/src/helpers/workflow-helpers.ts new file mode 100644 index 00000000..908a16da --- /dev/null +++ b/src/helpers/workflow-helpers.ts @@ -0,0 +1,11 @@ +import { decodeWorkflowTaskInput, NestedTask } from '../external-api/conductor-network-types'; + +export function validateTasks(tasks: string): NestedTask[] { + try { + const json = JSON.parse(tasks); + const output = decodeWorkflowTaskInput(json); + return output; + } catch (e) { + throw new Error('tasks validation error'); + } +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 3ca9a299..354ae5c1 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -173,6 +173,14 @@ type CreateTransactionPayload { transactionId: String } +input CreateWorkflowInput { + workflow: WorkflowInput! +} + +type CreateWorkflowPayload { + workflow: Workflow! +} + type DataStore { config: String! operational: String! @@ -201,6 +209,10 @@ type DeleteSnapshotPayload { snapshot: Snapshot } +type DeleteWorkflowPayload { + workflow: Workflow! +} + type Device implements Node { address: String blueprint: Blueprint @@ -472,10 +484,12 @@ type Mutation { commitConfig(input: CommitConfigInput!, transactionId: String!): CommitConfigPayload! createLabel(input: CreateLabelInput!): CreateLabelPayload! createTransaction(deviceId: String!): CreateTransactionPayload! + createWorkflow(input: CreateWorkflowInput!): CreateWorkflowPayload! deleteBlueprint(id: String!): DeleteBlueprintPayload! deleteDevice(id: String!): DeleteDevicePayload! deleteLabel(id: String!): DeleteLabelPayload! deleteSnapshot(input: DeleteSnapshotInput!): DeleteSnapshotPayload + deleteWorkflow(name: String!, version: Int!): DeleteWorkflowPayload! importCSV(input: CSVImportInput!): CSVImport installDevice(id: String!): InstallDevicePayload! pauseWorkflow(workflowId: String!): String @@ -488,6 +502,7 @@ type Mutation { updateDataStore(deviceId: String!, input: UpdateDataStoreInput!, transactionId: String!): UpdateDataStorePayload! updateDevice(id: String!, input: UpdateDeviceInput!): UpdateDevicePayload! updateGraphNodeCoordinates(input: [GraphNodeCoordinatesInput!]!): UpdateGraphNodeCoordinatesPayload! + updateWorkflow(id: String!, input: UpdateWorkflowInput!): UpdateWorkflowPayload! } interface Node { @@ -529,7 +544,7 @@ type Query { topologyVersions: [String!] transactions: [Transaction!]! uniconfigShellSession: String - worfklows(after: String, before: String, first: Int, last: Int): WorkflowConnection! + workflows(after: String, before: String, first: Int, last: Int): WorkflowConnection! zones(after: String, before: String, first: Int, last: Int): ZonesConnection! } @@ -645,6 +660,14 @@ type UpdateGraphNodeCoordinatesPayload { deviceNames: [String!]! } +input UpdateWorkflowInput { + workflow: WorkflowInput! +} + +type UpdateWorkflowPayload { + workflow: Workflow! +} + """ The `Upload` scalar type represents a file upload. """ @@ -653,11 +676,13 @@ scalar Upload type Workflow implements Node { createdAt: String createdBy: String + description: String id: ID! name: String! tasks: String updatedAt: String updatedBy: String + version: Int } type WorkflowConnection { @@ -671,6 +696,14 @@ type WorkflowEdge { node: Workflow! } +input WorkflowInput { + description: String + name: String! + tasks: String! + timeoutSeconds: Int! + version: Int +} + type Zone implements Node { createdAt: String! id: ID! diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index b23b1e27..8a87d2ce 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -87,6 +87,10 @@ export interface NexusGenInputs { // input type name: string; // String! }; + CreateWorkflowInput: { + // input type + workflow: NexusGenInputs['WorkflowInput']; // WorkflowInput! + }; DeleteSnapshotInput: { // input type deviceId: string; // String! @@ -161,6 +165,18 @@ export interface NexusGenInputs { vendor?: string | null; // String version?: string | null; // String }; + UpdateWorkflowInput: { + // input type + workflow: NexusGenInputs['WorkflowInput']; // WorkflowInput! + }; + WorkflowInput: { + // input type + description?: string | null; // String + name: string; // String! + tasks: string; // String! + timeoutSeconds: number; // Int! + version?: number | null; // Int + }; } export interface NexusGenEnums { @@ -289,6 +305,10 @@ export interface NexusGenObjects { // root type transactionId?: string | null; // String }; + CreateWorkflowPayload: { + // root type + workflow: NexusGenRootTypes['Workflow']; // Workflow! + }; DataStore: SourceTypes.DataStore; DeleteBlueprintPayload: { // root type @@ -306,6 +326,10 @@ export interface NexusGenObjects { // root type snapshot?: NexusGenRootTypes['Snapshot'] | null; // Snapshot }; + DeleteWorkflowPayload: { + // root type + workflow: NexusGenRootTypes['Workflow']; // Workflow! + }; Device: SourceTypes.Device; DeviceConnection: { // root type @@ -492,6 +516,10 @@ export interface NexusGenObjects { // root type deviceNames: string[]; // [String!]! }; + UpdateWorkflowPayload: { + // root type + workflow: NexusGenRootTypes['Workflow']; // Workflow! + }; Workflow: SourceTypes.Workflow; WorkflowConnection: { // root type @@ -647,6 +675,10 @@ export interface NexusGenFieldTypes { // field return type transactionId: string | null; // String }; + CreateWorkflowPayload: { + // field return type + workflow: NexusGenRootTypes['Workflow']; // Workflow! + }; DataStore: { // field return type config: string; // String! @@ -669,6 +701,10 @@ export interface NexusGenFieldTypes { // field return type snapshot: NexusGenRootTypes['Snapshot'] | null; // Snapshot }; + DeleteWorkflowPayload: { + // field return type + workflow: NexusGenRootTypes['Workflow']; // Workflow! + }; Device: { // field return type address: string | null; // String @@ -860,10 +896,12 @@ export interface NexusGenFieldTypes { commitConfig: NexusGenRootTypes['CommitConfigPayload']; // CommitConfigPayload! createLabel: NexusGenRootTypes['CreateLabelPayload']; // CreateLabelPayload! createTransaction: NexusGenRootTypes['CreateTransactionPayload']; // CreateTransactionPayload! + createWorkflow: NexusGenRootTypes['CreateWorkflowPayload']; // CreateWorkflowPayload! deleteBlueprint: NexusGenRootTypes['DeleteBlueprintPayload']; // DeleteBlueprintPayload! deleteDevice: NexusGenRootTypes['DeleteDevicePayload']; // DeleteDevicePayload! deleteLabel: NexusGenRootTypes['DeleteLabelPayload']; // DeleteLabelPayload! deleteSnapshot: NexusGenRootTypes['DeleteSnapshotPayload'] | null; // DeleteSnapshotPayload + deleteWorkflow: NexusGenRootTypes['DeleteWorkflowPayload']; // DeleteWorkflowPayload! importCSV: NexusGenRootTypes['CSVImport'] | null; // CSVImport installDevice: NexusGenRootTypes['InstallDevicePayload']; // InstallDevicePayload! pauseWorkflow: string | null; // String @@ -876,6 +914,7 @@ export interface NexusGenFieldTypes { updateDataStore: NexusGenRootTypes['UpdateDataStorePayload']; // UpdateDataStorePayload! updateDevice: NexusGenRootTypes['UpdateDevicePayload']; // UpdateDevicePayload! updateGraphNodeCoordinates: NexusGenRootTypes['UpdateGraphNodeCoordinatesPayload']; // UpdateGraphNodeCoordinatesPayload! + updateWorkflow: NexusGenRootTypes['UpdateWorkflowPayload']; // UpdateWorkflowPayload! }; PageInfo: { // field return type @@ -901,7 +940,7 @@ export interface NexusGenFieldTypes { topologyVersions: string[] | null; // [String!] transactions: NexusGenRootTypes['Transaction'][]; // [Transaction!]! uniconfigShellSession: string | null; // String - worfklows: NexusGenRootTypes['WorkflowConnection']; // WorkflowConnection! + workflows: NexusGenRootTypes['WorkflowConnection']; // WorkflowConnection! zones: NexusGenRootTypes['ZonesConnection']; // ZonesConnection! }; ResetConfigPayload: { @@ -980,15 +1019,21 @@ export interface NexusGenFieldTypes { // field return type deviceNames: string[]; // [String!]! }; + UpdateWorkflowPayload: { + // field return type + workflow: NexusGenRootTypes['Workflow']; // Workflow! + }; Workflow: { // field return type createdAt: string | null; // String createdBy: string | null; // String + description: string | null; // String id: string; // ID! name: string; // String! tasks: string | null; // String updatedAt: string | null; // String updatedBy: string | null; // String + version: number | null; // Int }; WorkflowConnection: { // field return type @@ -1142,6 +1187,10 @@ export interface NexusGenFieldTypeNames { // field return type name transactionId: 'String'; }; + CreateWorkflowPayload: { + // field return type name + workflow: 'Workflow'; + }; DataStore: { // field return type name config: 'String'; @@ -1164,6 +1213,10 @@ export interface NexusGenFieldTypeNames { // field return type name snapshot: 'Snapshot'; }; + DeleteWorkflowPayload: { + // field return type name + workflow: 'Workflow'; + }; Device: { // field return type name address: 'String'; @@ -1355,10 +1408,12 @@ export interface NexusGenFieldTypeNames { commitConfig: 'CommitConfigPayload'; createLabel: 'CreateLabelPayload'; createTransaction: 'CreateTransactionPayload'; + createWorkflow: 'CreateWorkflowPayload'; deleteBlueprint: 'DeleteBlueprintPayload'; deleteDevice: 'DeleteDevicePayload'; deleteLabel: 'DeleteLabelPayload'; deleteSnapshot: 'DeleteSnapshotPayload'; + deleteWorkflow: 'DeleteWorkflowPayload'; importCSV: 'CSVImport'; installDevice: 'InstallDevicePayload'; pauseWorkflow: 'String'; @@ -1371,6 +1426,7 @@ export interface NexusGenFieldTypeNames { updateDataStore: 'UpdateDataStorePayload'; updateDevice: 'UpdateDevicePayload'; updateGraphNodeCoordinates: 'UpdateGraphNodeCoordinatesPayload'; + updateWorkflow: 'UpdateWorkflowPayload'; }; PageInfo: { // field return type name @@ -1396,7 +1452,7 @@ export interface NexusGenFieldTypeNames { topologyVersions: 'String'; transactions: 'Transaction'; uniconfigShellSession: 'String'; - worfklows: 'WorkflowConnection'; + workflows: 'WorkflowConnection'; zones: 'ZonesConnection'; }; ResetConfigPayload: { @@ -1475,15 +1531,21 @@ export interface NexusGenFieldTypeNames { // field return type name deviceNames: 'String'; }; + UpdateWorkflowPayload: { + // field return type name + workflow: 'Workflow'; + }; Workflow: { // field return type name createdAt: 'String'; createdBy: 'String'; + description: 'String'; id: 'ID'; name: 'String'; tasks: 'String'; updatedAt: 'String'; updatedBy: 'String'; + version: 'Int'; }; WorkflowConnection: { // field return type name @@ -1591,6 +1653,10 @@ export interface NexusGenArgTypes { // args deviceId: string; // String! }; + createWorkflow: { + // args + input: NexusGenInputs['CreateWorkflowInput']; // CreateWorkflowInput! + }; deleteBlueprint: { // args id: string; // String! @@ -1607,6 +1673,11 @@ export interface NexusGenArgTypes { // args input: NexusGenInputs['DeleteSnapshotInput']; // DeleteSnapshotInput! }; + deleteWorkflow: { + // args + name: string; // String! + version: number; // Int! + }; importCSV: { // args input: NexusGenInputs['CSVImportInput']; // CSVImportInput! @@ -1661,6 +1732,11 @@ export interface NexusGenArgTypes { // args input: NexusGenInputs['GraphNodeCoordinatesInput'][]; // [GraphNodeCoordinatesInput!]! }; + updateWorkflow: { + // args + id: string; // String! + input: NexusGenInputs['UpdateWorkflowInput']; // UpdateWorkflowInput! + }; }; Query: { blueprints: { @@ -1731,7 +1807,7 @@ export interface NexusGenArgTypes { // args version: string; // String! }; - worfklows: { + workflows: { // args after?: string | null; // String before?: string | null; // String diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 2583310f..59eae7f9 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -1,7 +1,9 @@ import { connectionFromArray } from 'graphql-relay'; -import { extendType, list, mutationField, nonNull, objectType, stringArg } from 'nexus'; +import { arg, extendType, inputObjectType, list, mutationField, intArg, nonNull, objectType, stringArg } from 'nexus'; import config from '../config'; +import { WorkflowDetailInput } from '../external-api/conductor-network-types'; import { toGraphId } from '../helpers/id-helper'; +import { validateTasks } from '../helpers/workflow-helpers'; import { Node, PageInfo, PaginationConnectionArgs } from './global-types'; export const Workflow = objectType({ @@ -12,6 +14,8 @@ export const Workflow = objectType({ resolve: (workflow) => toGraphId('Workflow', workflow.name), }); t.nonNull.string('name'); + t.string('description'); + t.int('version'); t.string('createdBy', { resolve: (workflow) => workflow.createdBy ?? null }); t.string('updatedBy', { resolve: (workflow) => workflow.updatedBy ?? null }); t.string('createdAt', { @@ -50,7 +54,7 @@ export const WorkflowConnection = objectType({ export const WorkflowsQuery = extendType({ type: 'Query', definition: (t) => { - t.nonNull.field('worfklows', { + t.nonNull.field('workflows', { type: WorkflowConnection, args: PaginationConnectionArgs, resolve: async (_, args, { conductorAPI }) => { @@ -69,6 +73,156 @@ export const WorkflowsQuery = extendType({ }, }); +export const CreateWorkflowPayload = objectType({ + name: 'CreateWorkflowPayload', + definition: (t) => { + t.nonNull.field('workflow', { type: Workflow }); + }, +}); + +const WorkflowInput = inputObjectType({ + name: 'WorkflowInput', + definition: (t) => { + t.nonNull.string('name'); + t.nonNull.int('timeoutSeconds'); + t.nonNull.string('tasks'); + t.string('description'); + t.int('version'); + }, +}); + +export const CreateWorkflowInput = inputObjectType({ + name: 'CreateWorkflowInput', + definition: (t) => { + t.nonNull.field('workflow', { + type: WorkflowInput, + }); + }, +}); + +export const CreateWorkflowMutation = extendType({ + type: 'Mutation', + definition: (t) => { + t.nonNull.field('createWorkflow', { + type: CreateWorkflowPayload, + args: { + input: nonNull(arg({ type: CreateWorkflowInput })), + }, + resolve: async (_, args, { conductorAPI }) => { + const { input } = args; + const { workflow } = input; + + const parsedTasks = validateTasks(workflow.tasks); + + const apiWorkflow: WorkflowDetailInput = { + name: workflow.name, + timeoutSeconds: 60, + tasks: parsedTasks, + version: workflow.version || undefined, + description: workflow.description || undefined, + }; + + await conductorAPI.createWorkflow(config.conductorApiURL, apiWorkflow); + return { + workflow: { + id: toGraphId('Workflow', apiWorkflow.name), + ...apiWorkflow, + }, + }; + }, + }); + }, +}); + +export const UpdateWorkflowPayload = objectType({ + name: 'UpdateWorkflowPayload', + definition: (t) => { + t.nonNull.field('workflow', { type: Workflow }); + }, +}); + +export const UpdateWorkflowInput = inputObjectType({ + name: 'UpdateWorkflowInput', + definition: (t) => { + t.nonNull.field('workflow', { + type: WorkflowInput, + }); + }, +}); + +export const UpdateWorkflowMutation = extendType({ + type: 'Mutation', + definition: (t) => { + t.nonNull.field('updateWorkflow', { + type: UpdateWorkflowPayload, + args: { + id: nonNull(stringArg()), + input: nonNull(arg({ type: UpdateWorkflowInput })), + }, + resolve: async (_, args, { conductorAPI }) => { + const { input } = args; + const { workflow } = input; + + const parsedTasks = validateTasks(workflow.tasks); + + const apiWorkflow: WorkflowDetailInput = { + name: workflow.name, + timeoutSeconds: 60, + tasks: parsedTasks, + version: workflow.version || undefined, + description: workflow.description || undefined, + }; + + const result = await conductorAPI.editWorkflow(config.conductorApiURL, apiWorkflow); + + if (result.bulkErrorResults[workflow.name]) { + throw new Error(`update workflow error: ${result.bulkErrorResults[workflow.name]}`); + } + + return { + workflow: { + id: toGraphId('Workflow', apiWorkflow.name), + ...apiWorkflow, + }, + }; + }, + }); + }, +}); + +const DeleteWorkflowPayload = objectType({ + name: 'DeleteWorkflowPayload', + definition: (t) => { + t.nonNull.field('workflow', { + type: Workflow, + }); + }, +}); + +export const DeleteWorkflowMutation = extendType({ + type: 'Mutation', + definition: (t) => { + t.nonNull.field('deleteWorkflow', { + type: DeleteWorkflowPayload, + args: { + name: nonNull(stringArg()), + version: nonNull(intArg()), + }, + resolve: async (_, args, { conductorAPI }) => { + const { name, version } = args; + const workflowToDelete = await conductorAPI.getWorkflowDetail(config.conductorApiURL, name); + await conductorAPI.deleteWorkflow(config.conductorApiURL, name, version); + return { + workflow: { + ...workflowToDelete, + id: toGraphId('Workflow', workflowToDelete.name), + }, + }; + }, + }); + }, +}); + export const PauseWorkflowMutation = mutationField('pauseWorkflow', { type: 'String', args: { From 5a7d0fe16c9fa0f02e0c8daba33213a7b6dee35e Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Tue, 28 Mar 2023 10:43:45 +0200 Subject: [PATCH 06/69] add scheduler api to inventory server (#270) --- .env.example | 1 + src/config.ts | 1 + src/context.ts | 4 +- src/external-api/scheduler-network-types.ts | 47 +++++++++++++++++++++ src/external-api/scheduler.ts | 24 +++++++++++ src/schema/api.graphql | 1 + src/schema/nexus-typegen.ts | 2 + src/schema/workflow.ts | 14 ++++++ 8 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 src/external-api/scheduler-network-types.ts create mode 100644 src/external-api/scheduler.ts diff --git a/.env.example b/.env.example index 6ce4cbf8..4519bb9e 100644 --- a/.env.example +++ b/.env.example @@ -5,6 +5,7 @@ UNICONFIG_API_PROTOCOL=http UNICONFIG_API_PORT=4000 UNICONFIG_LIST_URL=http://localhost:4000/static/list/uniconfig CONDUCTOR_API_URL="http:/10.19.0.7:8080/api" +SCHEDULER_API_URL="http://10.19.0.7:3001" SHELL_HOST=10.19.0.12 X_TENANT_ID="frinx" TOPOLOGY_ENABLED=true diff --git a/src/config.ts b/src/config.ts index ba123eec..245f3591 100644 --- a/src/config.ts +++ b/src/config.ts @@ -68,6 +68,7 @@ const config = { uniconfigApiPort: envString('UNICONFIG_API_PORT'), uniconfigListURL: envString('UNICONFIG_LIST_URL'), conductorApiURL: envString('CONDUCTOR_API_URL'), + schedulerApiURL: envString('SCHEDULER_API_URL'), defaultTenantId: envString('X_TENANT_ID'), shellHost: envString('SHELL_HOST'), ...getTopologyConfig(), diff --git a/src/context.ts b/src/context.ts index e5959c1d..a704239b 100644 --- a/src/context.ts +++ b/src/context.ts @@ -3,6 +3,7 @@ import { ExpressContext } from 'apollo-server-express'; import topologyDiscoveryAPI, { TopologyDiscoveryAPI } from './external-api/topology-discovery'; import conductorAPI, { ConductorAPI } from './external-api/conductor'; import uniconfigAPI, { UniConfigAPI } from './external-api/uniconfig'; +import schedulerAPI, { SchedulerAPI } from './external-api/scheduler'; import prismaClient from './prisma-client'; export type Context = { @@ -11,6 +12,7 @@ export type Context = { uniconfigAPI: UniConfigAPI; topologyDiscoveryAPI: TopologyDiscoveryAPI; conductorAPI: ConductorAPI; + schedulerAPI: SchedulerAPI; }; export default function createContext(context: ExpressContext): Context { @@ -24,5 +26,5 @@ export default function createContext(context: ExpressContext): Context { tenantId = headers['x-tenant-id'] as string; } - return { prisma: prismaClient, tenantId, uniconfigAPI, topologyDiscoveryAPI, conductorAPI }; + return { prisma: prismaClient, tenantId, uniconfigAPI, topologyDiscoveryAPI, conductorAPI, schedulerAPI }; } diff --git a/src/external-api/scheduler-network-types.ts b/src/external-api/scheduler-network-types.ts new file mode 100644 index 00000000..0fd75421 --- /dev/null +++ b/src/external-api/scheduler-network-types.ts @@ -0,0 +1,47 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import { Either, fold } from 'fp-ts/lib/Either'; +import * as t from 'io-ts'; +import { PathReporter } from 'io-ts/lib/PathReporter'; + +export function optional(type: t.Type) { + return t.union([type, t.void]); +} + +export function extractResult(result: Either): A { + return fold( + () => { + const errorMessages = PathReporter.report(result); + throw new Error(`BAD_REQUEST: ${errorMessages.join(',')}`); + }, + (data: A) => data, + )(result); +} + +const ScheduleOutputValidator = t.type({ + name: t.string, + workflowName: t.string, + workflowVersion: t.string, + cronString: t.string, + lastUpdate: t.string, + correlationId: t.string, + enabled: optional(t.boolean), + parallelRuns: optional(t.boolean), + fromDate: optional(t.string), + toDate: optional(t.string), + taskToDomain: optional(t.record(t.string, t.string)), + workflowContext: optional(t.record(t.string, t.string)), +}); + +export type ScheduleOutput = t.TypeOf; + +export function decodeScheduleOutput(value: unknown): ScheduleOutput { + return extractResult(ScheduleOutputValidator.decode(value)); +} + +const ScheduleListOutputValidator = t.array(ScheduleOutputValidator); + +export type ScheduleListOutput = t.TypeOf; + +export function decodeScheduleListOutput(value: unknown): ScheduleListOutput { + return extractResult(ScheduleListOutputValidator.decode(value)); +} diff --git a/src/external-api/scheduler.ts b/src/external-api/scheduler.ts new file mode 100644 index 00000000..28ee620a --- /dev/null +++ b/src/external-api/scheduler.ts @@ -0,0 +1,24 @@ +import { sendGetRequest } from './helpers'; +import { decodeScheduleListOutput, decodeScheduleOutput } from './scheduler-network-types'; + +async function listSchedules(baseURL: string): Promise { + const json = await sendGetRequest([baseURL, 'schedule']); + const data = decodeScheduleListOutput(json); + + return data; +} + +async function getSchedule(baseURL: string, workflowName: string, workflowVersion: number): Promise { + const json = await sendGetRequest([baseURL, `schedule/${workflowName}:${workflowVersion}`]); + const data = decodeScheduleOutput(json); + + return data; +} + +const schedulerAPI = { + listSchedules, + getSchedule, +}; + +export type SchedulerAPI = typeof schedulerAPI; +export default schedulerAPI; diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 354ae5c1..a36222d7 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -677,6 +677,7 @@ type Workflow implements Node { createdAt: String createdBy: String description: String + hasSchedule: Boolean id: ID! name: String! tasks: String diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 8a87d2ce..5e64019d 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -1028,6 +1028,7 @@ export interface NexusGenFieldTypes { createdAt: string | null; // String createdBy: string | null; // String description: string | null; // String + hasSchedule: boolean | null; // Boolean id: string; // ID! name: string; // String! tasks: string | null; // String @@ -1540,6 +1541,7 @@ export interface NexusGenFieldTypeNames { createdAt: 'String'; createdBy: 'String'; description: 'String'; + hasSchedule: 'Boolean'; id: 'ID'; name: 'String'; tasks: 'String'; diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 59eae7f9..77dcc713 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -5,6 +5,9 @@ import { WorkflowDetailInput } from '../external-api/conductor-network-types'; import { toGraphId } from '../helpers/id-helper'; import { validateTasks } from '../helpers/workflow-helpers'; import { Node, PageInfo, PaginationConnectionArgs } from './global-types'; +import getLogger from '../get-logger'; + +const log = getLogger('frinx-inventory-server'); export const Workflow = objectType({ name: 'Workflow', @@ -25,6 +28,17 @@ export const Workflow = objectType({ resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), }); t.string('tasks', { resolve: (workflow) => JSON.stringify(workflow.tasks) }); + t.boolean('hasSchedule', { + resolve: async (workflow, _, { schedulerAPI }) => { + try { + await schedulerAPI.getSchedule(config.schedulerApiURL, workflow.name, workflow.version ?? 1); + return true; + } catch (e) { + log.info(`cannot get schedule info for workflow ${workflow.name}: ${e}`); + return false; + } + }, + }); }, }); From 9a29bb7b8cce50e0ade0fc0019384c3ea7893851 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Tue, 28 Mar 2023 15:40:02 +0200 Subject: [PATCH 07/69] workflow labels query added (#271) --- src/schema/api.graphql | 1 + src/schema/index.ts | 2 ++ src/schema/nexus-typegen.ts | 2 ++ src/schema/workflow-labels.ts | 45 +++++++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 src/schema/workflow-labels.ts diff --git a/src/schema/api.graphql b/src/schema/api.graphql index a36222d7..c1a864b0 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -544,6 +544,7 @@ type Query { topologyVersions: [String!] transactions: [Transaction!]! uniconfigShellSession: String + workflowLabels: [String!]! workflows(after: String, before: String, first: Int, last: Int): WorkflowConnection! zones(after: String, before: String, first: Int, last: Int): ZonesConnection! } diff --git a/src/schema/index.ts b/src/schema/index.ts index 1da56472..1bd4cf97 100644 --- a/src/schema/index.ts +++ b/src/schema/index.ts @@ -12,6 +12,7 @@ import * as topology from './topology'; import * as workflow from './workflow'; import * as executedWorkflow from './executed-workflow'; import * as executedWorkflowTask from './task'; +import * as workflowLabels from './workflow-labels'; export default makeSchema({ features: { @@ -40,6 +41,7 @@ export default makeSchema({ transaction, topology, workflow, + workflowLabels, executedWorkflow, executedWorkflowTask, ], diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 5e64019d..a5fe81df 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -940,6 +940,7 @@ export interface NexusGenFieldTypes { topologyVersions: string[] | null; // [String!] transactions: NexusGenRootTypes['Transaction'][]; // [Transaction!]! uniconfigShellSession: string | null; // String + workflowLabels: string[]; // [String!]! workflows: NexusGenRootTypes['WorkflowConnection']; // WorkflowConnection! zones: NexusGenRootTypes['ZonesConnection']; // ZonesConnection! }; @@ -1453,6 +1454,7 @@ export interface NexusGenFieldTypeNames { topologyVersions: 'String'; transactions: 'Transaction'; uniconfigShellSession: 'String'; + workflowLabels: 'String'; workflows: 'WorkflowConnection'; zones: 'ZonesConnection'; }; diff --git a/src/schema/workflow-labels.ts b/src/schema/workflow-labels.ts new file mode 100644 index 00000000..8d10b783 --- /dev/null +++ b/src/schema/workflow-labels.ts @@ -0,0 +1,45 @@ +import { extendType, list, nonNull } from 'nexus'; +import config from '../config'; +import { Workflow } from './source-types'; + +type DescriptionJSON = { labels?: string[]; description: string }; + +const jsonParse = (json?: string | null): T | null => { + if (json == null) { + return null; + } + + try { + return JSON.parse(json); + } catch (e) { + return null; + } +}; + +const getLabels = (workflows: Omit[]): string[] => { + const labelsSet = new Set(); + + workflows.forEach((w) => { + const descriptionJSON = jsonParse(w.description ?? ''); + if (!descriptionJSON) { + return; + } + const { labels } = descriptionJSON; + labels?.forEach((l) => labelsSet.add(l)); + }); + return [...labelsSet].sort(); +}; + +export const WorkflowsQuery = extendType({ + type: 'Query', + definition: (t) => { + t.nonNull.field('workflowLabels', { + type: list(nonNull('String')), + resolve: async (_, _args, { conductorAPI }) => { + const workflows = await conductorAPI.getWorkflowMetadata(config.conductorApiURL); + const labels = getLabels(workflows); + return labels; + }, + }); + }, +}); From 2a8bb52d6edf6b07aa3a3a745688f60c7b74d0e2 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Wed, 29 Mar 2023 17:51:19 +0200 Subject: [PATCH 08/69] Add mutation execute workflow (#268) * add mutation to start new workflow * move from executed to workflow file and create start new workflow mutation * add mutation to execute workflow * use our custom logger and use correct name convention * remove trycatches and loggers * add jsdocs and handle JSON parsing * use void instead of custom string and fix errored imports * remove logger --- src/external-api/conductor.ts | 81 ++++--- src/helpers/conductor.helpers.spec.ts | 5 +- src/helpers/conductor.helpers.ts | 30 +-- src/helpers/utils.helpers.ts | 13 + src/helpers/workflow.helpers.ts | 2 +- src/schema/api.graphql | 105 +++++++- src/schema/executed-workflow.ts | 148 ------------ src/schema/global-types.ts | 7 + src/schema/index.ts | 2 - src/schema/nexus-typegen.ts | 115 ++++++++- src/schema/task.ts | 50 +++- src/schema/workflow.ts | 335 +++++++++++++++++++++++--- src/types/conductor.types.ts | 143 +++++++++++ 13 files changed, 777 insertions(+), 259 deletions(-) delete mode 100644 src/schema/executed-workflow.ts create mode 100644 src/types/conductor.types.ts diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts index bf50ad88..4a106c6a 100644 --- a/src/external-api/conductor.ts +++ b/src/external-api/conductor.ts @@ -1,4 +1,6 @@ -import { makeStringQueryFromSearchQueryObject, PaginationArgs, SearchQuery } from '../helpers/conductor.helpers'; +import getLogger from '../get-logger'; +import { makeStringQueryFromSearchQueryObject } from '../helpers/conductor.helpers'; +import { PaginationArgs, SearchQuery, StartWorkflowInput } from '../types/conductor.types'; import { BulkOperationOutput, ApiExecutedWorkflow, @@ -16,6 +18,8 @@ import { } from './conductor-network-types'; import { sendDeleteRequest, sendGetRequest, sendPostRequest, sendPutRequest } from './helpers'; +export const log = getLogger('frinx-graphql-conductor'); + async function getWorkflowMetadata(baseURL: string): Promise { const json = await sendGetRequest([baseURL, 'metadata/workflow']); const data = decodeWorkflowMetadataOutput(json); @@ -41,46 +45,27 @@ async function editWorkflow(baseURL: string, workflow: WorkflowDetailInput): Pro async function deleteWorkflow(baseURL: string, name: string, version: number): Promise { await sendDeleteRequest([baseURL, `metadata/workflow/${name}/${version}`]); } -async function pauseWorkflow(baseURL: string, workflowId: string): Promise { - try { - const json = await sendPutRequest([baseURL, `workflow/${workflowId}/pause`]); - return String(json); - } catch (error) { - throw new Error("Workflow couldn't be paused"); - } +async function pauseWorkflow(baseURL: string, workflowId: string): Promise { + await sendPutRequest([baseURL, `workflow/${workflowId}/pause`]); } -async function resumeWorkflow(baseURL: string, workflowId: string): Promise { - try { - const json = await sendPutRequest([baseURL, `workflow/${workflowId}/resume`]); - - return String(json); - } catch (error) { - throw new Error("Workflow couldn't be resumed"); - } +async function resumeWorkflow(baseURL: string, workflowId: string): Promise { + await sendPutRequest([baseURL, `workflow/${workflowId}/resume`]); } async function bulkResumeWorkflow(baseURL: string, workflowIds: string[]): Promise { - try { - const json = await sendPutRequest([baseURL, `workflow/bulk/resume`], workflowIds); - const data = decodeBulkOperationOutput(json); + const json = await sendPutRequest([baseURL, `workflow/bulk/resume`], workflowIds); + const data = decodeBulkOperationOutput(json); - return data; - } catch (error) { - throw new Error('Bulk resume of workflows was not successful'); - } + return data; } async function bulkPauseWorkflow(baseURL: string, workflowIds: string[]): Promise { - try { - const json = await sendPutRequest([baseURL, `workflow/bulk/pause`], workflowIds); - const data = decodeBulkOperationOutput(json); + const json = await sendPutRequest([baseURL, `workflow/bulk/pause`], workflowIds); + const data = decodeBulkOperationOutput(json); - return data; - } catch (error) { - throw new Error('Bulk pause of workflows was not successful'); - } + return data; } async function getExecutedWorkflows( @@ -102,6 +87,40 @@ async function getExecutedWorkflowDetail(baseURL: string, workflowId: string): P return data; } +async function executeNewWorkflow(baseURL: string, input: StartWorkflowInput): Promise { + const executedWorkflowId = await sendPostRequest([baseURL, 'workflow'], input); + + if (executedWorkflowId != null && typeof executedWorkflowId === 'string') { + return executedWorkflowId; + } else { + throw new Error('We could not execute the workflow'); + } +} + +type ExecuteWorkflowByNameInput = { + name: string; + inputParameters: Record; + correlationId?: string | null; + version?: number | null; + priority?: number | null; +}; + +async function executeWorkflowByName( + baseURL: string, + { name, inputParameters, correlationId, version, priority }: ExecuteWorkflowByNameInput, +): Promise { + const executedWorkflowId = await sendPostRequest( + [baseURL, `workflow/${name}?version=${version}&correlationId=${correlationId}&priority=${priority}`], + inputParameters, + ); + + if (executedWorkflowId != null && typeof executedWorkflowId === 'string') { + return executedWorkflowId; + } else { + throw new Error('We could not execute the workflow'); + } +} + const conductorAPI = { getWorkflowMetadata, getWorkflowDetail, @@ -114,6 +133,8 @@ const conductorAPI = { bulkPauseWorkflow, getExecutedWorkflows, getExecutedWorkflowDetail, + executeNewWorkflow, + executeWorkflowByName, }; export type ConductorAPI = typeof conductorAPI; diff --git a/src/helpers/conductor.helpers.spec.ts b/src/helpers/conductor.helpers.spec.ts index 603dbe3f..a882f57f 100644 --- a/src/helpers/conductor.helpers.spec.ts +++ b/src/helpers/conductor.helpers.spec.ts @@ -1,8 +1,5 @@ +import { ConductorQuerySearchTime, PaginationArgs, ConductorQuery, SearchQuery } from '../types/conductor.types'; import { - ConductorQuery, - ConductorQuerySearchTime, - PaginationArgs, - SearchQuery, makeStringFromIsRootWorkflow, makeStringFromPagination, makeStringFromQuery, diff --git a/src/helpers/conductor.helpers.ts b/src/helpers/conductor.helpers.ts index 93bd4488..e2f665d4 100644 --- a/src/helpers/conductor.helpers.ts +++ b/src/helpers/conductor.helpers.ts @@ -1,34 +1,6 @@ +import { ConductorQuerySearchTime, ConductorQuery, PaginationArgs, SearchQuery } from '../types/conductor.types'; import { isValidType } from './utils.helpers'; -export type ExecutedWorkflowResult = { - results: unknown[]; - totalHits: number; -}; - -export type ConductorQuerySearchTime = { - from: number; - to?: number | null; -}; - -export type ConductorQueryStatus = 'RUNNING' | 'COMPLETED' | 'FAILED' | 'TERMINATED' | 'TIMED_OUT' | 'PAUSED'; - -export type ConductorQuery = { - status?: ConductorQueryStatus[] | null; - startTime?: ConductorQuerySearchTime | null; - workflowId?: string[] | null; - workflowType?: string[] | null; -}; - -export type SearchQuery = { - isRootWorkflow?: boolean | null; - query?: ConductorQuery | null; -}; - -export type PaginationArgs = { - size: number; - start: number; -}; - export function makeStringQueryFromSearchTime(searchTime: ConductorQuerySearchTime): string { const { from, to } = searchTime; diff --git a/src/helpers/utils.helpers.ts b/src/helpers/utils.helpers.ts index 59d4d7eb..0efb959e 100644 --- a/src/helpers/utils.helpers.ts +++ b/src/helpers/utils.helpers.ts @@ -23,3 +23,16 @@ export function isValidType(key: string, obj: unknown): obj is T { return key in obj; } + +export function parseJson(json?: string | null, throwError = true): T { + try { + const parsed = JSON.parse(json ?? ''); + return parsed; + } catch (error) { + if (throwError) { + throw new Error('Could not parse JSON'); + } else { + return {} as T; + } + } +} diff --git a/src/helpers/workflow.helpers.ts b/src/helpers/workflow.helpers.ts index 73b1fb4d..62ac86f2 100644 --- a/src/helpers/workflow.helpers.ts +++ b/src/helpers/workflow.helpers.ts @@ -1,4 +1,4 @@ -import { PaginationArgs, SearchQuery } from './conductor.helpers'; +import { SearchQuery, PaginationArgs } from '../types/conductor.types'; type GraphQLSearchQuery = { isRootWorkflow?: boolean | null; diff --git a/src/schema/api.graphql b/src/schema/api.graphql index c1a864b0..a3b93a6b 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -276,6 +276,16 @@ type EdgeSourceTarget { nodeId: String! } +input ExecuteNewWorkflowInput { + correlationId: String + externalInputPayloadStoragePath: String + input: String + name: String! + priority: Int + taskToDomain: String + version: Int +} + type ExecutedWorkflow implements Node { createdAt: String createdBy: String @@ -434,6 +444,10 @@ type InstallDevicePayload { device: Device! } +type IsOkResponse { + isOk: Boolean! +} + type Label implements Node { createdAt: String! id: ID! @@ -490,11 +504,23 @@ type Mutation { deleteLabel(id: String!): DeleteLabelPayload! deleteSnapshot(input: DeleteSnapshotInput!): DeleteSnapshotPayload deleteWorkflow(name: String!, version: Int!): DeleteWorkflowPayload! + executeNewWorkflow(input: StartWorkflowRequestInput!): String + executeWorkflowByName( + correlationId: String + + """ + JSON string of input parameters + """ + inputParameters: String! + priority: Int + workflowName: String! + workflowVersion: Int + ): String importCSV(input: CSVImportInput!): CSVImport installDevice(id: String!): InstallDevicePayload! - pauseWorkflow(workflowId: String!): String + pauseWorkflow(workflowId: String!): IsOkResponse resetConfig(deviceId: String!, transactionId: String!): ResetConfigPayload! - resumeWorkflow(workflowId: String!): String + resumeWorkflow(workflowId: String!): IsOkResponse revertChanges(transactionId: String!): RevertChangesPayload! syncFromNetwork(deviceId: String!, transactionId: String!): SyncFromNetworkPayload! uninstallDevice(id: String!): UninstallDevicePayload! @@ -572,6 +598,11 @@ enum SortDirection { DESC } +input StartWorkflowRequestInput { + workflow: ExecuteNewWorkflowInput! + workflowDefinition: WorkflowDefinitionInput +} + type Subscription { uniconfigShell(input: String, sessionId: String!, trigger: Int): String } @@ -580,6 +611,28 @@ type SyncFromNetworkPayload { dataStore: DataStore } +input TaskInput { + asyncComplete: Boolean + decisionCases: String + defaultCase: String + description: String + inputParameters: String + joinOn: [String] + loopCondition: String + name: String! + optional: Boolean + retryCount: Int + startDelay: Int + taskReferenceName: String! + type: String + workflowTaskType: [WorkflowTaskType] +} + +enum TimeoutPolicy { + ALERT_ONLY + TIME_OUT_WF +} + type Topology { edges: [GraphEdge!]! nodes: [GraphNode!]! @@ -693,6 +746,29 @@ type WorkflowConnection { totalCount: Int! } +input WorkflowDefinitionInput { + createTime: Int + createdAt: Int + createdBy: String + description: String + inputParameters: [String] + inputTemplate: String + name: String! + outputParameters: String + ownerApp: String + ownerEmail: String + restartable: Boolean + schemaVersion: Int + tasks: [TaskInput!]! + timeoutPolicy: TimeoutPolicy + timeoutSeconds: Int! + updateTime: Int + updatedAt: Int + updatedBy: String + variables: String + version: Int +} + type WorkflowEdge { cursor: String! node: Workflow! @@ -706,6 +782,31 @@ input WorkflowInput { version: Int } +enum WorkflowTaskType { + DECISION + DO_WHILE + DYNAMIC + EVENT + EXCLUSIVE_JOIN + FORK_JOIN + FORK_JOIN_DYNAMIC + HTTP + HUMAN + INLINE + JOIN + JSON_JQ_TRANSFORM + KAFKA_PUBLISH + LAMBDA + SET_VARIABLE + SIMPLE + START_WORKFLOW + SUB_WORKFLOW + SWITCH + TERMINATE + USER_DEFINED + WAIT +} + type Zone implements Node { createdAt: String! id: ID! diff --git a/src/schema/executed-workflow.ts b/src/schema/executed-workflow.ts deleted file mode 100644 index 1e87a7cc..00000000 --- a/src/schema/executed-workflow.ts +++ /dev/null @@ -1,148 +0,0 @@ -import { arg, enumType, inputObjectType, objectType, queryField } from 'nexus'; -import { v4 as uuid } from 'uuid'; -import config from '../config'; -import { toGraphId } from '../helpers/id-helper'; -import { makePaginationFromArgs, makeSearchQueryFromArgs } from '../helpers/workflow.helpers'; -import { Node, PageInfo } from './global-types'; -import { ExecutedWorkflowTask } from './task'; -import { Workflow } from './workflow'; - -export const ExecutedWorkflowStatus = enumType({ - name: 'ExecutedWorkflowStatus', - members: ['RUNNING', 'COMPLETED', 'FAILED', 'TERMINATED', 'TIMED_OUT', 'PAUSED'], -}); - -export const ExecutedWorkflow = objectType({ - name: 'ExecutedWorkflow', - definition(t) { - t.implements(Node); - t.nonNull.id('id', { - resolve: (executedWorkflow) => toGraphId('ExecutedWorkflow', executedWorkflow.workflowId ?? uuid()), - }); - t.string('createdBy', { resolve: (executedWorkflow) => executedWorkflow.createdBy ?? null }); - t.string('updatedBy', { resolve: (workflow) => workflow.updatedBy ?? null }); - t.string('createdAt', { - resolve: (workflow) => (workflow.createTime ? new Date(workflow.createTime).toISOString() : null), - }); - t.string('updatedAt', { - resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), - }); - t.field('status', { type: ExecutedWorkflowStatus }); - t.string('parentWorkflowId'); - t.string('ownerApp'); - t.string('input', { resolve: (workflow) => JSON.stringify(workflow.input) }); - t.string('output', { resolve: (workflow) => JSON.stringify(workflow.output) }); - t.string('reasonForIncompletion'); - t.list.string('failedReferenceTaskNames'); - t.field('workflowDefinition', { type: Workflow }); - t.string('variables', { resolve: (workflow) => JSON.stringify(workflow.variables) }); - t.string('lastRetriedTime', { - resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), - }); - t.string('startTime', { - resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), - }); - t.string('endTime', { - resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), - }); - t.int('workflowVersion'); - t.string('workflowName'); - t.string('workflowId'); - t.list.field('tasks', { - type: ExecutedWorkflowTask, - }); - }, -}); - -export const ExecutedWorkflowEdge = objectType({ - name: 'ExecutedWorkflowEdge', - definition: (t) => { - t.nonNull.field('node', { - type: ExecutedWorkflow, - }); - t.nonNull.string('cursor'); - }, -}); - -export const ExecutedWorkflowConnection = objectType({ - name: 'ExecutedWorkflowConnection', - definition: (t) => { - t.nonNull.list.nonNull.field('edges', { - type: ExecutedWorkflowEdge, - }); - t.nonNull.field('pageInfo', { - type: PageInfo, - }); - t.nonNull.int('totalCount'); - }, -}); - -export const ExecutedWorkflowStartTimeRange = inputObjectType({ - name: 'ExecutedWorkflowStartTimeRange', - definition: (t) => { - t.nonNull.string('from'); - t.string('to'); - }, -}); - -export const ExecutedWorkflowFilterInput = inputObjectType({ - name: 'ExecutedWorkflowFilterInput', - definition: (t) => { - t.list.nonNull.string('workflowId'); - t.list.nonNull.string('workflowType'); - t.list.nonNull.field('status', { type: ExecutedWorkflowStatus }); - t.field('startTime', { type: ExecutedWorkflowStartTimeRange }); - }, -}); - -export const ExecutedWorkflowSearchInput = inputObjectType({ - name: 'ExecutedWorkflowSearchInput', - definition: (t) => { - t.boolean('isRootWorkflow'); - t.field('query', { type: ExecutedWorkflowFilterInput }); - }, -}); - -export const PaginationArgs = inputObjectType({ - name: 'PaginationArgs', - definition: (t) => { - t.nonNull.int('size'); - t.nonNull.int('start'); - }, -}); - -export const ExecutedWorkflowsQuery = queryField('executedWorkflows', { - type: ExecutedWorkflowConnection, - args: { - pagination: arg({ type: PaginationArgs }), - searchQuery: arg({ type: ExecutedWorkflowSearchInput }), - }, - resolve: async (_, args, { conductorAPI }) => { - const { results: executedWorkflows } = await conductorAPI.getExecutedWorkflows( - config.conductorApiURL, - makeSearchQueryFromArgs(args.searchQuery), - makePaginationFromArgs(args.pagination), - ); - - const executedWorkflowsWithId = executedWorkflows - .map((w) => ({ - ...w, - id: toGraphId('ExecutedWorkflow', w.workflowId || uuid()), - })) - .slice(0, args.pagination?.size ?? 0 - 1); - - return { - edges: executedWorkflowsWithId.map((w) => ({ - node: w, - cursor: w.id, - })), - pageInfo: { - hasNextPage: args.pagination ? executedWorkflowsWithId.length < executedWorkflows.length : false, - hasPreviousPage: args.pagination ? args.pagination.start >= args.pagination.size : false, - endCursor: executedWorkflowsWithId[executedWorkflowsWithId.length - 1]?.id, - startCursor: executedWorkflowsWithId[0]?.id, - }, - totalCount: executedWorkflows.length, - }; - }, -}); diff --git a/src/schema/global-types.ts b/src/schema/global-types.ts index 41b11f4e..c0c12fa2 100644 --- a/src/schema/global-types.ts +++ b/src/schema/global-types.ts @@ -121,3 +121,10 @@ export const NodeQuery = extendType({ }); }, }); + +export const IsOkResponse = objectType({ + name: 'IsOkResponse', + definition: (t) => { + t.nonNull.boolean('isOk'); + }, +}); diff --git a/src/schema/index.ts b/src/schema/index.ts index 1bd4cf97..0389cad1 100644 --- a/src/schema/index.ts +++ b/src/schema/index.ts @@ -10,7 +10,6 @@ import * as zone from './zone'; import * as transaction from './transaction'; import * as topology from './topology'; import * as workflow from './workflow'; -import * as executedWorkflow from './executed-workflow'; import * as executedWorkflowTask from './task'; import * as workflowLabels from './workflow-labels'; @@ -42,7 +41,6 @@ export default makeSchema({ topology, workflow, workflowLabels, - executedWorkflow, executedWorkflowTask, ], sourceTypes: { diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index a5fe81df..785a9b74 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -102,6 +102,16 @@ export interface NexusGenInputs { direction: NexusGenEnums['SortDirection']; // SortDirection! sortKey: NexusGenEnums['SortDeviceBy']; // SortDeviceBy! }; + ExecuteNewWorkflowInput: { + // input type + correlationId?: string | null; // String + externalInputPayloadStoragePath?: string | null; // String + input?: string | null; // String + name: string; // String! + priority?: number | null; // Int + taskToDomain?: string | null; // String + version?: number | null; // Int + }; ExecutedWorkflowFilterInput: { // input type startTime?: NexusGenInputs['ExecutedWorkflowStartTimeRange'] | null; // ExecutedWorkflowStartTimeRange @@ -139,6 +149,28 @@ export interface NexusGenInputs { size: number; // Int! start: number; // Int! }; + StartWorkflowRequestInput: { + // input type + workflow: NexusGenInputs['ExecuteNewWorkflowInput']; // ExecuteNewWorkflowInput! + workflowDefinition?: NexusGenInputs['WorkflowDefinitionInput'] | null; // WorkflowDefinitionInput + }; + TaskInput: { + // input type + asyncComplete?: boolean | null; // Boolean + decisionCases?: string | null; // String + defaultCase?: string | null; // String + description?: string | null; // String + inputParameters?: string | null; // String + joinOn?: Array | null; // [String] + loopCondition?: string | null; // String + name: string; // String! + optional?: boolean | null; // Boolean + retryCount?: number | null; // Int + startDelay?: number | null; // Int + taskReferenceName: string; // String! + type?: string | null; // String + workflowTaskType?: Array | null; // [WorkflowTaskType] + }; UpdateBlueprintInput: { // input type name?: string | null; // String @@ -169,6 +201,29 @@ export interface NexusGenInputs { // input type workflow: NexusGenInputs['WorkflowInput']; // WorkflowInput! }; + WorkflowDefinitionInput: { + // input type + createTime?: number | null; // Int + createdAt?: number | null; // Int + createdBy?: string | null; // String + description?: string | null; // String + inputParameters?: Array | null; // [String] + inputTemplate?: string | null; // String + name: string; // String! + outputParameters?: string | null; // String + ownerApp?: string | null; // String + ownerEmail?: string | null; // String + restartable?: boolean | null; // Boolean + schemaVersion?: number | null; // Int + tasks: NexusGenInputs['TaskInput'][]; // [TaskInput!]! + timeoutPolicy?: NexusGenEnums['TimeoutPolicy'] | null; // TimeoutPolicy + timeoutSeconds: number; // Int! + updateTime?: number | null; // Int + updatedAt?: number | null; // Int + updatedBy?: string | null; // String + variables?: string | null; // String + version?: number | null; // Int + }; WorkflowInput: { // input type description?: string | null; // String @@ -197,6 +252,30 @@ export interface NexusGenEnums { GraphEdgeStatus: 'ok' | 'unknown'; SortDeviceBy: 'CREATED_AT' | 'NAME'; SortDirection: 'ASC' | 'DESC'; + TimeoutPolicy: 'ALERT_ONLY' | 'TIME_OUT_WF'; + WorkflowTaskType: + | 'DECISION' + | 'DO_WHILE' + | 'DYNAMIC' + | 'EVENT' + | 'EXCLUSIVE_JOIN' + | 'FORK_JOIN' + | 'FORK_JOIN_DYNAMIC' + | 'HTTP' + | 'HUMAN' + | 'INLINE' + | 'JOIN' + | 'JSON_JQ_TRANSFORM' + | 'KAFKA_PUBLISH' + | 'LAMBDA' + | 'SET_VARIABLE' + | 'SIMPLE' + | 'START_WORKFLOW' + | 'SUB_WORKFLOW' + | 'SWITCH' + | 'TERMINATE' + | 'USER_DEFINED' + | 'WAIT'; } export interface NexusGenScalars { @@ -410,6 +489,10 @@ export interface NexusGenObjects { // root type device: NexusGenRootTypes['Device']; // Device! }; + IsOkResponse: { + // root type + isOk: boolean; // Boolean! + }; Label: SourceTypes.Label; LabelConnection: { // root type @@ -845,6 +928,10 @@ export interface NexusGenFieldTypes { // field return type device: NexusGenRootTypes['Device']; // Device! }; + IsOkResponse: { + // field return type + isOk: boolean; // Boolean! + }; Label: { // field return type createdAt: string; // String! @@ -902,11 +989,13 @@ export interface NexusGenFieldTypes { deleteLabel: NexusGenRootTypes['DeleteLabelPayload']; // DeleteLabelPayload! deleteSnapshot: NexusGenRootTypes['DeleteSnapshotPayload'] | null; // DeleteSnapshotPayload deleteWorkflow: NexusGenRootTypes['DeleteWorkflowPayload']; // DeleteWorkflowPayload! + executeNewWorkflow: string | null; // String + executeWorkflowByName: string | null; // String importCSV: NexusGenRootTypes['CSVImport'] | null; // CSVImport installDevice: NexusGenRootTypes['InstallDevicePayload']; // InstallDevicePayload! - pauseWorkflow: string | null; // String + pauseWorkflow: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse resetConfig: NexusGenRootTypes['ResetConfigPayload']; // ResetConfigPayload! - resumeWorkflow: string | null; // String + resumeWorkflow: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse revertChanges: NexusGenRootTypes['RevertChangesPayload']; // RevertChangesPayload! syncFromNetwork: NexusGenRootTypes['SyncFromNetworkPayload']; // SyncFromNetworkPayload! uninstallDevice: NexusGenRootTypes['UninstallDevicePayload']; // UninstallDevicePayload! @@ -1359,6 +1448,10 @@ export interface NexusGenFieldTypeNames { // field return type name device: 'Device'; }; + IsOkResponse: { + // field return type name + isOk: 'Boolean'; + }; Label: { // field return type name createdAt: 'String'; @@ -1416,11 +1509,13 @@ export interface NexusGenFieldTypeNames { deleteLabel: 'DeleteLabelPayload'; deleteSnapshot: 'DeleteSnapshotPayload'; deleteWorkflow: 'DeleteWorkflowPayload'; + executeNewWorkflow: 'String'; + executeWorkflowByName: 'String'; importCSV: 'CSVImport'; installDevice: 'InstallDevicePayload'; - pauseWorkflow: 'String'; + pauseWorkflow: 'IsOkResponse'; resetConfig: 'ResetConfigPayload'; - resumeWorkflow: 'String'; + resumeWorkflow: 'IsOkResponse'; revertChanges: 'RevertChangesPayload'; syncFromNetwork: 'SyncFromNetworkPayload'; uninstallDevice: 'UninstallDevicePayload'; @@ -1682,6 +1777,18 @@ export interface NexusGenArgTypes { name: string; // String! version: number; // Int! }; + executeNewWorkflow: { + // args + input: NexusGenInputs['StartWorkflowRequestInput']; // StartWorkflowRequestInput! + }; + executeWorkflowByName: { + // args + correlationId?: string | null; // String + inputParameters: string; // String! + priority?: number | null; // Int + workflowName: string; // String! + workflowVersion?: number | null; // Int + }; importCSV: { // args input: NexusGenInputs['CSVImportInput']; // CSVImportInput! diff --git a/src/schema/task.ts b/src/schema/task.ts index 0d727670..be07d935 100644 --- a/src/schema/task.ts +++ b/src/schema/task.ts @@ -1,4 +1,4 @@ -import { enumType, objectType } from 'nexus'; +import { enumType, inputObjectType, objectType } from 'nexus'; import { v4 as uuid } from 'uuid'; import { toGraphId } from '../helpers/id-helper'; @@ -17,6 +17,34 @@ export const ExecutedWorkflowTaskStatus = enumType({ ], }); +export const WorkflowTaskType = enumType({ + name: 'WorkflowTaskType', + members: [ + 'SIMPLE', + 'DECISION', + 'DYNAMIC', + 'FORK_JOIN', + 'JOIN', + 'SUB_WORKFLOW', + 'FORK_JOIN_DYNAMIC', + 'EVENT', + 'LAMBDA', + 'HTTP', + 'KAFKA_PUBLISH', + 'TERMINATE', + 'HUMAN', + 'WAIT', + 'JSON_JQ_TRANSFORM', + 'SET_VARIABLE', + 'DO_WHILE', + 'START_WORKFLOW', + 'USER_DEFINED', + 'INLINE', + 'EXCLUSIVE_JOIN', + 'SWITCH', + ], +}); + export const ExecutedWorkflowTask = objectType({ name: 'ExecutedWorkflowTask', definition: (t) => { @@ -50,3 +78,23 @@ export const ExecutedWorkflowTask = objectType({ t.string('subWorkflowId'); }, }); + +export const TaskInput = inputObjectType({ + name: 'TaskInput', + definition: (t) => { + t.nonNull.string('name'); + t.nonNull.string('taskReferenceName'); + t.string('description'); + t.string('inputParameters'); + t.string('type'); + t.int('startDelay'); + t.boolean('optional'); + t.boolean('asyncComplete'); + t.list.field('workflowTaskType', { type: WorkflowTaskType }); + t.list.string('joinOn'); + t.string('decisionCases'); + t.string('defaultCase'); + t.string('loopCondition'); + t.int('retryCount'); + }, +}); diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 77dcc713..476e8851 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -1,13 +1,27 @@ import { connectionFromArray } from 'graphql-relay'; -import { arg, extendType, inputObjectType, list, mutationField, intArg, nonNull, objectType, stringArg } from 'nexus'; +import { v4 as uuid } from 'uuid'; +import { + arg, + enumType, + extendType, + inputObjectType, + intArg, + list, + mutationField, + nonNull, + objectType, + queryField, + stringArg, +} from 'nexus'; import config from '../config'; import { WorkflowDetailInput } from '../external-api/conductor-network-types'; import { toGraphId } from '../helpers/id-helper'; import { validateTasks } from '../helpers/workflow-helpers'; -import { Node, PageInfo, PaginationConnectionArgs } from './global-types'; -import getLogger from '../get-logger'; - -const log = getLogger('frinx-inventory-server'); +import { IsOkResponse, Node, PageInfo, PaginationConnectionArgs } from './global-types'; +import { TaskInput, ExecutedWorkflowTask } from './task'; +import { makePaginationFromArgs, makeSearchQueryFromArgs } from '../helpers/workflow.helpers'; +import { StartWorkflowInput } from '../types/conductor.types'; +import { parseJson } from '../helpers/utils.helpers'; export const Workflow = objectType({ name: 'Workflow', @@ -34,7 +48,6 @@ export const Workflow = objectType({ await schedulerAPI.getSchedule(config.schedulerApiURL, workflow.name, workflow.version ?? 1); return true; } catch (e) { - log.info(`cannot get schedule info for workflow ${workflow.name}: ${e}`); return false; } }, @@ -87,6 +100,206 @@ export const WorkflowsQuery = extendType({ }, }); +export const TimeoutPolicy = enumType({ + name: 'TimeoutPolicy', + members: ['TIME_OUT_WF', 'ALERT_ONLY'], +}); + +export const WorkflowDefinitionInput = inputObjectType({ + name: 'WorkflowDefinitionInput', + definition: (t) => { + t.nonNull.string('name'); + t.nonNull.list.nonNull.field('tasks', { + type: TaskInput, + }); + t.nonNull.int('timeoutSeconds'); + t.list.string('inputParameters'); + t.string('outputParameters'); + t.string('description'); + t.int('version'); + t.int('schemaVersion'); + t.string('ownerApp'); + t.string('ownerEmail'); + t.string('variables'); + t.string('inputTemplate'); + t.boolean('restartable'); + t.field('timeoutPolicy', { + type: TimeoutPolicy, + }); + t.int('createdAt'); + t.int('updatedAt'); + t.int('createTime'); + t.int('updateTime'); + t.string('createdBy'); + t.string('updatedBy'); + }, +}); + +export const ExecutedWorkflowStatus = enumType({ + name: 'ExecutedWorkflowStatus', + members: ['RUNNING', 'COMPLETED', 'FAILED', 'TERMINATED', 'TIMED_OUT', 'PAUSED'], +}); + +export const ExecutedWorkflow = objectType({ + name: 'ExecutedWorkflow', + definition(t) { + t.implements(Node); + t.nonNull.id('id', { + resolve: (executedWorkflow) => toGraphId('ExecutedWorkflow', executedWorkflow.workflowId ?? uuid()), + }); + t.string('createdBy', { resolve: (executedWorkflow) => executedWorkflow.createdBy ?? null }); + t.string('updatedBy', { resolve: (workflow) => workflow.updatedBy ?? null }); + t.string('createdAt', { + resolve: (workflow) => (workflow.createTime ? new Date(workflow.createTime).toISOString() : null), + }); + t.string('updatedAt', { + resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), + }); + t.field('status', { type: ExecutedWorkflowStatus }); + t.string('parentWorkflowId'); + t.string('ownerApp'); + t.string('input', { resolve: (workflow) => JSON.stringify(workflow.input) }); + t.string('output', { resolve: (workflow) => JSON.stringify(workflow.output) }); + t.string('reasonForIncompletion'); + t.list.string('failedReferenceTaskNames'); + t.field('workflowDefinition', { type: Workflow }); + t.string('variables', { resolve: (workflow) => JSON.stringify(workflow.variables) }); + t.string('lastRetriedTime', { + resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), + }); + t.string('startTime', { + resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), + }); + t.string('endTime', { + resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), + }); + t.int('workflowVersion'); + t.string('workflowName'); + t.string('workflowId'); + t.list.field('tasks', { + type: ExecutedWorkflowTask, + }); + }, +}); + +export const ExecutedWorkflowEdge = objectType({ + name: 'ExecutedWorkflowEdge', + definition: (t) => { + t.nonNull.field('node', { + type: ExecutedWorkflow, + }); + t.nonNull.string('cursor'); + }, +}); + +export const ExecutedWorkflowConnection = objectType({ + name: 'ExecutedWorkflowConnection', + definition: (t) => { + t.nonNull.list.nonNull.field('edges', { + type: ExecutedWorkflowEdge, + }); + t.nonNull.field('pageInfo', { + type: PageInfo, + }); + t.nonNull.int('totalCount'); + }, +}); + +export const ExecutedWorkflowStartTimeRange = inputObjectType({ + name: 'ExecutedWorkflowStartTimeRange', + definition: (t) => { + t.nonNull.string('from'); + t.string('to'); + }, +}); + +export const ExecutedWorkflowFilterInput = inputObjectType({ + name: 'ExecutedWorkflowFilterInput', + definition: (t) => { + t.list.nonNull.string('workflowId'); + t.list.nonNull.string('workflowType'); + t.list.nonNull.field('status', { type: ExecutedWorkflowStatus }); + t.field('startTime', { type: ExecutedWorkflowStartTimeRange }); + }, +}); + +export const ExecutedWorkflowSearchInput = inputObjectType({ + name: 'ExecutedWorkflowSearchInput', + definition: (t) => { + t.boolean('isRootWorkflow'); + t.field('query', { type: ExecutedWorkflowFilterInput }); + }, +}); + +export const PaginationArgs = inputObjectType({ + name: 'PaginationArgs', + definition: (t) => { + t.nonNull.int('size'); + t.nonNull.int('start'); + }, +}); + +export const ExecutedWorkflowsQuery = queryField('executedWorkflows', { + type: ExecutedWorkflowConnection, + args: { + pagination: arg({ type: PaginationArgs }), + searchQuery: arg({ type: ExecutedWorkflowSearchInput }), + }, + resolve: async (_, args, { conductorAPI }) => { + const { results: executedWorkflows } = await conductorAPI.getExecutedWorkflows( + config.conductorApiURL, + makeSearchQueryFromArgs(args.searchQuery), + makePaginationFromArgs(args.pagination), + ); + + const executedWorkflowsWithId = executedWorkflows + .map((w) => ({ + ...w, + id: toGraphId('ExecutedWorkflow', w.workflowId || uuid()), + })) + .slice(0, args.pagination?.size ?? 0 - 1); + + return { + edges: executedWorkflowsWithId.map((w) => ({ + node: w, + cursor: w.id, + })), + pageInfo: { + hasNextPage: args.pagination ? executedWorkflowsWithId.length < executedWorkflows.length : false, + hasPreviousPage: args.pagination ? args.pagination.start >= args.pagination.size : false, + endCursor: executedWorkflowsWithId[executedWorkflowsWithId.length - 1]?.id, + startCursor: executedWorkflowsWithId[0]?.id, + }, + totalCount: executedWorkflows.length, + }; + }, +}); + +export const ExecuteNewWorkflowInput = inputObjectType({ + name: 'ExecuteNewWorkflowInput', + definition: (t) => { + t.nonNull.string('name'); + t.int('version'); + t.string('correlationId'); + t.string('input'); + t.string('taskToDomain'); + t.string('externalInputPayloadStoragePath'); + t.int('priority'); + }, +}); + +export const StartWorkflowRequestInput = inputObjectType({ + name: 'StartWorkflowRequestInput', + definition: (t) => { + t.nonNull.field('workflow', { + type: ExecuteNewWorkflowInput, + }); + t.field('workflowDefinition', { + type: WorkflowDefinitionInput, + }); + }, +}); + export const CreateWorkflowPayload = objectType({ name: 'CreateWorkflowPayload', definition: (t) => { @@ -114,6 +327,46 @@ export const CreateWorkflowInput = inputObjectType({ }, }); +export const ExecuteNewWorkflow = mutationField('executeNewWorkflow', { + type: 'String', + args: { + input: nonNull(arg({ type: StartWorkflowRequestInput })), + }, + resolve: async (_, { input }, { conductorAPI }) => { + const { workflow, workflowDefinition } = input; + + let newWorkflow: StartWorkflowInput; + + try { + newWorkflow = { + ...workflow, + input: parseJson(workflow.input), + taskToDomain: parseJson(workflow.taskToDomain), + ...(workflowDefinition && { + workflowDef: { + ...workflowDefinition, + inputTemplate: parseJson(workflowDefinition.inputTemplate), + outputParameters: parseJson(workflowDefinition.outputParameters), + variables: parseJson(workflowDefinition.variables), + tasks: workflowDefinition.tasks.map((t) => ({ + ...t, + inputParameters: parseJson>(t.inputParameters), + decisionCases: parseJson>(t.decisionCases), + defaultCase: parseJson(t.defaultCase), + })), + }, + }), + }; + } catch (error) { + throw new Error(`Invalid JSON: ${error}`); + } + + const workflowId = await conductorAPI.executeNewWorkflow(config.conductorApiURL, newWorkflow); + + return workflowId; + }, +}); + export const CreateWorkflowMutation = extendType({ type: 'Mutation', definition: (t) => { @@ -238,34 +491,26 @@ export const DeleteWorkflowMutation = extendType({ }); export const PauseWorkflowMutation = mutationField('pauseWorkflow', { - type: 'String', + type: IsOkResponse, args: { workflowId: nonNull(stringArg()), }, resolve: async (_, { workflowId }, { conductorAPI }) => { - try { - await conductorAPI.pauseWorkflow(config.conductorApiURL, workflowId); + await conductorAPI.pauseWorkflow(config.conductorApiURL, workflowId); - return 'Workflow paused'; - } catch (error) { - throw new Error("Workflow couldn't be paused"); - } + return { isOk: true }; }, }); export const ResumeWorkflowMutation = mutationField('resumeWorkflow', { - type: 'String', + type: IsOkResponse, args: { workflowId: nonNull(stringArg()), }, resolve: async (_, { workflowId }, { conductorAPI }) => { - try { - await conductorAPI.resumeWorkflow(config.conductorApiURL, workflowId); + await conductorAPI.resumeWorkflow(config.conductorApiURL, workflowId); - return 'Workflow resumed'; - } catch (error) { - throw new Error("Workflow couldn't be resumed"); - } + return { isOk: true }; }, }); @@ -283,16 +528,34 @@ export const BulkResumeWorkflowMutation = mutationField('bulkResumeWorkflow', { workflowIds: nonNull(list(nonNull(stringArg()))), }, resolve: async (_, { workflowIds }, { conductorAPI }) => { - try { - const data = await conductorAPI.bulkResumeWorkflow(config.conductorApiURL, workflowIds); + const data = await conductorAPI.bulkResumeWorkflow(config.conductorApiURL, workflowIds); - return { - bulkErrorResults: JSON.stringify(data.bulkErrorResults), - bulkSuccessfulResults: data.bulkSuccessfulResults, - }; - } catch (error) { - throw new Error('Bulk resume of workflows was not successful'); - } + return { + bulkErrorResults: JSON.stringify(data.bulkErrorResults), + bulkSuccessfulResults: data.bulkSuccessfulResults, + }; + }, +}); + +export const ExecuteWorkflowByName = mutationField('executeWorkflowByName', { + type: 'String', + args: { + inputParameters: nonNull(stringArg({ description: 'JSON string of input parameters' })), + workflowName: nonNull(stringArg()), + workflowVersion: intArg(), + correlationId: stringArg(), + priority: intArg(), + }, + resolve: async (_, { inputParameters, workflowName, workflowVersion, correlationId, priority }, { conductorAPI }) => { + const workflowId = await conductorAPI.executeWorkflowByName(config.conductorApiURL, { + inputParameters: parseJson(inputParameters), + name: workflowName, + version: workflowVersion, + correlationId, + priority, + }); + + return workflowId; }, }); @@ -302,15 +565,11 @@ export const BulkPauseWorkflowMutation = mutationField('bulkPauseWorkflow', { workflowIds: nonNull(list(nonNull(stringArg()))), }, resolve: async (_, { workflowIds }, { conductorAPI }) => { - try { - const data = await conductorAPI.bulkPauseWorkflow(config.conductorApiURL, workflowIds); + const data = await conductorAPI.bulkPauseWorkflow(config.conductorApiURL, workflowIds); - return { - bulkErrorResults: JSON.stringify(data.bulkErrorResults), - bulkSuccessfulResults: data.bulkSuccessfulResults, - }; - } catch (error) { - throw new Error('Bulk pause of workflows was not successful'); - } + return { + bulkErrorResults: JSON.stringify(data.bulkErrorResults), + bulkSuccessfulResults: data.bulkSuccessfulResults, + }; }, }); diff --git a/src/types/conductor.types.ts b/src/types/conductor.types.ts new file mode 100644 index 00000000..13ac6a52 --- /dev/null +++ b/src/types/conductor.types.ts @@ -0,0 +1,143 @@ +export type ExecutedWorkflowResult = { + results: unknown[]; + totalHits: number; +}; + +export type ConductorQuerySearchTime = { + from: number; + to?: number | null; +}; + +export type ConductorQueryStatus = 'RUNNING' | 'COMPLETED' | 'FAILED' | 'TERMINATED' | 'TIMED_OUT' | 'PAUSED'; + +export type ConductorQuery = { + status?: ConductorQueryStatus[] | null; + startTime?: ConductorQuerySearchTime | null; + workflowId?: string[] | null; + workflowType?: string[] | null; +}; + +export type SearchQuery = { + isRootWorkflow?: boolean | null; + query?: ConductorQuery | null; +}; + +export type PaginationArgs = { + size: number; + start: number; +}; + +/** + * @typedef {Task} Task + * + * this Data structure type definition is used only for NexusJS stringified JSONs validation + * + * when graphql mutation accepts stringified JSONs as input, we need to validate the JSONs + * + * this Type is used only when we need to validate the JSONs that are generated by NexusJS + * and Conductor API instead of stringified JSONs works with Record type + * + * @readonly + */ +export type Task = { + name: string; + taskReferenceName: string; + description?: string | null; + inputParameters?: Record | null; + type?: string | null; + startDelay?: number | null; + optional?: boolean | null; + asyncComplete?: boolean | null; + workflowTaskType?: + | ( + | 'SIMPLE' + | 'DECISION' + | 'DYNAMIC' + | 'FORK_JOIN' + | 'JOIN' + | 'SUB_WORKFLOW' + | 'FORK_JOIN_DYNAMIC' + | 'EVENT' + | 'LAMBDA' + | 'HTTP' + | 'KAFKA_PUBLISH' + | 'TERMINATE' + | 'HUMAN' + | 'WAIT' + | 'JSON_JQ_TRANSFORM' + | 'SET_VARIABLE' + | 'DO_WHILE' + | 'START_WORKFLOW' + | 'USER_DEFINED' + | 'INLINE' + | 'EXCLUSIVE_JOIN' + | 'SWITCH' + | null + )[] + | null; + joinOn?: (string | null)[] | null; + decisionCases?: Record | null; + defaultCase?: unknown[] | null; + loopCondition?: string | null; + retryCount?: number | null; +}; + +/** + * @typedef {WorkflowDefinition} WorkflowDefinition + * + * this Data structure type definition is used only for NexusJS stringified JSONs validation + * + * when graphql mutation accepts stringified JSONs as input, we need to validate the JSONs + * + * this Type is used only when we need to validate the JSONs that are generated by NexusJS + * and Conductor API instead of stringified JSONs works with Record type + * + * this type is used only to define workflowDef property in @typedef {StartWorkflowInput} + * + * @readonly + */ +export type WorkflowDefinition = { + name: string; + tasks: Task[]; + timeoutSeconds: number; + inputParameters?: (string | null)[] | null; + outputParameters?: Record | null; + description?: string | null; + schemaVersion?: number | null; + version?: number | null; + ownerApp?: string | null; + ownerEmail?: string | null; + variables?: Record | null; + inputTemplate?: Record | null; + timeoutPolicy?: 'TIME_OUT_WF' | 'ALERT_ONLY' | null; + restartable?: boolean | null; + createdBy?: string | null; + updatedBy?: string | null; + createTime?: number | null; + updateTime?: number | null; + createdAt?: number | null; + updatedAt?: number | null; +}; + +/** + * @typedef {StartWorkflowInput} StartWorkflowInput + * + * this Data structure type definition is used only for NexusJS stringified JSONs validation + * + * when graphql mutation accepts stringified JSONs as input, we need to validate the JSONs + * + * this Type is used only when we need to validate the JSONs that are generated by NexusJS + * and Conductor API instead of stringified JSONs works with Record type + * + * @readonly + */ +export type StartWorkflowInput = { + name: string; + version?: number | null; + correlationId?: string | null; + input?: Record | null; + taskToDomain?: Record | null; + externalInputPayloadStoragePath?: string | null; + priority?: number | null; + workflowDef?: WorkflowDefinition | null; +}; From 941bc00294dafca4a3d3c507f5b5e9f57234d65b Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 30 Mar 2023 10:27:53 +0200 Subject: [PATCH 09/69] FD-504 workflow filters (#272) * add workflow filters * move workflow filter to separate function --- src/helpers/workflow.helpers.ts | 35 +++++++++++++++++++++++++++++++++ src/schema/api.graphql | 7 ++++++- src/schema/nexus-typegen.ts | 6 ++++++ src/schema/workflow-labels.ts | 13 +----------- src/schema/workflow.ts | 29 ++++++++++++++++++++++----- 5 files changed, 72 insertions(+), 18 deletions(-) diff --git a/src/helpers/workflow.helpers.ts b/src/helpers/workflow.helpers.ts index 62ac86f2..613bb059 100644 --- a/src/helpers/workflow.helpers.ts +++ b/src/helpers/workflow.helpers.ts @@ -1,3 +1,4 @@ +import { Workflow } from '../schema/source-types'; import { SearchQuery, PaginationArgs } from '../types/conductor.types'; type GraphQLSearchQuery = { @@ -36,3 +37,37 @@ export function makePaginationFromArgs(pagination?: PaginationArgs | null) { } : null; } + +export function jsonParse(json?: string | null): T | null { + if (json == null) { + return null; + } + + try { + return JSON.parse(json); + } catch (e) { + return null; + } +} + +type WorkflowFilter = { + keyword?: string | null; + labels?: string[] | null; +}; + +type DescriptionJSON = { labels?: string[]; description: string }; +type WorkflowWithoutId = Omit; + +export function getFilteredWorkflows(workflows: WorkflowWithoutId[], filter: WorkflowFilter): WorkflowWithoutId[] { + const filteredWorkflows = workflows + .map((w) => ({ + ...w, + parsedDescription: jsonParse(w.description ?? ''), + })) + // labels filter = true if all filter labels are present in description labels + .filter((w) => filter?.labels?.every((f) => w.parsedDescription?.labels?.includes(f)) ?? true) + // keyword filter = true if keyword filter is substring of workflow + .filter((w) => (filter.keyword ? w.name.toLowerCase().includes(filter.keyword.toLowerCase()) : true)); + + return filteredWorkflows; +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index a3b93a6b..c5ca2aa3 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -388,6 +388,11 @@ input FilterTopologyInput { labels: [String!] } +input FilterWorkflowsInput { + keyword: String + labels: [String!] +} + type GraphEdge { id: ID! source: EdgeSourceTarget! @@ -571,7 +576,7 @@ type Query { transactions: [Transaction!]! uniconfigShellSession: String workflowLabels: [String!]! - workflows(after: String, before: String, first: Int, last: Int): WorkflowConnection! + workflows(after: String, before: String, filter: FilterWorkflowsInput, first: Int, last: Int): WorkflowConnection! zones(after: String, before: String, first: Int, last: Int): ZonesConnection! } diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 785a9b74..61c20940 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -138,6 +138,11 @@ export interface NexusGenInputs { // input type labels?: string[] | null; // [String!] }; + FilterWorkflowsInput: { + // input type + keyword?: string | null; // String + labels?: string[] | null; // [String!] + }; GraphNodeCoordinatesInput: { // input type deviceName: string; // String! @@ -1922,6 +1927,7 @@ export interface NexusGenArgTypes { // args after?: string | null; // String before?: string | null; // String + filter?: NexusGenInputs['FilterWorkflowsInput'] | null; // FilterWorkflowsInput first?: number | null; // Int last?: number | null; // Int }; diff --git a/src/schema/workflow-labels.ts b/src/schema/workflow-labels.ts index 8d10b783..fdea4218 100644 --- a/src/schema/workflow-labels.ts +++ b/src/schema/workflow-labels.ts @@ -1,21 +1,10 @@ import { extendType, list, nonNull } from 'nexus'; import config from '../config'; +import { jsonParse } from '../helpers/workflow.helpers'; import { Workflow } from './source-types'; type DescriptionJSON = { labels?: string[]; description: string }; -const jsonParse = (json?: string | null): T | null => { - if (json == null) { - return null; - } - - try { - return JSON.parse(json); - } catch (e) { - return null; - } -}; - const getLabels = (workflows: Omit[]): string[] => { const labelsSet = new Set(); diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 476e8851..4396d19b 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -17,12 +17,15 @@ import config from '../config'; import { WorkflowDetailInput } from '../external-api/conductor-network-types'; import { toGraphId } from '../helpers/id-helper'; import { validateTasks } from '../helpers/workflow-helpers'; +import getLogger from '../get-logger'; import { IsOkResponse, Node, PageInfo, PaginationConnectionArgs } from './global-types'; import { TaskInput, ExecutedWorkflowTask } from './task'; -import { makePaginationFromArgs, makeSearchQueryFromArgs } from '../helpers/workflow.helpers'; +import { getFilteredWorkflows, makePaginationFromArgs, makeSearchQueryFromArgs } from '../helpers/workflow.helpers'; import { StartWorkflowInput } from '../types/conductor.types'; import { parseJson } from '../helpers/utils.helpers'; +const log = getLogger('frinx-inventory-server'); + export const Workflow = objectType({ name: 'Workflow', definition: (t) => { @@ -48,6 +51,7 @@ export const Workflow = objectType({ await schedulerAPI.getSchedule(config.schedulerApiURL, workflow.name, workflow.version ?? 1); return true; } catch (e) { + log.info(`cannot get schedule info for workflow ${workflow.name}: ${e}`); return false; } }, @@ -78,22 +82,37 @@ export const WorkflowConnection = objectType({ }, }); +export const FilterWorkflowsInput = inputObjectType({ + name: 'FilterWorkflowsInput', + definition: (t) => { + t.list.nonNull.string('labels'); + t.string('keyword'); + }, +}); + export const WorkflowsQuery = extendType({ type: 'Query', definition: (t) => { t.nonNull.field('workflows', { type: WorkflowConnection, - args: PaginationConnectionArgs, + args: { + ...PaginationConnectionArgs, + filter: FilterWorkflowsInput, + }, resolve: async (_, args, { conductorAPI }) => { + const { filter, ...paginationArgs } = args; const workflows = await conductorAPI.getWorkflowMetadata(config.conductorApiURL); - const workflowsWithId = workflows.map((w) => ({ + const filteredWorkflows = + filter?.labels || filter?.keyword ? getFilteredWorkflows(workflows, filter) : workflows; + + const workflowsWithId = filteredWorkflows.map((w) => ({ ...w, id: w.name, })); return { - ...connectionFromArray(workflowsWithId, args), - totalCount: workflows.length, + ...connectionFromArray(workflowsWithId, paginationArgs), + totalCount: filteredWorkflows.length, }; }, }); From b9eeff4498d784e3c05e8d1e820b7ac91ddbc04b Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 30 Mar 2023 14:13:11 +0200 Subject: [PATCH 10/69] Add workflow input params (#273) * add input parameters property to workflow * pr-check fix --- .github/workflows/pr-check.yml | 1 + src/external-api/conductor-network-types.ts | 6 +++--- src/schema/api.graphql | 1 + src/schema/nexus-typegen.ts | 2 ++ src/schema/workflow.ts | 1 + 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 82031f73..9fe90bda 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -43,6 +43,7 @@ jobs: TOPOLOGY_ENABLED: false SHELL_HOST: 10.19.0.12 CONDUCTOR_API_URL: 10.19.0.7 + SCHEDULER_API_URL: 10.19.0.7 - name: Check code formatting run: yarn run formatter:check - name: Run eslint check diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index fd5ac8b3..78f6939e 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -20,9 +20,9 @@ export function extractResult(result: Either): A { export const ApiBaseTask = t.type({ name: t.string, taskReferenceName: t.string, - // description: optional(t.string), - // inputParameters: optional(t.record(t.string, t.any)), - // type: optional(t.string), + description: optional(t.string), + inputParameters: optional(t.record(t.string, t.any)), + type: optional(t.string), // dynamicTaskNameParam: optional(t.string), // scriptExpression: optional(t.string), // dynamicForkTasksParam: optional(t.string), diff --git a/src/schema/api.graphql b/src/schema/api.graphql index c5ca2aa3..a8c5844e 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -738,6 +738,7 @@ type Workflow implements Node { description: String hasSchedule: Boolean id: ID! + inputParameters: [String!] name: String! tasks: String updatedAt: String diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 61c20940..89cfb99f 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -1125,6 +1125,7 @@ export interface NexusGenFieldTypes { description: string | null; // String hasSchedule: boolean | null; // Boolean id: string; // ID! + inputParameters: string[] | null; // [String!] name: string; // String! tasks: string | null; // String updatedAt: string | null; // String @@ -1645,6 +1646,7 @@ export interface NexusGenFieldTypeNames { description: 'String'; hasSchedule: 'Boolean'; id: 'ID'; + inputParameters: 'String'; name: 'String'; tasks: 'String'; updatedAt: 'String'; diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 4396d19b..c286fd79 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -45,6 +45,7 @@ export const Workflow = objectType({ resolve: (workflow) => (workflow.updateTime ? new Date(workflow.updateTime).toISOString() : null), }); t.string('tasks', { resolve: (workflow) => JSON.stringify(workflow.tasks) }); + t.list.nonNull.string('inputParameters', { resolve: (w) => w.inputParameters ?? null }); t.boolean('hasSchedule', { resolve: async (workflow, _, { schedulerAPI }) => { try { From 0cd6187362c776022dd2147e2c37c3d4efd5495e Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Thu, 30 Mar 2023 16:26:58 +0200 Subject: [PATCH 11/69] Retry, restart, terminate and remove workflow mutations (#269) * add retry, resume, terminate and remove workflow mutations * remove custom string responses and return isOk * remove redundant trycatch and custom string responses in API calls * rename optional args by our naming conventiosn --- src/external-api/conductor.ts | 42 +++++++++++++++++++++++++-- src/schema/api.graphql | 22 +++++++++++++++ src/schema/nexus-typegen.ts | 28 ++++++++++++++++++ src/schema/workflow.ts | 53 +++++++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+), 3 deletions(-) diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts index 4a106c6a..90d1e693 100644 --- a/src/external-api/conductor.ts +++ b/src/external-api/conductor.ts @@ -1,4 +1,3 @@ -import getLogger from '../get-logger'; import { makeStringQueryFromSearchQueryObject } from '../helpers/conductor.helpers'; import { PaginationArgs, SearchQuery, StartWorkflowInput } from '../types/conductor.types'; import { @@ -18,8 +17,6 @@ import { } from './conductor-network-types'; import { sendDeleteRequest, sendGetRequest, sendPostRequest, sendPutRequest } from './helpers'; -export const log = getLogger('frinx-graphql-conductor'); - async function getWorkflowMetadata(baseURL: string): Promise { const json = await sendGetRequest([baseURL, 'metadata/workflow']); const data = decodeWorkflowMetadataOutput(json); @@ -87,6 +84,41 @@ async function getExecutedWorkflowDetail(baseURL: string, workflowId: string): P return data; } +async function retryWorkflow( + baseURL: string, + workflowId: string, + shouldResumeSubworkflowTasks: boolean | null = true, +): Promise { + await sendPostRequest([ + baseURL, + `workflow/${workflowId}/retry?resumeSubworkflowTasks=${shouldResumeSubworkflowTasks}`, + ]); +} + +async function restartWorkflow( + baseURL: string, + workflowId: string, + shouldUseLatestDefinitions: boolean | null = true, +): Promise { + await sendPostRequest([baseURL, `workflow/${workflowId}/restart?useLatestDefinitions=${shouldUseLatestDefinitions}`]); +} + +async function terminateWorkflow(baseURL: string, workflowId: string, reason?: string | null): Promise { + if (reason) { + await sendDeleteRequest([baseURL, `workflow/${workflowId}?reason=${reason}`]); + } else { + await sendDeleteRequest([baseURL, `workflow/${workflowId}`]); + } +} + +async function removeWorkflow( + baseURL: string, + workflowId: string, + shouldArchiveWorkflow: boolean | null = true, +): Promise { + await sendDeleteRequest([baseURL, `workflow/${workflowId}/remove?archiveWorkflow=${shouldArchiveWorkflow}`]); +} + async function executeNewWorkflow(baseURL: string, input: StartWorkflowInput): Promise { const executedWorkflowId = await sendPostRequest([baseURL, 'workflow'], input); @@ -133,6 +165,10 @@ const conductorAPI = { bulkPauseWorkflow, getExecutedWorkflows, getExecutedWorkflowDetail, + retryWorkflow, + restartWorkflow, + terminateWorkflow, + removeWorkflow, executeNewWorkflow, executeWorkflowByName, }; diff --git a/src/schema/api.graphql b/src/schema/api.graphql index a8c5844e..facafc6a 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -524,10 +524,32 @@ type Mutation { importCSV(input: CSVImportInput!): CSVImport installDevice(id: String!): InstallDevicePayload! pauseWorkflow(workflowId: String!): IsOkResponse + removeWorkflow( + """ + Default value is true + """ + shouldArchiveWorkflow: Boolean + workflowId: String! + ): IsOkResponse resetConfig(deviceId: String!, transactionId: String!): ResetConfigPayload! + restartWorkflow( + """ + Default value is true + """ + shouldUseLatestDefinitions: Boolean + workflowId: String! + ): IsOkResponse resumeWorkflow(workflowId: String!): IsOkResponse + retryWorkflow( + """ + Default value is true + """ + shouldResumeSubworkflowTasks: Boolean + workflowId: String! + ): IsOkResponse revertChanges(transactionId: String!): RevertChangesPayload! syncFromNetwork(deviceId: String!, transactionId: String!): SyncFromNetworkPayload! + terminateWorkflow(reason: String, workflowId: String!): IsOkResponse uninstallDevice(id: String!): UninstallDevicePayload! updateBlueprint(id: String!, input: UpdateBlueprintInput!): UpdateBlueprintPayload! updateDataStore(deviceId: String!, input: UpdateDataStoreInput!, transactionId: String!): UpdateDataStorePayload! diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 89cfb99f..e154333b 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -999,10 +999,14 @@ export interface NexusGenFieldTypes { importCSV: NexusGenRootTypes['CSVImport'] | null; // CSVImport installDevice: NexusGenRootTypes['InstallDevicePayload']; // InstallDevicePayload! pauseWorkflow: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse + removeWorkflow: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse resetConfig: NexusGenRootTypes['ResetConfigPayload']; // ResetConfigPayload! + restartWorkflow: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse resumeWorkflow: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse + retryWorkflow: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse revertChanges: NexusGenRootTypes['RevertChangesPayload']; // RevertChangesPayload! syncFromNetwork: NexusGenRootTypes['SyncFromNetworkPayload']; // SyncFromNetworkPayload! + terminateWorkflow: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse uninstallDevice: NexusGenRootTypes['UninstallDevicePayload']; // UninstallDevicePayload! updateBlueprint: NexusGenRootTypes['UpdateBlueprintPayload']; // UpdateBlueprintPayload! updateDataStore: NexusGenRootTypes['UpdateDataStorePayload']; // UpdateDataStorePayload! @@ -1520,10 +1524,14 @@ export interface NexusGenFieldTypeNames { importCSV: 'CSVImport'; installDevice: 'InstallDevicePayload'; pauseWorkflow: 'IsOkResponse'; + removeWorkflow: 'IsOkResponse'; resetConfig: 'ResetConfigPayload'; + restartWorkflow: 'IsOkResponse'; resumeWorkflow: 'IsOkResponse'; + retryWorkflow: 'IsOkResponse'; revertChanges: 'RevertChangesPayload'; syncFromNetwork: 'SyncFromNetworkPayload'; + terminateWorkflow: 'IsOkResponse'; uninstallDevice: 'UninstallDevicePayload'; updateBlueprint: 'UpdateBlueprintPayload'; updateDataStore: 'UpdateDataStorePayload'; @@ -1808,15 +1816,30 @@ export interface NexusGenArgTypes { // args workflowId: string; // String! }; + removeWorkflow: { + // args + shouldArchiveWorkflow?: boolean | null; // Boolean + workflowId: string; // String! + }; resetConfig: { // args deviceId: string; // String! transactionId: string; // String! }; + restartWorkflow: { + // args + shouldUseLatestDefinitions?: boolean | null; // Boolean + workflowId: string; // String! + }; resumeWorkflow: { // args workflowId: string; // String! }; + retryWorkflow: { + // args + shouldResumeSubworkflowTasks?: boolean | null; // Boolean + workflowId: string; // String! + }; revertChanges: { // args transactionId: string; // String! @@ -1826,6 +1849,11 @@ export interface NexusGenArgTypes { deviceId: string; // String! transactionId: string; // String! }; + terminateWorkflow: { + // args + reason?: string | null; // String + workflowId: string; // String! + }; uninstallDevice: { // args id: string; // String! diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index c286fd79..9f8cd97f 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -2,6 +2,7 @@ import { connectionFromArray } from 'graphql-relay'; import { v4 as uuid } from 'uuid'; import { arg, + booleanArg, enumType, extendType, inputObjectType, @@ -593,3 +594,55 @@ export const BulkPauseWorkflowMutation = mutationField('bulkPauseWorkflow', { }; }, }); + +export const RetryWorkflowMutation = mutationField('retryWorkflow', { + type: IsOkResponse, + args: { + workflowId: nonNull(stringArg()), + shouldResumeSubworkflowTasks: booleanArg({ description: 'Default value is true' }), + }, + resolve: async (_, { workflowId, shouldResumeSubworkflowTasks }, { conductorAPI }) => { + await conductorAPI.retryWorkflow(config.conductorApiURL, workflowId, shouldResumeSubworkflowTasks); + + return { isOk: true }; + }, +}); + +export const RestartWorkflowMutation = mutationField('restartWorkflow', { + type: IsOkResponse, + args: { + workflowId: nonNull(stringArg()), + shouldUseLatestDefinitions: booleanArg({ description: 'Default value is true' }), + }, + resolve: async (_, { workflowId, shouldUseLatestDefinitions }, { conductorAPI }) => { + await conductorAPI.restartWorkflow(config.conductorApiURL, workflowId, shouldUseLatestDefinitions); + + return { isOk: true }; + }, +}); + +export const TerminateWorkflowMutation = mutationField('terminateWorkflow', { + type: IsOkResponse, + args: { + workflowId: nonNull(stringArg()), + reason: stringArg(), + }, + resolve: async (_, { workflowId, reason }, { conductorAPI }) => { + await conductorAPI.terminateWorkflow(config.conductorApiURL, workflowId, reason); + + return { isOk: true }; + }, +}); + +export const RemoveWorkflowMutation = mutationField('removeWorkflow', { + type: IsOkResponse, + args: { + workflowId: nonNull(stringArg()), + shouldArchiveWorkflow: booleanArg({ description: 'Default value is true' }), + }, + resolve: async (_, { workflowId, shouldArchiveWorkflow }, { conductorAPI }) => { + await conductorAPI.removeWorkflow(config.conductorApiURL, workflowId, shouldArchiveWorkflow); + + return { isOk: true }; + }, +}); From 9f718d06539a0190130d3fac8f17ef897eceab65 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Wed, 5 Apr 2023 13:12:20 +0200 Subject: [PATCH 12/69] FD-517 task definitions query (#274) * task definitions query added * add missing file; fix type checking * changed task definition props to createdAt, updatedAt * add additional properties --- src/external-api/conductor-network-types.ts | 30 +++++++++++ src/external-api/conductor.ts | 9 ++++ src/schema/api.graphql | 36 +++++++++++++ src/schema/index.ts | 2 + src/schema/nexus-typegen.ts | 51 ++++++++++++++++++ src/schema/source-types.ts | 2 + src/schema/task-definitons.ts | 60 +++++++++++++++++++++ 7 files changed, 190 insertions(+) create mode 100644 src/schema/task-definitons.ts diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index 78f6939e..3c0c4384 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -190,12 +190,36 @@ const ExecutedWorkflowsValidator = t.type({ results: t.array(ExecutedWorkflow), }); +const TaskDefinition = t.type({ + name: t.string, + timeoutSeconds: t.number, + createTime: optional(t.number), + updateTime: optional(t.number), + createdBy: optional(t.string), + updatedBy: optional(t.string), + retryCount: optional(t.number), + pollTimeoutSeconds: optional(t.number), + inputKeys: optional(t.array(t.string)), + outputKeys: optional(t.array(t.string)), + inputTemplate: optional(t.record(t.string, t.string)), + timeoutPolicy: optional(t.union([t.literal('RETRY'), t.literal('TIME_OUT_WF'), t.literal('ALERT_ONLY')])), + retryLogic: optional(t.union([t.literal('FIXED'), t.literal('EXPONENTIAL_BACKOFF'), t.literal('LINEAR_BACKOFF')])), + retryDelaySeconds: optional(t.number), + responseTimeoutSeconds: optional(t.number), + concurrentExecLimit: optional(t.number), + rateLimitFrequencyInSeconds: optional(t.number), + rateLimitPerFrequency: optional(t.number), + ownerEmail: optional(t.string), +}); +const TaskDefinitionsValidator = t.array(TaskDefinition); + export type ExecutedWorkflowsOutput = t.TypeOf; export type WorfklowMetadataOutput = t.TypeOf; export type WorkflowMetadataOutput = t.TypeOf; export type ApiWorkflow = t.TypeOf; export type ApiExecutedWorkflow = t.TypeOf; export type ApiExecutedWorkflowTask = t.TypeOf; +export type ApiTaskDefinition = t.TypeOf; export function decodeWorkflowMetadataOutput(value: unknown): WorkflowMetadataOutput { return extractResult(WorkflowMetadataValidator.decode(value)); @@ -231,3 +255,9 @@ export function decodeExecutedWorkflowsOutput(value: unknown): ExecutedWorkflows export function decodeExecutedWorkflowDetailOutput(value: unknown): ApiExecutedWorkflow { return extractResult(ExecutedWorkflow.decode(value)); } + +export type TaskDefinitionsOutput = t.TypeOf; + +export function decodeTaskDefinitionsOutput(value: unknown): TaskDefinitionsOutput { + return extractResult(TaskDefinitionsValidator.decode(value)); +} diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts index 90d1e693..466d1062 100644 --- a/src/external-api/conductor.ts +++ b/src/external-api/conductor.ts @@ -14,6 +14,8 @@ import { ExecutedWorkflowsOutput, WorkflowDetailOutput, WorkflowEditOutput, + TaskDefinitionsOutput, + decodeTaskDefinitionsOutput, } from './conductor-network-types'; import { sendDeleteRequest, sendGetRequest, sendPostRequest, sendPutRequest } from './helpers'; @@ -153,6 +155,12 @@ async function executeWorkflowByName( } } +async function getTaskDefinitions(baseURL: string): Promise { + const json = await sendGetRequest([baseURL, 'metadata/taskdefs']); + const data = decodeTaskDefinitionsOutput(json); + return data; +} + const conductorAPI = { getWorkflowMetadata, getWorkflowDetail, @@ -171,6 +179,7 @@ const conductorAPI = { removeWorkflow, executeNewWorkflow, executeWorkflowByName, + getTaskDefinitions, }; export type ConductorAPI = typeof conductorAPI; diff --git a/src/schema/api.graphql b/src/schema/api.graphql index facafc6a..450382c9 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -591,6 +591,7 @@ type Query { labels(after: String, before: String, first: Int, last: Int): LabelConnection! locations(after: String, before: String, first: Int, last: Int): LocationConnection! node(id: ID!): Node + taskDefinitions: [TaskDefinition!]! topology(filter: FilterTopologyInput): Topology topologyCommonNodes(nodes: [String!]!): TopologyCommonNodes topologyVersionData(version: String!): TopologyVersionData! @@ -606,6 +607,12 @@ type ResetConfigPayload { dataStore: DataStore! } +enum RetryLogic { + EXPONENTIAL_BACKOFF + FIXED + LINEAR_BACKOFF +} + type RevertChangesPayload { isOk: Boolean! } @@ -638,6 +645,29 @@ type SyncFromNetworkPayload { dataStore: DataStore } +type TaskDefinition { + concurrentExecLimit: Int + createdAt: String + createdBy: String + description: String + inputKeys: [String!] + inputTemplate: String + name: String! + outputKeys: [String!] + ownerEmail: String + pollTimeoutSeconds: Int + rateLimitFrequencyInSeconds: Int + rateLimitPerFrequency: Int + responseTimeoutSeconds: Int + retryCount: Int + retryDelaySeconds: Int + retryLogic: RetryLogic + timeoutPolicy: TaskTimeoutPolicy + timeoutSeconds: Int! + updatedAt: String + updatedBy: String +} + input TaskInput { asyncComplete: Boolean decisionCases: String @@ -655,6 +685,12 @@ input TaskInput { workflowTaskType: [WorkflowTaskType] } +enum TaskTimeoutPolicy { + ALERT_ONLY + RETRY + TIME_OUT_WF +} + enum TimeoutPolicy { ALERT_ONLY TIME_OUT_WF diff --git a/src/schema/index.ts b/src/schema/index.ts index 0389cad1..55281de1 100644 --- a/src/schema/index.ts +++ b/src/schema/index.ts @@ -12,6 +12,7 @@ import * as topology from './topology'; import * as workflow from './workflow'; import * as executedWorkflowTask from './task'; import * as workflowLabels from './workflow-labels'; +import * as taskDefintions from './task-definitons'; export default makeSchema({ features: { @@ -42,6 +43,7 @@ export default makeSchema({ workflow, workflowLabels, executedWorkflowTask, + taskDefintions, ], sourceTypes: { modules: [ diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index e154333b..a363c136 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -255,8 +255,10 @@ export interface NexusGenEnums { | 'SKIPPED' | 'TIMED_OUT'; GraphEdgeStatus: 'ok' | 'unknown'; + RetryLogic: 'EXPONENTIAL_BACKOFF' | 'FIXED' | 'LINEAR_BACKOFF'; SortDeviceBy: 'CREATED_AT' | 'NAME'; SortDirection: 'ASC' | 'DESC'; + TaskTimeoutPolicy: 'ALERT_ONLY' | 'RETRY' | 'TIME_OUT_WF'; TimeoutPolicy: 'ALERT_ONLY' | 'TIME_OUT_WF'; WorkflowTaskType: | 'DECISION' @@ -549,6 +551,7 @@ export interface NexusGenObjects { // root type dataStore?: NexusGenRootTypes['DataStore'] | null; // DataStore }; + TaskDefinition: SourceTypes.TaskDefinition; Topology: { // root type edges: NexusGenRootTypes['GraphEdge'][]; // [GraphEdge!]! @@ -1032,6 +1035,7 @@ export interface NexusGenFieldTypes { labels: NexusGenRootTypes['LabelConnection']; // LabelConnection! locations: NexusGenRootTypes['LocationConnection']; // LocationConnection! node: NexusGenRootTypes['Node'] | null; // Node + taskDefinitions: NexusGenRootTypes['TaskDefinition'][]; // [TaskDefinition!]! topology: NexusGenRootTypes['Topology'] | null; // Topology topologyCommonNodes: NexusGenRootTypes['TopologyCommonNodes'] | null; // TopologyCommonNodes topologyVersionData: NexusGenRootTypes['TopologyVersionData']; // TopologyVersionData! @@ -1063,6 +1067,29 @@ export interface NexusGenFieldTypes { // field return type dataStore: NexusGenRootTypes['DataStore'] | null; // DataStore }; + TaskDefinition: { + // field return type + concurrentExecLimit: number | null; // Int + createdAt: string | null; // String + createdBy: string | null; // String + description: string | null; // String + inputKeys: string[] | null; // [String!] + inputTemplate: string | null; // String + name: string; // String! + outputKeys: string[] | null; // [String!] + ownerEmail: string | null; // String + pollTimeoutSeconds: number | null; // Int + rateLimitFrequencyInSeconds: number | null; // Int + rateLimitPerFrequency: number | null; // Int + responseTimeoutSeconds: number | null; // Int + retryCount: number | null; // Int + retryDelaySeconds: number | null; // Int + retryLogic: NexusGenEnums['RetryLogic'] | null; // RetryLogic + timeoutPolicy: NexusGenEnums['TaskTimeoutPolicy'] | null; // TaskTimeoutPolicy + timeoutSeconds: number; // Int! + updatedAt: string | null; // String + updatedBy: string | null; // String + }; Topology: { // field return type edges: NexusGenRootTypes['GraphEdge'][]; // [GraphEdge!]! @@ -1557,6 +1584,7 @@ export interface NexusGenFieldTypeNames { labels: 'LabelConnection'; locations: 'LocationConnection'; node: 'Node'; + taskDefinitions: 'TaskDefinition'; topology: 'Topology'; topologyCommonNodes: 'TopologyCommonNodes'; topologyVersionData: 'TopologyVersionData'; @@ -1588,6 +1616,29 @@ export interface NexusGenFieldTypeNames { // field return type name dataStore: 'DataStore'; }; + TaskDefinition: { + // field return type name + concurrentExecLimit: 'Int'; + createdAt: 'String'; + createdBy: 'String'; + description: 'String'; + inputKeys: 'String'; + inputTemplate: 'String'; + name: 'String'; + outputKeys: 'String'; + ownerEmail: 'String'; + pollTimeoutSeconds: 'Int'; + rateLimitFrequencyInSeconds: 'Int'; + rateLimitPerFrequency: 'Int'; + responseTimeoutSeconds: 'Int'; + retryCount: 'Int'; + retryDelaySeconds: 'Int'; + retryLogic: 'RetryLogic'; + timeoutPolicy: 'TaskTimeoutPolicy'; + timeoutSeconds: 'Int'; + updatedAt: 'String'; + updatedBy: 'String'; + }; Topology: { // field return type name edges: 'GraphEdge'; diff --git a/src/schema/source-types.ts b/src/schema/source-types.ts index 43b6eb63..f0a51c45 100644 --- a/src/schema/source-types.ts +++ b/src/schema/source-types.ts @@ -4,6 +4,7 @@ import { ApiExecutedWorkflowTask, ApiWorkflow, NestedTask, + ApiTaskDefinition, } from '../external-api/conductor-network-types'; export type Label = label; @@ -25,3 +26,4 @@ export type Workflow = ApiWorkflow & { id: string }; export type ExecutedWorkflow = ApiExecutedWorkflow & { id: string }; export type ExecutedWorkflowTask = ApiExecutedWorkflowTask & { id: string }; export type WorkflowTask = NestedTask; +export type TaskDefinition = ApiTaskDefinition; diff --git a/src/schema/task-definitons.ts b/src/schema/task-definitons.ts new file mode 100644 index 00000000..c6a63fe4 --- /dev/null +++ b/src/schema/task-definitons.ts @@ -0,0 +1,60 @@ +import { enumType, extendType, list, nonNull, objectType } from 'nexus'; +import config from '../config'; + +const TaskTimeoutPolicy = enumType({ + name: 'TaskTimeoutPolicy', + members: ['RETRY', 'TIME_OUT_WF', 'ALERT_ONLY'], +}); + +const RetryLogic = enumType({ + name: 'RetryLogic', + members: ['FIXED', 'EXPONENTIAL_BACKOFF', 'LINEAR_BACKOFF'], +}); + +export const TaskDefinition = objectType({ + name: 'TaskDefinition', + definition: (t) => { + t.nonNull.string('name'); + t.nonNull.int('timeoutSeconds'); + t.string('createdAt', { + resolve: (taskDefinition) => + taskDefinition.createTime ? new Date(taskDefinition.createTime).toISOString() : new Date().toISOString(), + }); + t.string('updatedAt', { + resolve: (taskDefinition) => + taskDefinition.updateTime ? new Date(taskDefinition.updateTime).toISOString() : new Date().toISOString(), + }); + t.string('createdBy'); + t.string('updatedBy'); + t.string('description'); + t.int('retryCount'); + t.int('pollTimeoutSeconds'); + t.list.nonNull.string('inputKeys'); + t.list.nonNull.string('outputKeys'); + t.string('inputTemplate', { + resolve: (taskDefinition) => JSON.stringify(taskDefinition.inputTemplate), + }); + t.field('timeoutPolicy', { type: TaskTimeoutPolicy }); + t.field('retryLogic', { type: RetryLogic }); + t.int('retryDelaySeconds'); + t.int('responseTimeoutSeconds'); + t.int('concurrentExecLimit'); + t.int('rateLimitFrequencyInSeconds'); + t.int('rateLimitPerFrequency'); + t.string('ownerEmail'); + }, +}); + +export const TaskDefinitionsQuery = extendType({ + type: 'Query', + definition: (t) => { + t.nonNull.field('taskDefinitions', { + type: list(nonNull(TaskDefinition)), + resolve: async (_, _args, { conductorAPI }) => { + const taskDefinitions = await conductorAPI.getTaskDefinitions(config.conductorApiURL); + + return taskDefinitions; + }, + }); + }, +}); From 9d09d98119564f0754a31ec675d23c524334b6aa Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Mon, 17 Apr 2023 17:01:55 +0200 Subject: [PATCH 13/69] bulk operations added (terminate, restart, retry) (#275) --- src/external-api/conductor-network-types.ts | 22 ++++----- src/external-api/conductor.ts | 28 ++++++++++-- src/schema/api.graphql | 3 ++ src/schema/nexus-typegen.ts | 18 ++++++++ src/schema/workflow.ts | 50 ++++++++++++++++++++- 5 files changed, 106 insertions(+), 15 deletions(-) diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index 3c0c4384..4e78f24d 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -232,16 +232,6 @@ export function decodeWorkflowDetailOutput(value: unknown): WorkflowDetailOutput return extractResult(WorkflowMetadata.decode(value)); } -const WorkflowEditValidator = t.type({ - bulkErrorResults: t.record(t.string, t.string), - bulkSuccessfulResults: t.array(t.string), -}); - -export type WorkflowEditOutput = t.TypeOf; - -export function decodeWorkflowEditOutput(value: unknown): WorkflowEditOutput { - return extractResult(WorkflowEditValidator.decode(value)); -} export type BulkOperationOutput = t.TypeOf; export function decodeBulkOperationOutput(value: unknown): BulkOperationOutput { @@ -261,3 +251,15 @@ export type TaskDefinitionsOutput = t.TypeOf; export function decodeTaskDefinitionsOutput(value: unknown): TaskDefinitionsOutput { return extractResult(TaskDefinitionsValidator.decode(value)); } + +export function decodeBulkTerminateOutput(value: unknown): BulkOperationOutput { + return extractResult(BulkOperation.decode(value)); +} + +export function decodeBulkRetryOutput(value: unknown): BulkOperationOutput { + return extractResult(BulkOperation.decode(value)); +} + +export function decodeBulkRestartOutput(value: unknown): BulkOperationOutput { + return extractResult(BulkOperation.decode(value)); +} diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts index 466d1062..d62a2045 100644 --- a/src/external-api/conductor.ts +++ b/src/external-api/conductor.ts @@ -7,15 +7,14 @@ import { decodeExecutedWorkflowDetailOutput, decodeExecutedWorkflowsOutput, decodeWorkflowDetailOutput, - decodeWorkflowEditOutput, decodeWorkflowMetadataOutput, WorkflowMetadataOutput, WorkflowDetailInput, ExecutedWorkflowsOutput, WorkflowDetailOutput, - WorkflowEditOutput, TaskDefinitionsOutput, decodeTaskDefinitionsOutput, + decodeBulkTerminateOutput, } from './conductor-network-types'; import { sendDeleteRequest, sendGetRequest, sendPostRequest, sendPutRequest } from './helpers'; @@ -35,9 +34,9 @@ async function createWorkflow(baseURL: string, workflow: WorkflowDetailInput): P await sendPostRequest([baseURL, 'metadata/workflow'], workflow); } -async function editWorkflow(baseURL: string, workflow: WorkflowDetailInput): Promise { +async function editWorkflow(baseURL: string, workflow: WorkflowDetailInput): Promise { const json = await sendPutRequest([baseURL, 'metadata/workflow'], [workflow]); - const data = decodeWorkflowEditOutput(json); + const data = decodeBulkOperationOutput(json); return data; } @@ -67,6 +66,24 @@ async function bulkPauseWorkflow(baseURL: string, workflowIds: string[]): Promis return data; } +async function bulkTerminateWorkflow(baseURL: string, workflowIds: string[]): Promise { + const json = await sendPostRequest([baseURL, `workflow/bulk/terminate`], workflowIds); + const data = decodeBulkTerminateOutput(json); + return data; +} + +async function bulkRetryWorkflow(baseURL: string, workflowIds: string[]): Promise { + const json = await sendPostRequest([baseURL, `workflow/bulk/retry`], workflowIds); + const data = decodeBulkTerminateOutput(json); + return data; +} + +async function bulkRestartWorkflow(baseURL: string, workflowIds: string[]): Promise { + const json = await sendPostRequest([baseURL, `workflow/bulk/restart`], workflowIds); + const data = decodeBulkTerminateOutput(json); + return data; +} + async function getExecutedWorkflows( baseURL: string, query?: SearchQuery | null, @@ -171,6 +188,9 @@ const conductorAPI = { resumeWorkflow, bulkResumeWorkflow, bulkPauseWorkflow, + bulkTerminateWorkflow, + bulkRetryWorkflow, + bulkRestartWorkflow, getExecutedWorkflows, getExecutedWorkflowDetail, retryWorkflow, diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 7320ec05..7dca5cc6 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -498,7 +498,10 @@ type Mutation { addZone(input: AddZoneInput!): AddZonePayload! applySnapshot(input: ApplySnapshotInput!, transactionId: String!): ApplySnapshotPayload! bulkPauseWorkflow(workflowIds: [String!]!): BulkOperationResponse + bulkRestartWorkflow(workflowIds: [String!]!): BulkOperationResponse bulkResumeWorkflow(workflowIds: [String!]!): BulkOperationResponse + bulkRetryWorkflow(workflowIds: [String!]!): BulkOperationResponse + bulkTerminateWorkflow(workflowIds: [String!]!): BulkOperationResponse closeTransaction(deviceId: String!, transactionId: String!): CloseTransactionPayload! commitConfig(input: CommitConfigInput!, transactionId: String!): CommitConfigPayload! createLabel(input: CreateLabelInput!): CreateLabelPayload! diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index a4517ca5..43481e8c 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -1010,7 +1010,10 @@ export interface NexusGenFieldTypes { addZone: NexusGenRootTypes['AddZonePayload']; // AddZonePayload! applySnapshot: NexusGenRootTypes['ApplySnapshotPayload']; // ApplySnapshotPayload! bulkPauseWorkflow: NexusGenRootTypes['BulkOperationResponse'] | null; // BulkOperationResponse + bulkRestartWorkflow: NexusGenRootTypes['BulkOperationResponse'] | null; // BulkOperationResponse bulkResumeWorkflow: NexusGenRootTypes['BulkOperationResponse'] | null; // BulkOperationResponse + bulkRetryWorkflow: NexusGenRootTypes['BulkOperationResponse'] | null; // BulkOperationResponse + bulkTerminateWorkflow: NexusGenRootTypes['BulkOperationResponse'] | null; // BulkOperationResponse closeTransaction: NexusGenRootTypes['CloseTransactionPayload']; // CloseTransactionPayload! commitConfig: NexusGenRootTypes['CommitConfigPayload']; // CommitConfigPayload! createLabel: NexusGenRootTypes['CreateLabelPayload']; // CreateLabelPayload! @@ -1584,7 +1587,10 @@ export interface NexusGenFieldTypeNames { addZone: 'AddZonePayload'; applySnapshot: 'ApplySnapshotPayload'; bulkPauseWorkflow: 'BulkOperationResponse'; + bulkRestartWorkflow: 'BulkOperationResponse'; bulkResumeWorkflow: 'BulkOperationResponse'; + bulkRetryWorkflow: 'BulkOperationResponse'; + bulkTerminateWorkflow: 'BulkOperationResponse'; closeTransaction: 'CloseTransactionPayload'; commitConfig: 'CommitConfigPayload'; createLabel: 'CreateLabelPayload'; @@ -1870,10 +1876,22 @@ export interface NexusGenArgTypes { // args workflowIds: string[]; // [String!]! }; + bulkRestartWorkflow: { + // args + workflowIds: string[]; // [String!]! + }; bulkResumeWorkflow: { // args workflowIds: string[]; // [String!]! }; + bulkRetryWorkflow: { + // args + workflowIds: string[]; // [String!]! + }; + bulkTerminateWorkflow: { + // args + workflowIds: string[]; // [String!]! + }; closeTransaction: { // args deviceId: string; // String! diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 9f8cd97f..55754e76 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -16,7 +16,7 @@ import { } from 'nexus'; import config from '../config'; import { WorkflowDetailInput } from '../external-api/conductor-network-types'; -import { toGraphId } from '../helpers/id-helper'; +import { fromGraphId, toGraphId } from '../helpers/id-helper'; import { validateTasks } from '../helpers/workflow-helpers'; import getLogger from '../get-logger'; import { IsOkResponse, Node, PageInfo, PaginationConnectionArgs } from './global-types'; @@ -595,6 +595,54 @@ export const BulkPauseWorkflowMutation = mutationField('bulkPauseWorkflow', { }, }); +export const BulkTerminateWorkflow = mutationField('bulkTerminateWorkflow', { + type: BulkOperationResponse, + args: { + workflowIds: nonNull(list(nonNull(stringArg()))), + }, + resolve: async (_, { workflowIds }, { conductorAPI }) => { + const nativeWorkflowIds = workflowIds.map((id) => fromGraphId('Workflow', id)); + const data = await conductorAPI.bulkTerminateWorkflow(config.conductorApiURL, nativeWorkflowIds); + + return { + bulkErrorResults: JSON.stringify(data.bulkErrorResults), + bulkSuccessfulResults: data.bulkSuccessfulResults, + }; + }, +}); + +export const BulkRetryWorkflow = mutationField('bulkRetryWorkflow', { + type: BulkOperationResponse, + args: { + workflowIds: nonNull(list(nonNull(stringArg()))), + }, + resolve: async (_, { workflowIds }, { conductorAPI }) => { + const nativeWorkflowIds = workflowIds.map((id) => fromGraphId('Workflow', id)); + const data = await conductorAPI.bulkRetryWorkflow(config.conductorApiURL, nativeWorkflowIds); + + return { + bulkErrorResults: JSON.stringify(data.bulkErrorResults), + bulkSuccessfulResults: data.bulkSuccessfulResults, + }; + }, +}); + +export const BulkRestartWorkflow = mutationField('bulkRestartWorkflow', { + type: BulkOperationResponse, + args: { + workflowIds: nonNull(list(nonNull(stringArg()))), + }, + resolve: async (_, { workflowIds }, { conductorAPI }) => { + const nativeWorkflowIds = workflowIds.map((id) => fromGraphId('Workflow', id)); + const data = await conductorAPI.bulkRestartWorkflow(config.conductorApiURL, nativeWorkflowIds); + + return { + bulkErrorResults: JSON.stringify(data.bulkErrorResults), + bulkSuccessfulResults: data.bulkSuccessfulResults, + }; + }, +}); + export const RetryWorkflowMutation = mutationField('retryWorkflow', { type: IsOkResponse, args: { From d507c3c2f5fa085ff226f51d40080410c41a9543 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Mon, 17 Apr 2023 17:05:35 +0200 Subject: [PATCH 14/69] add workflow instance detail query (#278) --- src/external-api/conductor-network-types.ts | 3 +- src/external-api/conductor.ts | 27 ++++++-- src/helpers/utils.helpers.ts | 2 +- src/helpers/workflow-helpers.ts | 11 ---- src/helpers/workflow.helpers.ts | 64 ++++++++++++++++++- src/schema/api.graphql | 15 ++++- src/schema/nexus-typegen.ts | 45 +++++++++++++- src/schema/workflow.ts | 68 +++++++++++++++++++-- 8 files changed, 211 insertions(+), 24 deletions(-) delete mode 100644 src/helpers/workflow-helpers.ts diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index 4e78f24d..44e17d25 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -117,6 +117,7 @@ const ExecutedWorkflowStatus = t.union([ const ExecutedWorkflowTask = t.type({ taskType: optional(t.string), status: optional(ExecutedWorkflowTaskStatus), + inputData: optional(t.record(t.string, t.unknown)), referenceTaskName: optional(t.string), retryCount: optional(t.number), seq: optional(t.number), @@ -165,7 +166,7 @@ const ExecutedWorkflow = t.type({ workflowId: optional(t.string), parentWorkflowId: optional(t.string), parentWorkflowTaskId: optional(t.string), - tasks: t.array(optional(ExecutedWorkflowTask)), + tasks: optional(t.array(ExecutedWorkflowTask)), input: optional(t.UnknownRecord), output: optional(t.UnknownRecord), correlationId: optional(t.string), diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts index d62a2045..baf3d04d 100644 --- a/src/external-api/conductor.ts +++ b/src/external-api/conductor.ts @@ -24,8 +24,22 @@ async function getWorkflowMetadata(baseURL: string): Promise { - const json = await sendGetRequest([baseURL, `metadata/workflow/${workflowName}`]); +// this type is annotated based on real request data (it is no annotated in swagger) +export type SubWorkflowInputData = { + subWorkflowDefinition: WorkflowDetailOutput | null; + workflowInput: Record; + subWorkflowTaskToDomain: unknown | null; + subWorkflowName: string; + subWorkflowVersion: number; +}; + +async function getWorkflowDetail( + baseURL: string, + workflowName: string, + version?: number, +): Promise { + const query = version ? `?version=${version}` : null; + const json = await sendGetRequest([baseURL, `metadata/workflow/${workflowName}${query}`]); const data = decodeWorkflowDetailOutput(json); return data; } @@ -96,8 +110,13 @@ async function getExecutedWorkflows( return data; } -async function getExecutedWorkflowDetail(baseURL: string, workflowId: string): Promise { - const json = await sendGetRequest([baseURL, `workflow/${workflowId}`]); +async function getExecutedWorkflowDetail( + baseURL: string, + workflowId: string, + shouldIncludeTasks?: boolean, +): Promise { + const query = shouldIncludeTasks === false ? '?includeTasks=false' : ''; + const json = await sendGetRequest([baseURL, `workflow/${workflowId}${query}`]); const data = decodeExecutedWorkflowDetailOutput(json); return data; diff --git a/src/helpers/utils.helpers.ts b/src/helpers/utils.helpers.ts index 0efb959e..9d5d2e3a 100644 --- a/src/helpers/utils.helpers.ts +++ b/src/helpers/utils.helpers.ts @@ -1,4 +1,4 @@ -export function unwrap(value: T | null | undefined): T { +export function unwrap(value: T | null | undefined | void): T { if (value == null) { throw new Error(`value is of type ${typeof value}`); } diff --git a/src/helpers/workflow-helpers.ts b/src/helpers/workflow-helpers.ts deleted file mode 100644 index 908a16da..00000000 --- a/src/helpers/workflow-helpers.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { decodeWorkflowTaskInput, NestedTask } from '../external-api/conductor-network-types'; - -export function validateTasks(tasks: string): NestedTask[] { - try { - const json = JSON.parse(tasks); - const output = decodeWorkflowTaskInput(json); - return output; - } catch (e) { - throw new Error('tasks validation error'); - } -} diff --git a/src/helpers/workflow.helpers.ts b/src/helpers/workflow.helpers.ts index 613bb059..592662d8 100644 --- a/src/helpers/workflow.helpers.ts +++ b/src/helpers/workflow.helpers.ts @@ -1,5 +1,10 @@ -import { Workflow } from '../schema/source-types'; +import { ExecutedWorkflow, ExecutedWorkflowTask, Workflow } from '../schema/source-types'; import { SearchQuery, PaginationArgs } from '../types/conductor.types'; +import { NestedTask, decodeWorkflowTaskInput } from '../external-api/conductor-network-types'; +import conductorAPI, { SubWorkflowInputData } from '../external-api/conductor'; +import { omitNullValue, unwrap } from './utils.helpers'; +import config from '../config'; +import { toGraphId } from './id-helper'; type GraphQLSearchQuery = { isRootWorkflow?: boolean | null; @@ -71,3 +76,60 @@ export function getFilteredWorkflows(workflows: WorkflowWithoutId[], filter: Wor return filteredWorkflows; } + +export function validateTasks(tasks: string): NestedTask[] { + try { + const json = JSON.parse(tasks); + const output = decodeWorkflowTaskInput(json); + return output; + } catch (e) { + throw new Error('tasks validation error'); + } +} + +type SubWorkflow = { + name: string; + version: number; + referenceTaskName: string; +}; + +function extractSubworkflowsFromTasks(task: ExecutedWorkflowTask): SubWorkflow | null { + if (task && task.taskType === 'SUB_WORKFLOW' && task.inputData) { + const { subWorkflowName, subWorkflowVersion } = task.inputData as SubWorkflowInputData; + + if (subWorkflowName) { + return { + name: subWorkflowName, + version: subWorkflowVersion, + referenceTaskName: unwrap(task.referenceTaskName), + }; + } + } + return null; +} + +async function getSubworklowsDetail(subWorkflow: SubWorkflow) { + const { name, version, referenceTaskName } = subWorkflow; + const workflowDetailPromise = conductorAPI.getWorkflowDetail(config.conductorApiURL, name, version); + const executedWorkflowDetailPromise = conductorAPI.getExecutedWorkflowDetail(config.conductorApiURL, name); + const [workflowDetail, executedWorkflowDetail] = await Promise.all([ + workflowDetailPromise, + executedWorkflowDetailPromise, + ]); + + return { referenceTaskName, workflowDetail, executedWorkflowDetail }; +} + +export async function getSubworkflows(workflow: ExecutedWorkflow) { + if (!workflow.tasks) { + return []; + } + const promises = workflow.tasks + .map((t) => ({ ...t, id: toGraphId('ExecutedWorkflowTask', unwrap(t.taskId || null)) })) + .map(extractSubworkflowsFromTasks) + .filter(omitNullValue) + .map(getSubworklowsDetail); + + const subWorkflows = await Promise.all(promises); + return subWorkflows; +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 7dca5cc6..2968a4c3 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -300,7 +300,7 @@ type ExecutedWorkflow implements Node { reasonForIncompletion: String startTime: String status: ExecutedWorkflowStatus - tasks: [ExecutedWorkflowTask] + tasks: [ExecutedWorkflowTask!] updatedAt: String updatedBy: String variables: String @@ -626,6 +626,7 @@ type Query { topologyVersions: [String!] transactions: [Transaction!]! uniconfigShellSession: String + workflowInstanceDetail(id: String!, shouldIncludeTasks: Boolean): WorkflowInstanceDetail workflowLabels: [String!]! workflows(after: String, before: String, filter: FilterWorkflowsInput, first: Int, last: Int): WorkflowConnection! zones(after: String, before: String, first: Int, last: Int): ZonesConnection! @@ -665,6 +666,12 @@ input StartWorkflowRequestInput { workflowDefinition: WorkflowDefinitionInput } +type SubWorkflow { + executedWorkflowDetail: [Workflow!] + taskReferenceName: String! + workflowDetail: [Workflow!] +} + type Subscription { uniconfigShell(input: String, sessionId: String!, trigger: Int): String } @@ -874,6 +881,12 @@ input WorkflowInput { version: Int } +type WorkflowInstanceDetail { + meta: Workflow + result: ExecutedWorkflow! + subworkflows: [SubWorkflow!] +} + enum WorkflowTaskType { DECISION DO_WHILE diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 43481e8c..d1b37304 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -570,6 +570,12 @@ export interface NexusGenObjects { createdAt: string; // String! name: string; // String! }; + SubWorkflow: { + // root type + executedWorkflowDetail?: NexusGenRootTypes['Workflow'][] | null; // [Workflow!] + taskReferenceName: string; // String! + workflowDetail?: NexusGenRootTypes['Workflow'][] | null; // [Workflow!] + }; Subscription: {}; SyncFromNetworkPayload: { // root type @@ -647,6 +653,12 @@ export interface NexusGenObjects { cursor: string; // String! node: NexusGenRootTypes['Workflow']; // Workflow! }; + WorkflowInstanceDetail: { + // root type + meta?: NexusGenRootTypes['Workflow'] | null; // Workflow + result: NexusGenRootTypes['ExecutedWorkflow']; // ExecutedWorkflow! + subworkflows?: NexusGenRootTypes['SubWorkflow'][] | null; // [SubWorkflow!] + }; Zone: SourceTypes.Zone; ZoneEdge: { // root type @@ -875,7 +887,7 @@ export interface NexusGenFieldTypes { reasonForIncompletion: string | null; // String startTime: string | null; // String status: NexusGenEnums['ExecutedWorkflowStatus'] | null; // ExecutedWorkflowStatus - tasks: Array | null; // [ExecutedWorkflowTask] + tasks: NexusGenRootTypes['ExecutedWorkflowTask'][] | null; // [ExecutedWorkflowTask!] updatedAt: string | null; // String updatedBy: string | null; // String variables: string | null; // String @@ -1094,6 +1106,7 @@ export interface NexusGenFieldTypes { topologyVersions: string[] | null; // [String!] transactions: NexusGenRootTypes['Transaction'][]; // [Transaction!]! uniconfigShellSession: string | null; // String + workflowInstanceDetail: NexusGenRootTypes['WorkflowInstanceDetail'] | null; // WorkflowInstanceDetail workflowLabels: string[]; // [String!]! workflows: NexusGenRootTypes['WorkflowConnection']; // WorkflowConnection! zones: NexusGenRootTypes['ZonesConnection']; // ZonesConnection! @@ -1111,6 +1124,12 @@ export interface NexusGenFieldTypes { createdAt: string; // String! name: string; // String! }; + SubWorkflow: { + // field return type + executedWorkflowDetail: NexusGenRootTypes['Workflow'][] | null; // [Workflow!] + taskReferenceName: string; // String! + workflowDetail: NexusGenRootTypes['Workflow'][] | null; // [Workflow!] + }; Subscription: { // field return type uniconfigShell: string | null; // String @@ -1226,6 +1245,12 @@ export interface NexusGenFieldTypes { cursor: string; // String! node: NexusGenRootTypes['Workflow']; // Workflow! }; + WorkflowInstanceDetail: { + // field return type + meta: NexusGenRootTypes['Workflow'] | null; // Workflow + result: NexusGenRootTypes['ExecutedWorkflow']; // ExecutedWorkflow! + subworkflows: NexusGenRootTypes['SubWorkflow'][] | null; // [SubWorkflow!] + }; Zone: { // field return type createdAt: string; // String! @@ -1671,6 +1696,7 @@ export interface NexusGenFieldTypeNames { topologyVersions: 'String'; transactions: 'Transaction'; uniconfigShellSession: 'String'; + workflowInstanceDetail: 'WorkflowInstanceDetail'; workflowLabels: 'String'; workflows: 'WorkflowConnection'; zones: 'ZonesConnection'; @@ -1688,6 +1714,12 @@ export interface NexusGenFieldTypeNames { createdAt: 'String'; name: 'String'; }; + SubWorkflow: { + // field return type name + executedWorkflowDetail: 'Workflow'; + taskReferenceName: 'String'; + workflowDetail: 'Workflow'; + }; Subscription: { // field return type name uniconfigShell: 'String'; @@ -1803,6 +1835,12 @@ export interface NexusGenFieldTypeNames { cursor: 'String'; node: 'Workflow'; }; + WorkflowInstanceDetail: { + // field return type name + meta: 'Workflow'; + result: 'ExecutedWorkflow'; + subworkflows: 'SubWorkflow'; + }; Zone: { // field return type name createdAt: 'String'; @@ -2096,6 +2134,11 @@ export interface NexusGenArgTypes { // args version: string; // String! }; + workflowInstanceDetail: { + // args + id: string; // String! + shouldIncludeTasks?: boolean | null; // Boolean + }; workflows: { // args after?: string | null; // String diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 55754e76..572d9c49 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -17,13 +17,18 @@ import { import config from '../config'; import { WorkflowDetailInput } from '../external-api/conductor-network-types'; import { fromGraphId, toGraphId } from '../helpers/id-helper'; -import { validateTasks } from '../helpers/workflow-helpers'; import getLogger from '../get-logger'; import { IsOkResponse, Node, PageInfo, PaginationConnectionArgs } from './global-types'; import { TaskInput, ExecutedWorkflowTask } from './task'; -import { getFilteredWorkflows, makePaginationFromArgs, makeSearchQueryFromArgs } from '../helpers/workflow.helpers'; +import { + getFilteredWorkflows, + getSubworkflows, + makePaginationFromArgs, + makeSearchQueryFromArgs, + validateTasks, +} from '../helpers/workflow.helpers'; import { StartWorkflowInput } from '../types/conductor.types'; -import { parseJson } from '../helpers/utils.helpers'; +import { parseJson, unwrap } from '../helpers/utils.helpers'; const log = getLogger('frinx-inventory-server'); @@ -197,7 +202,7 @@ export const ExecutedWorkflow = objectType({ t.int('workflowVersion'); t.string('workflowName'); t.string('workflowId'); - t.list.field('tasks', { + t.list.nonNull.field('tasks', { type: ExecutedWorkflowTask, }); }, @@ -296,6 +301,61 @@ export const ExecutedWorkflowsQuery = queryField('executedWorkflows', { }, }); +const SubWorkflow = objectType({ + name: 'SubWorkflow', + definition: (t) => { + t.nonNull.string('taskReferenceName'); + t.list.nonNull.field('workflowDetail', { type: Workflow }); + t.list.nonNull.field('executedWorkflowDetail', { type: Workflow }); + }, +}); + +const WorkflowInstanceDetail = objectType({ + name: 'WorkflowInstanceDetail', + definition: (t) => { + t.nonNull.field('result', { type: ExecutedWorkflow }); + t.field('meta', { type: Workflow }); + t.field('subworkflows', { type: list(nonNull(SubWorkflow)) }); + }, +}); + +export const WorkflowInstanceQuery = queryField('workflowInstanceDetail', { + type: WorkflowInstanceDetail, + args: { + id: nonNull(stringArg()), + shouldIncludeTasks: booleanArg(), + }, + resolve: async (_, args, { conductorAPI }) => { + const { id, shouldIncludeTasks } = args; + const workflowId = fromGraphId('ExecutedWorkflow', id); + + const result = await conductorAPI.getExecutedWorkflowDetail( + config.conductorApiURL, + workflowId, + shouldIncludeTasks ?? false, + ); + + const meta = result.workflowDefinition + ? null + : await conductorAPI.getWorkflowDetail( + config.conductorApiURL, + unwrap(result.workflowName || null), + result.workflowVersion || undefined, + ); + + const subWorkflows = getSubworkflows({ + ...result, + id: toGraphId('ExecutedWorkflow', unwrap(result.workflowName || null)), + }); + + return { + result: { ...result, id: toGraphId('ExecutedWorkflow', unwrap(result.workflowName || null)) }, + meta: meta ? { ...meta, id: toGraphId('Workflow', meta.name) } : null, + subWorkflows, + }; + }, +}); + export const ExecuteNewWorkflowInput = inputObjectType({ name: 'ExecuteNewWorkflowInput', definition: (t) => { From 24cba7f9a0b3c61858f62d98f53d0ac939da7f5f Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Wed, 19 Apr 2023 15:56:17 +0200 Subject: [PATCH 15/69] instance detail query fix (#283) --- src/external-api/conductor.ts | 2 +- src/helpers/workflow.helpers.ts | 32 ++++++++++++++++++++++++++++---- src/schema/api.graphql | 4 ++-- src/schema/nexus-typegen.ts | 10 +++++----- src/schema/workflow.ts | 8 ++++---- 5 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts index baf3d04d..a7d29b21 100644 --- a/src/external-api/conductor.ts +++ b/src/external-api/conductor.ts @@ -38,7 +38,7 @@ async function getWorkflowDetail( workflowName: string, version?: number, ): Promise { - const query = version ? `?version=${version}` : null; + const query = version ? `?version=${version}` : ''; const json = await sendGetRequest([baseURL, `metadata/workflow/${workflowName}${query}`]); const data = decodeWorkflowDetailOutput(json); return data; diff --git a/src/helpers/workflow.helpers.ts b/src/helpers/workflow.helpers.ts index 592662d8..0d5421e6 100644 --- a/src/helpers/workflow.helpers.ts +++ b/src/helpers/workflow.helpers.ts @@ -1,3 +1,4 @@ +import { v4 as uuid } from 'uuid'; import { ExecutedWorkflow, ExecutedWorkflowTask, Workflow } from '../schema/source-types'; import { SearchQuery, PaginationArgs } from '../types/conductor.types'; import { NestedTask, decodeWorkflowTaskInput } from '../external-api/conductor-network-types'; @@ -91,6 +92,7 @@ type SubWorkflow = { name: string; version: number; referenceTaskName: string; + subWorkflowId: string; }; function extractSubworkflowsFromTasks(task: ExecutedWorkflowTask): SubWorkflow | null { @@ -102,28 +104,50 @@ function extractSubworkflowsFromTasks(task: ExecutedWorkflowTask): SubWorkflow | name: subWorkflowName, version: subWorkflowVersion, referenceTaskName: unwrap(task.referenceTaskName), + subWorkflowId: unwrap(task.subWorkflowId), }; } } return null; } -async function getSubworklowsDetail(subWorkflow: SubWorkflow) { - const { name, version, referenceTaskName } = subWorkflow; +type SubworkflowDetail = { + taskReferenceName: string; + workflowDetail: Workflow; + executedWorkflowDetail: ExecutedWorkflow; +}; + +async function getSubworklowsDetail(subWorkflow: SubWorkflow): Promise { + const { name, version, referenceTaskName, subWorkflowId } = subWorkflow; const workflowDetailPromise = conductorAPI.getWorkflowDetail(config.conductorApiURL, name, version); - const executedWorkflowDetailPromise = conductorAPI.getExecutedWorkflowDetail(config.conductorApiURL, name); + const executedWorkflowDetailPromise = conductorAPI.getExecutedWorkflowDetail(config.conductorApiURL, subWorkflowId); const [workflowDetail, executedWorkflowDetail] = await Promise.all([ workflowDetailPromise, executedWorkflowDetailPromise, ]); - return { referenceTaskName, workflowDetail, executedWorkflowDetail }; + const workflowDetailWithId = { + ...workflowDetail, + id: uuid(), + }; + + const executedWorkflowDetailWithId = { + ...executedWorkflowDetail, + id: uuid(), + }; + + return { + taskReferenceName: referenceTaskName, + workflowDetail: workflowDetailWithId, + executedWorkflowDetail: executedWorkflowDetailWithId, + }; } export async function getSubworkflows(workflow: ExecutedWorkflow) { if (!workflow.tasks) { return []; } + const promises = workflow.tasks .map((t) => ({ ...t, id: toGraphId('ExecutedWorkflowTask', unwrap(t.taskId || null)) })) .map(extractSubworkflowsFromTasks) diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 2968a4c3..f93000aa 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -667,9 +667,9 @@ input StartWorkflowRequestInput { } type SubWorkflow { - executedWorkflowDetail: [Workflow!] + executedWorkflowDetail: ExecutedWorkflow! taskReferenceName: String! - workflowDetail: [Workflow!] + workflowDetail: Workflow! } type Subscription { diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index d1b37304..eb128c64 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -572,9 +572,9 @@ export interface NexusGenObjects { }; SubWorkflow: { // root type - executedWorkflowDetail?: NexusGenRootTypes['Workflow'][] | null; // [Workflow!] + executedWorkflowDetail: NexusGenRootTypes['ExecutedWorkflow']; // ExecutedWorkflow! taskReferenceName: string; // String! - workflowDetail?: NexusGenRootTypes['Workflow'][] | null; // [Workflow!] + workflowDetail: NexusGenRootTypes['Workflow']; // Workflow! }; Subscription: {}; SyncFromNetworkPayload: { @@ -1126,9 +1126,9 @@ export interface NexusGenFieldTypes { }; SubWorkflow: { // field return type - executedWorkflowDetail: NexusGenRootTypes['Workflow'][] | null; // [Workflow!] + executedWorkflowDetail: NexusGenRootTypes['ExecutedWorkflow']; // ExecutedWorkflow! taskReferenceName: string; // String! - workflowDetail: NexusGenRootTypes['Workflow'][] | null; // [Workflow!] + workflowDetail: NexusGenRootTypes['Workflow']; // Workflow! }; Subscription: { // field return type @@ -1716,7 +1716,7 @@ export interface NexusGenFieldTypeNames { }; SubWorkflow: { // field return type name - executedWorkflowDetail: 'Workflow'; + executedWorkflowDetail: 'ExecutedWorkflow'; taskReferenceName: 'String'; workflowDetail: 'Workflow'; }; diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 572d9c49..caac305e 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -305,8 +305,8 @@ const SubWorkflow = objectType({ name: 'SubWorkflow', definition: (t) => { t.nonNull.string('taskReferenceName'); - t.list.nonNull.field('workflowDetail', { type: Workflow }); - t.list.nonNull.field('executedWorkflowDetail', { type: Workflow }); + t.nonNull.field('workflowDetail', { type: Workflow }); + t.nonNull.field('executedWorkflowDetail', { type: ExecutedWorkflow }); }, }); @@ -343,7 +343,7 @@ export const WorkflowInstanceQuery = queryField('workflowInstanceDetail', { result.workflowVersion || undefined, ); - const subWorkflows = getSubworkflows({ + const subworkflows = await getSubworkflows({ ...result, id: toGraphId('ExecutedWorkflow', unwrap(result.workflowName || null)), }); @@ -351,7 +351,7 @@ export const WorkflowInstanceQuery = queryField('workflowInstanceDetail', { return { result: { ...result, id: toGraphId('ExecutedWorkflow', unwrap(result.workflowName || null)) }, meta: meta ? { ...meta, id: toGraphId('Workflow', meta.name) } : null, - subWorkflows, + subworkflows, }; }, }); From f2601c3e94f5f75cb7d36e927a9221b8a09d438e Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 20 Apr 2023 09:02:08 +0200 Subject: [PATCH 16/69] bulk executed workflow id fix (#285) * use executed workflow ids as input in bulk operations * bulk resume fix --- src/schema/api.graphql | 10 +++++----- src/schema/nexus-typegen.ts | 10 +++++----- src/schema/workflow.ts | 32 +++++++++++++++++--------------- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/schema/api.graphql b/src/schema/api.graphql index f93000aa..1ce14867 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -497,11 +497,11 @@ type Mutation { addSnapshot(input: AddSnapshotInput!, transactionId: String!): AddSnapshotPayload addZone(input: AddZoneInput!): AddZonePayload! applySnapshot(input: ApplySnapshotInput!, transactionId: String!): ApplySnapshotPayload! - bulkPauseWorkflow(workflowIds: [String!]!): BulkOperationResponse - bulkRestartWorkflow(workflowIds: [String!]!): BulkOperationResponse - bulkResumeWorkflow(workflowIds: [String!]!): BulkOperationResponse - bulkRetryWorkflow(workflowIds: [String!]!): BulkOperationResponse - bulkTerminateWorkflow(workflowIds: [String!]!): BulkOperationResponse + bulkPauseWorkflow(executedWorkflowIds: [String!]!): BulkOperationResponse + bulkRestartWorkflow(executedWorkflowIds: [String!]!): BulkOperationResponse + bulkResumeWorkflow(executedWorkflowIds: [String!]!): BulkOperationResponse + bulkRetryWorkflow(executedWorkflowIds: [String!]!): BulkOperationResponse + bulkTerminateWorkflow(executedWorkflowIds: [String!]!): BulkOperationResponse closeTransaction(deviceId: String!, transactionId: String!): CloseTransactionPayload! commitConfig(input: CommitConfigInput!, transactionId: String!): CommitConfigPayload! createLabel(input: CreateLabelInput!): CreateLabelPayload! diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index eb128c64..b11879db 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -1912,23 +1912,23 @@ export interface NexusGenArgTypes { }; bulkPauseWorkflow: { // args - workflowIds: string[]; // [String!]! + executedWorkflowIds: string[]; // [String!]! }; bulkRestartWorkflow: { // args - workflowIds: string[]; // [String!]! + executedWorkflowIds: string[]; // [String!]! }; bulkResumeWorkflow: { // args - workflowIds: string[]; // [String!]! + executedWorkflowIds: string[]; // [String!]! }; bulkRetryWorkflow: { // args - workflowIds: string[]; // [String!]! + executedWorkflowIds: string[]; // [String!]! }; bulkTerminateWorkflow: { // args - workflowIds: string[]; // [String!]! + executedWorkflowIds: string[]; // [String!]! }; closeTransaction: { // args diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index caac305e..08bac3bb 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -606,10 +606,11 @@ export const BulkOperationResponse = objectType({ export const BulkResumeWorkflowMutation = mutationField('bulkResumeWorkflow', { type: BulkOperationResponse, args: { - workflowIds: nonNull(list(nonNull(stringArg()))), + executedWorkflowIds: nonNull(list(nonNull(stringArg()))), }, - resolve: async (_, { workflowIds }, { conductorAPI }) => { - const data = await conductorAPI.bulkResumeWorkflow(config.conductorApiURL, workflowIds); + resolve: async (_, { executedWorkflowIds }, { conductorAPI }) => { + const nativeWorkflowIds = executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); + const data = await conductorAPI.bulkResumeWorkflow(config.conductorApiURL, nativeWorkflowIds); return { bulkErrorResults: JSON.stringify(data.bulkErrorResults), @@ -643,10 +644,11 @@ export const ExecuteWorkflowByName = mutationField('executeWorkflowByName', { export const BulkPauseWorkflowMutation = mutationField('bulkPauseWorkflow', { type: BulkOperationResponse, args: { - workflowIds: nonNull(list(nonNull(stringArg()))), + executedWorkflowIds: nonNull(list(nonNull(stringArg()))), }, - resolve: async (_, { workflowIds }, { conductorAPI }) => { - const data = await conductorAPI.bulkPauseWorkflow(config.conductorApiURL, workflowIds); + resolve: async (_, { executedWorkflowIds }, { conductorAPI }) => { + const nativeWorkflowIds = executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); + const data = await conductorAPI.bulkPauseWorkflow(config.conductorApiURL, nativeWorkflowIds); return { bulkErrorResults: JSON.stringify(data.bulkErrorResults), @@ -658,10 +660,10 @@ export const BulkPauseWorkflowMutation = mutationField('bulkPauseWorkflow', { export const BulkTerminateWorkflow = mutationField('bulkTerminateWorkflow', { type: BulkOperationResponse, args: { - workflowIds: nonNull(list(nonNull(stringArg()))), + executedWorkflowIds: nonNull(list(nonNull(stringArg()))), }, - resolve: async (_, { workflowIds }, { conductorAPI }) => { - const nativeWorkflowIds = workflowIds.map((id) => fromGraphId('Workflow', id)); + resolve: async (_, { executedWorkflowIds }, { conductorAPI }) => { + const nativeWorkflowIds = executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); const data = await conductorAPI.bulkTerminateWorkflow(config.conductorApiURL, nativeWorkflowIds); return { @@ -674,10 +676,10 @@ export const BulkTerminateWorkflow = mutationField('bulkTerminateWorkflow', { export const BulkRetryWorkflow = mutationField('bulkRetryWorkflow', { type: BulkOperationResponse, args: { - workflowIds: nonNull(list(nonNull(stringArg()))), + executedWorkflowIds: nonNull(list(nonNull(stringArg()))), }, - resolve: async (_, { workflowIds }, { conductorAPI }) => { - const nativeWorkflowIds = workflowIds.map((id) => fromGraphId('Workflow', id)); + resolve: async (_, { executedWorkflowIds }, { conductorAPI }) => { + const nativeWorkflowIds = executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); const data = await conductorAPI.bulkRetryWorkflow(config.conductorApiURL, nativeWorkflowIds); return { @@ -690,10 +692,10 @@ export const BulkRetryWorkflow = mutationField('bulkRetryWorkflow', { export const BulkRestartWorkflow = mutationField('bulkRestartWorkflow', { type: BulkOperationResponse, args: { - workflowIds: nonNull(list(nonNull(stringArg()))), + executedWorkflowIds: nonNull(list(nonNull(stringArg()))), }, - resolve: async (_, { workflowIds }, { conductorAPI }) => { - const nativeWorkflowIds = workflowIds.map((id) => fromGraphId('Workflow', id)); + resolve: async (_, { executedWorkflowIds }, { conductorAPI }) => { + const nativeWorkflowIds = executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); const data = await conductorAPI.bulkRestartWorkflow(config.conductorApiURL, nativeWorkflowIds); return { From 3553a5a181d16c458f7d6479c06429e43d3019e1 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 4 May 2023 10:06:51 +0200 Subject: [PATCH 17/69] FD-526 new workflow attributes (#287) * new attributes added to workflow * add output paramters to workflow * add restartable and outputParameters to workflow input * add createdAt, updatedAt to workflow input --- src/helpers/workflow.helpers.ts | 21 ++++++++++++++ src/schema/api.graphql | 29 ++++++++++++++++++- src/schema/global-types.ts | 8 +++++- src/schema/nexus-typegen.ts | 51 +++++++++++++++++++++++++++++++++ src/schema/workflow.ts | 49 +++++++++++++++++++++++++++---- 5 files changed, 151 insertions(+), 7 deletions(-) diff --git a/src/helpers/workflow.helpers.ts b/src/helpers/workflow.helpers.ts index 0d5421e6..d010effe 100644 --- a/src/helpers/workflow.helpers.ts +++ b/src/helpers/workflow.helpers.ts @@ -157,3 +157,24 @@ export async function getSubworkflows(workflow: ExecutedWorkflow) { const subWorkflows = await Promise.all(promises); return subWorkflows; } + +type OutputParameter = { + key: string; + value: string; +}; + +export function convertToApiOutputParameters( + outputParameters?: OutputParameter[] | null, +): Record | null { + if (outputParameters == null) { + return null; + } + + return outputParameters.reduce((acc, next) => { + const { key, value } = next; + return { + ...acc, + [key]: value, + }; + }, {}); +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 1ce14867..5bc61329 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -82,6 +82,7 @@ type Blueprint implements Node { name: String! template: String! updatedAt: String! + version: Int } type BlueprintConnection { @@ -148,6 +149,7 @@ type Country implements Node { code: String! id: ID! name: String! + version: Int } type CountryConnection { @@ -229,6 +231,7 @@ type Device implements Node { source: DeviceSource! updatedAt: String! vendor: String + version: Int zone: Zone! } @@ -304,6 +307,7 @@ type ExecutedWorkflow implements Node { updatedAt: String updatedBy: String variables: String + version: Int workflowDefinition: Workflow workflowId: String workflowName: String @@ -364,6 +368,7 @@ type ExecutedWorkflowTask implements Node { taskReferenceName: String taskType: String updateTime: String + version: Int workflowType: String } @@ -458,6 +463,7 @@ type Label implements Node { id: ID! name: String! updatedAt: String! + version: Int } type LabelConnection { @@ -477,6 +483,7 @@ type Location implements Node { id: ID! name: String! updatedAt: String! + version: Int } type LocationConnection { @@ -587,6 +594,17 @@ type NetTopology { interface Node { id: ID! + version: Int +} + +type OutputParameter { + key: String! + value: String! +} + +input OutputParameterInput { + key: String! + value: String! } type PageInfo { @@ -618,7 +636,7 @@ type Query { labels(after: String, before: String, first: Int, last: Int): LabelConnection! locations(after: String, before: String, first: Int, last: Int): LocationConnection! netTopology: NetTopology - node(id: ID!): Node + node(id: ID!, version: Int): Node taskDefinitions: [TaskDefinition!]! topology(filter: FilterTopologyInput): Topology topologyCommonNodes(nodes: [String!]!): TopologyCommonNodes @@ -833,7 +851,11 @@ type Workflow implements Node { id: ID! inputParameters: [String!] name: String! + outputParameters: [OutputParameter!] + restartable: Boolean tasks: String + timeoutPolicy: TimeoutPolicy + timeoutSeconds: Int! updatedAt: String updatedBy: String version: Int @@ -874,10 +896,14 @@ type WorkflowEdge { } input WorkflowInput { + createdAt: String description: String name: String! + outputParameters: [OutputParameterInput!] + restartable: Boolean tasks: String! timeoutSeconds: Int! + updatedAt: String version: Int } @@ -917,6 +943,7 @@ type Zone implements Node { id: ID! name: String! updatedAt: String! + version: Int } type ZoneEdge { diff --git a/src/schema/global-types.ts b/src/schema/global-types.ts index c0c12fa2..9579d7e5 100644 --- a/src/schema/global-types.ts +++ b/src/schema/global-types.ts @@ -8,6 +8,7 @@ export const Node = interfaceType({ name: 'Node', definition: (t) => { t.nonNull.id('id'); + t.int('version'); // this is only used for Workflow, because it has composite id (name/version) }, }); export const PageInfo = objectType({ @@ -32,6 +33,7 @@ export const NodeQuery = extendType({ type: Node, args: { id: nonNull(idArg()), + version: intArg(), }, resolve: async (_, args, { prisma, tenantId }) => { /* eslint-disable @typescript-eslint/naming-convention */ @@ -99,7 +101,11 @@ export const NodeQuery = extendType({ } case 'Workflow': { const id = fromGraphId('Workflow', args.id); - const workflow = await conductorAPI.getWorkflowDetail(config.conductorApiURL, id); + const workflow = await conductorAPI.getWorkflowDetail( + config.conductorApiURL, + id, + args.version ?? undefined, + ); if (workflow == null) { return null; } diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index b11879db..e6d50b23 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -149,6 +149,11 @@ export interface NexusGenInputs { x: number; // Float! y: number; // Float! }; + OutputParameterInput: { + // input type + key: string; // String! + value: string; // String! + }; PaginationArgs: { // input type size: number; // Int! @@ -231,10 +236,14 @@ export interface NexusGenInputs { }; WorkflowInput: { // input type + createdAt?: string | null; // String description?: string | null; // String name: string; // String! + outputParameters?: NexusGenInputs['OutputParameterInput'][] | null; // [OutputParameterInput!] + restartable?: boolean | null; // Boolean tasks: string; // String! timeoutSeconds: number; // Int! + updatedAt?: string | null; // String version?: number | null; // Int }; } @@ -549,6 +558,11 @@ export interface NexusGenObjects { edges: NexusGenRootTypes['GraphEdge'][]; // [GraphEdge!]! nodes: NexusGenRootTypes['NetNode'][]; // [NetNode!]! }; + OutputParameter: { + // root type + key: string; // String! + value: string; // String! + }; PageInfo: { // root type endCursor?: string | null; // String @@ -726,6 +740,7 @@ export interface NexusGenFieldTypes { name: string; // String! template: string; // String! updatedAt: string; // String! + version: number | null; // Int }; BlueprintConnection: { // field return type @@ -782,6 +797,7 @@ export interface NexusGenFieldTypes { code: string; // String! id: string; // ID! name: string; // String! + version: number | null; // Int }; CountryConnection: { // field return type @@ -849,6 +865,7 @@ export interface NexusGenFieldTypes { source: NexusGenEnums['DeviceSource']; // DeviceSource! updatedAt: string; // String! vendor: string | null; // String + version: number | null; // Int zone: NexusGenRootTypes['Zone']; // Zone! }; DeviceConnection: { @@ -891,6 +908,7 @@ export interface NexusGenFieldTypes { updatedAt: string | null; // String updatedBy: string | null; // String variables: string | null; // String + version: number | null; // Int workflowDefinition: NexusGenRootTypes['Workflow'] | null; // Workflow workflowId: string | null; // String workflowName: string | null; // String @@ -925,6 +943,7 @@ export interface NexusGenFieldTypes { taskReferenceName: string | null; // String taskType: string | null; // String updateTime: string | null; // String + version: number | null; // Int workflowType: string | null; // String }; GraphEdge: { @@ -982,6 +1001,7 @@ export interface NexusGenFieldTypes { id: string; // ID! name: string; // String! updatedAt: string; // String! + version: number | null; // Int }; LabelConnection: { // field return type @@ -1001,6 +1021,7 @@ export interface NexusGenFieldTypes { id: string; // ID! name: string; // String! updatedAt: string; // String! + version: number | null; // Int }; LocationConnection: { // field return type @@ -1080,6 +1101,11 @@ export interface NexusGenFieldTypes { edges: NexusGenRootTypes['GraphEdge'][]; // [GraphEdge!]! nodes: NexusGenRootTypes['NetNode'][]; // [NetNode!]! }; + OutputParameter: { + // field return type + key: string; // String! + value: string; // String! + }; PageInfo: { // field return type endCursor: string | null; // String @@ -1229,7 +1255,11 @@ export interface NexusGenFieldTypes { id: string; // ID! inputParameters: string[] | null; // [String!] name: string; // String! + outputParameters: NexusGenRootTypes['OutputParameter'][] | null; // [OutputParameter!] + restartable: boolean | null; // Boolean tasks: string | null; // String + timeoutPolicy: NexusGenEnums['TimeoutPolicy'] | null; // TimeoutPolicy + timeoutSeconds: number; // Int! updatedAt: string | null; // String updatedBy: string | null; // String version: number | null; // Int @@ -1257,6 +1287,7 @@ export interface NexusGenFieldTypes { id: string; // ID! name: string; // String! updatedAt: string; // String! + version: number | null; // Int }; ZoneEdge: { // field return type @@ -1280,6 +1311,7 @@ export interface NexusGenFieldTypes { Node: { // field return type id: string; // ID! + version: number | null; // Int }; } @@ -1316,6 +1348,7 @@ export interface NexusGenFieldTypeNames { name: 'String'; template: 'String'; updatedAt: 'String'; + version: 'Int'; }; BlueprintConnection: { // field return type name @@ -1372,6 +1405,7 @@ export interface NexusGenFieldTypeNames { code: 'String'; id: 'ID'; name: 'String'; + version: 'Int'; }; CountryConnection: { // field return type name @@ -1439,6 +1473,7 @@ export interface NexusGenFieldTypeNames { source: 'DeviceSource'; updatedAt: 'String'; vendor: 'String'; + version: 'Int'; zone: 'Zone'; }; DeviceConnection: { @@ -1481,6 +1516,7 @@ export interface NexusGenFieldTypeNames { updatedAt: 'String'; updatedBy: 'String'; variables: 'String'; + version: 'Int'; workflowDefinition: 'Workflow'; workflowId: 'String'; workflowName: 'String'; @@ -1515,6 +1551,7 @@ export interface NexusGenFieldTypeNames { taskReferenceName: 'String'; taskType: 'String'; updateTime: 'String'; + version: 'Int'; workflowType: 'String'; }; GraphEdge: { @@ -1572,6 +1609,7 @@ export interface NexusGenFieldTypeNames { id: 'ID'; name: 'String'; updatedAt: 'String'; + version: 'Int'; }; LabelConnection: { // field return type name @@ -1591,6 +1629,7 @@ export interface NexusGenFieldTypeNames { id: 'ID'; name: 'String'; updatedAt: 'String'; + version: 'Int'; }; LocationConnection: { // field return type name @@ -1670,6 +1709,11 @@ export interface NexusGenFieldTypeNames { edges: 'GraphEdge'; nodes: 'NetNode'; }; + OutputParameter: { + // field return type name + key: 'String'; + value: 'String'; + }; PageInfo: { // field return type name endCursor: 'String'; @@ -1819,7 +1863,11 @@ export interface NexusGenFieldTypeNames { id: 'ID'; inputParameters: 'String'; name: 'String'; + outputParameters: 'OutputParameter'; + restartable: 'Boolean'; tasks: 'String'; + timeoutPolicy: 'TimeoutPolicy'; + timeoutSeconds: 'Int'; updatedAt: 'String'; updatedBy: 'String'; version: 'Int'; @@ -1847,6 +1895,7 @@ export interface NexusGenFieldTypeNames { id: 'ID'; name: 'String'; updatedAt: 'String'; + version: 'Int'; }; ZoneEdge: { // field return type name @@ -1870,6 +1919,7 @@ export interface NexusGenFieldTypeNames { Node: { // field return type name id: 'ID'; + version: 'Int'; }; } @@ -2121,6 +2171,7 @@ export interface NexusGenArgTypes { node: { // args id: string; // ID! + version?: number | null; // Int }; topology: { // args diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 08bac3bb..4b7f092c 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -21,6 +21,7 @@ import getLogger from '../get-logger'; import { IsOkResponse, Node, PageInfo, PaginationConnectionArgs } from './global-types'; import { TaskInput, ExecutedWorkflowTask } from './task'; import { + convertToApiOutputParameters, getFilteredWorkflows, getSubworkflows, makePaginationFromArgs, @@ -32,6 +33,19 @@ import { parseJson, unwrap } from '../helpers/utils.helpers'; const log = getLogger('frinx-inventory-server'); +const OutputParameter = objectType({ + name: 'OutputParameter', + definition: (t) => { + t.nonNull.string('key'); + t.nonNull.string('value'); + }, +}); + +export const TimeoutPolicy = enumType({ + name: 'TimeoutPolicy', + members: ['TIME_OUT_WF', 'ALERT_ONLY'], +}); + export const Workflow = objectType({ name: 'Workflow', definition: (t) => { @@ -39,6 +53,7 @@ export const Workflow = objectType({ t.nonNull.id('id', { resolve: (workflow) => toGraphId('Workflow', workflow.name), }); + t.nonNull.int('timeoutSeconds'); t.nonNull.string('name'); t.string('description'); t.int('version'); @@ -52,6 +67,16 @@ export const Workflow = objectType({ }); t.string('tasks', { resolve: (workflow) => JSON.stringify(workflow.tasks) }); t.list.nonNull.string('inputParameters', { resolve: (w) => w.inputParameters ?? null }); + t.list.nonNull.field('outputParameters', { + type: OutputParameter, + resolve: (w) => + w.outputParameters + ? Object.entries(w.outputParameters).map((e) => ({ + key: e[0], + value: e[1], + })) + : null, + }); t.boolean('hasSchedule', { resolve: async (workflow, _, { schedulerAPI }) => { try { @@ -63,6 +88,8 @@ export const Workflow = objectType({ } }, }); + t.boolean('restartable'); + t.field('timeoutPolicy', { type: TimeoutPolicy }); }, }); @@ -126,11 +153,6 @@ export const WorkflowsQuery = extendType({ }, }); -export const TimeoutPolicy = enumType({ - name: 'TimeoutPolicy', - members: ['TIME_OUT_WF', 'ALERT_ONLY'], -}); - export const WorkflowDefinitionInput = inputObjectType({ name: 'WorkflowDefinitionInput', definition: (t) => { @@ -388,6 +410,14 @@ export const CreateWorkflowPayload = objectType({ }, }); +const OutputParameterInput = inputObjectType({ + name: 'OutputParameterInput', + definition: (t) => { + t.nonNull.string('key'); + t.nonNull.string('value'); + }, +}); + const WorkflowInput = inputObjectType({ name: 'WorkflowInput', definition: (t) => { @@ -396,6 +426,10 @@ const WorkflowInput = inputObjectType({ t.nonNull.string('tasks'); t.string('description'); t.int('version'); + t.boolean('restartable'); + t.list.nonNull.field({ name: 'outputParameters', type: OutputParameterInput }); + t.string('createdAt'); + t.string('updatedAt'); }, }); @@ -512,6 +546,7 @@ export const UpdateWorkflowMutation = extendType({ const { workflow } = input; const parsedTasks = validateTasks(workflow.tasks); + const outputParameters = convertToApiOutputParameters(workflow.outputParameters); const apiWorkflow: WorkflowDetailInput = { name: workflow.name, @@ -519,6 +554,10 @@ export const UpdateWorkflowMutation = extendType({ tasks: parsedTasks, version: workflow.version || undefined, description: workflow.description || undefined, + restartable: workflow.restartable || undefined, + outputParameters: outputParameters || undefined, + createTime: workflow.createdAt ? Date.parse(workflow.createdAt) : undefined, + updateTime: workflow.updatedAt ? Date.parse(workflow.updatedAt) : undefined, }; const result = await conductorAPI.editWorkflow(config.conductorApiURL, apiWorkflow); From 7d71fadde746b3aed5b145fd8c6c45af92da3844 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Wed, 10 May 2023 10:30:35 +0200 Subject: [PATCH 18/69] Add graphql scheduler (#289) * add urql to handle schellar graphql requests * add graphql resolvers for schellar in inventory * add generated types from schellar server * fix hasSchedule logic of workflow * remove urql and use graphql-request * refactor property names * add resolvers for schedule schema properties and refactor query resolvers --- .env.example | 2 +- codegen.yml | 15 + package.json | 13 +- prisma/seed.ts | 2 +- src/__generated__/graphql.ts | 161 +++ src/external-api/scheduler.ts | 170 ++- src/helpers/id-helper.ts | 6 +- src/schema/api.graphql | 57 + src/schema/global-types.ts | 11 + src/schema/nexus-typegen.ts | 122 ++ src/schema/source-types.ts | 2 + src/schema/workflow.ts | 201 ++- yarn.lock | 2244 ++++++++++++++++++++++++++++++++- 13 files changed, 2921 insertions(+), 85 deletions(-) create mode 100644 codegen.yml create mode 100644 src/__generated__/graphql.ts diff --git a/.env.example b/.env.example index 4519bb9e..dc92e91b 100644 --- a/.env.example +++ b/.env.example @@ -5,7 +5,7 @@ UNICONFIG_API_PROTOCOL=http UNICONFIG_API_PORT=4000 UNICONFIG_LIST_URL=http://localhost:4000/static/list/uniconfig CONDUCTOR_API_URL="http:/10.19.0.7:8080/api" -SCHEDULER_API_URL="http://10.19.0.7:3001" +SCHEDULER_API_URL="http://10.19.0.7:3001/query" SHELL_HOST=10.19.0.12 X_TENANT_ID="frinx" TOPOLOGY_ENABLED=true diff --git a/codegen.yml b/codegen.yml new file mode 100644 index 00000000..874d0c3f --- /dev/null +++ b/codegen.yml @@ -0,0 +1,15 @@ +schema: + - 'http://10.19.0.7:3001/query' +documents: + - './src/**/*.ts' +generates: + src/__generated__/graphql.ts: + plugins: + - 'typescript' + - 'typescript-operations' + config: + enumsAsTypes: true + avoidOptionals: + field: true + object: false + inputValue: false diff --git a/package.json b/package.json index d61ad4e5..2dbfea9a 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,15 @@ "formatter:check": "prettier -l '*.md' '**/*.ts' '**/*.js' '**/*.json' ", "test:generate": "cross-env NODE_ENV=testing ts-node --transpile-only -r dotenv/config src/schema/index.ts", "jest": "cross-env NODE_ENV=testing jest --verbose", - "test": "run-s test:generate jest" + "test": "run-s test:generate jest", + "codegen": "graphql-codegen --config codegen.yml" }, "devDependencies": { "@frinx/eslint-config-typescript-base": "15.0.0-build.1", + "@graphql-codegen/cli": "3.3.1", + "@graphql-codegen/introspection": "^3.0.1", + "@graphql-codegen/typescript": "^3.0.4", + "@graphql-codegen/typescript-operations": "^3.0.4", "@types/jest": "28.1.8", "@types/ssh2": "^1.11.6", "@typescript-eslint/eslint-plugin": "5.54.0", @@ -38,7 +43,6 @@ "eslint-plugin-import": "2.26.0", "get-port": "5.1.1", "glob": "8.0.3", - "graphql-request": "4.3.0", "jest": "28.1.3", "npm-run-all": "4.1.5", "prettier": "2.7.1", @@ -46,7 +50,7 @@ "ts-jest": "28.0.8", "ts-node": "10.9.1", "ts-node-dev": "2.0.0", - "typescript": "4.7.4" + "typescript": "^5.0.4" }, "dependencies": { "@devoxa/prisma-relay-cursor-connection": "2.2.2", @@ -69,8 +73,9 @@ "csv-parse": "5.3.5", "express": "4.18.1", "fp-ts": "2.12.2", - "graphql": "16.6.0", + "graphql": "^16.6.0", "graphql-relay": "0.10.0", + "graphql-request": "^6.0.0", "graphql-upload": "15.0.2", "graphql-ws": "^5.11.2", "i18n-iso-countries": "7.5.0", diff --git a/prisma/seed.ts b/prisma/seed.ts index 8463aaf2..4175c2aa 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -3,7 +3,7 @@ import { parse } from 'csv-parse'; import { createReadStream } from 'fs'; import jsonParse from 'json-templates'; import { CSVParserToPromise, CSVValuesToJSON, isHeaderValid, JSONDevice } from '../src/helpers/import-csv.helpers'; -import unwrap from '../src/helpers/unwrap'; +import { unwrap } from '../src/helpers/utils.helpers'; const DEFAULT_UNICONFIG_ZONE = 'localhost'; diff --git a/src/__generated__/graphql.ts b/src/__generated__/graphql.ts new file mode 100644 index 00000000..56634941 --- /dev/null +++ b/src/__generated__/graphql.ts @@ -0,0 +1,161 @@ +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 }; +/** All built-in and custom scalars, mapped to their actual values */ +export type Scalars = { + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; + DateTime: any; + JSON: any; +}; + +export type CreateScheduleInput = { + cronString: Scalars['String']; + enabled?: InputMaybe; + fromDate?: InputMaybe; + name: Scalars['String']; + parallelRuns?: InputMaybe; + toDate?: InputMaybe; + workflowContext?: InputMaybe; + workflowName: Scalars['String']; + workflowVersion: Scalars['String']; +}; + +export type Mutation = { + __typename?: 'Mutation'; + createSchedule: Schedule; + deleteSchedule: Scalars['Boolean']; + updateSchedule: Schedule; +}; + + +export type MutationCreateScheduleArgs = { + input: CreateScheduleInput; +}; + + +export type MutationDeleteScheduleArgs = { + name: Scalars['String']; +}; + + +export type MutationUpdateScheduleArgs = { + input: UpdateScheduleInput; + name: Scalars['String']; +}; + +export type PageInfo = { + __typename?: 'PageInfo'; + endCursor: Maybe; + hasNextPage: Scalars['Boolean']; + hasPreviousPage: Scalars['Boolean']; + startCursor: Maybe; +}; + +export type Query = { + __typename?: 'Query'; + schedule: Maybe; + schedules: Maybe; +}; + + +export type QueryScheduleArgs = { + name: Scalars['String']; +}; + + +export type QuerySchedulesArgs = { + after?: InputMaybe; + before?: InputMaybe; + filter?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; +}; + +export type Schedule = { + __typename?: 'Schedule'; + cronString: Scalars['String']; + enabled: Scalars['Boolean']; + fromDate: Scalars['DateTime']; + name: Scalars['String']; + parallelRuns: Scalars['Boolean']; + status: Scalars['String']; + toDate: Scalars['DateTime']; + workflowContext: Scalars['String']; + workflowName: Scalars['String']; + workflowVersion: Scalars['String']; +}; + +export type ScheduleConnection = { + __typename?: 'ScheduleConnection'; + edges: Array>; + pageInfo: PageInfo; + totalCount: Scalars['Int']; +}; + +export type ScheduleEdge = { + __typename?: 'ScheduleEdge'; + cursor: Scalars['String']; + node: Schedule; +}; + +export type SchedulesFilterInput = { + workflowName: Scalars['String']; + workflowVersion: Scalars['String']; +}; + +export type UpdateScheduleInput = { + cronString?: InputMaybe; + enabled?: InputMaybe; + fromDate?: InputMaybe; + parallelRuns?: InputMaybe; + toDate?: InputMaybe; + workflowContext?: InputMaybe; + workflowName?: InputMaybe; + workflowVersion?: InputMaybe; +}; + +export type DeleteScheduleMutationVariables = Exact<{ + scheduleName: Scalars['String']; +}>; + + +export type DeleteScheduleMutation = { __typename?: 'Mutation', deleteSchedule: boolean }; + +export type UpdateScheduleMutationVariables = Exact<{ + scheduleName: Scalars['String']; + input: UpdateScheduleInput; +}>; + + +export type UpdateScheduleMutation = { __typename?: 'Mutation', updateSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: string } }; + +export type CreateScheduleMutationVariables = Exact<{ + input: CreateScheduleInput; +}>; + + +export type CreateScheduleMutation = { __typename?: 'Mutation', createSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: string } }; + +export type GetScheduleQueryVariables = Exact<{ + scheduleName: Scalars['String']; +}>; + + +export type GetScheduleQuery = { __typename?: 'Query', schedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: string } | null }; + +export type GetSchedulesQueryVariables = Exact<{ + first?: InputMaybe; + last?: InputMaybe; + before?: InputMaybe; + after?: InputMaybe; + filter?: InputMaybe; +}>; + + +export type GetSchedulesQuery = { __typename?: 'Query', schedules: { __typename?: 'ScheduleConnection', totalCount: number, edges: Array<{ __typename?: 'ScheduleEdge', cursor: string, node: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: string } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null } } | null }; diff --git a/src/external-api/scheduler.ts b/src/external-api/scheduler.ts index 28ee620a..6703d945 100644 --- a/src/external-api/scheduler.ts +++ b/src/external-api/scheduler.ts @@ -1,23 +1,171 @@ -import { sendGetRequest } from './helpers'; -import { decodeScheduleListOutput, decodeScheduleOutput } from './scheduler-network-types'; +import { PaginationArgs } from 'nexus/dist/plugins/connectionPlugin'; +import { GraphQLClient, gql } from 'graphql-request'; +import { + CreateScheduleInput, + CreateScheduleMutation, + CreateScheduleMutationVariables, + DeleteScheduleMutation, + DeleteScheduleMutationVariables, + GetScheduleQuery, + GetScheduleQueryVariables, + GetSchedulesQuery, + GetSchedulesQueryVariables, + SchedulesFilterInput, + UpdateScheduleInput, + UpdateScheduleMutation, + UpdateScheduleMutationVariables, +} from '../__generated__/graphql'; +import config from '../config'; -async function listSchedules(baseURL: string): Promise { - const json = await sendGetRequest([baseURL, 'schedule']); - const data = decodeScheduleListOutput(json); +const client = new GraphQLClient(config.schedulerApiURL, { headers: {} }); - return data; +const DELETE_SCHEDULE_MUTATION = gql` + mutation DeleteSchedule($scheduleName: String!) { + deleteSchedule(name: $scheduleName) + } +`; + +const UPDATE_SCHEDULE_MUTATION = gql` + mutation UpdateSchedule($scheduleName: String!, $input: UpdateScheduleInput!) { + updateSchedule(name: $scheduleName, input: $input) { + name + enabled + parallelRuns + workflowName + workflowVersion + cronString + workflowContext + fromDate + toDate + status + } + } +`; + +const CREATE_SCHEDULE_MUTATION = gql` + mutation CreateSchedule($input: CreateScheduleInput!) { + createSchedule(input: $input) { + name + enabled + parallelRuns + workflowName + workflowVersion + cronString + workflowContext + fromDate + toDate + status + } + } +`; + +const GET_SCHEDULE_QUERY = gql` + query GetSchedule($scheduleName: String!) { + schedule(name: $scheduleName) { + name + enabled + parallelRuns + workflowName + workflowVersion + cronString + workflowContext + fromDate + toDate + status + } + } +`; + +const GET_SCHEDULES_QUERY = gql` + query GetSchedules($first: Int, $last: Int, $before: String, $after: String, $filter: SchedulesFilterInput) { + schedules(after: $after, before: $before, first: $first, last: $last, filter: $filter) { + edges { + node { + name + enabled + parallelRuns + workflowName + workflowVersion + cronString + workflowContext + fromDate + toDate + status + } + cursor + } + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + totalCount + } + } +`; + +async function getSchedules( + paginationArgs: PaginationArgs, + filter: SchedulesFilterInput | null | undefined, +): Promise { + const response = await client.request(GET_SCHEDULES_QUERY, { + ...paginationArgs, + filter, + }); + + return response; +} + +async function getSchedule(scheduleName: string): Promise { + const response = await client.request(GET_SCHEDULE_QUERY, { + scheduleName, + }); + + return response.schedule; +} + +async function createWorkflowSchedule( + input: CreateScheduleInput, +): Promise['createSchedule']> { + const response = await client.request( + CREATE_SCHEDULE_MUTATION, + { input }, + ); + + return response.createSchedule; +} + +async function editWorkflowSchedule( + name: string, + input: UpdateScheduleInput, +): Promise { + const response = await client.request( + UPDATE_SCHEDULE_MUTATION, + { + input, + scheduleName: name, + }, + ); + + return response.updateSchedule; } -async function getSchedule(baseURL: string, workflowName: string, workflowVersion: number): Promise { - const json = await sendGetRequest([baseURL, `schedule/${workflowName}:${workflowVersion}`]); - const data = decodeScheduleOutput(json); +async function deleteSchedule(scheduleName: string): Promise { + const response = await client.request( + DELETE_SCHEDULE_MUTATION, + { scheduleName }, + ); - return data; + return response.deleteSchedule; } const schedulerAPI = { - listSchedules, + getSchedules, getSchedule, + createWorkflowSchedule, + editWorkflowSchedule, + deleteSchedule, }; export type SchedulerAPI = typeof schedulerAPI; diff --git a/src/helpers/id-helper.ts b/src/helpers/id-helper.ts index 6d40d489..0230a0fc 100644 --- a/src/helpers/id-helper.ts +++ b/src/helpers/id-helper.ts @@ -11,7 +11,8 @@ export type DataType = | 'Country' | 'Blueprint' | 'GraphNode' - | 'GraphEdge'; + | 'GraphEdge' + | 'Schedule'; function isDataType(value: string): value is DataType { return ( @@ -25,7 +26,8 @@ function isDataType(value: string): value is DataType { value === 'Country' || value === 'Blueprint' || value === 'GraphNode' || - value === 'GraphEdge' + value === 'GraphEdge' || + value === 'Schedule' ); } diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 5bc61329..2d522990 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -171,6 +171,18 @@ type CreateLabelPayload { label: Label } +input CreateScheduleInput { + cronString: String! + isEnabled: Boolean + name: String! + parallelRuns: Boolean + performFromDate: String + performTillDate: String + workflowContext: String + workflowName: String! + workflowVersion: String! +} + type CreateTransactionPayload { transactionId: String } @@ -279,6 +291,17 @@ type EdgeSourceTarget { nodeId: String! } +input EditWorkflowScheduleInput { + cronString: String + isEnabled: Boolean + parallelRuns: Boolean + performFromDate: String + performTillDate: String + workflowContext: String + workflowName: String + workflowVersion: String +} + input ExecuteNewWorkflowInput { correlationId: String externalInputPayloadStoragePath: String @@ -517,8 +540,10 @@ type Mutation { deleteBlueprint(id: String!): DeleteBlueprintPayload! deleteDevice(id: String!): DeleteDevicePayload! deleteLabel(id: String!): DeleteLabelPayload! + deleteSchedule(name: String!): IsOkResponse deleteSnapshot(input: DeleteSnapshotInput!): DeleteSnapshotPayload deleteWorkflow(name: String!, version: Int!): DeleteWorkflowPayload! + editWorkflowSchedule(input: EditWorkflowScheduleInput!, name: String!): Schedule executeNewWorkflow(input: StartWorkflowRequestInput!): String executeWorkflowByName( correlationId: String @@ -558,6 +583,7 @@ type Mutation { workflowId: String! ): IsOkResponse revertChanges(transactionId: String!): RevertChangesPayload! + scheduleWorkflow(input: CreateScheduleInput!): Schedule syncFromNetwork(deviceId: String!, transactionId: String!): SyncFromNetworkPayload! terminateWorkflow(reason: String, workflowId: String!): IsOkResponse uninstallDevice(id: String!): UninstallDevicePayload! @@ -637,6 +663,7 @@ type Query { locations(after: String, before: String, first: Int, last: Int): LocationConnection! netTopology: NetTopology node(id: ID!, version: Int): Node + schedules(after: String, before: String, filter: ScheduleFilterInput, first: Int, last: Int): ScheduleConnection! taskDefinitions: [TaskDefinition!]! topology(filter: FilterTopologyInput): Topology topologyCommonNodes(nodes: [String!]!): TopologyCommonNodes @@ -664,6 +691,36 @@ type RevertChangesPayload { isOk: Boolean! } +type Schedule implements Node { + cronString: String! + id: ID! + isEnabled: Boolean! + name: String! + parallelRuns: Boolean! + performFromDate: String! + performTillDate: String! + version: Int + workflowContext: String! + workflowName: String! + workflowVersion: String! +} + +type ScheduleConnection { + edges: [ScheduleEdge]! + pageInfo: PageInfo! + totalCount: Int! +} + +type ScheduleEdge { + cursor: String! + node: Schedule! +} + +input ScheduleFilterInput { + workflowName: String! + workflowVersion: String! +} + type Snapshot { createdAt: String! name: String! diff --git a/src/schema/global-types.ts b/src/schema/global-types.ts index 9579d7e5..46fd1360 100644 --- a/src/schema/global-types.ts +++ b/src/schema/global-types.ts @@ -3,6 +3,7 @@ import { extendType, idArg, intArg, interfaceType, nonNull, objectType, stringAr import config from '../config'; import conductorAPI from '../external-api/conductor'; import { fromGraphId, getType } from '../helpers/id-helper'; +import schedulerAPI from '../external-api/scheduler'; export const Node = interfaceType({ name: 'Node', @@ -119,6 +120,16 @@ export const NodeQuery = extendType({ } return { ...workflow, id: args.id, __typename: 'ExecutedWorkflow' }; } + case 'Schedule': { + const id = fromGraphId('Schedule', args.id); + const schedule = await schedulerAPI.getSchedule(id); + + if (schedule == null) { + return null; + } + + return { ...schedule, id: args.id, __typename: 'Schedule' }; + } /* eslint-enable */ default: return null; diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index e6d50b23..72f3500f 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -87,6 +87,18 @@ export interface NexusGenInputs { // input type name: string; // String! }; + CreateScheduleInput: { + // input type + cronString: string; // String! + isEnabled?: boolean | null; // Boolean + name: string; // String! + parallelRuns?: boolean | null; // Boolean + performFromDate?: string | null; // String + performTillDate?: string | null; // String + workflowContext?: string | null; // String + workflowName: string; // String! + workflowVersion: string; // String! + }; CreateWorkflowInput: { // input type workflow: NexusGenInputs['WorkflowInput']; // WorkflowInput! @@ -102,6 +114,17 @@ export interface NexusGenInputs { direction: NexusGenEnums['SortDirection']; // SortDirection! sortKey: NexusGenEnums['SortDeviceBy']; // SortDeviceBy! }; + EditWorkflowScheduleInput: { + // input type + cronString?: string | null; // String + isEnabled?: boolean | null; // Boolean + parallelRuns?: boolean | null; // Boolean + performFromDate?: string | null; // String + performTillDate?: string | null; // String + workflowContext?: string | null; // String + workflowName?: string | null; // String + workflowVersion?: string | null; // String + }; ExecuteNewWorkflowInput: { // input type correlationId?: string | null; // String @@ -159,6 +182,11 @@ export interface NexusGenInputs { size: number; // Int! start: number; // Int! }; + ScheduleFilterInput: { + // input type + workflowName: string; // String! + workflowVersion: string; // String! + }; StartWorkflowRequestInput: { // input type workflow: NexusGenInputs['ExecuteNewWorkflowInput']; // ExecuteNewWorkflowInput! @@ -579,6 +607,18 @@ export interface NexusGenObjects { // root type isOk: boolean; // Boolean! }; + Schedule: SourceTypes.Schedule; + ScheduleConnection: { + // root type + edges: Array; // [ScheduleEdge]! + pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! + totalCount: number; // Int! + }; + ScheduleEdge: { + // root type + cursor: string; // String! + node: NexusGenRootTypes['Schedule']; // Schedule! + }; Snapshot: { // root type createdAt: string; // String! @@ -697,6 +737,7 @@ export interface NexusGenInterfaces { | core.Discriminate<'ExecutedWorkflowTask', 'required'> | core.Discriminate<'Label', 'required'> | core.Discriminate<'Location', 'required'> + | core.Discriminate<'Schedule', 'required'> | core.Discriminate<'Workflow', 'required'> | core.Discriminate<'Zone', 'required'>; } @@ -1055,8 +1096,10 @@ export interface NexusGenFieldTypes { deleteBlueprint: NexusGenRootTypes['DeleteBlueprintPayload']; // DeleteBlueprintPayload! deleteDevice: NexusGenRootTypes['DeleteDevicePayload']; // DeleteDevicePayload! deleteLabel: NexusGenRootTypes['DeleteLabelPayload']; // DeleteLabelPayload! + deleteSchedule: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse deleteSnapshot: NexusGenRootTypes['DeleteSnapshotPayload'] | null; // DeleteSnapshotPayload deleteWorkflow: NexusGenRootTypes['DeleteWorkflowPayload']; // DeleteWorkflowPayload! + editWorkflowSchedule: NexusGenRootTypes['Schedule'] | null; // Schedule executeNewWorkflow: string | null; // String executeWorkflowByName: string | null; // String importCSV: NexusGenRootTypes['CSVImport'] | null; // CSVImport @@ -1068,6 +1111,7 @@ export interface NexusGenFieldTypes { resumeWorkflow: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse retryWorkflow: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse revertChanges: NexusGenRootTypes['RevertChangesPayload']; // RevertChangesPayload! + scheduleWorkflow: NexusGenRootTypes['Schedule'] | null; // Schedule syncFromNetwork: NexusGenRootTypes['SyncFromNetworkPayload']; // SyncFromNetworkPayload! terminateWorkflow: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse uninstallDevice: NexusGenRootTypes['UninstallDevicePayload']; // UninstallDevicePayload! @@ -1125,6 +1169,7 @@ export interface NexusGenFieldTypes { locations: NexusGenRootTypes['LocationConnection']; // LocationConnection! netTopology: NexusGenRootTypes['NetTopology'] | null; // NetTopology node: NexusGenRootTypes['Node'] | null; // Node + schedules: NexusGenRootTypes['ScheduleConnection']; // ScheduleConnection! taskDefinitions: NexusGenRootTypes['TaskDefinition'][]; // [TaskDefinition!]! topology: NexusGenRootTypes['Topology'] | null; // Topology topologyCommonNodes: NexusGenRootTypes['TopologyCommonNodes'] | null; // TopologyCommonNodes @@ -1145,6 +1190,31 @@ export interface NexusGenFieldTypes { // field return type isOk: boolean; // Boolean! }; + Schedule: { + // field return type + cronString: string; // String! + id: string; // ID! + isEnabled: boolean; // Boolean! + name: string; // String! + parallelRuns: boolean; // Boolean! + performFromDate: string; // String! + performTillDate: string; // String! + version: number | null; // Int + workflowContext: string; // String! + workflowName: string; // String! + workflowVersion: string; // String! + }; + ScheduleConnection: { + // field return type + edges: Array; // [ScheduleEdge]! + pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! + totalCount: number; // Int! + }; + ScheduleEdge: { + // field return type + cursor: string; // String! + node: NexusGenRootTypes['Schedule']; // Schedule! + }; Snapshot: { // field return type createdAt: string; // String! @@ -1663,8 +1733,10 @@ export interface NexusGenFieldTypeNames { deleteBlueprint: 'DeleteBlueprintPayload'; deleteDevice: 'DeleteDevicePayload'; deleteLabel: 'DeleteLabelPayload'; + deleteSchedule: 'IsOkResponse'; deleteSnapshot: 'DeleteSnapshotPayload'; deleteWorkflow: 'DeleteWorkflowPayload'; + editWorkflowSchedule: 'Schedule'; executeNewWorkflow: 'String'; executeWorkflowByName: 'String'; importCSV: 'CSVImport'; @@ -1676,6 +1748,7 @@ export interface NexusGenFieldTypeNames { resumeWorkflow: 'IsOkResponse'; retryWorkflow: 'IsOkResponse'; revertChanges: 'RevertChangesPayload'; + scheduleWorkflow: 'Schedule'; syncFromNetwork: 'SyncFromNetworkPayload'; terminateWorkflow: 'IsOkResponse'; uninstallDevice: 'UninstallDevicePayload'; @@ -1733,6 +1806,7 @@ export interface NexusGenFieldTypeNames { locations: 'LocationConnection'; netTopology: 'NetTopology'; node: 'Node'; + schedules: 'ScheduleConnection'; taskDefinitions: 'TaskDefinition'; topology: 'Topology'; topologyCommonNodes: 'TopologyCommonNodes'; @@ -1753,6 +1827,31 @@ export interface NexusGenFieldTypeNames { // field return type name isOk: 'Boolean'; }; + Schedule: { + // field return type name + cronString: 'String'; + id: 'ID'; + isEnabled: 'Boolean'; + name: 'String'; + parallelRuns: 'Boolean'; + performFromDate: 'String'; + performTillDate: 'String'; + version: 'Int'; + workflowContext: 'String'; + workflowName: 'String'; + workflowVersion: 'String'; + }; + ScheduleConnection: { + // field return type name + edges: 'ScheduleEdge'; + pageInfo: 'PageInfo'; + totalCount: 'Int'; + }; + ScheduleEdge: { + // field return type name + cursor: 'String'; + node: 'Schedule'; + }; Snapshot: { // field return type name createdAt: 'String'; @@ -2014,6 +2113,10 @@ export interface NexusGenArgTypes { // args id: string; // String! }; + deleteSchedule: { + // args + name: string; // String! + }; deleteSnapshot: { // args input: NexusGenInputs['DeleteSnapshotInput']; // DeleteSnapshotInput! @@ -2023,6 +2126,11 @@ export interface NexusGenArgTypes { name: string; // String! version: number; // Int! }; + editWorkflowSchedule: { + // args + input: NexusGenInputs['EditWorkflowScheduleInput']; // EditWorkflowScheduleInput! + name: string; // String! + }; executeNewWorkflow: { // args input: NexusGenInputs['StartWorkflowRequestInput']; // StartWorkflowRequestInput! @@ -2075,6 +2183,10 @@ export interface NexusGenArgTypes { // args transactionId: string; // String! }; + scheduleWorkflow: { + // args + input: NexusGenInputs['CreateScheduleInput']; // CreateScheduleInput! + }; syncFromNetwork: { // args deviceId: string; // String! @@ -2173,6 +2285,14 @@ export interface NexusGenArgTypes { id: string; // ID! version?: number | null; // Int }; + schedules: { + // args + after?: string | null; // String + before?: string | null; // String + filter?: NexusGenInputs['ScheduleFilterInput'] | null; // ScheduleFilterInput + first?: number | null; // Int + last?: number | null; // Int + }; topology: { // args filter?: NexusGenInputs['FilterTopologyInput'] | null; // FilterTopologyInput @@ -2226,6 +2346,7 @@ export interface NexusGenAbstractTypeMembers { | 'ExecutedWorkflowTask' | 'Label' | 'Location' + | 'Schedule' | 'Workflow' | 'Zone'; } @@ -2240,6 +2361,7 @@ export interface NexusGenTypeInterfaces { GraphVersionNode: 'BaseGraphNode'; Label: 'Node'; Location: 'Node'; + Schedule: 'Node'; Workflow: 'Node'; Zone: 'Node'; } diff --git a/src/schema/source-types.ts b/src/schema/source-types.ts index f0a51c45..4f80efad 100644 --- a/src/schema/source-types.ts +++ b/src/schema/source-types.ts @@ -6,6 +6,7 @@ import { NestedTask, ApiTaskDefinition, } from '../external-api/conductor-network-types'; +import { GetScheduleQuery } from '../__generated__/graphql'; export type Label = label; export type Device = device; @@ -27,3 +28,4 @@ export type ExecutedWorkflow = ApiExecutedWorkflow & { id: string }; export type ExecutedWorkflowTask = ApiExecutedWorkflowTask & { id: string }; export type WorkflowTask = NestedTask; export type TaskDefinition = ApiTaskDefinition; +export type Schedule = GetScheduleQuery['schedule'] & { id: string }; diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 4b7f092c..f84538ba 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -29,10 +29,18 @@ import { validateTasks, } from '../helpers/workflow.helpers'; import { StartWorkflowInput } from '../types/conductor.types'; -import { parseJson, unwrap } from '../helpers/utils.helpers'; +import { omitNullValue, parseJson, unwrap } from '../helpers/utils.helpers'; const log = getLogger('frinx-inventory-server'); +export const ScheduleFilterInput = inputObjectType({ + name: 'ScheduleFilterInput', + definition: (t) => { + t.nonNull.string('workflowName'); + t.nonNull.string('workflowVersion'); + }, +}); + const OutputParameter = objectType({ name: 'OutputParameter', definition: (t) => { @@ -80,8 +88,19 @@ export const Workflow = objectType({ t.boolean('hasSchedule', { resolve: async (workflow, _, { schedulerAPI }) => { try { - await schedulerAPI.getSchedule(config.schedulerApiURL, workflow.name, workflow.version ?? 1); - return true; + const { schedules } = await schedulerAPI.getSchedules( + {}, + { + workflowName: workflow.name, + workflowVersion: workflow.version?.toString() ?? '1', + }, + ); + + if (schedules == null) { + return false; + } + + return schedules.edges.length > 0; } catch (e) { log.info(`cannot get schedule info for workflow ${workflow.name}: ${e}`); return false; @@ -795,3 +814,179 @@ export const RemoveWorkflowMutation = mutationField('removeWorkflow', { return { isOk: true }; }, }); + +export const CreateScheduleInput = inputObjectType({ + name: 'CreateScheduleInput', + definition(t) { + t.nonNull.string('name'); + t.nonNull.string('workflowName'); + t.nonNull.string('workflowVersion'); + t.nonNull.string('cronString'); + t.string('workflowContext'); + t.boolean('isEnabled'); + t.string('performFromDate'); + t.string('performTillDate'); + t.boolean('parallelRuns'); + }, +}); + +export const Schedule = objectType({ + name: 'Schedule', + definition: (t) => { + t.implements(Node); + t.nonNull.id('id', { + resolve: (root) => toGraphId('Schedule', root.name), + }); + t.nonNull.string('name'); + t.nonNull.string('workflowName'); + t.nonNull.string('workflowVersion'); + t.nonNull.string('cronString'); + t.nonNull.string('workflowContext'); + t.nonNull.boolean('isEnabled', { + resolve: (root) => root.enabled, + }); + t.nonNull.string('performFromDate', { + resolve: (root) => root.fromDate, + }); + t.nonNull.string('performTillDate', { + resolve: (root) => root.toDate, + }); + t.nonNull.boolean('parallelRuns'); + }, +}); + +export const ScheduleWorkflow = mutationField('scheduleWorkflow', { + type: Schedule, + args: { + input: nonNull(arg({ type: CreateScheduleInput })), + }, + resolve: async (_, { input }, { schedulerAPI }) => { + const response = await schedulerAPI.createWorkflowSchedule({ + fromDate: input.performFromDate, + toDate: input.performTillDate, + enabled: input.isEnabled, + cronString: input.cronString, + name: input.name, + workflowName: input.workflowName, + workflowVersion: input.workflowVersion, + workflowContext: input.workflowContext, + parallelRuns: input.parallelRuns, + }); + + return { + ...response, + id: toGraphId('Schedule', response.name), + }; + }, +}); + +export const EditWorkflowScheduleInput = inputObjectType({ + name: 'EditWorkflowScheduleInput', + definition(t) { + t.string('workflowName'); + t.string('workflowVersion'); + t.string('cronString'); + t.string('workflowContext'); + t.boolean('isEnabled'); + t.string('performFromDate'); + t.string('performTillDate'); + t.boolean('parallelRuns'); + }, +}); + +export const EditWorkflowSchedule = mutationField('editWorkflowSchedule', { + type: Schedule, + args: { + input: nonNull(arg({ type: EditWorkflowScheduleInput })), + name: nonNull(stringArg()), + }, + resolve: async (_, { input, name }, { schedulerAPI }) => { + const response = await schedulerAPI.editWorkflowSchedule(name, { + fromDate: input.performFromDate, + toDate: input.performTillDate, + enabled: input.isEnabled, + cronString: input.cronString, + workflowName: input.workflowName, + workflowVersion: input.workflowVersion, + workflowContext: input.workflowContext, + parallelRuns: input.parallelRuns, + }); + + return { + ...response, + id: toGraphId('Schedule', response.name), + }; + }, +}); + +export const ScheduleEdge = objectType({ + name: 'ScheduleEdge', + definition: (t) => { + t.nonNull.field('node', { + type: Schedule, + }); + t.nonNull.string('cursor'); + }, +}); + +export const ScheduleConnection = objectType({ + name: 'ScheduleConnection', + definition: (t) => { + t.nonNull.list.field('edges', { + type: ScheduleEdge, + }); + t.nonNull.field('pageInfo', { + type: PageInfo, + }); + t.nonNull.int('totalCount'); + }, +}); + +export const WorkflowSchedules = queryField('schedules', { + type: nonNull(ScheduleConnection), + args: { + ...PaginationConnectionArgs, + filter: arg({ + type: ScheduleFilterInput, + }), + }, + resolve: async (_, { filter, ...args }, { schedulerAPI }) => { + const { schedules } = await schedulerAPI.getSchedules(args, filter); + + if (schedules == null || schedules.edges == null) { + throw new Error('No schedules found'); + } + + return { + totalCount: schedules.totalCount, + edges: schedules.edges.filter(omitNullValue).map((schedule) => ({ + ...schedule, + node: { + ...schedule.node, + id: toGraphId('Schedule', schedule.node.name), + }, + })), + pageInfo: schedules.pageInfo, + }; + }, +}); + +export const DeleteSchedule = mutationField('deleteSchedule', { + type: IsOkResponse, + args: { + name: nonNull(stringArg()), + }, + resolve: async (_, { name }, { schedulerAPI }) => { + try { + await schedulerAPI.deleteSchedule(name); + + return { + isOk: true, + }; + } catch (error) { + return { + isOk: false, + }; + } + }, +}); diff --git a/yarn.lock b/yarn.lock index 40a64165..703ff692 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,6 +9,14 @@ dependencies: "@jridgewell/trace-mapping" "^0.3.0" +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + "@apollo/protobufjs@1.2.2": version "1.2.2" resolved "https://registry.yarnpkg.com/@apollo/protobufjs/-/protobufjs-1.2.2.tgz#4bd92cd7701ccaef6d517cdb75af2755f049f87c" @@ -130,6 +138,36 @@ dependencies: xss "^1.0.8" +"@ardatan/relay-compiler@12.0.0": + version "12.0.0" + resolved "https://registry.yarnpkg.com/@ardatan/relay-compiler/-/relay-compiler-12.0.0.tgz#2e4cca43088e807adc63450e8cab037020e91106" + integrity sha512-9anThAaj1dQr6IGmzBMcfzOQKTa5artjuPmw8NYK/fiGEMjADbSguBY2FMDykt+QhilR3wc9VA/3yVju7JHg7Q== + dependencies: + "@babel/core" "^7.14.0" + "@babel/generator" "^7.14.0" + "@babel/parser" "^7.14.0" + "@babel/runtime" "^7.0.0" + "@babel/traverse" "^7.14.0" + "@babel/types" "^7.0.0" + babel-preset-fbjs "^3.4.0" + chalk "^4.0.0" + fb-watchman "^2.0.0" + fbjs "^3.0.0" + glob "^7.1.1" + immutable "~3.7.6" + invariant "^2.2.4" + nullthrows "^1.1.1" + relay-runtime "12.0.0" + signedsource "^1.0.0" + yargs "^15.3.1" + +"@ardatan/sync-fetch@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@ardatan/sync-fetch/-/sync-fetch-0.0.1.tgz#3385d3feedceb60a896518a1db857ec1e945348f" + integrity sha512-xhlTqH0m31mnsG0tIP4ETgfSB6gXDaYYsUWTrlUV93fFQPI9dd8hE0Ot6MHLCtqgB32hwJAC3YZMWlXZw7AleA== + dependencies: + node-fetch "^2.6.1" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" @@ -144,6 +182,13 @@ dependencies: "@babel/highlight" "^7.16.0" +"@babel/code-frame@^7.18.6", "@babel/code-frame@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39" + integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g== + dependencies: + "@babel/highlight" "^7.18.6" + "@babel/compat-data@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.0.tgz#ea269d7f78deb3a7826c39a4048eecda541ebdaa" @@ -154,6 +199,11 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.10.tgz#711dc726a492dfc8be8220028b1b92482362baab" integrity sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw== +"@babel/compat-data@^7.20.5", "@babel/compat-data@^7.21.5": + version "7.21.7" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.7.tgz#61caffb60776e49a57ba61a88f02bedd8714f6bc" + integrity sha512-KYMqFYTaenzMK4yUtf4EW9wc4N9ef80FsbMtkwool5zpwl4YrT1SdWYSTRcT94KO4hannogdS+LxY7L+arP3gA== + "@babel/core@^7.11.6": version "7.18.2" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.2.tgz#87b2fcd7cce9becaa7f5acebdc4f09f3dd19d876" @@ -196,6 +246,37 @@ semver "^6.3.0" source-map "^0.5.0" +"@babel/core@^7.14.0": + version "7.21.8" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.8.tgz#2a8c7f0f53d60100ba4c32470ba0281c92aa9aa4" + integrity sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.21.4" + "@babel/generator" "^7.21.5" + "@babel/helper-compilation-targets" "^7.21.5" + "@babel/helper-module-transforms" "^7.21.5" + "@babel/helpers" "^7.21.5" + "@babel/parser" "^7.21.8" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.5" + "@babel/types" "^7.21.5" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.2" + semver "^6.3.0" + +"@babel/generator@^7.14.0", "@babel/generator@^7.18.13", "@babel/generator@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.5.tgz#c0c0e5449504c7b7de8236d99338c3e2a340745f" + integrity sha512-SrKK/sRv8GesIW1bDagf9cCG38IOMYZusoe1dfg0D8aiUe3Amvoj1QtjTPAWcfrZFvIwlleLb0gxzQidL9w14w== + dependencies: + "@babel/types" "^7.21.5" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/generator@^7.16.0", "@babel/generator@^7.7.2": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.0.tgz#d40f3d1d5075e62d3500bccb67f3daa8a95265b2" @@ -214,6 +295,13 @@ "@jridgewell/gen-mapping" "^0.3.0" jsesc "^2.5.1" +"@babel/helper-annotate-as-pure@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== + dependencies: + "@babel/types" "^7.18.6" + "@babel/helper-compilation-targets@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.0.tgz#01d615762e796c17952c29e3ede9d6de07d235a8" @@ -234,6 +322,32 @@ browserslist "^4.20.2" semver "^6.3.0" +"@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.5.tgz#631e6cc784c7b660417421349aac304c94115366" + integrity sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w== + dependencies: + "@babel/compat-data" "^7.21.5" + "@babel/helper-validator-option" "^7.21.0" + browserslist "^4.21.3" + lru-cache "^5.1.1" + semver "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.18.6": + version "7.21.8" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.8.tgz#205b26330258625ef8869672ebca1e0dee5a0f02" + integrity sha512-+THiN8MqiH2AczyuZrnrKL6cAxFRRQDKW9h1YkBvbgKmAm6mwiacig1qT73DHIWMGo40GRnsEfN3LA+E6NtmSw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.21.5" + "@babel/helper-function-name" "^7.21.0" + "@babel/helper-member-expression-to-functions" "^7.21.5" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.21.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" + "@babel/helper-split-export-declaration" "^7.18.6" + semver "^6.3.0" + "@babel/helper-environment-visitor@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" @@ -246,6 +360,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz#8a6d2dedb53f6bf248e31b4baf38739ee4a637bd" integrity sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ== +"@babel/helper-environment-visitor@^7.18.9", "@babel/helper-environment-visitor@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz#c769afefd41d171836f7cb63e295bedf689d48ba" + integrity sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ== + "@babel/helper-function-name@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz#b7dd0797d00bbfee4f07e9c4ea5b0e30c8bb1481" @@ -263,6 +382,14 @@ "@babel/template" "^7.16.7" "@babel/types" "^7.17.0" +"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4" + integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg== + dependencies: + "@babel/template" "^7.20.7" + "@babel/types" "^7.21.0" + "@babel/helper-get-function-arity@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz#0088c7486b29a9cb5d948b1a1de46db66e089cfa" @@ -284,6 +411,13 @@ dependencies: "@babel/types" "^7.16.7" +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== + dependencies: + "@babel/types" "^7.18.6" + "@babel/helper-member-expression-to-functions@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz#29287040efd197c77636ef75188e81da8bccd5a4" @@ -291,6 +425,13 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-member-expression-to-functions@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.5.tgz#3b1a009af932e586af77c1030fba9ee0bde396c0" + integrity sha512-nIcGfgwpH2u4n9GG1HpStW5Ogx7x7ekiFHbjjFRKXbn5zUvqO9ZgotCO4x1aNbKn/x/xOUaXEhyNHCwtFCpxWg== + dependencies: + "@babel/types" "^7.21.5" + "@babel/helper-module-imports@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz#90538e60b672ecf1b448f5f4f5433d37e79a3ec3" @@ -305,6 +446,13 @@ dependencies: "@babel/types" "^7.16.7" +"@babel/helper-module-imports@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz#ac88b2f76093637489e718a90cec6cf8a9b029af" + integrity sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg== + dependencies: + "@babel/types" "^7.21.4" + "@babel/helper-module-transforms@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz#1c82a8dd4cb34577502ebd2909699b194c3e9bb5" @@ -333,6 +481,20 @@ "@babel/traverse" "^7.18.0" "@babel/types" "^7.18.0" +"@babel/helper-module-transforms@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.5.tgz#d937c82e9af68d31ab49039136a222b17ac0b420" + integrity sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw== + dependencies: + "@babel/helper-environment-visitor" "^7.21.5" + "@babel/helper-module-imports" "^7.21.4" + "@babel/helper-simple-access" "^7.21.5" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.5" + "@babel/types" "^7.21.5" + "@babel/helper-optimise-call-expression@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz#cecdb145d70c54096b1564f8e9f10cd7d193b338" @@ -340,11 +502,23 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-optimise-call-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== + dependencies: + "@babel/types" "^7.18.6" + "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== +"@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz#345f2377d05a720a4e5ecfa39cbf4474a4daed56" + integrity sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg== + "@babel/helper-replace-supers@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz#73055e8d3cf9bcba8ddb55cad93fedc860f68f17" @@ -355,6 +529,18 @@ "@babel/traverse" "^7.16.0" "@babel/types" "^7.16.0" +"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.20.7", "@babel/helper-replace-supers@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.21.5.tgz#a6ad005ba1c7d9bc2973dfde05a1bba7065dde3c" + integrity sha512-/y7vBgsr9Idu4M6MprbOVUfH3vs7tsIfnVWv/Ml2xgwvyH6LTngdfbf5AdsKwkJy4zgy1X/kuNrEKvhhK28Yrg== + dependencies: + "@babel/helper-environment-visitor" "^7.21.5" + "@babel/helper-member-expression-to-functions" "^7.21.5" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.5" + "@babel/types" "^7.21.5" + "@babel/helper-simple-access@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz#21d6a27620e383e37534cf6c10bba019a6f90517" @@ -369,6 +555,20 @@ dependencies: "@babel/types" "^7.17.0" +"@babel/helper-simple-access@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz#d697a7971a5c39eac32c7e63c0921c06c8a249ee" + integrity sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg== + dependencies: + "@babel/types" "^7.21.5" + +"@babel/helper-skip-transparent-expression-wrappers@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" + integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== + dependencies: + "@babel/types" "^7.20.0" + "@babel/helper-split-export-declaration@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz#29672f43663e936df370aaeb22beddb3baec7438" @@ -383,6 +583,18 @@ dependencies: "@babel/types" "^7.16.7" +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-string-parser@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz#2b3eea65443c6bdc31c22d037c65f6d323b6b2bd" + integrity sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w== + "@babel/helper-validator-identifier@^7.15.7": version "7.15.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" @@ -393,6 +605,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== +"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + "@babel/helper-validator-option@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" @@ -403,6 +620,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== +"@babel/helper-validator-option@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz#8224c7e13ace4bafdc4004da2cf064ef42673180" + integrity sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ== + "@babel/helpers@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.0.tgz#875519c979c232f41adfbd43a3b0398c2e388183" @@ -421,6 +643,15 @@ "@babel/traverse" "^7.18.2" "@babel/types" "^7.18.2" +"@babel/helpers@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.21.5.tgz#5bac66e084d7a4d2d9696bdf0175a93f7fb63c08" + integrity sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA== + dependencies: + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.21.5" + "@babel/types" "^7.21.5" + "@babel/highlight@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" @@ -439,11 +670,25 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.0": version "7.16.2" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.2.tgz#3723cd5c8d8773eef96ce57ea1d9b7faaccd12ac" integrity sha512-RUVpT0G2h6rOZwqLDTrKk7ksNv7YpAilTnYe1/Q+eDjxEceRMKVWbCsX7t8h6C1qCFi/1Y8WZjcEPBAFG27GPw== +"@babel/parser@^7.14.0", "@babel/parser@^7.16.8", "@babel/parser@^7.20.7", "@babel/parser@^7.21.5", "@babel/parser@^7.21.8": + version "7.21.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.8.tgz#642af7d0333eab9c0ad70b14ac5e76dbde7bfdf8" + integrity sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA== + "@babel/parser@^7.16.7": version "7.17.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.7.tgz#fc19b645a5456c8d6fdb6cecd3c66c0173902800" @@ -454,6 +699,25 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.4.tgz#6774231779dd700e0af29f6ad8d479582d7ce5ef" integrity sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow== +"@babel/plugin-proposal-class-properties@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-object-rest-spread@^7.0.0": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a" + integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg== + dependencies: + "@babel/compat-data" "^7.20.5" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.20.7" + "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" @@ -468,13 +732,27 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.8.3": +"@babel/plugin-syntax-class-properties@^7.0.0", "@babel/plugin-syntax-class-properties@^7.8.3": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" +"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.18.6": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.21.4.tgz#3e37fca4f06d93567c1cd9b75156422e90a67107" + integrity sha512-l9xd3N+XG4fZRxEP3vXdK6RW7vN1Uf5dxzRC/09wV86wqZ/YYQooBIGNsiRdfNR3/q2/5pPzV4B54J/9ctX5jw== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-syntax-import-assertions@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz#bb50e0d4bea0957235390641209394e87bdb9cc4" + integrity sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" @@ -489,6 +767,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz#f264ed7bf40ffc9ec239edabc17a50c4f5b6fea2" + integrity sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" @@ -510,7 +795,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-object-rest-spread@^7.8.3": +"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== @@ -545,6 +830,173 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-arrow-functions@^7.0.0": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.21.5.tgz#9bb42a53de447936a57ba256fbf537fc312b6929" + integrity sha512-wb1mhwGOCaXHDTcsRYMKF9e5bbMgqwxtqa2Y1ifH96dXJPwbuLX9qHy3clhrxVqgMz7nyNXs8VkxdH8UBcjKqA== + dependencies: + "@babel/helper-plugin-utils" "^7.21.5" + +"@babel/plugin-transform-block-scoped-functions@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" + integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-block-scoping@^7.0.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz#e737b91037e5186ee16b76e7ae093358a5634f02" + integrity sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-classes@^7.0.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz#f469d0b07a4c5a7dbb21afad9e27e57b47031665" + integrity sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.21.0" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-replace-supers" "^7.20.7" + "@babel/helper-split-export-declaration" "^7.18.6" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.0.0": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.21.5.tgz#3a2d8bb771cd2ef1cd736435f6552fe502e11b44" + integrity sha512-TR653Ki3pAwxBxUe8srfF3e4Pe3FTA46uaNHYyQwIoM4oWKSoOZiDNyHJ0oIoDIUPSRQbQG7jzgVBX3FPVne1Q== + dependencies: + "@babel/helper-plugin-utils" "^7.21.5" + "@babel/template" "^7.20.7" + +"@babel/plugin-transform-destructuring@^7.0.0": + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz#73b46d0fd11cd6ef57dea8a381b1215f4959d401" + integrity sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-flow-strip-types@^7.0.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.21.0.tgz#6aeca0adcb81dc627c8986e770bfaa4d9812aff5" + integrity sha512-FlFA2Mj87a6sDkW4gfGrQQqwY/dLlBAyJa2dJEZ+FHXUVHBflO2wyKvg+OOEzXfrKYIa4HWl0mgmbCzt0cMb7w== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-flow" "^7.18.6" + +"@babel/plugin-transform-for-of@^7.0.0": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.5.tgz#e890032b535f5a2e237a18535f56a9fdaa7b83fc" + integrity sha512-nYWpjKW/7j/I/mZkGVgHJXh4bA1sfdFnJoOXwJuj4m3Q2EraO/8ZyrkCau9P5tbHQk01RMSt6KYLCsW7730SXQ== + dependencies: + "@babel/helper-plugin-utils" "^7.21.5" + +"@babel/plugin-transform-function-name@^7.0.0": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" + integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== + dependencies: + "@babel/helper-compilation-targets" "^7.18.9" + "@babel/helper-function-name" "^7.18.9" + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-literals@^7.0.0": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" + integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-member-expression-literals@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" + integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-modules-commonjs@^7.0.0": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.5.tgz#d69fb947eed51af91de82e4708f676864e5e47bc" + integrity sha512-OVryBEgKUbtqMoB7eG2rs6UFexJi6Zj6FDXx+esBLPTCxCNxAY9o+8Di7IsUGJ+AVhp5ncK0fxWUBd0/1gPhrQ== + dependencies: + "@babel/helper-module-transforms" "^7.21.5" + "@babel/helper-plugin-utils" "^7.21.5" + "@babel/helper-simple-access" "^7.21.5" + +"@babel/plugin-transform-object-super@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" + integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + +"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.20.7": + version "7.21.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz#18fc4e797cf6d6d972cb8c411dbe8a809fa157db" + integrity sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-transform-property-literals@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" + integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-display-name@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" + integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-jsx@^7.0.0": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.21.5.tgz#bd98f3b429688243e4fa131fe1cbb2ef31ce6f38" + integrity sha512-ELdlq61FpoEkHO6gFRpfj0kUgSwQTGoaEU8eMRoS8Dv3v6e7BjEAj5WMtIBRdHUeAioMhKP5HyxNzNnP+heKbA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-module-imports" "^7.21.4" + "@babel/helper-plugin-utils" "^7.21.5" + "@babel/plugin-syntax-jsx" "^7.21.4" + "@babel/types" "^7.21.5" + +"@babel/plugin-transform-shorthand-properties@^7.0.0": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" + integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-spread@^7.0.0": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz#c2d83e0b99d3bf83e07b11995ee24bf7ca09401e" + integrity sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" + +"@babel/plugin-transform-template-literals@^7.0.0": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" + integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/runtime@^7.0.0": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.5.tgz#8492dddda9644ae3bda3b45eabe87382caee7200" + integrity sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q== + dependencies: + regenerator-runtime "^0.13.11" + "@babel/template@^7.16.0", "@babel/template@^7.3.3": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.0.tgz#d16a35ebf4cd74e202083356fab21dd89363ddd6" @@ -563,6 +1015,31 @@ "@babel/parser" "^7.16.7" "@babel/types" "^7.16.7" +"@babel/template@^7.18.10", "@babel/template@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" + integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + +"@babel/traverse@^7.14.0", "@babel/traverse@^7.16.8", "@babel/traverse@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.5.tgz#ad22361d352a5154b498299d523cf72998a4b133" + integrity sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw== + dependencies: + "@babel/code-frame" "^7.21.4" + "@babel/generator" "^7.21.5" + "@babel/helper-environment-visitor" "^7.21.5" + "@babel/helper-function-name" "^7.21.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.21.5" + "@babel/types" "^7.21.5" + debug "^4.1.0" + globals "^11.1.0" + "@babel/traverse@^7.16.0", "@babel/traverse@^7.7.2": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.0.tgz#965df6c6bfc0a958c1e739284d3c9fa4a6e3c45b" @@ -610,6 +1087,15 @@ "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" +"@babel/types@^7.16.8", "@babel/types@^7.18.13", "@babel/types@^7.18.6", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.4", "@babel/types@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.5.tgz#18dfbd47c39d3904d5db3d3dc2cc80bedb60e5b6" + integrity sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q== + dependencies: + "@babel/helper-string-parser" "^7.21.5" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + "@babel/types@^7.18.0", "@babel/types@^7.18.2": version "7.18.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.4.tgz#27eae9b9fd18e9dccc3f9d6ad051336f307be354" @@ -664,6 +1150,295 @@ dependencies: eslint-config-airbnb-base "^15.0.0" +"@graphql-codegen/cli@3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/cli/-/cli-3.3.1.tgz#103e7a2263126fdde168a1ce623fc2bdc05352f0" + integrity sha512-4Es8Y9zFeT0Zx2qRL7L3qXDbbqvXK6aID+8v8lP6gaYD+uWx3Jd4Hsq5vxwVBR+6flm0BW/C85Qm0cvmT7O6LA== + dependencies: + "@babel/generator" "^7.18.13" + "@babel/template" "^7.18.10" + "@babel/types" "^7.18.13" + "@graphql-codegen/core" "^3.1.0" + "@graphql-codegen/plugin-helpers" "^4.2.0" + "@graphql-tools/apollo-engine-loader" "^7.3.6" + "@graphql-tools/code-file-loader" "^7.3.17" + "@graphql-tools/git-loader" "^7.2.13" + "@graphql-tools/github-loader" "^7.3.20" + "@graphql-tools/graphql-file-loader" "^7.5.0" + "@graphql-tools/json-file-loader" "^7.4.1" + "@graphql-tools/load" "^7.8.0" + "@graphql-tools/prisma-loader" "^7.2.49" + "@graphql-tools/url-loader" "^7.13.2" + "@graphql-tools/utils" "^9.0.0" + "@parcel/watcher" "^2.1.0" + "@whatwg-node/fetch" "^0.8.0" + chalk "^4.1.0" + cosmiconfig "^7.0.0" + debounce "^1.2.0" + detect-indent "^6.0.0" + graphql-config "^4.5.0" + inquirer "^8.0.0" + is-glob "^4.0.1" + jiti "^1.17.1" + json-to-pretty-yaml "^1.2.2" + listr2 "^4.0.5" + log-symbols "^4.0.0" + micromatch "^4.0.5" + shell-quote "^1.7.3" + string-env-interpolation "^1.0.1" + ts-log "^2.2.3" + tslib "^2.4.0" + yaml "^1.10.0" + yargs "^17.0.0" + +"@graphql-codegen/core@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@graphql-codegen/core/-/core-3.1.0.tgz#ad859d52d509a4eb2ebe5aabba6543a628fb181b" + integrity sha512-DH1/yaR7oJE6/B+c6ZF2Tbdh7LixF1K8L+8BoSubjNyQ8pNwR4a70mvc1sv6H7qgp6y1bPQ9tKE+aazRRshysw== + dependencies: + "@graphql-codegen/plugin-helpers" "^4.1.0" + "@graphql-tools/schema" "^9.0.0" + "@graphql-tools/utils" "^9.1.1" + tslib "~2.5.0" + +"@graphql-codegen/introspection@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/introspection/-/introspection-3.0.1.tgz#403c9bb12abf998a3bd37a519eb0fd01b537d64d" + integrity sha512-D6vJQTEL/np4EmeUHm5spLK59cr+AMXEoLRoTI+dagFzlHYDTfXZH6F7uhKaakxcj0SAQhIWKvGMggotUdEtyg== + dependencies: + "@graphql-codegen/plugin-helpers" "^4.1.0" + "@graphql-codegen/visitor-plugin-common" "^3.0.1" + tslib "~2.5.0" + +"@graphql-codegen/plugin-helpers@^4.1.0", "@graphql-codegen/plugin-helpers@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@graphql-codegen/plugin-helpers/-/plugin-helpers-4.2.0.tgz#8324914d0f99162a223cfa01796cdd6be972d2ae" + integrity sha512-THFTCfg+46PXlXobYJ/OoCX6pzjI+9woQqCjdyKtgoI0tn3Xq2HUUCiidndxUpEYVrXb5pRiRXb7b/ZbMQqD0A== + dependencies: + "@graphql-tools/utils" "^9.0.0" + change-case-all "1.0.15" + common-tags "1.8.2" + import-from "4.0.0" + lodash "~4.17.0" + tslib "~2.5.0" + +"@graphql-codegen/schema-ast@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/schema-ast/-/schema-ast-3.0.1.tgz#37b458bb57b95715a9eb4259341c856dae2a461d" + integrity sha512-rTKTi4XiW4QFZnrEqetpiYEWVsOFNoiR/v3rY9mFSttXFbIwNXPme32EspTiGWmEEdHY8UuTDtZN3vEcs/31zw== + dependencies: + "@graphql-codegen/plugin-helpers" "^4.1.0" + "@graphql-tools/utils" "^9.0.0" + tslib "~2.5.0" + +"@graphql-codegen/typescript-operations@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-operations/-/typescript-operations-3.0.4.tgz#60163c07f0ef73655779ece450d02c1172c44027" + integrity sha512-6yE2OL2+WJ1vd5MwFEGXpaxsFGzjAGUytPVHDML3Bi3TwP1F3lnQlIko4untwvHW0JhZEGQ7Ck30H9HjcxpdKA== + dependencies: + "@graphql-codegen/plugin-helpers" "^4.2.0" + "@graphql-codegen/typescript" "^3.0.4" + "@graphql-codegen/visitor-plugin-common" "3.1.1" + auto-bind "~4.0.0" + tslib "~2.5.0" + +"@graphql-codegen/typescript@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript/-/typescript-3.0.4.tgz#e12dc106a2722ebc7d18556980ccf47fa9d0805f" + integrity sha512-x4O47447DZrWNtE/l5CU9QzzW4m1RbmCEdijlA3s2flG/y1Ckqdemob4CWfilSm5/tZ3w1junVDY616RDTSvZw== + dependencies: + "@graphql-codegen/plugin-helpers" "^4.2.0" + "@graphql-codegen/schema-ast" "^3.0.1" + "@graphql-codegen/visitor-plugin-common" "3.1.1" + auto-bind "~4.0.0" + tslib "~2.5.0" + +"@graphql-codegen/visitor-plugin-common@3.1.1", "@graphql-codegen/visitor-plugin-common@^3.0.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-3.1.1.tgz#50c2aa3c537a805ce68d2f115d0a9811b151428c" + integrity sha512-uAfp+zu/009R3HUAuTK2AamR1bxIltM6rrYYI6EXSmkM3rFtFsLTuJhjUDj98HcUCszJZrADppz8KKLGRUVlNg== + dependencies: + "@graphql-codegen/plugin-helpers" "^4.2.0" + "@graphql-tools/optimize" "^1.3.0" + "@graphql-tools/relay-operation-optimizer" "^6.5.0" + "@graphql-tools/utils" "^9.0.0" + auto-bind "~4.0.0" + change-case-all "1.0.15" + dependency-graph "^0.11.0" + graphql-tag "^2.11.0" + parse-filepath "^1.0.2" + tslib "~2.5.0" + +"@graphql-tools/apollo-engine-loader@^7.3.6": + version "7.3.26" + resolved "https://registry.yarnpkg.com/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-7.3.26.tgz#91e54460d5579933e42a2010b8688c3459c245d8" + integrity sha512-h1vfhdJFjnCYn9b5EY1Z91JTF0KB3hHVJNQIsiUV2mpQXZdeOXQoaWeYEKaiI5R6kwBw5PP9B0fv3jfUIG8LyQ== + dependencies: + "@ardatan/sync-fetch" "^0.0.1" + "@graphql-tools/utils" "^9.2.1" + "@whatwg-node/fetch" "^0.8.0" + tslib "^2.4.0" + +"@graphql-tools/batch-execute@^8.5.22": + version "8.5.22" + resolved "https://registry.yarnpkg.com/@graphql-tools/batch-execute/-/batch-execute-8.5.22.tgz#a742aa9d138fe794e786d8fb6429665dc7df5455" + integrity sha512-hcV1JaY6NJQFQEwCKrYhpfLK8frSXDbtNMoTur98u10Cmecy1zrqNKSqhEyGetpgHxaJRqszGzKeI3RuroDN6A== + dependencies: + "@graphql-tools/utils" "^9.2.1" + dataloader "^2.2.2" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/code-file-loader@^7.3.17": + version "7.3.23" + resolved "https://registry.yarnpkg.com/@graphql-tools/code-file-loader/-/code-file-loader-7.3.23.tgz#33793f9a1f8e74981f8ae6ec4ab7061f9713db15" + integrity sha512-8Wt1rTtyTEs0p47uzsPJ1vAtfAx0jmxPifiNdmo9EOCuUPyQGEbMaik/YkqZ7QUFIEYEQu+Vgfo8tElwOPtx5Q== + dependencies: + "@graphql-tools/graphql-tag-pluck" "7.5.2" + "@graphql-tools/utils" "^9.2.1" + globby "^11.0.3" + tslib "^2.4.0" + unixify "^1.0.0" + +"@graphql-tools/delegate@^9.0.31": + version "9.0.35" + resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-9.0.35.tgz#94683f4bcec63520b4a6c8b2abf2e2e9324ea4f1" + integrity sha512-jwPu8NJbzRRMqi4Vp/5QX1vIUeUPpWmlQpOkXQD2r1X45YsVceyUUBnktCrlJlDB4jPRVy7JQGwmYo3KFiOBMA== + dependencies: + "@graphql-tools/batch-execute" "^8.5.22" + "@graphql-tools/executor" "^0.0.20" + "@graphql-tools/schema" "^9.0.19" + "@graphql-tools/utils" "^9.2.1" + dataloader "^2.2.2" + tslib "^2.5.0" + value-or-promise "^1.0.12" + +"@graphql-tools/executor-graphql-ws@^0.0.14": + version "0.0.14" + resolved "https://registry.yarnpkg.com/@graphql-tools/executor-graphql-ws/-/executor-graphql-ws-0.0.14.tgz#e0f53fc4cfc8a06cc461b2bc1edb4bb9a8e837ed" + integrity sha512-P2nlkAsPZKLIXImFhj0YTtny5NQVGSsKnhi7PzXiaHSXc6KkzqbWZHKvikD4PObanqg+7IO58rKFpGXP7eeO+w== + dependencies: + "@graphql-tools/utils" "^9.2.1" + "@repeaterjs/repeater" "3.0.4" + "@types/ws" "^8.0.0" + graphql-ws "5.12.1" + isomorphic-ws "5.0.0" + tslib "^2.4.0" + ws "8.13.0" + +"@graphql-tools/executor-http@^0.1.7", "@graphql-tools/executor-http@^0.1.9": + version "0.1.9" + resolved "https://registry.yarnpkg.com/@graphql-tools/executor-http/-/executor-http-0.1.9.tgz#ddd74ef376b4a2ed59c622acbcca068890854a30" + integrity sha512-tNzMt5qc1ptlHKfpSv9wVBVKCZ7gks6Yb/JcYJluxZIT4qRV+TtOFjpptfBU63usgrGVOVcGjzWc/mt7KhmmpQ== + dependencies: + "@graphql-tools/utils" "^9.2.1" + "@repeaterjs/repeater" "^3.0.4" + "@whatwg-node/fetch" "^0.8.1" + dset "^3.1.2" + extract-files "^11.0.0" + meros "^1.2.1" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/executor-legacy-ws@^0.0.11": + version "0.0.11" + resolved "https://registry.yarnpkg.com/@graphql-tools/executor-legacy-ws/-/executor-legacy-ws-0.0.11.tgz#a1e12be8279e92a363a23d4105461a34cd9e389e" + integrity sha512-4ai+NnxlNfvIQ4c70hWFvOZlSUN8lt7yc+ZsrwtNFbFPH/EroIzFMapAxM9zwyv9bH38AdO3TQxZ5zNxgBdvUw== + dependencies: + "@graphql-tools/utils" "^9.2.1" + "@types/ws" "^8.0.0" + isomorphic-ws "5.0.0" + tslib "^2.4.0" + ws "8.13.0" + +"@graphql-tools/executor@^0.0.20": + version "0.0.20" + resolved "https://registry.yarnpkg.com/@graphql-tools/executor/-/executor-0.0.20.tgz#d51d159696e839522dd49d936636af251670e425" + integrity sha512-GdvNc4vszmfeGvUqlcaH1FjBoguvMYzxAfT6tDd4/LgwymepHhinqLNA5otqwVLW+JETcDaK7xGENzFomuE6TA== + dependencies: + "@graphql-tools/utils" "^9.2.1" + "@graphql-typed-document-node/core" "3.2.0" + "@repeaterjs/repeater" "^3.0.4" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/git-loader@^7.2.13": + version "7.2.22" + resolved "https://registry.yarnpkg.com/@graphql-tools/git-loader/-/git-loader-7.2.22.tgz#b937273adae69a992d5d1d2e43bc1df21b6654d3" + integrity sha512-9rpHggHiOeqA7/ZlKD3c5yXk5bPGw0zkIgKMerjCmFAQAZ6CEVfsa7nAzEWQxn6rpdaBft4/0A56rPMrsUwGBA== + dependencies: + "@graphql-tools/graphql-tag-pluck" "7.5.2" + "@graphql-tools/utils" "^9.2.1" + is-glob "4.0.3" + micromatch "^4.0.4" + tslib "^2.4.0" + unixify "^1.0.0" + +"@graphql-tools/github-loader@^7.3.20": + version "7.3.28" + resolved "https://registry.yarnpkg.com/@graphql-tools/github-loader/-/github-loader-7.3.28.tgz#a7166b136e8442bd8b3ab943ad3b66c84bcabfcf" + integrity sha512-OK92Lf9pmxPQvjUNv05b3tnVhw0JRfPqOf15jZjyQ8BfdEUrJoP32b4dRQQem/wyRL24KY4wOfArJNqzpsbwCA== + dependencies: + "@ardatan/sync-fetch" "^0.0.1" + "@graphql-tools/executor-http" "^0.1.9" + "@graphql-tools/graphql-tag-pluck" "^7.4.6" + "@graphql-tools/utils" "^9.2.1" + "@whatwg-node/fetch" "^0.8.0" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-tools/graphql-file-loader@^7.3.7", "@graphql-tools/graphql-file-loader@^7.5.0": + version "7.5.17" + resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-file-loader/-/graphql-file-loader-7.5.17.tgz#7c281617ea3ab4db4d42a2bdb49850f2b937f0f9" + integrity sha512-hVwwxPf41zOYgm4gdaZILCYnKB9Zap7Ys9OhY1hbwuAuC4MMNY9GpUjoTU3CQc3zUiPoYStyRtUGkHSJZ3HxBw== + dependencies: + "@graphql-tools/import" "6.7.18" + "@graphql-tools/utils" "^9.2.1" + globby "^11.0.3" + tslib "^2.4.0" + unixify "^1.0.0" + +"@graphql-tools/graphql-tag-pluck@7.5.2", "@graphql-tools/graphql-tag-pluck@^7.4.6": + version "7.5.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-7.5.2.tgz#502f1e066e19d832ebdeba5f571d7636dc27572d" + integrity sha512-RW+H8FqOOLQw0BPXaahYepVSRjuOHw+7IL8Opaa5G5uYGOBxoXR7DceyQ7BcpMgktAOOmpDNQ2WtcboChOJSRA== + dependencies: + "@babel/parser" "^7.16.8" + "@babel/plugin-syntax-import-assertions" "^7.20.0" + "@babel/traverse" "^7.16.8" + "@babel/types" "^7.16.8" + "@graphql-tools/utils" "^9.2.1" + tslib "^2.4.0" + +"@graphql-tools/import@6.7.18": + version "6.7.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/import/-/import-6.7.18.tgz#ad092d8a4546bb6ffc3e871e499eec7ac368680b" + integrity sha512-XQDdyZTp+FYmT7as3xRWH/x8dx0QZA2WZqfMF5EWb36a0PiH7WwlRQYIdyYXj8YCLpiWkeBXgBRHmMnwEYR8iQ== + dependencies: + "@graphql-tools/utils" "^9.2.1" + resolve-from "5.0.0" + tslib "^2.4.0" + +"@graphql-tools/json-file-loader@^7.3.7", "@graphql-tools/json-file-loader@^7.4.1": + version "7.4.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/json-file-loader/-/json-file-loader-7.4.18.tgz#d78ae40979bde51cfc59717757354afc9e35fba2" + integrity sha512-AJ1b6Y1wiVgkwsxT5dELXhIVUPs/u3VZ8/0/oOtpcoyO/vAeM5rOvvWegzicOOnQw8G45fgBRMkkRfeuwVt6+w== + dependencies: + "@graphql-tools/utils" "^9.2.1" + globby "^11.0.3" + tslib "^2.4.0" + unixify "^1.0.0" + +"@graphql-tools/load@^7.5.5", "@graphql-tools/load@^7.8.0": + version "7.8.14" + resolved "https://registry.yarnpkg.com/@graphql-tools/load/-/load-7.8.14.tgz#f2356f9a5f658a42e33934ae036e4b2cadf2d1e9" + integrity sha512-ASQvP+snHMYm+FhIaLxxFgVdRaM0vrN9wW2BKInQpktwWTXVyk+yP5nQUCEGmn0RTdlPKrffBaigxepkEAJPrg== + dependencies: + "@graphql-tools/schema" "^9.0.18" + "@graphql-tools/utils" "^9.2.1" + p-limit "3.1.0" + tslib "^2.4.0" + "@graphql-tools/merge@8.3.11": version "8.3.11" resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.3.11.tgz#f5eab764e8d7032c1b7e32d5dc6dea5b2f5bb21e" @@ -680,6 +1455,14 @@ "@graphql-tools/utils" "^8.5.1" tslib "~2.3.0" +"@graphql-tools/merge@^8.2.6", "@graphql-tools/merge@^8.4.1": + version "8.4.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.4.1.tgz#52879e5f73565f504ceea04fcd9ef90a6e733c62" + integrity sha512-hssnPpZ818mxgl5+GfyOOSnnflAxiaTn1A1AojZcIbh4J52sS1Q0gSuBR5VrnUDjuxiqoCotpXdAQl+K+U6KLQ== + dependencies: + "@graphql-tools/utils" "^9.2.1" + tslib "^2.4.0" + "@graphql-tools/mock@^8.1.2": version "8.4.2" resolved "https://registry.yarnpkg.com/@graphql-tools/mock/-/mock-8.4.2.tgz#301b8baf47588bf1cd87de4ad2130eb9f406781b" @@ -690,6 +1473,46 @@ fast-json-stable-stringify "^2.1.0" tslib "~2.3.0" +"@graphql-tools/optimize@^1.3.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/optimize/-/optimize-1.4.0.tgz#20d6a9efa185ef8fc4af4fd409963e0907c6e112" + integrity sha512-dJs/2XvZp+wgHH8T5J2TqptT9/6uVzIYvA6uFACha+ufvdMBedkfR4b4GbT8jAKLRARiqRTxy3dctnwkTM2tdw== + dependencies: + tslib "^2.4.0" + +"@graphql-tools/prisma-loader@^7.2.49": + version "7.2.71" + resolved "https://registry.yarnpkg.com/@graphql-tools/prisma-loader/-/prisma-loader-7.2.71.tgz#7540bfabcc9717c10c1ebdb359d265f721205199" + integrity sha512-FuIvhRrkduqPdj3QX0/anCxGViEETfoZ/1NvotfM6iVO1XxR75VXvP/iyKGbK6XvYRXwSstgj2DetlQnqdgXhA== + dependencies: + "@graphql-tools/url-loader" "^7.17.18" + "@graphql-tools/utils" "^9.2.1" + "@types/js-yaml" "^4.0.0" + "@types/json-stable-stringify" "^1.0.32" + "@whatwg-node/fetch" "^0.8.2" + chalk "^4.1.0" + debug "^4.3.1" + dotenv "^16.0.0" + graphql-request "^6.0.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + jose "^4.11.4" + js-yaml "^4.0.0" + json-stable-stringify "^1.0.1" + lodash "^4.17.20" + scuid "^1.1.0" + tslib "^2.4.0" + yaml-ast-parser "^0.0.43" + +"@graphql-tools/relay-operation-optimizer@^6.5.0": + version "6.5.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-6.5.18.tgz#a1b74a8e0a5d0c795b8a4d19629b654cf66aa5ab" + integrity sha512-mc5VPyTeV+LwiM+DNvoDQfPqwQYhPV/cl5jOBjTgSniyaq8/86aODfMkrE2OduhQ5E00hqrkuL2Fdrgk0w1QJg== + dependencies: + "@ardatan/relay-compiler" "12.0.0" + "@graphql-tools/utils" "^9.2.1" + tslib "^2.4.0" + "@graphql-tools/schema@^8.0.0", "@graphql-tools/schema@^8.3.1": version "8.3.1" resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-8.3.1.tgz#1ee9da494d2da457643b3c93502b94c3c4b68c74" @@ -700,6 +1523,16 @@ tslib "~2.3.0" value-or-promise "1.0.11" +"@graphql-tools/schema@^9.0.0", "@graphql-tools/schema@^9.0.18", "@graphql-tools/schema@^9.0.19": + version "9.0.19" + resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-9.0.19.tgz#c4ad373b5e1b8a0cf365163435b7d236ebdd06e7" + integrity sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w== + dependencies: + "@graphql-tools/merge" "^8.4.1" + "@graphql-tools/utils" "^9.2.1" + tslib "^2.4.0" + value-or-promise "^1.0.12" + "@graphql-tools/schema@^9.0.9": version "9.0.9" resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-9.0.9.tgz#aa24869a2231039dcd9b6b882a5c5cb186d1116e" @@ -710,6 +1543,25 @@ tslib "^2.4.0" value-or-promise "1.0.11" +"@graphql-tools/url-loader@^7.13.2", "@graphql-tools/url-loader@^7.17.18", "@graphql-tools/url-loader@^7.9.7": + version "7.17.18" + resolved "https://registry.yarnpkg.com/@graphql-tools/url-loader/-/url-loader-7.17.18.tgz#3e253594d23483e4c0dd3a4c3dd2ad5cd0141192" + integrity sha512-ear0CiyTj04jCVAxi7TvgbnGDIN2HgqzXzwsfcqiVg9cvjT40NcMlZ2P1lZDgqMkZ9oyLTV8Bw6j+SyG6A+xPw== + dependencies: + "@ardatan/sync-fetch" "^0.0.1" + "@graphql-tools/delegate" "^9.0.31" + "@graphql-tools/executor-graphql-ws" "^0.0.14" + "@graphql-tools/executor-http" "^0.1.7" + "@graphql-tools/executor-legacy-ws" "^0.0.11" + "@graphql-tools/utils" "^9.2.1" + "@graphql-tools/wrap" "^9.4.2" + "@types/ws" "^8.0.0" + "@whatwg-node/fetch" "^0.8.0" + isomorphic-ws "^5.0.0" + tslib "^2.4.0" + value-or-promise "^1.0.11" + ws "^8.12.0" + "@graphql-tools/utils@9.1.0": version "9.1.0" resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-9.1.0.tgz#c33893e0aa9cbd3760d94f1771477e722adb4e54" @@ -724,6 +1576,30 @@ dependencies: tslib "~2.3.0" +"@graphql-tools/utils@^9.0.0", "@graphql-tools/utils@^9.1.1", "@graphql-tools/utils@^9.2.1": + version "9.2.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-9.2.1.tgz#1b3df0ef166cfa3eae706e3518b17d5922721c57" + integrity sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A== + dependencies: + "@graphql-typed-document-node/core" "^3.1.1" + tslib "^2.4.0" + +"@graphql-tools/wrap@^9.4.2": + version "9.4.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/wrap/-/wrap-9.4.2.tgz#30835587c4c73be1780908a7cb077d8013aa2703" + integrity sha512-DFcd9r51lmcEKn0JW43CWkkI2D6T9XI1juW/Yo86i04v43O9w2/k4/nx2XTJv4Yv+iXwUw7Ok81PGltwGJSDSA== + dependencies: + "@graphql-tools/delegate" "^9.0.31" + "@graphql-tools/schema" "^9.0.18" + "@graphql-tools/utils" "^9.2.1" + tslib "^2.4.0" + value-or-promise "^1.0.12" + +"@graphql-typed-document-node/core@3.2.0", "@graphql-typed-document-node/core@^3.1.1", "@graphql-typed-document-node/core@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" + integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== + "@humanwhocodes/config-array@^0.11.8": version "0.11.8" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" @@ -985,6 +1861,20 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + "@jridgewell/resolve-uri@^3.0.3": version "3.0.5" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" @@ -995,6 +1885,16 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea" integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ== +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.11" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" @@ -1024,6 +1924,14 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/trace-mapping@^0.3.17": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + "@jridgewell/trace-mapping@^0.3.9": version "0.3.13" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea" @@ -1053,6 +1961,43 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@parcel/watcher@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.1.0.tgz#5f32969362db4893922c526a842d8af7a8538545" + integrity sha512-8s8yYjd19pDSsBpbkOHnT6Z2+UJSuLQx61pCFM0s5wSRvKCEMDjd/cHY3/GI1szHIWbpXpsJdg3V6ISGGx9xDw== + dependencies: + is-glob "^4.0.3" + micromatch "^4.0.5" + node-addon-api "^3.2.1" + node-gyp-build "^4.3.0" + +"@peculiar/asn1-schema@^2.3.6": + version "2.3.6" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.3.6.tgz#3dd3c2ade7f702a9a94dfb395c192f5fa5d6b922" + integrity sha512-izNRxPoaeJeg/AyH8hER6s+H7p4itk+03QCa4sbxI3lNdseQYCuxzgsuNK8bTXChtLTjpJz6NmXKA73qLa3rCA== + dependencies: + asn1js "^3.0.5" + pvtsutils "^1.3.2" + tslib "^2.4.0" + +"@peculiar/json-schema@^1.1.12": + version "1.1.12" + resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.12.tgz#fe61e85259e3b5ba5ad566cb62ca75b3d3cd5339" + integrity sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w== + dependencies: + tslib "^2.0.0" + +"@peculiar/webcrypto@^1.4.0": + version "1.4.3" + resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.4.3.tgz#078b3e8f598e847b78683dc3ba65feb5029b93a7" + integrity sha512-VtaY4spKTdN5LjJ04im/d/joXuvLbQdgy5Z4DXF4MFZhQ+MTrejbNMkfZBp1Bs3O5+bFqnJgyGdPuZQflvIa5A== + dependencies: + "@peculiar/asn1-schema" "^2.3.6" + "@peculiar/json-schema" "^1.1.12" + pvtsutils "^1.3.2" + tslib "^2.5.0" + webcrypto-core "^1.7.7" + "@pkgr/utils@^2.3.1": version "2.3.1" resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.3.1.tgz#0a9b06ffddee364d6642b3cd562ca76f55b34a03" @@ -1135,6 +2080,11 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= +"@repeaterjs/repeater@3.0.4", "@repeaterjs/repeater@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.4.tgz#a04d63f4d1bf5540a41b01a921c9a7fddc3bd1ca" + integrity sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA== + "@sinclair/typebox@^0.23.3": version "0.23.5" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.23.5.tgz#93f7b9f4e3285a7a9ade7557d9a8d36809cbc47d" @@ -1159,6 +2109,11 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + "@tsconfig/node10@^1.0.7": version "1.0.8" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" @@ -1351,11 +2306,21 @@ expect "^28.0.0" pretty-format "^28.0.0" +"@types/js-yaml@^4.0.0": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.5.tgz#738dd390a6ecc5442f35e7f03fa1431353f7e138" + integrity sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA== + "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== +"@types/json-stable-stringify@^1.0.32": + version "1.0.34" + resolved "https://registry.yarnpkg.com/@types/json-stable-stringify/-/json-stable-stringify-1.0.34.tgz#c0fb25e4d957e0ee2e497c1f553d7f8bb668fd75" + integrity sha512-s2cfwagOQAS8o06TcwKfr9Wx11dNGbH2E9vJz1cqV+a/LOyhWNLUNd6JSRYNzvB4d29UuJX2M0Dj9vE1T8fRXw== + "@types/json-templates@3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/json-templates/-/json-templates-3.0.0.tgz#0b5b59e141a244ac9a9946bc7ff1ccf52715bec9" @@ -1435,6 +2400,11 @@ resolved "https://registry.yarnpkg.com/@types/object-path/-/object-path-0.11.1.tgz#eea5b357518597fc9c0a067ea3147f599fc1514f" integrity sha512-219LSCO9HPcoXcRTC6DbCs0FRhZgBnEMzf16RRqkT40WbkKx3mOeQuz3e2XqbfhOz/AHfbru0kzB1n1RCAsIIg== +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + "@types/pino@7.0.4": version "7.0.4" resolved "https://registry.yarnpkg.com/@types/pino/-/pino-7.0.4.tgz#5aec417c12e42025f088bfca7a542640b3f26db2" @@ -1502,6 +2472,13 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.0.tgz#53ef263e5239728b56096b0a869595135b7952d2" integrity sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q== +"@types/ws@^8.0.0": + version "8.5.4" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5" + integrity sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg== + dependencies: + "@types/node" "*" + "@types/ws@^8.5.3": version "8.5.3" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" @@ -1610,6 +2587,33 @@ resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.29.2.tgz#29a35d21b03267a538b536168af766f4270ae8f4" integrity sha512-eUxibZD92k+rY0oZJFZooGqdVpGkDrrHlUhj9UAWrtoyXCGmNOWC1Kcr2KPrZoHRSlWwHOcRnkn2nGT+aHY2KA== +"@whatwg-node/events@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@whatwg-node/events/-/events-0.0.3.tgz#13a65dd4f5893f55280f766e29ae48074927acad" + integrity sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA== + +"@whatwg-node/fetch@^0.8.0", "@whatwg-node/fetch@^0.8.1", "@whatwg-node/fetch@^0.8.2": + version "0.8.8" + resolved "https://registry.yarnpkg.com/@whatwg-node/fetch/-/fetch-0.8.8.tgz#48c6ad0c6b7951a73e812f09dd22d75e9fa18cae" + integrity sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg== + dependencies: + "@peculiar/webcrypto" "^1.4.0" + "@whatwg-node/node-fetch" "^0.3.6" + busboy "^1.6.0" + urlpattern-polyfill "^8.0.0" + web-streams-polyfill "^3.2.1" + +"@whatwg-node/node-fetch@^0.3.6": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@whatwg-node/node-fetch/-/node-fetch-0.3.6.tgz#e28816955f359916e2d830b68a64493124faa6d0" + integrity sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA== + dependencies: + "@whatwg-node/events" "^0.0.3" + busboy "^1.6.0" + fast-querystring "^1.1.1" + fast-url-parser "^1.1.3" + tslib "^2.3.1" + abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" @@ -1653,6 +2657,21 @@ acorn@^8.8.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1663,7 +2682,7 @@ ajv@^6.10.0, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-escapes@^4.2.1: +ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -1908,6 +2927,11 @@ array.prototype.flat@^1.2.5: define-properties "^1.1.3" es-abstract "^1.19.0" +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + asn1@^0.2.4: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" @@ -1915,6 +2939,20 @@ asn1@^0.2.4: dependencies: safer-buffer "~2.1.0" +asn1js@^3.0.1, asn1js@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.5.tgz#5ea36820443dbefb51cc7f88a2ebb5b462114f38" + integrity sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ== + dependencies: + pvtsutils "^1.3.2" + pvutils "^1.1.3" + tslib "^2.4.0" + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + async-retry@^1.2.1: version "1.3.3" resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" @@ -1932,6 +2970,11 @@ atomic-sleep@^1.0.0: resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== +auto-bind@~4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb" + integrity sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ== + babel-jest@^28.1.3: version "28.1.3" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-28.1.3.tgz#c1187258197c099072156a0a121c11ee1e3917d5" @@ -1966,6 +3009,11 @@ babel-plugin-jest-hoist@^28.1.3: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" +babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: + version "7.0.0-beta.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" + integrity sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ== + babel-preset-current-node-syntax@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" @@ -1984,6 +3032,39 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" +babel-preset-fbjs@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz#38a14e5a7a3b285a3f3a86552d650dca5cf6111c" + integrity sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow== + dependencies: + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/plugin-syntax-class-properties" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-block-scoped-functions" "^7.0.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-for-of" "^7.0.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-member-expression-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-object-super" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-property-literals" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-template-literals" "^7.0.0" + babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" + babel-preset-jest@^28.1.3: version "28.1.3" resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-28.1.3.tgz#5dfc20b99abed5db994406c2b9ab94c73aaa419d" @@ -1997,6 +3078,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + base64url@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" @@ -2014,6 +3100,15 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + body-parser@1.19.0, body-parser@^1.19.0: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -2063,7 +3158,7 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.1, braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -2092,6 +3187,16 @@ browserslist@^4.20.2: node-releases "^2.0.5" picocolors "^1.0.0" +browserslist@^4.21.3: + version "4.21.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7" + integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w== + dependencies: + caniuse-lite "^1.0.30001449" + electron-to-chromium "^1.4.284" + node-releases "^2.0.8" + update-browserslist-db "^1.0.10" + bs-logger@0.x: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" @@ -2111,6 +3216,14 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + buildcheck@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/buildcheck/-/buildcheck-0.0.3.tgz#70451897a95d80f7807e68fc412eb2e7e35ff4d5" @@ -2146,7 +3259,15 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase@^5.3.1: +camel-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== + dependencies: + pascal-case "^3.1.2" + tslib "^2.0.3" + +camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== @@ -2166,6 +3287,20 @@ caniuse-lite@^1.0.30001349: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001352.tgz#cc6f5da3f983979ad1e2cdbae0505dccaa7c6a12" integrity sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA== +caniuse-lite@^1.0.30001449: + version "1.0.30001482" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001482.tgz#8b3fad73dc35b2674a5c96df2d4f9f1c561435de" + integrity sha512-F1ZInsg53cegyjroxLNW9DmrEQ1SuGRTO1QlpA0o2/6OpQ0gFeDRoq1yFmnr8Sakn9qwwt9DmbxHB6w167OSuQ== + +capital-case@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.4.tgz#9d130292353c9249f6b00fa5852bee38a717e669" + integrity sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case-first "^2.0.2" + chalk@^2.0.0, chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -2175,7 +3310,7 @@ chalk@^2.0.0, chalk@^2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2183,11 +3318,50 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +change-case-all@1.0.15: + version "1.0.15" + resolved "https://registry.yarnpkg.com/change-case-all/-/change-case-all-1.0.15.tgz#de29393167fc101d646cd76b0ef23e27d09756ad" + integrity sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ== + dependencies: + change-case "^4.1.2" + is-lower-case "^2.0.2" + is-upper-case "^2.0.2" + lower-case "^2.0.2" + lower-case-first "^2.0.2" + sponge-case "^1.0.1" + swap-case "^2.0.2" + title-case "^3.0.3" + upper-case "^2.0.2" + upper-case-first "^2.0.2" + +change-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" + integrity sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A== + dependencies: + camel-case "^4.1.2" + capital-case "^1.0.4" + constant-case "^3.0.4" + dot-case "^3.0.4" + header-case "^2.0.4" + no-case "^3.0.4" + param-case "^3.0.4" + pascal-case "^3.1.2" + path-case "^3.0.4" + sentence-case "^3.0.4" + snake-case "^3.0.4" + tslib "^2.0.3" + char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + chokidar@^3.5.1: version "3.5.2" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" @@ -2213,6 +3387,45 @@ cjs-module-lexer@^1.0.0: resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.5.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.0.tgz#5881d0ad96381e117bbe07ad91f2008fe6ffd8db" + integrity sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g== + +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -2222,6 +3435,20 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -2256,6 +3483,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colorette@^2.0.16: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + colorette@^2.0.7: version "2.0.16" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" @@ -2273,6 +3505,11 @@ commander@^2.20.3: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +common-tags@1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" + integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2283,6 +3520,15 @@ confusing-browser-globals@^1.0.10: resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz#30d1e7f3d1b882b25ec4933d1d1adac353d20a59" integrity sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA== +constant-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-3.0.4.tgz#3b84a9aeaf4cf31ec45e6bf5de91bdfb0589faf1" + integrity sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case "^2.0.2" + content-disposition@0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -2332,6 +3578,27 @@ cors@^2.8.5: object-assign "^4" vary "^1" +cosmiconfig@8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.0.0.tgz#e9feae014eab580f858f8a0288f38997a7bebe97" + integrity sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ== + dependencies: + import-fresh "^3.2.1" + js-yaml "^4.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + +cosmiconfig@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + cpu-features@~0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.4.tgz#0023475bb4f4c525869c162e4108099e35bf19d8" @@ -2389,11 +3656,21 @@ csv-parse@5.3.5: resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-5.3.5.tgz#9924bbba9f7056122f06b7af18edc1a7f022ce99" integrity sha512-8O5KTIRtwmtD3+EVfW6BCgbwZqJbhTYsQZry12F1TP5RUp0sD9tp1UnCWic3n0mLOhzeocYaCZNYxOGSg3dmmQ== +dataloader@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.2.2.tgz#216dc509b5abe39d43a9b9d97e6e5e473dfbe3e0" + integrity sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g== + dateformat@^4.6.3: version "4.6.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== +debounce@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" + integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== + debug@2.6.9, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -2401,6 +3678,13 @@ debug@2.6.9, debug@^2.6.9: dependencies: ms "2.0.0" +debug@4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -2415,12 +3699,10 @@ debug@^4.1.0, debug@^4.1.1: dependencies: ms "2.1.2" -debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== dedent@^0.7.0: version "0.7.0" @@ -2442,6 +3724,13 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" @@ -2469,6 +3758,11 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= +dependency-graph@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27" + integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg== + destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" @@ -2479,6 +3773,11 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +detect-indent@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" + integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -2520,11 +3819,24 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dotenv@16.0.3: +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +dotenv@16.0.3, dotenv@^16.0.0: version "16.0.3" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== +dset@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.2.tgz#89c436ca6450398396dc6538ea00abc0c54cd45a" + integrity sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q== + duplexify@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0" @@ -2557,6 +3869,11 @@ electron-to-chromium@^1.4.147: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.150.tgz#89f0e12505462d5df7e56c5b91aff7e1dfdd33ec" integrity sha512-MP3oBer0X7ZeS9GJ0H6lmkn561UxiwOIY9TTkdxVY7lI9G6GVCKfgJaHaDcakwdKxBXA4T3ybeswH/WBIN/KTA== +electron-to-chromium@^1.4.284: + version "1.4.380" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.380.tgz#195dc59d930c6b74efbee6f0e6a267ce4af5ed91" + integrity sha512-XKGdI4pWM78eLH2cbXJHiBnWUwFSzZM7XujsB6stDiGu9AeSqziedP6amNLpJzE3i0rLTcfAwdCTs5ecP5yeSg== + emittery@^0.10.2: version "0.10.2" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933" @@ -2953,16 +4270,30 @@ express@^4.17.1: utils-merge "1.0.1" vary "~1.1.2" -extract-files@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" - integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +extract-files@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-11.0.0.tgz#b72d428712f787eef1f5193aff8ab5351ca8469a" + integrity sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ== fast-copy@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.1.tgz#9e89ef498b8c04c1cd76b33b8e14271658a732aa" integrity sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA== +fast-decode-uri-component@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" + integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -2989,6 +4320,13 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-querystring@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/fast-querystring/-/fast-querystring-1.1.1.tgz#f4c56ef56b1a954880cfd8c01b83f9e1a3d3fda2" + integrity sha512-qR2r+e3HvhEFmpdHMv//U8FnFlnYjaC6QKDuaXALDkw2kvHO8WDjxH+f/rHGR4Me4pnk8p9JAkRNTjYHAKRn2Q== + dependencies: + fast-decode-uri-component "^1.0.1" + fast-redact@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.0.2.tgz#c940ba7162dde3aeeefc522926ae8c5231412904" @@ -3004,6 +4342,13 @@ fast-safe-stringify@^2.1.1: resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== +fast-url-parser@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" + integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== + dependencies: + punycode "^1.3.2" + fastq@^1.6.0: version "1.13.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" @@ -3018,6 +4363,31 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fbjs-css-vars@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" + integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== + +fbjs@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6" + integrity sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ== + dependencies: + cross-fetch "^3.1.5" + fbjs-css-vars "^1.0.0" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.30" + +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -3148,7 +4518,7 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^2.0.5: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -3215,6 +4585,18 @@ glob@8.0.3, glob@^8.0.0: minimatch "^5.0.1" once "^1.3.0" +glob@^7.1.1: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.1.3, glob@^7.1.4: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" @@ -3244,7 +4626,7 @@ globalyzer@0.1.0: resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465" integrity sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q== -globby@^11.1.0: +globby@^11.0.3, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -3292,6 +4674,23 @@ grapheme-splitter@^1.0.4: resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== +graphql-config@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/graphql-config/-/graphql-config-4.5.0.tgz#257c2338950b8dce295a27f75c5f6c39f8f777b2" + integrity sha512-x6D0/cftpLUJ0Ch1e5sj1TZn6Wcxx4oMfmhaG9shM0DKajA9iR+j1z86GSTQ19fShbGvrSSvbIQsHku6aQ6BBw== + dependencies: + "@graphql-tools/graphql-file-loader" "^7.3.7" + "@graphql-tools/json-file-loader" "^7.3.7" + "@graphql-tools/load" "^7.5.5" + "@graphql-tools/merge" "^8.2.6" + "@graphql-tools/url-loader" "^7.9.7" + "@graphql-tools/utils" "^9.0.0" + cosmiconfig "8.0.0" + jiti "1.17.1" + minimatch "4.2.3" + string-env-interpolation "1.0.1" + tslib "^2.4.0" + graphql-fields@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/graphql-fields/-/graphql-fields-2.0.3.tgz#5e68dff7afbb202be4f4f40623e983b22c96ab8f" @@ -3302,14 +4701,13 @@ graphql-relay@0.10.0: resolved "https://registry.yarnpkg.com/graphql-relay/-/graphql-relay-0.10.0.tgz#3b661432edf1cb414cd4a132cf595350e524db2b" integrity sha512-44yBuw2/DLNEiMypbNZBt1yMDbBmyVPVesPywnteGGALiBmdyy1JP8jSg8ClLePg8ZZxk0O4BLhd1a6U/1jDOQ== -graphql-request@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-4.3.0.tgz#b934e08fcae764aa2cdc697d3c821f046cb5dbf2" - integrity sha512-2v6hQViJvSsifK606AliqiNiijb1uwWp6Re7o0RTyH+uRTv/u7Uqm2g4Fjq/LgZIzARB38RZEvVBFOQOVdlBow== +graphql-request@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-6.0.0.tgz#9c8b6a0c341f289e049936d03cc9205300faae1c" + integrity sha512-2BmHTuglonjZvmNVw6ZzCfFlW/qkIPds0f+Qdi/Lvjsl3whJg2uvHmSvHnLWhUTEw6zcxPYAHiZoPvSVKOZ7Jw== dependencies: + "@graphql-typed-document-node/core" "^3.2.0" cross-fetch "^3.1.5" - extract-files "^9.0.0" - form-data "^3.0.0" graphql-tag@^2.11.0: version "2.12.5" @@ -3331,6 +4729,11 @@ graphql-upload@15.0.2: http-errors "^2.0.0" object-path "^0.11.8" +graphql-ws@5.12.1: + version "5.12.1" + resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.12.1.tgz#c62d5ac54dbd409cc6520b0b39de374b3d59d0dd" + integrity sha512-umt4f5NnMK46ChM2coO36PTFhHouBrK9stWWBczERguwYrGnPNxJ9dimU6IyOBfOkC6Izhkg4H8+F51W/8CYDg== + graphql-ws@^5.11.2: version "5.11.2" resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.11.2.tgz#d5e0acae8b4d4a4cf7be410a24135cfcefd7ddc0" @@ -3341,7 +4744,7 @@ graphql-ws@^5.11.2: resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.5.0.tgz#41b5c1182eaac7f3d47164fb247f61e4dfb69c85" integrity sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA== -graphql@16.6.0: +graphql@^16.6.0: version "16.6.0" resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== @@ -3380,6 +4783,14 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +header-case@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/header-case/-/header-case-2.0.4.tgz#5a42e63b55177349cf405beb8d775acabb92c063" + integrity sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q== + dependencies: + capital-case "^1.0.4" + tslib "^2.0.3" + help-me@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/help-me/-/help-me-4.0.1.tgz#b618ca10ae1392508dfad5eca75fce03e25f7616" @@ -3431,6 +4842,23 @@ http-errors@~1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -3443,18 +4871,28 @@ i18n-iso-countries@7.5.0: dependencies: diacritics "1.3.0" -iconv-lite@0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== +immutable@~3.7.6: + version "3.7.6" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b" + integrity sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw== + import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -3463,6 +4901,11 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-from@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-4.0.0.tgz#2710b8d66817d232e16f4166e319248d3d5492e2" + integrity sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ== + import-local@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.3.tgz#4d51c2c495ca9393da259ec66b62e022920211e0" @@ -3476,6 +4919,11 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -3484,7 +4932,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3494,6 +4942,27 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= +inquirer@^8.0.0: + version "8.2.5" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.5.tgz#d8654a7542c35a9b9e069d27e2df4858784d54f8" + integrity sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ== + dependencies: + ansi-escapes "^4.2.1" + chalk "^4.1.1" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.21" + mute-stream "0.0.8" + ora "^5.4.1" + run-async "^2.4.0" + rxjs "^7.5.5" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + wrap-ansi "^7.0.0" + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -3503,6 +4972,13 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + io-ts@2.2.20: version "2.2.20" resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.20.tgz#be42b75f6668a2c44f706f72ee6e4c906777c7f5" @@ -3513,6 +4989,14 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +is-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -3593,13 +5077,25 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: +is-glob@4.0.3, is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + +is-lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-2.0.2.tgz#1c0884d3012c841556243483aa5d522f47396d2a" + integrity sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ== + dependencies: + tslib "^2.0.3" + is-negative-zero@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" @@ -3630,6 +5126,13 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== + dependencies: + is-unc-path "^1.0.0" + is-shared-array-buffer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" @@ -3654,6 +5157,25 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== + dependencies: + unc-path-regex "^0.1.2" + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-upper-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-2.0.2.tgz#f1105ced1fe4de906a5f39553e7d3803fd804649" + integrity sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ== + dependencies: + tslib "^2.0.3" + is-weakref@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.1.tgz#842dba4ec17fa9ac9850df2d6efbc1737274f2a2" @@ -3661,6 +5183,11 @@ is-weakref@^1.0.1: dependencies: call-bind "^1.0.0" +is-windows@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" @@ -3673,6 +5200,11 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= +isomorphic-ws@5.0.0, isomorphic-ws@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== + istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" @@ -4090,6 +5622,21 @@ jest@28.1.3: import-local "^3.0.2" jest-cli "^28.1.3" +jiti@1.17.1: + version "1.17.1" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.17.1.tgz#264daa43ee89a03e8be28c3d712ccc4eb9f1e8ed" + integrity sha512-NZIITw8uZQFuzQimqjUxIrIcEdxYDFIe/0xYfIlVXTkiBjjyBEvgasj5bb0/cHtPRD/NziPbT312sFrkI5ALpw== + +jiti@^1.17.1: + version "1.18.2" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.18.2.tgz#80c3ef3d486ebf2450d9335122b32d121f2a83cd" + integrity sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg== + +jose@^4.11.4: + version "4.14.4" + resolved "https://registry.yarnpkg.com/jose/-/jose-4.14.4.tgz#59e09204e2670c3164ee24cbfe7115c6f8bff9ca" + integrity sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g== + joycon@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" @@ -4100,7 +5647,7 @@ js-sdsl@^4.1.4: resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.3.0.tgz#aeefe32a451f7af88425b11fdb5f58c90ae1d711" integrity sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ== -js-tokens@^4.0.0: +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -4113,7 +5660,7 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: +js-yaml@^4.0.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -4145,6 +5692,13 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= +json-stable-stringify@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" + integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== + dependencies: + jsonify "^0.0.1" + json-templates@4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/json-templates/-/json-templates-4.2.0.tgz#34fdd6fedbe6955e934d86812a89d30d1df87415" @@ -4153,6 +5707,14 @@ json-templates@4.2.0: dedupe "^3.0.2" object-path "^0.11.8" +json-to-pretty-yaml@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz#f4cd0bd0a5e8fe1df25aaf5ba118b099fd992d5b" + integrity sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A== + dependencies: + remedial "^1.0.7" + remove-trailing-spaces "^1.0.6" + json5@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" @@ -4165,6 +5727,16 @@ json5@^2.1.2, json5@^2.2.1: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== +json5@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonify@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" + integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== + kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -4188,6 +5760,20 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +listr2@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-4.0.5.tgz#9dcc50221583e8b4c71c43f9c7dfd0ef546b75d5" + integrity sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA== + dependencies: + cli-truncate "^2.1.0" + colorette "^2.0.16" + log-update "^4.0.0" + p-map "^4.0.0" + rfdc "^1.3.0" + rxjs "^7.5.5" + through "^2.3.8" + wrap-ansi "^7.0.0" + load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" @@ -4235,11 +5821,29 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash@4.17.21: +lodash@4.17.21, lodash@^4.17.20, lodash@^4.17.21, lodash@~4.17.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-symbols@^4.0.0, log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +log-update@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== + dependencies: + ansi-escapes "^4.3.0" + cli-cursor "^3.1.0" + slice-ansi "^4.0.0" + wrap-ansi "^6.2.0" + loglevel@^1.6.8: version "1.7.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" @@ -4250,6 +5854,34 @@ long@^4.0.0: resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lower-case-first@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-2.0.2.tgz#64c2324a2250bf7c37c5901e76a5b5309301160b" + integrity sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg== + dependencies: + tslib "^2.0.3" + +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -4281,6 +5913,11 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" +map-cache@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -4306,6 +5943,11 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +meros@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/meros/-/meros-1.2.1.tgz#056f7a76e8571d0aaf3c7afcbe7eb6407ff7329e" + integrity sha512-R2f/jxYqCAGI19KhAvaxSOxALBMkaXWH2a7rOyqQw+ZmizX5bKkEYWLzdhC+U82ZVVPVp6MCXe3EkVligh+12g== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -4319,6 +5961,14 @@ micromatch@^4.0.4: braces "^3.0.1" picomatch "^2.2.3" +micromatch@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + mime-db@1.50.0: version "1.50.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" @@ -4353,7 +6003,14 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2: +minimatch@4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.3.tgz#b4dcece1d674dee104bb0fb833ebb85a78cbbca6" + integrity sha512-lIUdtK5hdofgCTu3aT0sOaHsYR37viUuIc0rwnnDXImbwFRcumyLMeZaM0t0I/fgxS6s6JMfu0rLD1Wz9pv1ng== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -4397,6 +6054,11 @@ ms@2.1.3, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + nan@^2.15.0, nan@^2.16.0: version "2.17.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" @@ -4435,11 +6097,24 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + node-abort-controller@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.0.1.tgz#f91fa50b1dee3f909afabb7e261b1e1d6b0cb74e" integrity sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw== +node-addon-api@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" + integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== + node-fetch@2.6.7, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -4447,13 +6122,18 @@ node-fetch@2.6.7, node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@2.6.9: +node-fetch@2.6.9, node-fetch@^2.6.1: version "2.6.9" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== dependencies: whatwg-url "^5.0.0" +node-gyp-build@^4.3.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -4469,6 +6149,11 @@ node-releases@^2.0.5: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666" integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q== +node-releases@^2.0.8: + version "2.0.10" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f" + integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w== + node-ssh@^13.0.0: version "13.0.0" resolved "https://registry.yarnpkg.com/node-ssh/-/node-ssh-13.0.0.tgz#5e24ea6ce9c73168544f26d680d8a867f07843ea" @@ -4491,6 +6176,13 @@ normalize-package-data@^2.3.2: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== + dependencies: + remove-trailing-separator "^1.0.1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -4518,7 +6210,12 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -object-assign@^4: +nullthrows@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" + integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== + +object-assign@^4, object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -4597,7 +6294,7 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.2: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -4625,6 +6322,33 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +p-limit@3.1.0, p-limit@^3.0.2, p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -4639,13 +6363,6 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -4667,6 +6384,13 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -4677,6 +6401,14 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +param-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" + integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -4684,6 +6416,15 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-filepath@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" + integrity sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q== + dependencies: + is-absolute "^1.0.0" + map-cache "^0.2.0" + path-root "^0.1.1" + parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -4692,7 +6433,7 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" -parse-json@^5.2.0: +parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== @@ -4707,6 +6448,22 @@ parseurl@^1.3.3, parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +path-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/path-case/-/path-case-3.0.4.tgz#9168645334eb942658375c56f80b4c0cb5f82c6f" + integrity sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -4737,6 +6494,18 @@ path-parse@^1.0.6, path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-root-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + integrity sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ== + +path-root@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + integrity sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg== + dependencies: + path-root-regex "^0.1.0" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -4764,6 +6533,11 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + pidtree@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a" @@ -4903,6 +6677,13 @@ process-warning@^2.0.0: resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.0.0.tgz#341dbeaac985b90a04ebcd844d50097c7737b2ee" integrity sha512-+MmoAXoUX+VTHAlwns0h+kFUWFs/3FZy+ZuchkgjyOu3oioLAo2LB5aCfKPh2+P9O18i3m43tUEv3YqttSy0Ww== +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== + dependencies: + asap "~2.0.3" + prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -4927,11 +6708,28 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" +punycode@^1.3.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +pvtsutils@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.2.tgz#9f8570d132cdd3c27ab7d51a2799239bf8d8d5de" + integrity sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ== + dependencies: + tslib "^2.4.0" + +pvutils@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3" + integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ== + qs@6.10.3: version "6.10.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" @@ -5002,6 +6800,15 @@ readable-stream@^3.1.1, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.1.0.tgz#280d0a29f559d3fb684a277254e02b6f61ae0631" @@ -5026,16 +6833,50 @@ real-require@^0.2.0: resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== +relay-runtime@12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/relay-runtime/-/relay-runtime-12.0.0.tgz#1e039282bdb5e0c1b9a7dc7f6b9a09d4f4ff8237" + integrity sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug== + dependencies: + "@babel/runtime" "^7.0.0" + fbjs "^3.0.0" + invariant "^2.2.4" + +remedial@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/remedial/-/remedial-1.0.8.tgz#a5e4fd52a0e4956adbaf62da63a5a46a78c578a0" + integrity sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg== + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== + +remove-trailing-spaces@^1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz#4354d22f3236374702f58ee373168f6d6887ada7" + integrity sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA== + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -5043,16 +6884,16 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" +resolve-from@5.0.0, resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - resolve.exports@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" @@ -5075,6 +6916,14 @@ resolve@^1.22.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + retry@0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" @@ -5085,6 +6934,11 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -5099,6 +6953,11 @@ rimraf@^2.6.1: dependencies: glob "^7.1.3" +run-async@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -5106,6 +6965,13 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rxjs@^7.5.5: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + safe-buffer@5.1.2, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -5138,6 +7004,11 @@ sb-scandir@^3.1.0: dependencies: sb-promise-queue "^2.1.0" +scuid@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/scuid/-/scuid-1.1.0.tgz#d3f9f920956e737a60f72d0e4ad280bf324d5dab" + integrity sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg== + secure-json-parse@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.4.0.tgz#5aaeaaef85c7a417f76271a4f5b0cc3315ddca85" @@ -5205,6 +7076,15 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" +sentence-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-3.0.4.tgz#3645a7b8c117c787fde8702056225bb62a45131f" + integrity sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case-first "^2.0.2" + serve-static@1.14.1: version "1.14.1" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" @@ -5225,6 +7105,16 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + setprototypeof@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" @@ -5277,6 +7167,11 @@ shell-quote@^1.6.1: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== +shell-quote@^1.7.3: + version "1.8.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -5286,15 +7181,20 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +signal-exit@^3.0.2, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + signal-exit@^3.0.3: version "3.0.5" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== -signal-exit@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signedsource@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/signedsource/-/signedsource-1.0.0.tgz#1ddace4981798f93bd833973803d80d52e93ad6a" + integrity sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww== sisteransi@^1.0.5: version "1.0.5" @@ -5311,6 +7211,32 @@ slash@^4.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +snake-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" + integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + sonic-boom@^2.2.1: version "2.7.0" resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.7.0.tgz#55c9390cc123ae4e42c044e822eb7e7246b01c9c" @@ -5382,6 +7308,13 @@ split2@^4.0.0: resolved "https://registry.yarnpkg.com/split2/-/split2-4.1.0.tgz#101907a24370f85bb782f08adaabe4e281ecf809" integrity sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ== +sponge-case@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sponge-case/-/sponge-case-1.0.1.tgz#260833b86453883d974f84854cdb63aecc5aef4c" + integrity sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA== + dependencies: + tslib "^2.0.3" + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -5425,6 +7358,11 @@ streamsearch@^1.1.0: resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== +string-env-interpolation@1.0.1, string-env-interpolation@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz#ad4397ae4ac53fe6c91d1402ad6f6a52862c7152" + integrity sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg== + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -5540,6 +7478,13 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +swap-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-2.0.2.tgz#671aedb3c9c137e2985ef51c51f9e98445bf70d9" + integrity sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw== + dependencies: + tslib "^2.0.3" + synckit@^0.8.4: version "0.8.5" resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.5.tgz#b7f4358f9bb559437f9f167eb6bc46b3c9818fa3" @@ -5589,6 +7534,11 @@ thread-stream@^2.0.0: dependencies: real-require "^0.2.0" +through@^2.3.6, through@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + tiny-glob@^0.2.9: version "0.2.9" resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2" @@ -5597,6 +7547,20 @@ tiny-glob@^0.2.9: globalyzer "0.1.0" globrex "^0.1.2" +title-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/title-case/-/title-case-3.0.3.tgz#bc689b46f02e411f1d1e1d081f7c3deca0489982" + integrity sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA== + dependencies: + tslib "^2.0.3" + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -5648,6 +7612,11 @@ ts-jest@28.0.8: semver "7.x" yargs-parser "^21.0.1" +ts-log@^2.2.3: + version "2.2.5" + resolved "https://registry.yarnpkg.com/ts-log/-/ts-log-2.2.5.tgz#aef3252f1143d11047e2cb6f7cfaac7408d96623" + integrity sha512-PGcnJoTBnVGy6yYNFxWVNkdcAuAMstvutN9MgDJIV6L0oG8fB+ZNNy1T+wJzah8RPGor1mZuPQkVfXNDpy9eHA== + ts-node-dev@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-2.0.0.tgz#bdd53e17ab3b5d822ef519928dc6b4a7e0f13065" @@ -5727,6 +7696,11 @@ tslib@^1.8.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.0.0, tslib@^2.3.1, tslib@^2.5.0, tslib@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" + integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== + tslib@^2.0.3, tslib@^2.1.0, tslib@~2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" @@ -5737,11 +7711,6 @@ tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== -tslib@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" - integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== - tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -5784,10 +7753,15 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typescript@4.7.4: - version "4.7.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" - integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== +typescript@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" + integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== + +ua-parser-js@^0.7.30: + version "0.7.35" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.35.tgz#8bda4827be4f0b1dda91699a29499575a1f1d307" + integrity sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g== unbox-primitive@^1.0.1: version "1.0.1" @@ -5799,11 +7773,45 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg== + +unixify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unixify/-/unixify-1.0.0.tgz#3a641c8c2ffbce4da683a5c70f03a462940c2090" + integrity sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg== + dependencies: + normalize-path "^2.1.1" + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= +update-browserslist-db@^1.0.10: + version "1.0.11" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" + integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +upper-case-first@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-2.0.2.tgz#992c3273f882abd19d1e02894cc147117f844324" + integrity sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg== + dependencies: + tslib "^2.0.3" + +upper-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-2.0.2.tgz#d89810823faab1df1549b7d97a76f8662bae6f7a" + integrity sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg== + dependencies: + tslib "^2.0.3" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -5816,6 +7824,11 @@ url-join@4.0.1: resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== +urlpattern-polyfill@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz#99f096e35eff8bf4b5a2aa7d58a1523d6ebc7ce5" + integrity sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ== + util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -5863,6 +7876,11 @@ value-or-promise@1.0.11: resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.11.tgz#3e90299af31dd014fe843fe309cefa7c1d94b140" integrity sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg== +value-or-promise@^1.0.11, value-or-promise@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.12.tgz#0e5abfeec70148c78460a849f6b003ea7986f15c" + integrity sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q== + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -5875,6 +7893,29 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + +web-streams-polyfill@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" + integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== + +webcrypto-core@^1.7.7: + version "1.7.7" + resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.7.7.tgz#06f24b3498463e570fed64d7cab149e5437b162c" + integrity sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g== + dependencies: + "@peculiar/asn1-schema" "^2.3.6" + "@peculiar/json-schema" "^1.1.12" + asn1js "^3.0.1" + pvtsutils "^1.3.2" + tslib "^2.4.0" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -5904,6 +7945,11 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-module@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -5923,6 +7969,15 @@ word-wrap@^1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -5945,6 +8000,11 @@ write-file-atomic@^4.0.1: imurmurhash "^0.1.4" signal-exit "^3.0.7" +ws@8.13.0, ws@^8.12.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + ws@^8.11.0: version "8.11.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" @@ -5963,26 +8023,84 @@ xtend@^4.0.0: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml-ast-parser@^0.0.43: + version "0.0.43" + resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb" + integrity sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A== + +yaml@^1.10.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^21.0.0: version "21.0.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35" integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg== -yargs-parser@^21.0.1: +yargs-parser@^21.0.1, yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== +yargs@^15.3.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + +yargs@^17.0.0: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + yargs@^17.3.1: version "17.5.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e" From abb7b03a2cf6993633592d7d842275b894eec7b6 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Wed, 10 May 2023 10:39:43 +0200 Subject: [PATCH 19/69] FD-527 custom connection from array (#288) * custom connectionFromArray helper function added * remove unused eslint comment --- .eslintignore | 4 +- src/helpers/base64.helpers.ts | 161 ++++++++++++++++++++++++++++++ src/helpers/connection.helpers.ts | 124 +++++++++++++++++++++++ src/schema/workflow.ts | 2 +- 4 files changed, 289 insertions(+), 2 deletions(-) create mode 100644 src/helpers/base64.helpers.ts create mode 100644 src/helpers/connection.helpers.ts diff --git a/.eslintignore b/.eslintignore index 65dfeaf5..964bd07c 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,4 +5,6 @@ prettier.config.js nexus-typegen.ts jest.config.js seed.ts -init.ts \ No newline at end of file +init.ts +src/helpers/base64.helpers.ts +src/helpers/connection.helpers.ts \ No newline at end of file diff --git a/src/helpers/base64.helpers.ts b/src/helpers/base64.helpers.ts new file mode 100644 index 00000000..88fb00ce --- /dev/null +++ b/src/helpers/base64.helpers.ts @@ -0,0 +1,161 @@ +// INFO: code shamelessly stolen from https://github.com/graphql/graphql-relay-js/blob/3796e0904fbfe0dd86e540d5b4df236330c8a5e7/src/utils/base64.ts +// used for custom connectionFromArray function + +export type Base64String = string; + +export function base64(input: string): Base64String { + const utf8Array = stringToUTF8Array(input); + let result = ''; + + const length = utf8Array.length; + const rest = length % 3; + for (let i = 0; i < length - rest; i += 3) { + const a = utf8Array[i]; + const b = utf8Array[i + 1]; + const c = utf8Array[i + 2]; + + result += first6Bits(a); + result += last2BitsAndFirst4Bits(a, b); + result += last4BitsAndFirst2Bits(b, c); + result += last6Bits(c); + } + + if (rest === 1) { + const a = utf8Array[length - 1]; + result += first6Bits(a) + last2BitsAndFirst4Bits(a, 0) + '=='; + } else if (rest === 2) { + const a = utf8Array[length - 2]; + const b = utf8Array[length - 1]; + result += first6Bits(a) + last2BitsAndFirst4Bits(a, b) + last4BitsAndFirst2Bits(b, 0) + '='; + } + + return result; +} + +function first6Bits(a: number): string { + return toBase64Char((a >> 2) & 63); +} + +function last2BitsAndFirst4Bits(a: number, b: number): string { + return toBase64Char(((a << 4) | (b >> 4)) & 63); +} + +function last4BitsAndFirst2Bits(b: number, c: number): string { + return toBase64Char(((b << 2) | (c >> 6)) & 63); +} + +function last6Bits(c: number): string { + return toBase64Char(c & 63); +} + +export function unbase64(input: Base64String): string { + const utf8Array = []; + + for (let i = 0; i < input.length; i += 4) { + const a = fromBase64Char(input[i]); + const b = fromBase64Char(input[i + 1]); + const c = fromBase64Char(input[i + 2]); + const d = fromBase64Char(input[i + 3]); + + if (a === -1 || b === -1 || c === -1 || d === -1) { + /* + * Previously we used Node's API for parsing Base64 and following code + * Buffer.from(i, 'utf8').toString('base64') + * That silently ignored incorrect input and returned empty string instead + * Let's keep this behaviour for a time being and hopefully fix it in the future. + */ + return ''; + } + + const bitmap24 = (a << 18) | (b << 12) | (c << 6) | d; + utf8Array.push((bitmap24 >> 16) & 255); + utf8Array.push((bitmap24 >> 8) & 255); + utf8Array.push(bitmap24 & 255); + } + + let paddingIndex = input.length - 1; + while (input[paddingIndex] === '=') { + --paddingIndex; + utf8Array.pop(); + } + + return utf8ArrayToString(utf8Array); +} + +const b64CharacterSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +function toBase64Char(bitMap6: number): string { + return b64CharacterSet.charAt(bitMap6); +} + +function fromBase64Char(base64Char: string | undefined): number { + if (base64Char === undefined) { + return -1; + } + return base64Char === '=' ? 0 : b64CharacterSet.indexOf(base64Char); +} + +function stringToUTF8Array(input: string): Array { + const result = []; + for (const utfChar of input) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const code = utfChar.codePointAt(0)!; + if (code < 0x80) { + result.push(code); + } else if (code < 0x800) { + result.push(0xc0 | (code >> 6)); + result.push(0x80 | (code & 0x3f)); + } else if (code < 0x10000) { + result.push(0xe0 | (code >> 12)); + result.push(0x80 | ((code >> 6) & 0x3f)); + result.push(0x80 | (code & 0x3f)); + } else { + result.push(0xf0 | (code >> 18)); + result.push(0x80 | ((code >> 12) & 0x3f)); + result.push(0x80 | ((code >> 6) & 0x3f)); + result.push(0x80 | (code & 0x3f)); + } + } + return result; +} + +function utf8ArrayToString(input: Array) { + let result = ''; + for (let i = 0; i < input.length; ) { + const a = input[i++]; + if ((a & 0x80) === 0) { + result += fromCodePoint(a); + continue; + } + + const b = input[i++]; + if ((a & 0xe0) === 0xc0) { + result += fromCodePoint(((a & 0x1f) << 6) | (b & 0x3f)); + continue; + } + + const c = input[i++]; + if ((a & 0xf0) === 0xe0) { + result += fromCodePoint(((a & 0x0f) << 12) | ((b & 0x3f) << 6) | (c & 0x3f)); + continue; + } + + const d = input[i++]; + result += fromCodePoint(((a & 0x07) << 18) | ((b & 0x3f) << 12) | ((c & 0x3f) << 6) | (d & 0x3f)); + } + + return result; +} + +function fromCodePoint(code: number): string { + if (code > 0x10ffff) { + /* + * Previously we used Node's API for parsing Base64 and following code + * Buffer.from(i, 'base64').toString('utf8') + * That silently ignored incorrect input and returned empty string instead + * Let's keep this behaviour for a time being and hopefully fix it in the future. + */ + return ''; + } + return String.fromCodePoint(code); +} diff --git a/src/helpers/connection.helpers.ts b/src/helpers/connection.helpers.ts new file mode 100644 index 00000000..3e009303 --- /dev/null +++ b/src/helpers/connection.helpers.ts @@ -0,0 +1,124 @@ +import { Connection, ConnectionArguments, ConnectionCursor } from 'graphql-relay'; +import { base64, unbase64 } from './base64.helpers'; + +// INFO: code below shamelessly stolen from https://github.com/graphql/graphql-relay-js/blob/3796e0904fbfe0dd86e540d5b4df236330c8a5e7/src/connection/arrayConnection.ts +// customization of connectionFromArray to get proper connection object (hasPreviousPage returns always false in lib) + +interface ArraySliceMetaInfo { + sliceStart: number; + arrayLength: number; +} + +/** + * A simple function that accepts an array and connection arguments, and returns + * a connection object for use in GraphQL. It uses array offsets as pagination, + * so pagination will only work if the array is static. + */ +export function connectionFromArray(data: ReadonlyArray, args: ConnectionArguments): Connection { + return connectionFromArraySlice(data, args, { + sliceStart: 0, + arrayLength: data.length, + }); +} + +/** + * Given a slice (subset) of an array, returns a connection object for use in + * GraphQL. + * + * This function is similar to `connectionFromArray`, but is intended for use + * cases where you know the cardinality of the connection, consider it too large + * to materialize the entire array, and instead wish pass in a slice of the + * total result large enough to cover the range specified in `args`. + */ +export function connectionFromArraySlice( + arraySlice: ReadonlyArray, + args: ConnectionArguments, + meta: ArraySliceMetaInfo, +): Connection { + const { after, before, first, last } = args; + const { sliceStart, arrayLength } = meta; + const sliceEnd = sliceStart + arraySlice.length; + + let startOffset = Math.max(sliceStart, 0); + let endOffset = Math.min(sliceEnd, arrayLength); + + const afterOffset = getOffsetWithDefault(after, -1); + if (0 <= afterOffset && afterOffset < arrayLength) { + startOffset = Math.max(startOffset, afterOffset + 1); + } + + const beforeOffset = getOffsetWithDefault(before, endOffset); + if (0 <= beforeOffset && beforeOffset < arrayLength) { + endOffset = Math.min(endOffset, beforeOffset); + } + + if (typeof first === 'number') { + if (first < 0) { + throw new Error('Argument "first" must be a non-negative integer'); + } + + endOffset = Math.min(endOffset, startOffset + first); + } + if (typeof last === 'number') { + if (last < 0) { + throw new Error('Argument "last" must be a non-negative integer'); + } + + startOffset = Math.max(startOffset, endOffset - last); + } + + // If supplied slice is too large, trim it down before mapping over it. + const slice = arraySlice.slice(startOffset - sliceStart, endOffset - sliceStart); + + const edges = slice.map((value, index) => ({ + cursor: offsetToCursor(startOffset + index), + node: value, + })); + + const firstEdge = edges[0]; + const lastEdge = edges[edges.length - 1]; + const lowerBound = after != null ? afterOffset + 1 : 0; + const upperBound = before != null ? beforeOffset : arrayLength; + return { + edges, + pageInfo: { + startCursor: firstEdge ? firstEdge.cursor : null, + endCursor: lastEdge ? lastEdge.cursor : null, + // INFO: here is the change comparing to graphql-relay-js + // we return lowerBound > 0 (instead of false) + hasPreviousPage: typeof last === 'number' ? startOffset > lowerBound : lowerBound > 0, + // INFO: here is the change comparing to graphql-relay-js + // we return upperBound < arrayLength (instead of false) + hasNextPage: typeof first === 'number' ? endOffset < upperBound : upperBound < arrayLength, + }, + }; +} + +const PREFIX = 'arrayconnection:'; + +/** + * Creates the cursor string from an offset. + */ +export function offsetToCursor(offset: number): ConnectionCursor { + return base64(PREFIX + offset.toString()); +} + +/** + * Extracts the offset from the cursor string. + */ +export function cursorToOffset(cursor: ConnectionCursor): number { + return parseInt(unbase64(cursor).substring(PREFIX.length), 10); +} + +/** + * Given an optional cursor and a default offset, returns the offset + * to use; if the cursor contains a valid offset, that will be used, + * otherwise it will be the default. + */ +export function getOffsetWithDefault(cursor: ConnectionCursor | null | undefined, defaultOffset: number): number { + if (typeof cursor !== 'string') { + return defaultOffset; + } + const offset = cursorToOffset(cursor); + return isNaN(offset) ? defaultOffset : offset; +} diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index f84538ba..916dade0 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -1,4 +1,3 @@ -import { connectionFromArray } from 'graphql-relay'; import { v4 as uuid } from 'uuid'; import { arg, @@ -30,6 +29,7 @@ import { } from '../helpers/workflow.helpers'; import { StartWorkflowInput } from '../types/conductor.types'; import { omitNullValue, parseJson, unwrap } from '../helpers/utils.helpers'; +import { connectionFromArray } from '../helpers/connection.helpers'; const log = getLogger('frinx-inventory-server'); From e2d582692e44e2325c0b6dea9d98e07cf646518e Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 11 May 2023 15:53:18 +0200 Subject: [PATCH 20/69] unify workflow mutation input (#291) --- .eslintignore | 3 +- src/schema/api.graphql | 104 +++++++++++++---------- src/schema/nexus-typegen.ts | 76 +++++++++++------ src/schema/workflow.ts | 160 ++++++++++++++++++++++++------------ 4 files changed, 222 insertions(+), 121 deletions(-) diff --git a/.eslintignore b/.eslintignore index 964bd07c..10ad9282 100644 --- a/.eslintignore +++ b/.eslintignore @@ -7,4 +7,5 @@ jest.config.js seed.ts init.ts src/helpers/base64.helpers.ts -src/helpers/connection.helpers.ts \ No newline at end of file +src/helpers/connection.helpers.ts +src/__generated__/graphql.ts \ No newline at end of file diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 2d522990..8740dee3 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -96,6 +96,10 @@ type BlueprintEdge { node: Blueprint! } +input BulkOperationInput { + executedWorkflowIds: [String!]! +} + type BulkOperationResponse { bulkErrorResults: String bulkSuccessfulResults: [String!] @@ -223,6 +227,11 @@ type DeleteSnapshotPayload { snapshot: Snapshot } +input DeleteWorkflowInput { + name: String! + version: Int! +} + type DeleteWorkflowPayload { workflow: Workflow! } @@ -312,6 +321,18 @@ input ExecuteNewWorkflowInput { version: Int } +input ExecuteWorkflowByName { + correlationId: String + + """ + JSON string of input parameters + """ + inputParameters: String! + priority: Int + workflowName: String! + workflowVersion: Int +} + type ExecutedWorkflow implements Node { createdAt: String createdBy: String @@ -527,11 +548,11 @@ type Mutation { addSnapshot(input: AddSnapshotInput!, transactionId: String!): AddSnapshotPayload addZone(input: AddZoneInput!): AddZonePayload! applySnapshot(input: ApplySnapshotInput!, transactionId: String!): ApplySnapshotPayload! - bulkPauseWorkflow(executedWorkflowIds: [String!]!): BulkOperationResponse - bulkRestartWorkflow(executedWorkflowIds: [String!]!): BulkOperationResponse - bulkResumeWorkflow(executedWorkflowIds: [String!]!): BulkOperationResponse - bulkRetryWorkflow(executedWorkflowIds: [String!]!): BulkOperationResponse - bulkTerminateWorkflow(executedWorkflowIds: [String!]!): BulkOperationResponse + bulkPauseWorkflow(input: BulkOperationInput!): BulkOperationResponse + bulkRestartWorkflow(input: BulkOperationInput!): BulkOperationResponse + bulkResumeWorkflow(input: BulkOperationInput!): BulkOperationResponse + bulkRetryWorkflow(input: BulkOperationInput!): BulkOperationResponse + bulkTerminateWorkflow(input: BulkOperationInput!): BulkOperationResponse closeTransaction(deviceId: String!, transactionId: String!): CloseTransactionPayload! commitConfig(input: CommitConfigInput!, transactionId: String!): CommitConfigPayload! createLabel(input: CreateLabelInput!): CreateLabelPayload! @@ -540,52 +561,24 @@ type Mutation { deleteBlueprint(id: String!): DeleteBlueprintPayload! deleteDevice(id: String!): DeleteDevicePayload! deleteLabel(id: String!): DeleteLabelPayload! - deleteSchedule(name: String!): IsOkResponse + deleteSchedule(id: String!): IsOkResponse deleteSnapshot(input: DeleteSnapshotInput!): DeleteSnapshotPayload - deleteWorkflow(name: String!, version: Int!): DeleteWorkflowPayload! - editWorkflowSchedule(input: EditWorkflowScheduleInput!, name: String!): Schedule + deleteWorkflow(input: DeleteWorkflowInput!): DeleteWorkflowPayload! + editWorkflowSchedule(id: String!, input: EditWorkflowScheduleInput!): Schedule executeNewWorkflow(input: StartWorkflowRequestInput!): String - executeWorkflowByName( - correlationId: String - - """ - JSON string of input parameters - """ - inputParameters: String! - priority: Int - workflowName: String! - workflowVersion: Int - ): String + executeWorkflowByName(input: ExecuteWorkflowByName!): String importCSV(input: CSVImportInput!): CSVImport installDevice(id: String!): InstallDevicePayload! - pauseWorkflow(workflowId: String!): IsOkResponse - removeWorkflow( - """ - Default value is true - """ - shouldArchiveWorkflow: Boolean - workflowId: String! - ): IsOkResponse + pauseWorkflow(id: String!): IsOkResponse + removeWorkflow(id: String!, input: RemoveWorkflowInput): IsOkResponse resetConfig(deviceId: String!, transactionId: String!): ResetConfigPayload! - restartWorkflow( - """ - Default value is true - """ - shouldUseLatestDefinitions: Boolean - workflowId: String! - ): IsOkResponse - resumeWorkflow(workflowId: String!): IsOkResponse - retryWorkflow( - """ - Default value is true - """ - shouldResumeSubworkflowTasks: Boolean - workflowId: String! - ): IsOkResponse + restartWorkflow(id: String!, input: RestartWorkflowInput): IsOkResponse + resumeWorkflow(id: String!): IsOkResponse + retryWorkflow(id: String!, input: RetryWorkflowInput): IsOkResponse revertChanges(transactionId: String!): RevertChangesPayload! scheduleWorkflow(input: CreateScheduleInput!): Schedule syncFromNetwork(deviceId: String!, transactionId: String!): SyncFromNetworkPayload! - terminateWorkflow(reason: String, workflowId: String!): IsOkResponse + terminateWorkflow(id: String!, input: TerminateWorkflowInput): IsOkResponse uninstallDevice(id: String!): UninstallDevicePayload! updateBlueprint(id: String!, input: UpdateBlueprintInput!): UpdateBlueprintPayload! updateDataStore(deviceId: String!, input: UpdateDataStoreInput!, transactionId: String!): UpdateDataStorePayload! @@ -677,16 +670,37 @@ type Query { zones(after: String, before: String, first: Int, last: Int): ZonesConnection! } +input RemoveWorkflowInput { + """ + Default value is true + """ + shouldArchiveWorkflow: Boolean +} + type ResetConfigPayload { dataStore: DataStore! } +input RestartWorkflowInput { + """ + Default value is true + """ + shouldUseLatestDefinitions: Boolean +} + enum RetryLogic { EXPONENTIAL_BACKOFF FIXED LINEAR_BACKOFF } +input RetryWorkflowInput { + """ + Default value is true + """ + shouldResumeSubworkflowTasks: Boolean +} + type RevertChangesPayload { isOk: Boolean! } @@ -801,6 +815,10 @@ enum TaskTimeoutPolicy { TIME_OUT_WF } +input TerminateWorkflowInput { + reason: String +} + enum TimeoutPolicy { ALERT_ONLY TIME_OUT_WF diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 72f3500f..252988d8 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -73,6 +73,10 @@ export interface NexusGenInputs { deviceId: string; // String! name: string; // String! }; + BulkOperationInput: { + // input type + executedWorkflowIds: string[]; // [String!]! + }; CSVImportInput: { // input type file: NexusGenScalars['Upload']; // Upload! @@ -109,6 +113,11 @@ export interface NexusGenInputs { name: string; // String! transactionId: string; // String! }; + DeleteWorkflowInput: { + // input type + name: string; // String! + version: number; // Int! + }; DeviceOrderByInput: { // input type direction: NexusGenEnums['SortDirection']; // SortDirection! @@ -135,6 +144,14 @@ export interface NexusGenInputs { taskToDomain?: string | null; // String version?: number | null; // Int }; + ExecuteWorkflowByName: { + // input type + correlationId?: string | null; // String + inputParameters: string; // String! + priority?: number | null; // Int + workflowName: string; // String! + workflowVersion?: number | null; // Int + }; ExecutedWorkflowFilterInput: { // input type startTime?: NexusGenInputs['ExecutedWorkflowStartTimeRange'] | null; // ExecutedWorkflowStartTimeRange @@ -182,6 +199,18 @@ export interface NexusGenInputs { size: number; // Int! start: number; // Int! }; + RemoveWorkflowInput: { + // input type + shouldArchiveWorkflow?: boolean | null; // Boolean + }; + RestartWorkflowInput: { + // input type + shouldUseLatestDefinitions?: boolean | null; // Boolean + }; + RetryWorkflowInput: { + // input type + shouldResumeSubworkflowTasks?: boolean | null; // Boolean + }; ScheduleFilterInput: { // input type workflowName: string; // String! @@ -209,6 +238,10 @@ export interface NexusGenInputs { type?: string | null; // String workflowTaskType?: Array | null; // [WorkflowTaskType] }; + TerminateWorkflowInput: { + // input type + reason?: string | null; // String + }; UpdateBlueprintInput: { // input type name?: string | null; // String @@ -2061,23 +2094,23 @@ export interface NexusGenArgTypes { }; bulkPauseWorkflow: { // args - executedWorkflowIds: string[]; // [String!]! + input: NexusGenInputs['BulkOperationInput']; // BulkOperationInput! }; bulkRestartWorkflow: { // args - executedWorkflowIds: string[]; // [String!]! + input: NexusGenInputs['BulkOperationInput']; // BulkOperationInput! }; bulkResumeWorkflow: { // args - executedWorkflowIds: string[]; // [String!]! + input: NexusGenInputs['BulkOperationInput']; // BulkOperationInput! }; bulkRetryWorkflow: { // args - executedWorkflowIds: string[]; // [String!]! + input: NexusGenInputs['BulkOperationInput']; // BulkOperationInput! }; bulkTerminateWorkflow: { // args - executedWorkflowIds: string[]; // [String!]! + input: NexusGenInputs['BulkOperationInput']; // BulkOperationInput! }; closeTransaction: { // args @@ -2115,7 +2148,7 @@ export interface NexusGenArgTypes { }; deleteSchedule: { // args - name: string; // String! + id: string; // String! }; deleteSnapshot: { // args @@ -2123,13 +2156,12 @@ export interface NexusGenArgTypes { }; deleteWorkflow: { // args - name: string; // String! - version: number; // Int! + input: NexusGenInputs['DeleteWorkflowInput']; // DeleteWorkflowInput! }; editWorkflowSchedule: { // args + id: string; // String! input: NexusGenInputs['EditWorkflowScheduleInput']; // EditWorkflowScheduleInput! - name: string; // String! }; executeNewWorkflow: { // args @@ -2137,11 +2169,7 @@ export interface NexusGenArgTypes { }; executeWorkflowByName: { // args - correlationId?: string | null; // String - inputParameters: string; // String! - priority?: number | null; // Int - workflowName: string; // String! - workflowVersion?: number | null; // Int + input: NexusGenInputs['ExecuteWorkflowByName']; // ExecuteWorkflowByName! }; importCSV: { // args @@ -2153,12 +2181,12 @@ export interface NexusGenArgTypes { }; pauseWorkflow: { // args - workflowId: string; // String! + id: string; // String! }; removeWorkflow: { // args - shouldArchiveWorkflow?: boolean | null; // Boolean - workflowId: string; // String! + id: string; // String! + input?: NexusGenInputs['RemoveWorkflowInput'] | null; // RemoveWorkflowInput }; resetConfig: { // args @@ -2167,17 +2195,17 @@ export interface NexusGenArgTypes { }; restartWorkflow: { // args - shouldUseLatestDefinitions?: boolean | null; // Boolean - workflowId: string; // String! + id: string; // String! + input?: NexusGenInputs['RestartWorkflowInput'] | null; // RestartWorkflowInput }; resumeWorkflow: { // args - workflowId: string; // String! + id: string; // String! }; retryWorkflow: { // args - shouldResumeSubworkflowTasks?: boolean | null; // Boolean - workflowId: string; // String! + id: string; // String! + input?: NexusGenInputs['RetryWorkflowInput'] | null; // RetryWorkflowInput }; revertChanges: { // args @@ -2194,8 +2222,8 @@ export interface NexusGenArgTypes { }; terminateWorkflow: { // args - reason?: string | null; // String - workflowId: string; // String! + id: string; // String! + input?: NexusGenInputs['TerminateWorkflowInput'] | null; // TerminateWorkflowInput }; uninstallDevice: { // args diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 916dade0..015473b0 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -5,7 +5,6 @@ import { enumType, extendType, inputObjectType, - intArg, list, mutationField, nonNull, @@ -605,19 +604,26 @@ const DeleteWorkflowPayload = objectType({ }, }); +const DeleteWorkflowInput = inputObjectType({ + name: 'DeleteWorkflowInput', + definition: (t) => { + t.nonNull.string('name'); + t.nonNull.int('version'); + }, +}); + export const DeleteWorkflowMutation = extendType({ type: 'Mutation', definition: (t) => { t.nonNull.field('deleteWorkflow', { type: DeleteWorkflowPayload, args: { - name: nonNull(stringArg()), - version: nonNull(intArg()), + input: nonNull(arg({ type: DeleteWorkflowInput })), }, resolve: async (_, args, { conductorAPI }) => { - const { name, version } = args; - const workflowToDelete = await conductorAPI.getWorkflowDetail(config.conductorApiURL, name); - await conductorAPI.deleteWorkflow(config.conductorApiURL, name, version); + const { input } = args; + const workflowToDelete = await conductorAPI.getWorkflowDetail(config.conductorApiURL, input.name); + await conductorAPI.deleteWorkflow(config.conductorApiURL, input.name, input.version); return { workflow: { ...workflowToDelete, @@ -632,10 +638,10 @@ export const DeleteWorkflowMutation = extendType({ export const PauseWorkflowMutation = mutationField('pauseWorkflow', { type: IsOkResponse, args: { - workflowId: nonNull(stringArg()), + id: nonNull(stringArg()), }, - resolve: async (_, { workflowId }, { conductorAPI }) => { - await conductorAPI.pauseWorkflow(config.conductorApiURL, workflowId); + resolve: async (_, { id }, { conductorAPI }) => { + await conductorAPI.pauseWorkflow(config.conductorApiURL, id); return { isOk: true }; }, @@ -644,10 +650,10 @@ export const PauseWorkflowMutation = mutationField('pauseWorkflow', { export const ResumeWorkflowMutation = mutationField('resumeWorkflow', { type: IsOkResponse, args: { - workflowId: nonNull(stringArg()), + id: nonNull(stringArg()), }, - resolve: async (_, { workflowId }, { conductorAPI }) => { - await conductorAPI.resumeWorkflow(config.conductorApiURL, workflowId); + resolve: async (_, { id }, { conductorAPI }) => { + await conductorAPI.resumeWorkflow(config.conductorApiURL, id); return { isOk: true }; }, @@ -661,13 +667,20 @@ export const BulkOperationResponse = objectType({ }, }); +const BulkOperationInput = inputObjectType({ + name: 'BulkOperationInput', + definition: (t) => { + t.nonNull.list.nonNull.string('executedWorkflowIds'); + }, +}); + export const BulkResumeWorkflowMutation = mutationField('bulkResumeWorkflow', { type: BulkOperationResponse, args: { - executedWorkflowIds: nonNull(list(nonNull(stringArg()))), + input: nonNull(arg({ type: BulkOperationInput })), }, - resolve: async (_, { executedWorkflowIds }, { conductorAPI }) => { - const nativeWorkflowIds = executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); + resolve: async (_, { input }, { conductorAPI }) => { + const nativeWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); const data = await conductorAPI.bulkResumeWorkflow(config.conductorApiURL, nativeWorkflowIds); return { @@ -677,16 +690,27 @@ export const BulkResumeWorkflowMutation = mutationField('bulkResumeWorkflow', { }, }); +const ExecuteWorkflowByNameInput = inputObjectType({ + name: 'ExecuteWorkflowByName', + definition: (t) => { + t.nonNull.string('inputParameters', { description: 'JSON string of input parameters' }); + t.nonNull.string('workflowName'); + t.int('workflowVersion'); + t.string('correlationId'); + t.int('priority'); + }, +}); + export const ExecuteWorkflowByName = mutationField('executeWorkflowByName', { type: 'String', args: { - inputParameters: nonNull(stringArg({ description: 'JSON string of input parameters' })), - workflowName: nonNull(stringArg()), - workflowVersion: intArg(), - correlationId: stringArg(), - priority: intArg(), + input: nonNull(arg({ type: ExecuteWorkflowByNameInput })), }, - resolve: async (_, { inputParameters, workflowName, workflowVersion, correlationId, priority }, { conductorAPI }) => { + resolve: async ( + _, + { input: { inputParameters, workflowName, workflowVersion, correlationId, priority } }, + { conductorAPI }, + ) => { const workflowId = await conductorAPI.executeWorkflowByName(config.conductorApiURL, { inputParameters: parseJson(inputParameters), name: workflowName, @@ -702,10 +726,10 @@ export const ExecuteWorkflowByName = mutationField('executeWorkflowByName', { export const BulkPauseWorkflowMutation = mutationField('bulkPauseWorkflow', { type: BulkOperationResponse, args: { - executedWorkflowIds: nonNull(list(nonNull(stringArg()))), + input: nonNull(arg({ type: BulkOperationInput })), }, - resolve: async (_, { executedWorkflowIds }, { conductorAPI }) => { - const nativeWorkflowIds = executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); + resolve: async (_, { input }, { conductorAPI }) => { + const nativeWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); const data = await conductorAPI.bulkPauseWorkflow(config.conductorApiURL, nativeWorkflowIds); return { @@ -718,10 +742,10 @@ export const BulkPauseWorkflowMutation = mutationField('bulkPauseWorkflow', { export const BulkTerminateWorkflow = mutationField('bulkTerminateWorkflow', { type: BulkOperationResponse, args: { - executedWorkflowIds: nonNull(list(nonNull(stringArg()))), + input: nonNull(arg({ type: BulkOperationInput })), }, - resolve: async (_, { executedWorkflowIds }, { conductorAPI }) => { - const nativeWorkflowIds = executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); + resolve: async (_, { input }, { conductorAPI }) => { + const nativeWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); const data = await conductorAPI.bulkTerminateWorkflow(config.conductorApiURL, nativeWorkflowIds); return { @@ -734,10 +758,10 @@ export const BulkTerminateWorkflow = mutationField('bulkTerminateWorkflow', { export const BulkRetryWorkflow = mutationField('bulkRetryWorkflow', { type: BulkOperationResponse, args: { - executedWorkflowIds: nonNull(list(nonNull(stringArg()))), + input: nonNull(arg({ type: BulkOperationInput })), }, - resolve: async (_, { executedWorkflowIds }, { conductorAPI }) => { - const nativeWorkflowIds = executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); + resolve: async (_, { input }, { conductorAPI }) => { + const nativeWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); const data = await conductorAPI.bulkRetryWorkflow(config.conductorApiURL, nativeWorkflowIds); return { @@ -750,10 +774,10 @@ export const BulkRetryWorkflow = mutationField('bulkRetryWorkflow', { export const BulkRestartWorkflow = mutationField('bulkRestartWorkflow', { type: BulkOperationResponse, args: { - executedWorkflowIds: nonNull(list(nonNull(stringArg()))), + input: nonNull(arg({ type: BulkOperationInput })), }, - resolve: async (_, { executedWorkflowIds }, { conductorAPI }) => { - const nativeWorkflowIds = executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); + resolve: async (_, { input }, { conductorAPI }) => { + const nativeWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); const data = await conductorAPI.bulkRestartWorkflow(config.conductorApiURL, nativeWorkflowIds); return { @@ -763,53 +787,81 @@ export const BulkRestartWorkflow = mutationField('bulkRestartWorkflow', { }, }); +const RetryWorkflowInput = inputObjectType({ + name: 'RetryWorkflowInput', + definition: (t) => { + t.boolean('shouldResumeSubworkflowTasks', { description: 'Default value is true' }); + }, +}); + export const RetryWorkflowMutation = mutationField('retryWorkflow', { type: IsOkResponse, args: { - workflowId: nonNull(stringArg()), - shouldResumeSubworkflowTasks: booleanArg({ description: 'Default value is true' }), + id: nonNull(stringArg()), + input: arg({ type: RetryWorkflowInput }), }, - resolve: async (_, { workflowId, shouldResumeSubworkflowTasks }, { conductorAPI }) => { - await conductorAPI.retryWorkflow(config.conductorApiURL, workflowId, shouldResumeSubworkflowTasks); + resolve: async (_, { id, input }, { conductorAPI }) => { + await conductorAPI.retryWorkflow(config.conductorApiURL, id, input?.shouldResumeSubworkflowTasks); return { isOk: true }; }, }); +const RestartWorkflowInput = inputObjectType({ + name: 'RestartWorkflowInput', + definition: (t) => { + t.boolean('shouldUseLatestDefinitions', { description: 'Default value is true' }); + }, +}); + export const RestartWorkflowMutation = mutationField('restartWorkflow', { type: IsOkResponse, args: { - workflowId: nonNull(stringArg()), - shouldUseLatestDefinitions: booleanArg({ description: 'Default value is true' }), + id: nonNull(stringArg()), + input: arg({ type: RestartWorkflowInput }), }, - resolve: async (_, { workflowId, shouldUseLatestDefinitions }, { conductorAPI }) => { - await conductorAPI.restartWorkflow(config.conductorApiURL, workflowId, shouldUseLatestDefinitions); + resolve: async (_, { id, input }, { conductorAPI }) => { + await conductorAPI.restartWorkflow(config.conductorApiURL, id, input?.shouldUseLatestDefinitions); return { isOk: true }; }, }); +const TerminateWorkflowInput = inputObjectType({ + name: 'TerminateWorkflowInput', + definition: (t) => { + t.string('reason'); + }, +}); + export const TerminateWorkflowMutation = mutationField('terminateWorkflow', { type: IsOkResponse, args: { - workflowId: nonNull(stringArg()), - reason: stringArg(), + id: nonNull(stringArg()), + input: arg({ type: TerminateWorkflowInput }), }, - resolve: async (_, { workflowId, reason }, { conductorAPI }) => { - await conductorAPI.terminateWorkflow(config.conductorApiURL, workflowId, reason); + resolve: async (_, { id, input }, { conductorAPI }) => { + await conductorAPI.terminateWorkflow(config.conductorApiURL, id, input?.reason); return { isOk: true }; }, }); +const RemoveWorkflowInput = inputObjectType({ + name: 'RemoveWorkflowInput', + definition: (t) => { + t.boolean('shouldArchiveWorkflow', { description: 'Default value is true' }); + }, +}); + export const RemoveWorkflowMutation = mutationField('removeWorkflow', { type: IsOkResponse, args: { - workflowId: nonNull(stringArg()), - shouldArchiveWorkflow: booleanArg({ description: 'Default value is true' }), + id: nonNull(stringArg()), + input: arg({ type: RemoveWorkflowInput }), }, - resolve: async (_, { workflowId, shouldArchiveWorkflow }, { conductorAPI }) => { - await conductorAPI.removeWorkflow(config.conductorApiURL, workflowId, shouldArchiveWorkflow); + resolve: async (_, { id, input }, { conductorAPI }) => { + await conductorAPI.removeWorkflow(config.conductorApiURL, id, input?.shouldArchiveWorkflow); return { isOk: true }; }, @@ -898,9 +950,10 @@ export const EditWorkflowSchedule = mutationField('editWorkflowSchedule', { type: Schedule, args: { input: nonNull(arg({ type: EditWorkflowScheduleInput })), - name: nonNull(stringArg()), + id: nonNull(stringArg()), }, - resolve: async (_, { input, name }, { schedulerAPI }) => { + resolve: async (_, { input, id }, { schedulerAPI }) => { + const name = fromGraphId('Schedule', id); const response = await schedulerAPI.editWorkflowSchedule(name, { fromDate: input.performFromDate, toDate: input.performTillDate, @@ -974,10 +1027,11 @@ export const WorkflowSchedules = queryField('schedules', { export const DeleteSchedule = mutationField('deleteSchedule', { type: IsOkResponse, args: { - name: nonNull(stringArg()), + id: nonNull(stringArg()), }, - resolve: async (_, { name }, { schedulerAPI }) => { + resolve: async (_, { id }, { schedulerAPI }) => { try { + const name = fromGraphId('Schedule', id); await schedulerAPI.deleteSchedule(name); return { From 905c65633004bbcca81977d02e6743099d032341 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Mon, 15 May 2023 08:43:04 +0200 Subject: [PATCH 21/69] add status to schedule (#292) --- src/__generated__/graphql.ts | 19 ++++++++++++++----- src/schema/api.graphql | 11 +++++++++++ src/schema/nexus-typegen.ts | 3 +++ src/schema/workflow.ts | 9 +++++++++ 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/__generated__/graphql.ts b/src/__generated__/graphql.ts index 56634941..af39c7c6 100644 --- a/src/__generated__/graphql.ts +++ b/src/__generated__/graphql.ts @@ -84,7 +84,7 @@ export type Schedule = { fromDate: Scalars['DateTime']; name: Scalars['String']; parallelRuns: Scalars['Boolean']; - status: Scalars['String']; + status: Status; toDate: Scalars['DateTime']; workflowContext: Scalars['String']; workflowName: Scalars['String']; @@ -109,6 +109,15 @@ export type SchedulesFilterInput = { workflowVersion: Scalars['String']; }; +export type Status = + | 'COMPLETED' + | 'FAILED' + | 'PAUSED' + | 'RUNNING' + | 'TERMINATED' + | 'TIMED_OUT' + | 'UNKNOWN'; + export type UpdateScheduleInput = { cronString?: InputMaybe; enabled?: InputMaybe; @@ -133,21 +142,21 @@ export type UpdateScheduleMutationVariables = Exact<{ }>; -export type UpdateScheduleMutation = { __typename?: 'Mutation', updateSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: string } }; +export type UpdateScheduleMutation = { __typename?: 'Mutation', updateSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; export type CreateScheduleMutationVariables = Exact<{ input: CreateScheduleInput; }>; -export type CreateScheduleMutation = { __typename?: 'Mutation', createSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: string } }; +export type CreateScheduleMutation = { __typename?: 'Mutation', createSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; export type GetScheduleQueryVariables = Exact<{ scheduleName: Scalars['String']; }>; -export type GetScheduleQuery = { __typename?: 'Query', schedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: string } | null }; +export type GetScheduleQuery = { __typename?: 'Query', schedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } | null }; export type GetSchedulesQueryVariables = Exact<{ first?: InputMaybe; @@ -158,4 +167,4 @@ export type GetSchedulesQueryVariables = Exact<{ }>; -export type GetSchedulesQuery = { __typename?: 'Query', schedules: { __typename?: 'ScheduleConnection', totalCount: number, edges: Array<{ __typename?: 'ScheduleEdge', cursor: string, node: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: string } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null } } | null }; +export type GetSchedulesQuery = { __typename?: 'Query', schedules: { __typename?: 'ScheduleConnection', totalCount: number, edges: Array<{ __typename?: 'ScheduleEdge', cursor: string, node: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null } } | null }; diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 8740dee3..cadaebcf 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -713,6 +713,7 @@ type Schedule implements Node { parallelRuns: Boolean! performFromDate: String! performTillDate: String! + status: ScheduleStatus! version: Int workflowContext: String! workflowName: String! @@ -735,6 +736,16 @@ input ScheduleFilterInput { workflowVersion: String! } +enum ScheduleStatus { + COMPLETED + FAILED + PAUSED + RUNNING + TERMINATED + TIMED_OUT + UNKNOWN +} + type Snapshot { createdAt: String! name: String! diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 252988d8..6c6c16d3 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -326,6 +326,7 @@ export interface NexusGenEnums { | 'TIMED_OUT'; GraphEdgeStatus: 'ok' | 'unknown'; RetryLogic: 'EXPONENTIAL_BACKOFF' | 'FIXED' | 'LINEAR_BACKOFF'; + ScheduleStatus: 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; SortDeviceBy: 'CREATED_AT' | 'NAME'; SortDirection: 'ASC' | 'DESC'; TaskTimeoutPolicy: 'ALERT_ONLY' | 'RETRY' | 'TIME_OUT_WF'; @@ -1232,6 +1233,7 @@ export interface NexusGenFieldTypes { parallelRuns: boolean; // Boolean! performFromDate: string; // String! performTillDate: string; // String! + status: NexusGenEnums['ScheduleStatus']; // ScheduleStatus! version: number | null; // Int workflowContext: string; // String! workflowName: string; // String! @@ -1869,6 +1871,7 @@ export interface NexusGenFieldTypeNames { parallelRuns: 'Boolean'; performFromDate: 'String'; performTillDate: 'String'; + status: 'ScheduleStatus'; version: 'Int'; workflowContext: 'String'; workflowName: 'String'; diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 015473b0..d4d0b9e9 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -882,6 +882,11 @@ export const CreateScheduleInput = inputObjectType({ }, }); +export const ScheduleStatus = enumType({ + name: 'ScheduleStatus', + members: ['UNKNOWN', 'COMPLETED', 'FAILED', 'PAUSED', 'RUNNING', 'TERMINATED', 'TIMED_OUT'], +}); + export const Schedule = objectType({ name: 'Schedule', definition: (t) => { @@ -904,6 +909,10 @@ export const Schedule = objectType({ resolve: (root) => root.toDate, }); t.nonNull.boolean('parallelRuns'); + t.nonNull.field('status', { + type: ScheduleStatus, + resolve: (root) => root.status, + }); }, }); From f2a3974d8d2a77a7946b3b41414eb7c54ccac312 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Mon, 22 May 2023 13:34:07 +0200 Subject: [PATCH 22/69] Workflow status subscription (#293) * add subscription for executed workflow * refactor naming and remove uuid * id generated by uuid and workflowId used for mutations --- src/context.ts | 8 ++++ src/helpers/conductor.helpers.ts | 35 ++++++++++++++++++ src/schema/api.graphql | 3 +- src/schema/nexus-typegen.ts | 8 +++- src/schema/workflow.ts | 63 ++++++++++++++++++++++---------- src/server.ts | 10 ++++- 6 files changed, 104 insertions(+), 23 deletions(-) diff --git a/src/context.ts b/src/context.ts index a704239b..f979a48f 100644 --- a/src/context.ts +++ b/src/context.ts @@ -28,3 +28,11 @@ export default function createContext(context: ExpressContext): Context { return { prisma: prismaClient, tenantId, uniconfigAPI, topologyDiscoveryAPI, conductorAPI, schedulerAPI }; } + +export function createSubscriptionContext() { + return { + conductorAPI, + schedulerAPI, + prisma: prismaClient, + }; +} diff --git a/src/helpers/conductor.helpers.ts b/src/helpers/conductor.helpers.ts index e2f665d4..9e88d007 100644 --- a/src/helpers/conductor.helpers.ts +++ b/src/helpers/conductor.helpers.ts @@ -73,3 +73,38 @@ export function makeStringQueryFromSearchQueryObject( return result.join('&'); } + +export type AsyncGeneratorHookParams = { + fn: (abortController: AbortController) => () => Promise; + repeatTill: (data?: T | null) => boolean; + timeout?: number; + updateDeps?: unknown[]; +}; + +export type AsyncGeneratorParams = { + fn: () => Promise; + repeatTill: (data?: T | null) => boolean; + timeout?: number; +}; + +export async function* asyncGenerator({ + fn, + repeatTill, + timeout = 800, +}: AsyncGeneratorParams): AsyncGenerator { + let data = await fn(); + const controller = new AbortController(); + + while (repeatTill(data)) { + // eslint-disable-next-line no-await-in-loop + await new Promise((resolve) => { + setTimeout(resolve, timeout); + }); + yield data; + // eslint-disable-next-line no-await-in-loop + data = await fn(); + } + // we need to do an additional yield for the last task status change + yield data; + controller.abort(); +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index cadaebcf..25f39233 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -664,7 +664,7 @@ type Query { topologyVersions: [String!] transactions: [Transaction!]! uniconfigShellSession: String - workflowInstanceDetail(id: String!, shouldIncludeTasks: Boolean): WorkflowInstanceDetail + workflowInstanceDetail(shouldIncludeTasks: Boolean, workflowId: String!): WorkflowInstanceDetail workflowLabels: [String!]! workflows(after: String, before: String, filter: FilterWorkflowsInput, first: Int, last: Int): WorkflowConnection! zones(after: String, before: String, first: Int, last: Int): ZonesConnection! @@ -773,6 +773,7 @@ type SubWorkflow { } type Subscription { + controlExecutedWorkflow(id: String!): ExecutedWorkflow uniconfigShell(input: String, sessionId: String!, trigger: Int): String } diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 6c6c16d3..a2bfa667 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -1263,6 +1263,7 @@ export interface NexusGenFieldTypes { }; Subscription: { // field return type + controlExecutedWorkflow: NexusGenRootTypes['ExecutedWorkflow'] | null; // ExecutedWorkflow uniconfigShell: string | null; // String }; SyncFromNetworkPayload: { @@ -1901,6 +1902,7 @@ export interface NexusGenFieldTypeNames { }; Subscription: { // field return type name + controlExecutedWorkflow: 'ExecutedWorkflow'; uniconfigShell: 'String'; }; SyncFromNetworkPayload: { @@ -2338,8 +2340,8 @@ export interface NexusGenArgTypes { }; workflowInstanceDetail: { // args - id: string; // String! shouldIncludeTasks?: boolean | null; // Boolean + workflowId: string; // String! }; workflows: { // args @@ -2358,6 +2360,10 @@ export interface NexusGenArgTypes { }; }; Subscription: { + controlExecutedWorkflow: { + // args + id: string; // String! + }; uniconfigShell: { // args input?: string | null; // String diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index d4d0b9e9..bece9947 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -11,6 +11,7 @@ import { objectType, queryField, stringArg, + subscriptionField, } from 'nexus'; import config from '../config'; import { WorkflowDetailInput } from '../external-api/conductor-network-types'; @@ -27,8 +28,9 @@ import { validateTasks, } from '../helpers/workflow.helpers'; import { StartWorkflowInput } from '../types/conductor.types'; -import { omitNullValue, parseJson, unwrap } from '../helpers/utils.helpers'; +import { omitNullValue, parseJson } from '../helpers/utils.helpers'; import { connectionFromArray } from '../helpers/connection.helpers'; +import { asyncGenerator } from '../helpers/conductor.helpers'; const log = getLogger('frinx-inventory-server'); @@ -211,7 +213,7 @@ export const ExecutedWorkflow = objectType({ definition(t) { t.implements(Node); t.nonNull.id('id', { - resolve: (executedWorkflow) => toGraphId('ExecutedWorkflow', executedWorkflow.workflowId ?? uuid()), + resolve: () => toGraphId('ExecutedWorkflow', uuid()), }); t.string('createdBy', { resolve: (executedWorkflow) => executedWorkflow.createdBy ?? null }); t.string('updatedBy', { resolve: (workflow) => workflow.updatedBy ?? null }); @@ -321,7 +323,7 @@ export const ExecutedWorkflowsQuery = queryField('executedWorkflows', { const executedWorkflowsWithId = executedWorkflows .map((w) => ({ ...w, - id: toGraphId('ExecutedWorkflow', w.workflowId || uuid()), + id: toGraphId('ExecutedWorkflow', uuid()), })) .slice(0, args.pagination?.size ?? 0 - 1); @@ -362,12 +364,11 @@ const WorkflowInstanceDetail = objectType({ export const WorkflowInstanceQuery = queryField('workflowInstanceDetail', { type: WorkflowInstanceDetail, args: { - id: nonNull(stringArg()), + workflowId: nonNull(stringArg()), shouldIncludeTasks: booleanArg(), }, resolve: async (_, args, { conductorAPI }) => { - const { id, shouldIncludeTasks } = args; - const workflowId = fromGraphId('ExecutedWorkflow', id); + const { workflowId, shouldIncludeTasks } = args; const result = await conductorAPI.getExecutedWorkflowDetail( config.conductorApiURL, @@ -375,21 +376,25 @@ export const WorkflowInstanceQuery = queryField('workflowInstanceDetail', { shouldIncludeTasks ?? false, ); + if (result.workflowName == null) { + throw new Error(`Workflow not found`); + } + const meta = result.workflowDefinition ? null : await conductorAPI.getWorkflowDetail( config.conductorApiURL, - unwrap(result.workflowName || null), + result.workflowName, result.workflowVersion || undefined, ); const subworkflows = await getSubworkflows({ ...result, - id: toGraphId('ExecutedWorkflow', unwrap(result.workflowName || null)), + id: toGraphId('ExecutedWorkflow', uuid()), }); return { - result: { ...result, id: toGraphId('ExecutedWorkflow', unwrap(result.workflowName || null)) }, + result: { ...result, id: toGraphId('ExecutedWorkflow', uuid()) }, meta: meta ? { ...meta, id: toGraphId('Workflow', meta.name) } : null, subworkflows, }; @@ -680,8 +685,7 @@ export const BulkResumeWorkflowMutation = mutationField('bulkResumeWorkflow', { input: nonNull(arg({ type: BulkOperationInput })), }, resolve: async (_, { input }, { conductorAPI }) => { - const nativeWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); - const data = await conductorAPI.bulkResumeWorkflow(config.conductorApiURL, nativeWorkflowIds); + const data = await conductorAPI.bulkResumeWorkflow(config.conductorApiURL, input.executedWorkflowIds); return { bulkErrorResults: JSON.stringify(data.bulkErrorResults), @@ -729,8 +733,7 @@ export const BulkPauseWorkflowMutation = mutationField('bulkPauseWorkflow', { input: nonNull(arg({ type: BulkOperationInput })), }, resolve: async (_, { input }, { conductorAPI }) => { - const nativeWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); - const data = await conductorAPI.bulkPauseWorkflow(config.conductorApiURL, nativeWorkflowIds); + const data = await conductorAPI.bulkPauseWorkflow(config.conductorApiURL, input.executedWorkflowIds); return { bulkErrorResults: JSON.stringify(data.bulkErrorResults), @@ -745,8 +748,7 @@ export const BulkTerminateWorkflow = mutationField('bulkTerminateWorkflow', { input: nonNull(arg({ type: BulkOperationInput })), }, resolve: async (_, { input }, { conductorAPI }) => { - const nativeWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); - const data = await conductorAPI.bulkTerminateWorkflow(config.conductorApiURL, nativeWorkflowIds); + const data = await conductorAPI.bulkTerminateWorkflow(config.conductorApiURL, input.executedWorkflowIds); return { bulkErrorResults: JSON.stringify(data.bulkErrorResults), @@ -761,8 +763,7 @@ export const BulkRetryWorkflow = mutationField('bulkRetryWorkflow', { input: nonNull(arg({ type: BulkOperationInput })), }, resolve: async (_, { input }, { conductorAPI }) => { - const nativeWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); - const data = await conductorAPI.bulkRetryWorkflow(config.conductorApiURL, nativeWorkflowIds); + const data = await conductorAPI.bulkRetryWorkflow(config.conductorApiURL, input.executedWorkflowIds); return { bulkErrorResults: JSON.stringify(data.bulkErrorResults), @@ -777,8 +778,7 @@ export const BulkRestartWorkflow = mutationField('bulkRestartWorkflow', { input: nonNull(arg({ type: BulkOperationInput })), }, resolve: async (_, { input }, { conductorAPI }) => { - const nativeWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); - const data = await conductorAPI.bulkRestartWorkflow(config.conductorApiURL, nativeWorkflowIds); + const data = await conductorAPI.bulkRestartWorkflow(config.conductorApiURL, input.executedWorkflowIds); return { bulkErrorResults: JSON.stringify(data.bulkErrorResults), @@ -1053,3 +1053,28 @@ export const DeleteSchedule = mutationField('deleteSchedule', { } }, }); + +export const ExecutedWorkflowSubscription = subscriptionField('controlExecutedWorkflow', { + type: ExecutedWorkflow, + args: { + id: nonNull(stringArg()), + }, + subscribe: async (_, { id }, { conductorAPI }) => + asyncGenerator({ + repeatTill: (workflow) => workflow?.status === 'RUNNING' || workflow?.status === 'PAUSED', + fn: () => conductorAPI.getExecutedWorkflowDetail(config.conductorApiURL, id, false), + }), + resolve: (workflow) => { + if (workflow == null) { + return null; + } + + return { + ...workflow, + id: toGraphId('ExecutedWorkflow', uuid()), + }; + }, +}); + +// id generujem podla nasej hodnoty nejakej +// ked budem chciet query alebo presmerovat niekam pouzijem workflowId a ak bude null vratim error ze neexistuje workflow s tymto id diff --git a/src/server.ts b/src/server.ts index 12f92533..18216bc8 100644 --- a/src/server.ts +++ b/src/server.ts @@ -8,7 +8,7 @@ import https from 'https'; import http, { Server } from 'http'; import path from 'path'; import { WebSocketServer } from 'ws'; -import createContext from './context'; +import createContext, { createSubscriptionContext } from './context'; import { UniconfigCache } from './external-api/uniconfig-cache'; import getLogger from './get-logger'; import isDev from './is-dev'; @@ -46,7 +46,13 @@ const wsServer = new WebSocketServer({ server, path: '/graphql', }); -const serverCleanup = useServer({ schema }, wsServer); +const serverCleanup = useServer( + { + schema, + context: createSubscriptionContext, + }, + wsServer, +); const apolloServer = new ApolloServer({ csrfPrevention: true, From 38ef6f2197e233d198127dc0d48d5e499d64c557 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Wed, 7 Jun 2023 09:16:56 +0200 Subject: [PATCH 23/69] Change executed task query (#307) * refactor ID for executed workflow * refactor property naming and url handling of empty value * remove warnings * set default value if priority was not defined * handle optional values from input --- src/external-api/conductor-network-types.ts | 7 +- src/external-api/conductor.ts | 16 +++- src/external-api/helpers.ts | 11 ++- src/helpers/workflow.helpers.ts | 4 +- src/schema/api.graphql | 14 +++- src/schema/global-types.ts | 9 +++ src/schema/nexus-typegen.ts | 28 +++++-- src/schema/task.ts | 9 ++- src/schema/workflow.ts | 82 +++++++++++++-------- 9 files changed, 132 insertions(+), 48 deletions(-) diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index 44e17d25..d6cc487e 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -118,6 +118,7 @@ const ExecutedWorkflowTask = t.type({ taskType: optional(t.string), status: optional(ExecutedWorkflowTaskStatus), inputData: optional(t.record(t.string, t.unknown)), + outputData: optional(t.record(t.string, t.unknown)), referenceTaskName: optional(t.string), retryCount: optional(t.number), seq: optional(t.number), @@ -163,7 +164,7 @@ const ExecutedWorkflow = t.type({ updatedBy: optional(t.string), status: ExecutedWorkflowStatus, endTime: optional(t.number), - workflowId: optional(t.string), + workflowId: t.string, parentWorkflowId: optional(t.string), parentWorkflowTaskId: optional(t.string), tasks: optional(t.array(ExecutedWorkflowTask)), @@ -264,3 +265,7 @@ export function decodeBulkRetryOutput(value: unknown): BulkOperationOutput { export function decodeBulkRestartOutput(value: unknown): BulkOperationOutput { return extractResult(BulkOperation.decode(value)); } + +export function decodeExecutedWorkflowTaskDetailOutput(value: unknown): ApiExecutedWorkflowTask { + return extractResult(ExecutedWorkflowTask.decode(value)); +} diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts index a7d29b21..37107143 100644 --- a/src/external-api/conductor.ts +++ b/src/external-api/conductor.ts @@ -15,6 +15,8 @@ import { TaskDefinitionsOutput, decodeTaskDefinitionsOutput, decodeBulkTerminateOutput, + decodeExecutedWorkflowTaskDetailOutput, + ApiExecutedWorkflowTask, } from './conductor-network-types'; import { sendDeleteRequest, sendGetRequest, sendPostRequest, sendPutRequest } from './helpers'; @@ -180,7 +182,12 @@ async function executeWorkflowByName( { name, inputParameters, correlationId, version, priority }: ExecuteWorkflowByNameInput, ): Promise { const executedWorkflowId = await sendPostRequest( - [baseURL, `workflow/${name}?version=${version}&correlationId=${correlationId}&priority=${priority}`], + [ + baseURL, + `workflow/${name}?${version == null ? '' : `version=${version}`}${ + correlationId == null ? '' : `&correlationId=${correlationId}` + }&priority=${priority == null ? 0 : priority}`, + ], inputParameters, ); @@ -197,6 +204,12 @@ async function getTaskDefinitions(baseURL: string): Promise { + const json = await sendGetRequest([baseURL, `/tasks/${taskId}`]); + const data = decodeExecutedWorkflowTaskDetailOutput(json); + return data; +} + const conductorAPI = { getWorkflowMetadata, getWorkflowDetail, @@ -219,6 +232,7 @@ const conductorAPI = { executeNewWorkflow, executeWorkflowByName, getTaskDefinitions, + getExecutedWorkflowTaskDetail, }; export type ConductorAPI = typeof conductorAPI; diff --git a/src/external-api/helpers.ts b/src/external-api/helpers.ts index 7e0c53a9..0af2cef9 100644 --- a/src/external-api/helpers.ts +++ b/src/external-api/helpers.ts @@ -89,10 +89,13 @@ async function apiFetch(path: APIPath, options: RequestInit): Promise { return response; } - const json = JSON.parse(text); - logResponse(requestId, json); - - return json; + try { + const json = JSON.parse(text); + return json; + } catch (e) { + logResponse(requestId, text); + return text; + } } export async function sendGetRequest(path: APIPath, cookie?: string): Promise { diff --git a/src/helpers/workflow.helpers.ts b/src/helpers/workflow.helpers.ts index d010effe..30347ba7 100644 --- a/src/helpers/workflow.helpers.ts +++ b/src/helpers/workflow.helpers.ts @@ -112,7 +112,7 @@ function extractSubworkflowsFromTasks(task: ExecutedWorkflowTask): SubWorkflow | } type SubworkflowDetail = { - taskReferenceName: string; + referenceTaskName: string; workflowDetail: Workflow; executedWorkflowDetail: ExecutedWorkflow; }; @@ -137,7 +137,7 @@ async function getSubworklowsDetail(subWorkflow: SubWorkflow): Promise toGraphId('ExecutedWorkflowTask', executedWorkflowTask.taskId ?? uuid()), }); t.string('taskType'); - t.string('taskReferenceName'); + t.string('referenceTaskName'); t.field('status', { type: ExecutedWorkflowTaskStatus }); t.int('retryCount'); t.string('startTime', { @@ -76,6 +76,13 @@ export const ExecutedWorkflowTask = objectType({ t.string('reasonForIncompletion'); t.string('taskDefinition', { resolve: (task) => JSON.stringify(task.taskDefinition) }); t.string('subWorkflowId'); + t.string('inputData', { resolve: (task) => JSON.stringify(task.inputData) }); + t.string('outputData', { resolve: (task) => JSON.stringify(task.outputData) }); + t.string('externalOutputPayloadStoragePath'); + t.string('externalInputPayloadStoragePath'); + t.int('callbackAfterSeconds'); + t.int('seq'); + t.int('pollCount'); }, }); diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index bece9947..f1acb5a3 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -213,7 +213,7 @@ export const ExecutedWorkflow = objectType({ definition(t) { t.implements(Node); t.nonNull.id('id', { - resolve: () => toGraphId('ExecutedWorkflow', uuid()), + resolve: (root) => toGraphId('ExecutedWorkflow', root.workflowId), }); t.string('createdBy', { resolve: (executedWorkflow) => executedWorkflow.createdBy ?? null }); t.string('updatedBy', { resolve: (workflow) => workflow.updatedBy ?? null }); @@ -243,10 +243,11 @@ export const ExecutedWorkflow = objectType({ }); t.int('workflowVersion'); t.string('workflowName'); - t.string('workflowId'); + t.nonNull.string('workflowId'); t.list.nonNull.field('tasks', { type: ExecutedWorkflowTask, }); + t.string('correlationId'); }, }); @@ -323,7 +324,7 @@ export const ExecutedWorkflowsQuery = queryField('executedWorkflows', { const executedWorkflowsWithId = executedWorkflows .map((w) => ({ ...w, - id: toGraphId('ExecutedWorkflow', uuid()), + id: toGraphId('ExecutedWorkflow', w.workflowId), })) .slice(0, args.pagination?.size ?? 0 - 1); @@ -346,7 +347,7 @@ export const ExecutedWorkflowsQuery = queryField('executedWorkflows', { const SubWorkflow = objectType({ name: 'SubWorkflow', definition: (t) => { - t.nonNull.string('taskReferenceName'); + t.nonNull.string('referenceTaskName'); t.nonNull.field('workflowDetail', { type: Workflow }); t.nonNull.field('executedWorkflowDetail', { type: ExecutedWorkflow }); }, @@ -372,7 +373,7 @@ export const WorkflowInstanceQuery = queryField('workflowInstanceDetail', { const result = await conductorAPI.getExecutedWorkflowDetail( config.conductorApiURL, - workflowId, + fromGraphId('ExecutedWorkflow', workflowId), shouldIncludeTasks ?? false, ); @@ -390,7 +391,7 @@ export const WorkflowInstanceQuery = queryField('workflowInstanceDetail', { const subworkflows = await getSubworkflows({ ...result, - id: toGraphId('ExecutedWorkflow', uuid()), + id: toGraphId('ExecutedWorkflow', result.workflowId), }); return { @@ -646,7 +647,7 @@ export const PauseWorkflowMutation = mutationField('pauseWorkflow', { id: nonNull(stringArg()), }, resolve: async (_, { id }, { conductorAPI }) => { - await conductorAPI.pauseWorkflow(config.conductorApiURL, id); + await conductorAPI.pauseWorkflow(config.conductorApiURL, fromGraphId('ExecutedWorkflow', id)); return { isOk: true }; }, @@ -658,7 +659,7 @@ export const ResumeWorkflowMutation = mutationField('resumeWorkflow', { id: nonNull(stringArg()), }, resolve: async (_, { id }, { conductorAPI }) => { - await conductorAPI.resumeWorkflow(config.conductorApiURL, id); + await conductorAPI.resumeWorkflow(config.conductorApiURL, fromGraphId('ExecutedWorkflow', id)); return { isOk: true }; }, @@ -685,11 +686,12 @@ export const BulkResumeWorkflowMutation = mutationField('bulkResumeWorkflow', { input: nonNull(arg({ type: BulkOperationInput })), }, resolve: async (_, { input }, { conductorAPI }) => { - const data = await conductorAPI.bulkResumeWorkflow(config.conductorApiURL, input.executedWorkflowIds); + const executedWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); + const data = await conductorAPI.bulkResumeWorkflow(config.conductorApiURL, executedWorkflowIds); return { bulkErrorResults: JSON.stringify(data.bulkErrorResults), - bulkSuccessfulResults: data.bulkSuccessfulResults, + bulkSuccessfulResults: data.bulkSuccessfulResults.map((id) => toGraphId('ExecutedWorkflow', id)), }; }, }); @@ -715,15 +717,21 @@ export const ExecuteWorkflowByName = mutationField('executeWorkflowByName', { { input: { inputParameters, workflowName, workflowVersion, correlationId, priority } }, { conductorAPI }, ) => { + const json = parseJson>(inputParameters); + + if (json == null) { + throw new Error('inputParameters must be a valid JSON string'); + } + const workflowId = await conductorAPI.executeWorkflowByName(config.conductorApiURL, { - inputParameters: parseJson(inputParameters), + inputParameters: json, name: workflowName, version: workflowVersion, correlationId, priority, }); - return workflowId; + return toGraphId('ExecutedWorkflow', workflowId); }, }); @@ -733,11 +741,12 @@ export const BulkPauseWorkflowMutation = mutationField('bulkPauseWorkflow', { input: nonNull(arg({ type: BulkOperationInput })), }, resolve: async (_, { input }, { conductorAPI }) => { - const data = await conductorAPI.bulkPauseWorkflow(config.conductorApiURL, input.executedWorkflowIds); + const executedWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); + const data = await conductorAPI.bulkPauseWorkflow(config.conductorApiURL, executedWorkflowIds); return { bulkErrorResults: JSON.stringify(data.bulkErrorResults), - bulkSuccessfulResults: data.bulkSuccessfulResults, + bulkSuccessfulResults: data.bulkSuccessfulResults.map((id) => toGraphId('ExecutedWorkflow', id)), }; }, }); @@ -748,11 +757,12 @@ export const BulkTerminateWorkflow = mutationField('bulkTerminateWorkflow', { input: nonNull(arg({ type: BulkOperationInput })), }, resolve: async (_, { input }, { conductorAPI }) => { - const data = await conductorAPI.bulkTerminateWorkflow(config.conductorApiURL, input.executedWorkflowIds); + const executedWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); + const data = await conductorAPI.bulkTerminateWorkflow(config.conductorApiURL, executedWorkflowIds); return { bulkErrorResults: JSON.stringify(data.bulkErrorResults), - bulkSuccessfulResults: data.bulkSuccessfulResults, + bulkSuccessfulResults: data.bulkSuccessfulResults.map((id) => toGraphId('ExecutedWorkflow', id)), }; }, }); @@ -763,11 +773,12 @@ export const BulkRetryWorkflow = mutationField('bulkRetryWorkflow', { input: nonNull(arg({ type: BulkOperationInput })), }, resolve: async (_, { input }, { conductorAPI }) => { - const data = await conductorAPI.bulkRetryWorkflow(config.conductorApiURL, input.executedWorkflowIds); + const executedWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); + const data = await conductorAPI.bulkRetryWorkflow(config.conductorApiURL, executedWorkflowIds); return { bulkErrorResults: JSON.stringify(data.bulkErrorResults), - bulkSuccessfulResults: data.bulkSuccessfulResults, + bulkSuccessfulResults: data.bulkSuccessfulResults.map((id) => toGraphId('ExecutedWorkflow', id)), }; }, }); @@ -778,11 +789,12 @@ export const BulkRestartWorkflow = mutationField('bulkRestartWorkflow', { input: nonNull(arg({ type: BulkOperationInput })), }, resolve: async (_, { input }, { conductorAPI }) => { - const data = await conductorAPI.bulkRestartWorkflow(config.conductorApiURL, input.executedWorkflowIds); + const executedWorkflowIds = input.executedWorkflowIds.map((id) => fromGraphId('ExecutedWorkflow', id)); + const data = await conductorAPI.bulkRestartWorkflow(config.conductorApiURL, executedWorkflowIds); return { bulkErrorResults: JSON.stringify(data.bulkErrorResults), - bulkSuccessfulResults: data.bulkSuccessfulResults, + bulkSuccessfulResults: data.bulkSuccessfulResults.map((id) => toGraphId('ExecutedWorkflow', id)), }; }, }); @@ -801,7 +813,11 @@ export const RetryWorkflowMutation = mutationField('retryWorkflow', { input: arg({ type: RetryWorkflowInput }), }, resolve: async (_, { id, input }, { conductorAPI }) => { - await conductorAPI.retryWorkflow(config.conductorApiURL, id, input?.shouldResumeSubworkflowTasks); + await conductorAPI.retryWorkflow( + config.conductorApiURL, + fromGraphId('ExecutedWorkflow', id), + input?.shouldResumeSubworkflowTasks, + ); return { isOk: true }; }, @@ -821,7 +837,11 @@ export const RestartWorkflowMutation = mutationField('restartWorkflow', { input: arg({ type: RestartWorkflowInput }), }, resolve: async (_, { id, input }, { conductorAPI }) => { - await conductorAPI.restartWorkflow(config.conductorApiURL, id, input?.shouldUseLatestDefinitions); + await conductorAPI.restartWorkflow( + config.conductorApiURL, + fromGraphId('ExecutedWorkflow', id), + input?.shouldUseLatestDefinitions, + ); return { isOk: true }; }, @@ -841,7 +861,7 @@ export const TerminateWorkflowMutation = mutationField('terminateWorkflow', { input: arg({ type: TerminateWorkflowInput }), }, resolve: async (_, { id, input }, { conductorAPI }) => { - await conductorAPI.terminateWorkflow(config.conductorApiURL, id, input?.reason); + await conductorAPI.terminateWorkflow(config.conductorApiURL, fromGraphId('ExecutedWorkflow', id), input?.reason); return { isOk: true }; }, @@ -861,7 +881,11 @@ export const RemoveWorkflowMutation = mutationField('removeWorkflow', { input: arg({ type: RemoveWorkflowInput }), }, resolve: async (_, { id, input }, { conductorAPI }) => { - await conductorAPI.removeWorkflow(config.conductorApiURL, id, input?.shouldArchiveWorkflow); + await conductorAPI.removeWorkflow( + config.conductorApiURL, + fromGraphId('ExecutedWorkflow', id), + input?.shouldArchiveWorkflow, + ); return { isOk: true }; }, @@ -1059,10 +1083,11 @@ export const ExecutedWorkflowSubscription = subscriptionField('controlExecutedWo args: { id: nonNull(stringArg()), }, - subscribe: async (_, { id }, { conductorAPI }) => + subscribe: (_, { id }, { conductorAPI }) => asyncGenerator({ repeatTill: (workflow) => workflow?.status === 'RUNNING' || workflow?.status === 'PAUSED', - fn: () => conductorAPI.getExecutedWorkflowDetail(config.conductorApiURL, id, false), + fn: () => + conductorAPI.getExecutedWorkflowDetail(config.conductorApiURL, fromGraphId('ExecutedWorkflow', id), true), }), resolve: (workflow) => { if (workflow == null) { @@ -1071,10 +1096,7 @@ export const ExecutedWorkflowSubscription = subscriptionField('controlExecutedWo return { ...workflow, - id: toGraphId('ExecutedWorkflow', uuid()), + id: toGraphId('ExecutedWorkflow', workflow.workflowId), }; }, }); - -// id generujem podla nasej hodnoty nejakej -// ked budem chciet query alebo presmerovat niekam pouzijem workflowId a ak bude null vratim error ze neexistuje workflow s tymto id From 4a8e3b5b0e2f2f6d4a0179c9f7b876afd76ca928 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 8 Jun 2023 15:32:46 +0200 Subject: [PATCH 24/69] prettier fix --- src/__generated__/graphql.ts | 104 +++++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 23 deletions(-) diff --git a/src/__generated__/graphql.ts b/src/__generated__/graphql.ts index af39c7c6..db014ee9 100644 --- a/src/__generated__/graphql.ts +++ b/src/__generated__/graphql.ts @@ -33,17 +33,14 @@ export type Mutation = { updateSchedule: Schedule; }; - export type MutationCreateScheduleArgs = { input: CreateScheduleInput; }; - export type MutationDeleteScheduleArgs = { name: Scalars['String']; }; - export type MutationUpdateScheduleArgs = { input: UpdateScheduleInput; name: Scalars['String']; @@ -63,12 +60,10 @@ export type Query = { schedules: Maybe; }; - export type QueryScheduleArgs = { name: Scalars['String']; }; - export type QuerySchedulesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -109,14 +104,7 @@ export type SchedulesFilterInput = { workflowVersion: Scalars['String']; }; -export type Status = - | 'COMPLETED' - | 'FAILED' - | 'PAUSED' - | 'RUNNING' - | 'TERMINATED' - | 'TIMED_OUT' - | 'UNKNOWN'; +export type Status = 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; export type UpdateScheduleInput = { cronString?: InputMaybe; @@ -133,30 +121,71 @@ export type DeleteScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; }>; - -export type DeleteScheduleMutation = { __typename?: 'Mutation', deleteSchedule: boolean }; +export type DeleteScheduleMutation = { __typename?: 'Mutation'; deleteSchedule: boolean }; export type UpdateScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; input: UpdateScheduleInput; }>; - -export type UpdateScheduleMutation = { __typename?: 'Mutation', updateSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; +export type UpdateScheduleMutation = { + __typename?: 'Mutation'; + updateSchedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; +}; export type CreateScheduleMutationVariables = Exact<{ input: CreateScheduleInput; }>; - -export type CreateScheduleMutation = { __typename?: 'Mutation', createSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; +export type CreateScheduleMutation = { + __typename?: 'Mutation'; + createSchedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; +}; export type GetScheduleQueryVariables = Exact<{ scheduleName: Scalars['String']; }>; - -export type GetScheduleQuery = { __typename?: 'Query', schedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } | null }; +export type GetScheduleQuery = { + __typename?: 'Query'; + schedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + } | null; +}; export type GetSchedulesQueryVariables = Exact<{ first?: InputMaybe; @@ -166,5 +195,34 @@ export type GetSchedulesQueryVariables = Exact<{ filter?: InputMaybe; }>; - -export type GetSchedulesQuery = { __typename?: 'Query', schedules: { __typename?: 'ScheduleConnection', totalCount: number, edges: Array<{ __typename?: 'ScheduleEdge', cursor: string, node: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null } } | null }; +export type GetSchedulesQuery = { + __typename?: 'Query'; + schedules: { + __typename?: 'ScheduleConnection'; + totalCount: number; + edges: Array<{ + __typename?: 'ScheduleEdge'; + cursor: string; + node: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; + } | null>; + pageInfo: { + __typename?: 'PageInfo'; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; + endCursor: string | null; + }; + } | null; +}; From 0c082263787a428d5abcee0ff8bb5eca11d35909 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Fri, 16 Jun 2023 15:40:11 +0200 Subject: [PATCH 25/69] FD-537 add resource manager (#312) * add resource manager to inventory server * push missing files * fix GetPool request --- .env.example | 1 + .eslintignore | 2 +- codegen-resource-manager.yml | 15 + codegen.yml => codegen-scheduler.yml | 4 +- package.json | 4 +- src/__generated__/resource-manager.graphql.ts | 732 ++++++++++++++++++ .../{graphql.ts => scheduler.graphql.ts} | 104 +-- src/config.ts | 1 + src/context.ts | 12 +- src/external-api/resource-manager.ts | 116 +++ src/external-api/scheduler.ts | 2 +- src/helpers/id-helper.ts | 6 +- src/helpers/resource-manager.helpers.ts | 45 ++ src/schema/api.graphql | 52 ++ src/schema/global-types.ts | 14 + src/schema/index.ts | 2 + src/schema/nexus-typegen.ts | 113 +++ src/schema/pool.ts | 93 +++ src/schema/source-types.ts | 4 +- 19 files changed, 1232 insertions(+), 90 deletions(-) create mode 100644 codegen-resource-manager.yml rename codegen.yml => codegen-scheduler.yml (76%) create mode 100644 src/__generated__/resource-manager.graphql.ts rename src/__generated__/{graphql.ts => scheduler.graphql.ts} (66%) create mode 100644 src/external-api/resource-manager.ts create mode 100644 src/helpers/resource-manager.helpers.ts create mode 100644 src/schema/pool.ts diff --git a/.env.example b/.env.example index dc92e91b..8461c225 100644 --- a/.env.example +++ b/.env.example @@ -6,6 +6,7 @@ UNICONFIG_API_PORT=4000 UNICONFIG_LIST_URL=http://localhost:4000/static/list/uniconfig CONDUCTOR_API_URL="http:/10.19.0.7:8080/api" SCHEDULER_API_URL="http://10.19.0.7:3001/query" +RESOURCE_MANAGER_API_URL="http://10.19.0.7/api/resource" SHELL_HOST=10.19.0.12 X_TENANT_ID="frinx" TOPOLOGY_ENABLED=true diff --git a/.eslintignore b/.eslintignore index 10ad9282..122b77b6 100644 --- a/.eslintignore +++ b/.eslintignore @@ -8,4 +8,4 @@ seed.ts init.ts src/helpers/base64.helpers.ts src/helpers/connection.helpers.ts -src/__generated__/graphql.ts \ No newline at end of file +src/__generated__/*.graphql.ts \ No newline at end of file diff --git a/codegen-resource-manager.yml b/codegen-resource-manager.yml new file mode 100644 index 00000000..47a4679a --- /dev/null +++ b/codegen-resource-manager.yml @@ -0,0 +1,15 @@ +schema: + - 'http://10.19.0.7/api/resource' +documents: + - './src/external-api/resource-manager.ts' +generates: + src/__generated__/resource-manager.graphql.ts: + plugins: + - 'typescript' + - 'typescript-operations' + config: + enumsAsTypes: true + avoidOptionals: + field: true + object: false + inputValue: false diff --git a/codegen.yml b/codegen-scheduler.yml similarity index 76% rename from codegen.yml rename to codegen-scheduler.yml index 874d0c3f..974feb19 100644 --- a/codegen.yml +++ b/codegen-scheduler.yml @@ -1,9 +1,9 @@ schema: - 'http://10.19.0.7:3001/query' documents: - - './src/**/*.ts' + - './src/external-api/scheduler.ts' generates: - src/__generated__/graphql.ts: + src/__generated__/scheduler.graphql.ts: plugins: - 'typescript' - 'typescript-operations' diff --git a/package.json b/package.json index a42cfee6..0857c205 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,9 @@ "test:generate": "cross-env NODE_ENV=testing ts-node --transpile-only -r dotenv/config src/schema/index.ts", "jest": "cross-env NODE_ENV=testing jest --verbose", "test": "run-s test:generate jest", - "codegen": "graphql-codegen --config codegen.yml" + "codegen:scheduler": "graphql-codegen --config codegen-scheduler.yml", + "codegen:resource-manager": "graphql-codegen --config codegen-resource-manager.yml", + "codegen": "yarn codegen:scheduler && yarn codegen:resource-manager" }, "devDependencies": { "@frinx/eslint-config-typescript-base": "15.0.0-build.1", diff --git a/src/__generated__/resource-manager.graphql.ts b/src/__generated__/resource-manager.graphql.ts new file mode 100644 index 00000000..d53d9352 --- /dev/null +++ b/src/__generated__/resource-manager.graphql.ts @@ -0,0 +1,732 @@ +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 }; +/** All built-in and custom scalars, mapped to their actual values */ +export type Scalars = { + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; + Cursor: any; + Map: any; +}; + +/** Represents an allocation strategy */ +export type AllocationStrategy = Node & { + __typename?: 'AllocationStrategy'; + Description: Maybe; + Lang: AllocationStrategyLang; + Name: Scalars['String']; + Script: Scalars['String']; + id: Scalars['ID']; +}; + +/** Supported languages for allocation strategy scripts */ +export type AllocationStrategyLang = + | 'js' + | 'py'; + +/** Input parameters for creating an allocation pool */ +export type CreateAllocatingPoolInput = { + allocationStrategyId: Scalars['ID']; + description?: InputMaybe; + poolDealocationSafetyPeriod: Scalars['Int']; + poolName: Scalars['String']; + poolProperties: Scalars['Map']; + poolPropertyTypes: Scalars['Map']; + resourceTypeId: Scalars['ID']; + tags?: InputMaybe>; +}; + +/** Output of creating an allocating pool */ +export type CreateAllocatingPoolPayload = { + __typename?: 'CreateAllocatingPoolPayload'; + pool: Maybe; +}; + +/** Input parameters for creating a new allocation strategy */ +export type CreateAllocationStrategyInput = { + description?: InputMaybe; + expectedPoolPropertyTypes?: InputMaybe; + lang: AllocationStrategyLang; + name: Scalars['String']; + script: Scalars['String']; +}; + +/** Output of creating a new allocation strategy */ +export type CreateAllocationStrategyPayload = { + __typename?: 'CreateAllocationStrategyPayload'; + strategy: Maybe; +}; + +/** Input parameters for creating a nested allocation pool */ +export type CreateNestedAllocatingPoolInput = { + allocationStrategyId: Scalars['ID']; + description?: InputMaybe; + parentResourceId: Scalars['ID']; + poolDealocationSafetyPeriod: Scalars['Int']; + poolName: Scalars['String']; + resourceTypeId: Scalars['ID']; + tags?: InputMaybe>; +}; + +/** Output of creating a nested allocating pool */ +export type CreateNestedAllocatingPoolPayload = { + __typename?: 'CreateNestedAllocatingPoolPayload'; + pool: Maybe; +}; + +/** Input parameters for creating a nested set pool */ +export type CreateNestedSetPoolInput = { + description?: InputMaybe; + parentResourceId: Scalars['ID']; + poolDealocationSafetyPeriod: Scalars['Int']; + poolName: Scalars['String']; + poolValues: Array>; + resourceTypeId: Scalars['ID']; + tags?: InputMaybe>; +}; + +/** Output of creating a nested set pool */ +export type CreateNestedSetPoolPayload = { + __typename?: 'CreateNestedSetPoolPayload'; + pool: Maybe; +}; + +/** Input parameters for creating a nested singleton pool */ +export type CreateNestedSingletonPoolInput = { + description?: InputMaybe; + parentResourceId: Scalars['ID']; + poolName: Scalars['String']; + poolValues: Array>; + resourceTypeId: Scalars['ID']; + tags?: InputMaybe>; +}; + +/** Output of creating a nested singleton pool */ +export type CreateNestedSingletonPoolPayload = { + __typename?: 'CreateNestedSingletonPoolPayload'; + pool: Maybe; +}; + +/** Creating a new resource-type */ +export type CreateResourceTypeInput = { + /** name of the resource type AND property type (should they be different?) */ + resourceName: Scalars['String']; + /** + * resourceProperties: Map! - for key "init" the value is the initial value of the property type (like 7) + * - for key "type" the value is the name of the type like "int" + */ + resourceProperties: Scalars['Map']; +}; + +/** Output of creating a new resource-type */ +export type CreateResourceTypePayload = { + __typename?: 'CreateResourceTypePayload'; + resourceType: ResourceType; +}; + +/** Input parameters for creating a set pool */ +export type CreateSetPoolInput = { + description?: InputMaybe; + poolDealocationSafetyPeriod: Scalars['Int']; + poolName: Scalars['String']; + poolValues: Array; + resourceTypeId: Scalars['ID']; + tags?: InputMaybe>; +}; + +/** Output of creating set pool */ +export type CreateSetPoolPayload = { + __typename?: 'CreateSetPoolPayload'; + pool: Maybe; +}; + +/** Input parameters for creating a singleton pool */ +export type CreateSingletonPoolInput = { + description?: InputMaybe; + poolName: Scalars['String']; + poolValues: Array; + resourceTypeId: Scalars['ID']; + tags?: InputMaybe>; +}; + +/** Output of creating a singleton pool */ +export type CreateSingletonPoolPayload = { + __typename?: 'CreateSingletonPoolPayload'; + pool: Maybe; +}; + +/** Input parameters for creating a new tag */ +export type CreateTagInput = { + tagText: Scalars['String']; +}; + +/** Output of creating a tag */ +export type CreateTagPayload = { + __typename?: 'CreateTagPayload'; + tag: Maybe; +}; + +/** Input parameters for deleting an existing allocation strategy */ +export type DeleteAllocationStrategyInput = { + allocationStrategyId: Scalars['ID']; +}; + +/** Output of deleting an existing allocation strategy */ +export type DeleteAllocationStrategyPayload = { + __typename?: 'DeleteAllocationStrategyPayload'; + strategy: Maybe; +}; + +/** Input entity for deleting a pool */ +export type DeleteResourcePoolInput = { + resourcePoolId: Scalars['ID']; +}; + +/** Output entity for deleting a pool */ +export type DeleteResourcePoolPayload = { + __typename?: 'DeleteResourcePoolPayload'; + resourcePoolId: Scalars['ID']; +}; + +/** Input parameters for deleting an existing resource-type */ +export type DeleteResourceTypeInput = { + resourceTypeId: Scalars['ID']; +}; + +/** Output of deleting a resource-type */ +export type DeleteResourceTypePayload = { + __typename?: 'DeleteResourceTypePayload'; + resourceTypeId: Scalars['ID']; +}; + +/** Input parameters for deleting an existing tag */ +export type DeleteTagInput = { + tagId: Scalars['ID']; +}; + +/** Output of deleting a tag */ +export type DeleteTagPayload = { + __typename?: 'DeleteTagPayload'; + tagId: Scalars['ID']; +}; + +export type Mutation = { + __typename?: 'Mutation'; + ClaimResource: Resource; + ClaimResourceWithAltId: Resource; + CreateAllocatingPool: CreateAllocatingPoolPayload; + CreateAllocationStrategy: CreateAllocationStrategyPayload; + CreateNestedAllocatingPool: CreateNestedAllocatingPoolPayload; + CreateNestedSetPool: CreateNestedSetPoolPayload; + CreateNestedSingletonPool: CreateNestedSingletonPoolPayload; + CreateResourceType: CreateResourceTypePayload; + CreateSetPool: CreateSetPoolPayload; + CreateSingletonPool: CreateSingletonPoolPayload; + CreateTag: CreateTagPayload; + DeleteAllocationStrategy: DeleteAllocationStrategyPayload; + DeleteResourcePool: DeleteResourcePoolPayload; + DeleteResourceType: DeleteResourceTypePayload; + DeleteTag: DeleteTagPayload; + FreeResource: Scalars['String']; + TagPool: TagPoolPayload; + TestAllocationStrategy: Scalars['Map']; + UntagPool: UntagPoolPayload; + UpdateResourceAltId: Resource; + UpdateResourceTypeName: UpdateResourceTypeNamePayload; + UpdateTag: UpdateTagPayload; +}; + + +export type MutationClaimResourceArgs = { + description?: InputMaybe; + poolId: Scalars['ID']; + userInput: Scalars['Map']; +}; + + +export type MutationClaimResourceWithAltIdArgs = { + alternativeId: Scalars['Map']; + description?: InputMaybe; + poolId: Scalars['ID']; + userInput: Scalars['Map']; +}; + + +export type MutationCreateAllocatingPoolArgs = { + input?: InputMaybe; +}; + + +export type MutationCreateAllocationStrategyArgs = { + input?: InputMaybe; +}; + + +export type MutationCreateNestedAllocatingPoolArgs = { + input: CreateNestedAllocatingPoolInput; +}; + + +export type MutationCreateNestedSetPoolArgs = { + input: CreateNestedSetPoolInput; +}; + + +export type MutationCreateNestedSingletonPoolArgs = { + input: CreateNestedSingletonPoolInput; +}; + + +export type MutationCreateResourceTypeArgs = { + input: CreateResourceTypeInput; +}; + + +export type MutationCreateSetPoolArgs = { + input: CreateSetPoolInput; +}; + + +export type MutationCreateSingletonPoolArgs = { + input?: InputMaybe; +}; + + +export type MutationCreateTagArgs = { + input: CreateTagInput; +}; + + +export type MutationDeleteAllocationStrategyArgs = { + input?: InputMaybe; +}; + + +export type MutationDeleteResourcePoolArgs = { + input: DeleteResourcePoolInput; +}; + + +export type MutationDeleteResourceTypeArgs = { + input: DeleteResourceTypeInput; +}; + + +export type MutationDeleteTagArgs = { + input: DeleteTagInput; +}; + + +export type MutationFreeResourceArgs = { + input: Scalars['Map']; + poolId: Scalars['ID']; +}; + + +export type MutationTagPoolArgs = { + input: TagPoolInput; +}; + + +export type MutationTestAllocationStrategyArgs = { + allocationStrategyId: Scalars['ID']; + currentResources: Array; + resourcePool: ResourcePoolInput; + userInput: Scalars['Map']; +}; + + +export type MutationUntagPoolArgs = { + input: UntagPoolInput; +}; + + +export type MutationUpdateResourceAltIdArgs = { + alternativeId: Scalars['Map']; + input: Scalars['Map']; + poolId: Scalars['ID']; +}; + + +export type MutationUpdateResourceTypeNameArgs = { + input: UpdateResourceTypeNameInput; +}; + + +export type MutationUpdateTagArgs = { + input: UpdateTagInput; +}; + +/** Interface for entities needed by the relay-framework */ +export type Node = { + /** The ID of the entity */ + id: Scalars['ID']; +}; + +/** Holds the string value for pagination */ +export type OutputCursor = { + __typename?: 'OutputCursor'; + ID: Scalars['String']; +}; + +/** Holds information about the requested pagination page */ +export type PageInfo = { + __typename?: 'PageInfo'; + endCursor: Maybe; + hasNextPage: Scalars['Boolean']; + hasPreviousPage: Scalars['Boolean']; + startCursor: Maybe; +}; + +/** Entity representing capacity of a pool */ +export type PoolCapacityPayload = { + __typename?: 'PoolCapacityPayload'; + freeCapacity: Scalars['String']; + utilizedCapacity: Scalars['String']; +}; + +/** Defines the type of pool */ +export type PoolType = + | 'allocating' + | 'set' + | 'singleton'; + +/** Defines the type of the property */ +export type PropertyType = Node & { + __typename?: 'PropertyType'; + FloatVal: Maybe; + IntVal: Maybe; + Mandatory: Maybe; + Name: Scalars['String']; + StringVal: Maybe; + Type: Scalars['String']; + id: Scalars['ID']; +}; + +export type Query = { + __typename?: 'Query'; + QueryAllocationStrategies: Array; + QueryAllocationStrategy: AllocationStrategy; + QueryEmptyResourcePools: ResourcePoolConnection; + QueryLeafResourcePools: ResourcePoolConnection; + QueryPoolCapacity: PoolCapacityPayload; + QueryPoolTypes: Array; + QueryRecentlyActiveResources: ResourceConnection; + QueryRequiredPoolProperties: Array; + QueryResource: Resource; + QueryResourcePool: ResourcePool; + QueryResourcePoolHierarchyPath: Array; + QueryResourcePools: ResourcePoolConnection; + QueryResourceTypes: Array; + QueryResources: ResourceConnection; + QueryResourcesByAltId: ResourceConnection; + QueryRootResourcePools: ResourcePoolConnection; + QueryTags: Array; + SearchPoolsByTags: ResourcePoolConnection; + node: Maybe; +}; + + +export type QueryQueryAllocationStrategiesArgs = { + byName?: InputMaybe; +}; + + +export type QueryQueryAllocationStrategyArgs = { + allocationStrategyId: Scalars['ID']; +}; + + +export type QueryQueryEmptyResourcePoolsArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + resourceTypeId?: InputMaybe; +}; + + +export type QueryQueryLeafResourcePoolsArgs = { + after?: InputMaybe; + before?: InputMaybe; + filterByResources?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + resourceTypeId?: InputMaybe; + tags?: InputMaybe; +}; + + +export type QueryQueryPoolCapacityArgs = { + poolId: Scalars['ID']; +}; + + +export type QueryQueryRecentlyActiveResourcesArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + fromDatetime: Scalars['String']; + last?: InputMaybe; + toDatetime?: InputMaybe; +}; + + +export type QueryQueryRequiredPoolPropertiesArgs = { + allocationStrategyName: Scalars['String']; +}; + + +export type QueryQueryResourceArgs = { + input: Scalars['Map']; + poolId: Scalars['ID']; +}; + + +export type QueryQueryResourcePoolArgs = { + poolId: Scalars['ID']; +}; + + +export type QueryQueryResourcePoolHierarchyPathArgs = { + poolId: Scalars['ID']; +}; + + +export type QueryQueryResourcePoolsArgs = { + after?: InputMaybe; + before?: InputMaybe; + filterByResources?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + resourceTypeId?: InputMaybe; + tags?: InputMaybe; +}; + + +export type QueryQueryResourceTypesArgs = { + byName?: InputMaybe; +}; + + +export type QueryQueryResourcesArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + poolId: Scalars['ID']; +}; + + +export type QueryQueryResourcesByAltIdArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + input: Scalars['Map']; + last?: InputMaybe; + poolId?: InputMaybe; +}; + + +export type QueryQueryRootResourcePoolsArgs = { + after?: InputMaybe; + before?: InputMaybe; + filterByResources?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + resourceTypeId?: InputMaybe; + tags?: InputMaybe; +}; + + +export type QuerySearchPoolsByTagsArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + tags?: InputMaybe; +}; + + +export type QueryNodeArgs = { + id: Scalars['ID']; +}; + +/** Represents an allocated resource */ +export type Resource = Node & { + __typename?: 'Resource'; + AlternativeId: Maybe; + Description: Maybe; + NestedPool: Maybe; + ParentPool: ResourcePool; + Properties: Scalars['Map']; + id: Scalars['ID']; +}; + +/** A Relay-specific entity holding information about pagination */ +export type ResourceConnection = { + __typename?: 'ResourceConnection'; + edges: Array>; + pageInfo: PageInfo; + totalCount: Scalars['Int']; +}; + +/** A Relay-specific entity that holds information about the requested pagination page */ +export type ResourceEdge = { + __typename?: 'ResourceEdge'; + cursor: OutputCursor; + node: Resource; +}; + +/** Alternative representation of identity of a resource (i.e. alternative to resource ID) */ +export type ResourceInput = { + Properties: Scalars['Map']; + Status: Scalars['String']; + UpdatedAt: Scalars['String']; +}; + +/** A pool is an entity that contains allocated and free resources */ +export type ResourcePool = Node & { + __typename?: 'ResourcePool'; + AllocationStrategy: Maybe; + Capacity: Maybe; + Name: Scalars['String']; + ParentResource: Maybe; + PoolProperties: Scalars['Map']; + PoolType: PoolType; + ResourceType: ResourceType; + Resources: Array; + Tags: Array; + allocatedResources: Maybe; + id: Scalars['ID']; +}; + + +/** A pool is an entity that contains allocated and free resources */ +export type ResourcePoolAllocatedResourcesArgs = { + after?: InputMaybe; + before?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; +}; + +export type ResourcePoolConnection = { + __typename?: 'ResourcePoolConnection'; + edges: Array>; + pageInfo: PageInfo; + totalCount: Scalars['Int']; +}; + +export type ResourcePoolEdge = { + __typename?: 'ResourcePoolEdge'; + cursor: OutputCursor; + node: ResourcePool; +}; + +/** Convenience entity representing the identity of a pool in some calls */ +export type ResourcePoolInput = { + ResourcePoolID: Scalars['ID']; + ResourcePoolName: Scalars['String']; + poolProperties: Scalars['Map']; +}; + +/** Describes the properties of a resource */ +export type ResourceType = Node & { + __typename?: 'ResourceType'; + Name: Scalars['String']; + Pools: Array; + PropertyTypes: Array; + id: Scalars['ID']; +}; + +/** Pools can be tagged for easier search */ +export type Tag = Node & { + __typename?: 'Tag'; + Pools: Maybe>>; + Tag: Scalars['String']; + id: Scalars['ID']; +}; + +/** Helper entities for tag search */ +export type TagAnd = { + matchesAll: Array; +}; + +/** Helper entities for tag search */ +export type TagOr = { + matchesAny: Array; +}; + +/** Input parameters for a call adding a tag to pool */ +export type TagPoolInput = { + poolId: Scalars['ID']; + tagId: Scalars['ID']; +}; + +/** Output of adding a specific tag to a pool */ +export type TagPoolPayload = { + __typename?: 'TagPoolPayload'; + tag: Maybe; +}; + +/** Input parameters for a call removing a tag from pool */ +export type UntagPoolInput = { + poolId: Scalars['ID']; + tagId: Scalars['ID']; +}; + +/** Output of removing a specific tag from a pool */ +export type UntagPoolPayload = { + __typename?: 'UntagPoolPayload'; + tag: Maybe; +}; + +/** Input parameters updating the name of a resource-type */ +export type UpdateResourceTypeNameInput = { + resourceName: Scalars['String']; + resourceTypeId: Scalars['ID']; +}; + +/** Output of updating the name of a resource-type */ +export type UpdateResourceTypeNamePayload = { + __typename?: 'UpdateResourceTypeNamePayload'; + resourceTypeId: Scalars['ID']; +}; + +/** Input parameters for updating an existing tag */ +export type UpdateTagInput = { + tagId: Scalars['ID']; + tagText: Scalars['String']; +}; + +/** Output of updating a tag */ +export type UpdateTagPayload = { + __typename?: 'UpdateTagPayload'; + tag: Maybe; +}; + +export type PoolFragmentFragment = { __typename?: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }; + +export type GetPoolQueryVariables = Exact<{ + nodeId: Scalars['ID']; +}>; + + +export type GetPoolQuery = { __typename?: 'Query', node: { __typename?: 'AllocationStrategy' } | { __typename?: 'PropertyType' } | { __typename?: 'Resource' } | { __typename?: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } } | { __typename?: 'ResourceType' } | { __typename?: 'Tag' } | null }; + +export type GetPoolsQueryVariables = Exact<{ + resourceTypeId?: InputMaybe; + first?: InputMaybe; + last?: InputMaybe; + before?: InputMaybe; + after?: InputMaybe; + filterByResources?: InputMaybe; +}>; + + +export type GetPoolsQuery = { __typename?: 'Query', QueryRootResourcePools: { __typename?: 'ResourcePoolConnection', totalCount: number, edges: Array<{ __typename?: 'ResourcePoolEdge', node: { __typename?: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }, cursor: { __typename?: 'OutputCursor', ID: string } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: { __typename?: 'OutputCursor', ID: string } | null, endCursor: { __typename?: 'OutputCursor', ID: string } | null } } }; diff --git a/src/__generated__/graphql.ts b/src/__generated__/scheduler.graphql.ts similarity index 66% rename from src/__generated__/graphql.ts rename to src/__generated__/scheduler.graphql.ts index db014ee9..af39c7c6 100644 --- a/src/__generated__/graphql.ts +++ b/src/__generated__/scheduler.graphql.ts @@ -33,14 +33,17 @@ export type Mutation = { updateSchedule: Schedule; }; + export type MutationCreateScheduleArgs = { input: CreateScheduleInput; }; + export type MutationDeleteScheduleArgs = { name: Scalars['String']; }; + export type MutationUpdateScheduleArgs = { input: UpdateScheduleInput; name: Scalars['String']; @@ -60,10 +63,12 @@ export type Query = { schedules: Maybe; }; + export type QueryScheduleArgs = { name: Scalars['String']; }; + export type QuerySchedulesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -104,7 +109,14 @@ export type SchedulesFilterInput = { workflowVersion: Scalars['String']; }; -export type Status = 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; +export type Status = + | 'COMPLETED' + | 'FAILED' + | 'PAUSED' + | 'RUNNING' + | 'TERMINATED' + | 'TIMED_OUT' + | 'UNKNOWN'; export type UpdateScheduleInput = { cronString?: InputMaybe; @@ -121,71 +133,30 @@ export type DeleteScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; }>; -export type DeleteScheduleMutation = { __typename?: 'Mutation'; deleteSchedule: boolean }; + +export type DeleteScheduleMutation = { __typename?: 'Mutation', deleteSchedule: boolean }; export type UpdateScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; input: UpdateScheduleInput; }>; -export type UpdateScheduleMutation = { - __typename?: 'Mutation'; - updateSchedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; -}; + +export type UpdateScheduleMutation = { __typename?: 'Mutation', updateSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; export type CreateScheduleMutationVariables = Exact<{ input: CreateScheduleInput; }>; -export type CreateScheduleMutation = { - __typename?: 'Mutation'; - createSchedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; -}; + +export type CreateScheduleMutation = { __typename?: 'Mutation', createSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; export type GetScheduleQueryVariables = Exact<{ scheduleName: Scalars['String']; }>; -export type GetScheduleQuery = { - __typename?: 'Query'; - schedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - } | null; -}; + +export type GetScheduleQuery = { __typename?: 'Query', schedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } | null }; export type GetSchedulesQueryVariables = Exact<{ first?: InputMaybe; @@ -195,34 +166,5 @@ export type GetSchedulesQueryVariables = Exact<{ filter?: InputMaybe; }>; -export type GetSchedulesQuery = { - __typename?: 'Query'; - schedules: { - __typename?: 'ScheduleConnection'; - totalCount: number; - edges: Array<{ - __typename?: 'ScheduleEdge'; - cursor: string; - node: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; - } | null>; - pageInfo: { - __typename?: 'PageInfo'; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; - endCursor: string | null; - }; - } | null; -}; + +export type GetSchedulesQuery = { __typename?: 'Query', schedules: { __typename?: 'ScheduleConnection', totalCount: number, edges: Array<{ __typename?: 'ScheduleEdge', cursor: string, node: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null } } | null }; diff --git a/src/config.ts b/src/config.ts index 245f3591..7cefd7a5 100644 --- a/src/config.ts +++ b/src/config.ts @@ -69,6 +69,7 @@ const config = { uniconfigListURL: envString('UNICONFIG_LIST_URL'), conductorApiURL: envString('CONDUCTOR_API_URL'), schedulerApiURL: envString('SCHEDULER_API_URL'), + resourceManagerApiURL: envString('RESOURCE_MANAGER_API_URL'), defaultTenantId: envString('X_TENANT_ID'), shellHost: envString('SHELL_HOST'), ...getTopologyConfig(), diff --git a/src/context.ts b/src/context.ts index f979a48f..e2daa4ff 100644 --- a/src/context.ts +++ b/src/context.ts @@ -4,6 +4,7 @@ import topologyDiscoveryAPI, { TopologyDiscoveryAPI } from './external-api/topol import conductorAPI, { ConductorAPI } from './external-api/conductor'; import uniconfigAPI, { UniConfigAPI } from './external-api/uniconfig'; import schedulerAPI, { SchedulerAPI } from './external-api/scheduler'; +import resourceManagerAPI, { ResourceManagerAPI } from './external-api/resource-manager'; import prismaClient from './prisma-client'; export type Context = { @@ -13,6 +14,7 @@ export type Context = { topologyDiscoveryAPI: TopologyDiscoveryAPI; conductorAPI: ConductorAPI; schedulerAPI: SchedulerAPI; + resourceManagerAPI: ResourceManagerAPI; }; export default function createContext(context: ExpressContext): Context { @@ -26,7 +28,15 @@ export default function createContext(context: ExpressContext): Context { tenantId = headers['x-tenant-id'] as string; } - return { prisma: prismaClient, tenantId, uniconfigAPI, topologyDiscoveryAPI, conductorAPI, schedulerAPI }; + return { + prisma: prismaClient, + tenantId, + uniconfigAPI, + topologyDiscoveryAPI, + conductorAPI, + schedulerAPI, + resourceManagerAPI, + }; } export function createSubscriptionContext() { diff --git a/src/external-api/resource-manager.ts b/src/external-api/resource-manager.ts new file mode 100644 index 00000000..b15b0736 --- /dev/null +++ b/src/external-api/resource-manager.ts @@ -0,0 +1,116 @@ +import { PaginationArgs } from 'nexus/dist/plugins/connectionPlugin'; +import { GraphQLClient, gql } from 'graphql-request'; +import config from '../config'; +import { + GetPoolQuery, + GetPoolQueryVariables, + GetPoolsQuery, + GetPoolsQueryVariables, + PoolFragmentFragment, +} from '../__generated__/resource-manager.graphql'; + +const client = new GraphQLClient(config.resourceManagerApiURL); + +const POOL_FRAGMENT = gql` + fragment PoolFragment on ResourcePool { + __typename + id + Name + PoolType + Tags { + id + Tag + } + PoolProperties + ResourceType { + id + Name + } + } +`; + +const GET_POOL_QUERY = gql` + query GetPool($nodeId: ID!) { + node(id: $nodeId) { + ... on ResourcePool { + ...PoolFragment + } + } + } + ${POOL_FRAGMENT} +`; + +const GET_POOLS_QUERY = gql` + query GetPools( + $resourceTypeId: ID + $first: Int + $last: Int + $before: Cursor + $after: Cursor + $filterByResources: Map + ) { + QueryRootResourcePools( + resourceTypeId: $resourceTypeId + first: $first + last: $last + before: $before + after: $after + filterByResources: $filterByResources + ) { + edges { + node { + ...PoolFragment + } + cursor { + ID + } + } + pageInfo { + hasNextPage + hasPreviousPage + startCursor { + ID + } + endCursor { + ID + } + } + totalCount + } + } + ${POOL_FRAGMENT} +`; + +async function getPool(nodeId: string): Promise { + const response = await client.request(GET_POOL_QUERY, { + nodeId, + }); + + if (response.node?.__typename !== 'ResourcePool') { + return null; + } + + return response.node; +} + +async function getPools( + resourceTypeId: string | null, + paginationArgs: PaginationArgs, + filter: Map | null, +) { + const response = await client.request(GET_POOLS_QUERY, { + resourceTypeId, + ...paginationArgs, + filterByResources: filter, + }); + + return response; +} + +const resourceManagerAPI = { + getPool, + getPools, +}; + +export type ResourceManagerAPI = typeof resourceManagerAPI; +export default resourceManagerAPI; diff --git a/src/external-api/scheduler.ts b/src/external-api/scheduler.ts index 6703d945..9a01943f 100644 --- a/src/external-api/scheduler.ts +++ b/src/external-api/scheduler.ts @@ -14,7 +14,7 @@ import { UpdateScheduleInput, UpdateScheduleMutation, UpdateScheduleMutationVariables, -} from '../__generated__/graphql'; +} from '../__generated__/scheduler.graphql'; import config from '../config'; const client = new GraphQLClient(config.schedulerApiURL, { headers: {} }); diff --git a/src/helpers/id-helper.ts b/src/helpers/id-helper.ts index 0230a0fc..b091ae31 100644 --- a/src/helpers/id-helper.ts +++ b/src/helpers/id-helper.ts @@ -12,7 +12,8 @@ export type DataType = | 'Blueprint' | 'GraphNode' | 'GraphEdge' - | 'Schedule'; + | 'Schedule' + | 'Pool'; function isDataType(value: string): value is DataType { return ( @@ -27,7 +28,8 @@ function isDataType(value: string): value is DataType { value === 'Blueprint' || value === 'GraphNode' || value === 'GraphEdge' || - value === 'Schedule' + value === 'Schedule' || + value === 'Pool' ); } diff --git a/src/helpers/resource-manager.helpers.ts b/src/helpers/resource-manager.helpers.ts new file mode 100644 index 00000000..5718be84 --- /dev/null +++ b/src/helpers/resource-manager.helpers.ts @@ -0,0 +1,45 @@ +import { compact } from 'lodash'; +import { GetPoolsQuery, PoolFragmentFragment } from '../__generated__/resource-manager.graphql'; +import { NexusGenObjects } from '../schema/nexus-typegen'; +import { toGraphId } from './id-helper'; +import { unwrap } from './utils.helpers'; + +export function apiPoolEdgeToGraphqlPoolEdge(apiPool: PoolFragmentFragment) { + return { + id: toGraphId('Pool', apiPool.id), + name: apiPool.Name, + poolType: apiPool.PoolType, + tags: apiPool.Tags.map((t) => ({ + id: t.id, + tag: t.Tag, + })), + resourceType: { + id: apiPool.id, + name: apiPool.Name, + }, + }; +} + +export function apiPoolsToGraphqlPools( + queryPools: GetPoolsQuery['QueryRootResourcePools'], +): NexusGenObjects['PoolConnection'] { + const { edges, pageInfo } = queryPools; + + const newEdges = compact(edges).map((e) => { + const { node, cursor } = unwrap(e); + return { + node: apiPoolEdgeToGraphqlPoolEdge(node), + cursor: cursor.toString(), + }; + }); + return { + edges: newEdges, + pageInfo: { + hasNextPage: pageInfo.hasNextPage, + hasPreviousPage: pageInfo.hasPreviousPage, + startCursor: pageInfo.startCursor?.ID, + endCursor: pageInfo.endCursor?.ID, + }, + totalCount: newEdges.length, + }; +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 47844afc..15c7c7b7 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -442,6 +442,10 @@ input FilterDevicesInput { labels: [String!] } +input FilterPoolsInput { + poolName: String +} + input FilterTopologyInput { labels: [String!] } @@ -647,6 +651,32 @@ input PaginationArgs { start: Int! } +type Pool implements Node { + id: ID! + name: String! + poolType: PoolType! + resourceType: ResourceType! + tags: [Tag]! + version: Int +} + +type PoolConnection { + edges: [PoolEdge!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type PoolEdge { + cursor: String! + node: Pool! +} + +enum PoolType { + allocating + set + singleton +} + type Query { blueprints(after: String, before: String, first: Int, last: Int): BlueprintConnection! calculatedDiff(deviceId: String!, transactionId: String!): CalculatedDiffPayload! @@ -665,6 +695,14 @@ type Query { locations(after: String, before: String, first: Int, last: Int): LocationConnection! netTopology: NetTopology node(id: ID!, version: Int): Node + pools( + after: String + before: String + filter: FilterPoolsInput + first: Int + last: Int + resourceTypeId: String + ): PoolConnection! schedules(after: String, before: String, filter: ScheduleFilterInput, first: Int, last: Int): ScheduleConnection! taskDefinitions: [TaskDefinition!]! topology(filter: FilterTopologyInput): Topology @@ -690,6 +728,15 @@ type ResetConfigPayload { dataStore: DataStore! } +type ResourceType { + id: ID! + name: String! +} + +input ResourceTypeInput { + resourceTypeId: String +} + input RestartWorkflowInput { """ Default value is true @@ -790,6 +837,11 @@ type SyncFromNetworkPayload { dataStore: DataStore } +type Tag { + id: ID! + tag: String! +} + type TaskDefinition { concurrentExecLimit: Int createdAt: String diff --git a/src/schema/global-types.ts b/src/schema/global-types.ts index 44127b0b..5794c64a 100644 --- a/src/schema/global-types.ts +++ b/src/schema/global-types.ts @@ -4,6 +4,8 @@ import config from '../config'; import conductorAPI from '../external-api/conductor'; import { fromGraphId, getType } from '../helpers/id-helper'; import schedulerAPI from '../external-api/scheduler'; +import resourceManagerAPI from '../external-api/resource-manager'; +import { apiPoolEdgeToGraphqlPoolEdge } from '../helpers/resource-manager.helpers'; export const Node = interfaceType({ name: 'Node', @@ -120,6 +122,18 @@ export const NodeQuery = extendType({ } return { ...workflow, id: args.id, __typename: 'ExecutedWorkflow' }; } + case 'Pool': { + const id = fromGraphId('Pool', args.id); + const apiPool = await resourceManagerAPI.getPool(id); + + if (apiPool == null) { + return null; + } + + const pool = apiPoolEdgeToGraphqlPoolEdge(apiPool); + + return { ...pool, id: args.id, __typename: 'Pool' }; + } case 'Schedule': { const id = fromGraphId('Schedule', args.id); const schedule = await schedulerAPI.getSchedule(id); diff --git a/src/schema/index.ts b/src/schema/index.ts index 55281de1..c9090491 100644 --- a/src/schema/index.ts +++ b/src/schema/index.ts @@ -13,6 +13,7 @@ import * as workflow from './workflow'; import * as executedWorkflowTask from './task'; import * as workflowLabels from './workflow-labels'; import * as taskDefintions from './task-definitons'; +import * as pool from './pool'; export default makeSchema({ features: { @@ -44,6 +45,7 @@ export default makeSchema({ workflowLabels, executedWorkflowTask, taskDefintions, + pool, ], sourceTypes: { modules: [ diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index b97ef31c..adaec8b3 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -174,6 +174,10 @@ export interface NexusGenInputs { deviceName?: string | null; // String labels?: string[] | null; // [String!] }; + FilterPoolsInput: { + // input type + poolName?: string | null; // String + }; FilterTopologyInput: { // input type labels?: string[] | null; // [String!] @@ -203,6 +207,10 @@ export interface NexusGenInputs { // input type shouldArchiveWorkflow?: boolean | null; // Boolean }; + ResourceTypeInput: { + // input type + resourceTypeId?: string | null; // String + }; RestartWorkflowInput: { // input type shouldUseLatestDefinitions?: boolean | null; // Boolean @@ -325,6 +333,7 @@ export interface NexusGenEnums { | 'SKIPPED' | 'TIMED_OUT'; GraphEdgeStatus: 'ok' | 'unknown'; + PoolType: 'allocating' | 'set' | 'singleton'; RetryLogic: 'EXPONENTIAL_BACKOFF' | 'FIXED' | 'LINEAR_BACKOFF'; ScheduleStatus: 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; SortDeviceBy: 'CREATED_AT' | 'NAME'; @@ -632,11 +641,36 @@ export interface NexusGenObjects { hasPreviousPage: boolean; // Boolean! startCursor?: string | null; // String }; + Pool: { + // root type + id: string; // ID! + name: string; // String! + poolType: NexusGenEnums['PoolType']; // PoolType! + resourceType: NexusGenRootTypes['ResourceType']; // ResourceType! + tags: Array; // [Tag]! + version?: number | null; // Int + }; + PoolConnection: { + // root type + edges: NexusGenRootTypes['PoolEdge'][]; // [PoolEdge!]! + pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! + totalCount: number; // Int! + }; + PoolEdge: { + // root type + cursor: string; // String! + node: NexusGenRootTypes['Pool']; // Pool! + }; Query: {}; ResetConfigPayload: { // root type dataStore: NexusGenRootTypes['DataStore']; // DataStore! }; + ResourceType: { + // root type + id: string; // ID! + name: string; // String! + }; RevertChangesPayload: { // root type isOk: boolean; // Boolean! @@ -669,6 +703,11 @@ export interface NexusGenObjects { // root type dataStore?: NexusGenRootTypes['DataStore'] | null; // DataStore }; + Tag: { + // root type + id: string; // ID! + tag: string; // String! + }; TaskDefinition: SourceTypes.TaskDefinition; Topology: { // root type @@ -771,6 +810,7 @@ export interface NexusGenInterfaces { | core.Discriminate<'ExecutedWorkflowTask', 'required'> | core.Discriminate<'Label', 'required'> | core.Discriminate<'Location', 'required'> + | core.Discriminate<'Pool', 'required'> | core.Discriminate<'Schedule', 'required'> | core.Discriminate<'Workflow', 'required'> | core.Discriminate<'Zone', 'required'>; @@ -1200,6 +1240,26 @@ export interface NexusGenFieldTypes { hasPreviousPage: boolean; // Boolean! startCursor: string | null; // String }; + Pool: { + // field return type + id: string; // ID! + name: string; // String! + poolType: NexusGenEnums['PoolType']; // PoolType! + resourceType: NexusGenRootTypes['ResourceType']; // ResourceType! + tags: Array; // [Tag]! + version: number | null; // Int + }; + PoolConnection: { + // field return type + edges: NexusGenRootTypes['PoolEdge'][]; // [PoolEdge!]! + pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! + totalCount: number; // Int! + }; + PoolEdge: { + // field return type + cursor: string; // String! + node: NexusGenRootTypes['Pool']; // Pool! + }; Query: { // field return type blueprints: NexusGenRootTypes['BlueprintConnection']; // BlueprintConnection! @@ -1212,6 +1272,7 @@ export interface NexusGenFieldTypes { locations: NexusGenRootTypes['LocationConnection']; // LocationConnection! netTopology: NexusGenRootTypes['NetTopology'] | null; // NetTopology node: NexusGenRootTypes['Node'] | null; // Node + pools: NexusGenRootTypes['PoolConnection']; // PoolConnection! schedules: NexusGenRootTypes['ScheduleConnection']; // ScheduleConnection! taskDefinitions: NexusGenRootTypes['TaskDefinition'][]; // [TaskDefinition!]! topology: NexusGenRootTypes['Topology'] | null; // Topology @@ -1229,6 +1290,11 @@ export interface NexusGenFieldTypes { // field return type dataStore: NexusGenRootTypes['DataStore']; // DataStore! }; + ResourceType: { + // field return type + id: string; // ID! + name: string; // String! + }; RevertChangesPayload: { // field return type isOk: boolean; // Boolean! @@ -1279,6 +1345,11 @@ export interface NexusGenFieldTypes { // field return type dataStore: NexusGenRootTypes['DataStore'] | null; // DataStore }; + Tag: { + // field return type + id: string; // ID! + tag: string; // String! + }; TaskDefinition: { // field return type concurrentExecLimit: number | null; // Int @@ -1848,6 +1919,26 @@ export interface NexusGenFieldTypeNames { hasPreviousPage: 'Boolean'; startCursor: 'String'; }; + Pool: { + // field return type name + id: 'ID'; + name: 'String'; + poolType: 'PoolType'; + resourceType: 'ResourceType'; + tags: 'Tag'; + version: 'Int'; + }; + PoolConnection: { + // field return type name + edges: 'PoolEdge'; + pageInfo: 'PageInfo'; + totalCount: 'Int'; + }; + PoolEdge: { + // field return type name + cursor: 'String'; + node: 'Pool'; + }; Query: { // field return type name blueprints: 'BlueprintConnection'; @@ -1860,6 +1951,7 @@ export interface NexusGenFieldTypeNames { locations: 'LocationConnection'; netTopology: 'NetTopology'; node: 'Node'; + pools: 'PoolConnection'; schedules: 'ScheduleConnection'; taskDefinitions: 'TaskDefinition'; topology: 'Topology'; @@ -1877,6 +1969,11 @@ export interface NexusGenFieldTypeNames { // field return type name dataStore: 'DataStore'; }; + ResourceType: { + // field return type name + id: 'ID'; + name: 'String'; + }; RevertChangesPayload: { // field return type name isOk: 'Boolean'; @@ -1927,6 +2024,11 @@ export interface NexusGenFieldTypeNames { // field return type name dataStore: 'DataStore'; }; + Tag: { + // field return type name + id: 'ID'; + tag: 'String'; + }; TaskDefinition: { // field return type name concurrentExecLimit: 'Int'; @@ -2336,6 +2438,15 @@ export interface NexusGenArgTypes { id: string; // ID! version?: number | null; // Int }; + pools: { + // args + after?: string | null; // String + before?: string | null; // String + filter?: NexusGenInputs['FilterPoolsInput'] | null; // FilterPoolsInput + first?: number | null; // Int + last?: number | null; // Int + resourceTypeId?: string | null; // String + }; schedules: { // args after?: string | null; // String @@ -2401,6 +2512,7 @@ export interface NexusGenAbstractTypeMembers { | 'ExecutedWorkflowTask' | 'Label' | 'Location' + | 'Pool' | 'Schedule' | 'Workflow' | 'Zone'; @@ -2416,6 +2528,7 @@ export interface NexusGenTypeInterfaces { GraphVersionNode: 'BaseGraphNode'; Label: 'Node'; Location: 'Node'; + Pool: 'Node'; Schedule: 'Node'; Workflow: 'Node'; Zone: 'Node'; diff --git a/src/schema/pool.ts b/src/schema/pool.ts new file mode 100644 index 00000000..09b51353 --- /dev/null +++ b/src/schema/pool.ts @@ -0,0 +1,93 @@ +import { enumType, extendType, inputObjectType, objectType, stringArg } from 'nexus'; +import { Node, PageInfo, PaginationConnectionArgs } from './global-types'; +import { apiPoolsToGraphqlPools } from '../helpers/resource-manager.helpers'; + +export const PoolType = enumType({ + name: 'PoolType', + members: ['allocating', 'set', 'singleton'], +}); + +export const Tag = objectType({ + name: 'Tag', + definition: (t) => { + t.nonNull.id('id'); + t.nonNull.string('tag'); + }, +}); + +export const ResourceType = objectType({ + name: 'ResourceType', + definition: (t) => { + t.nonNull.id('id'); + t.nonNull.string('name'); + }, +}); + +export const Pool = objectType({ + name: 'Pool', + definition: (t) => { + t.implements(Node); + t.nonNull.id('id'); + t.nonNull.string('name'); + t.nonNull.field('poolType', { type: PoolType }); + t.nonNull.list.field('tags', { type: Tag }); + t.nonNull.field('resourceType', { type: ResourceType }); + }, +}); + +export const PoolEdge = objectType({ + name: 'PoolEdge', + definition: (t) => { + t.nonNull.field('node', { type: Pool }); + t.nonNull.string('cursor'); + }, +}); + +export const PoolConnection = objectType({ + name: 'PoolConnection', + definition: (t) => { + t.nonNull.list.nonNull.field('edges', { type: PoolEdge }); + t.nonNull.field('pageInfo', { + type: PageInfo, + }); + t.nonNull.int('totalCount'); + }, +}); + +export const FilterPoolsInput = inputObjectType({ + name: 'FilterPoolsInput', + definition: (t) => { + t.string('poolName'); + }, +}); + +export const ResourceTypeInput = inputObjectType({ + name: 'ResourceTypeInput', + definition: (t) => { + t.string('resourceTypeId'); + }, +}); + +export const PoolQuery = extendType({ + type: 'Query', + definition: (t) => { + t.nonNull.field('pools', { + type: PoolConnection, + args: { + ...PaginationConnectionArgs, + filter: FilterPoolsInput, + resourceTypeId: stringArg(), + }, + resolve: async (_, args, { resourceManagerAPI }) => { + const { resourceTypeId, filter, ...paginationArgs } = args; + const { QueryRootResourcePools: resourcePoolsData } = await resourceManagerAPI.getPools( + resourceTypeId ?? null, + paginationArgs, + null, + ); + const result = apiPoolsToGraphqlPools(resourcePoolsData); + return result; + }, + }); + }, +}); diff --git a/src/schema/source-types.ts b/src/schema/source-types.ts index 4f80efad..c26357e0 100644 --- a/src/schema/source-types.ts +++ b/src/schema/source-types.ts @@ -6,7 +6,8 @@ import { NestedTask, ApiTaskDefinition, } from '../external-api/conductor-network-types'; -import { GetScheduleQuery } from '../__generated__/graphql'; +import { GetScheduleQuery } from '../__generated__/scheduler.graphql'; +import { PoolFragmentFragment } from '../__generated__/resource-manager.graphql'; export type Label = label; export type Device = device; @@ -29,3 +30,4 @@ export type ExecutedWorkflowTask = ApiExecutedWorkflowTask & { id: string }; export type WorkflowTask = NestedTask; export type TaskDefinition = ApiTaskDefinition; export type Schedule = GetScheduleQuery['schedule'] & { id: string }; +export type ResourcePool = PoolFragmentFragment; From afc4c90d9e83810aa181d176e19be53aa752aecf Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Fri, 16 Jun 2023 15:47:51 +0200 Subject: [PATCH 26/69] add resource manger api url to pr-check env --- .github/workflows/pr-check.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 9fe90bda..729d2cfc 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -44,6 +44,7 @@ jobs: SHELL_HOST: 10.19.0.12 CONDUCTOR_API_URL: 10.19.0.7 SCHEDULER_API_URL: 10.19.0.7 + RESOURCE_MANAGER_API_URL: 10.19.0.7 - name: Check code formatting run: yarn run formatter:check - name: Run eslint check From 154a0499ab09809423f3b5ddc2854a75a400aa7b Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Fri, 16 Jun 2023 15:58:26 +0200 Subject: [PATCH 27/69] fix formatter --- src/__generated__/resource-manager.graphql.ts | 109 +++++++++--------- src/__generated__/scheduler.graphql.ts | 104 +++++++++++++---- 2 files changed, 138 insertions(+), 75 deletions(-) diff --git a/src/__generated__/resource-manager.graphql.ts b/src/__generated__/resource-manager.graphql.ts index d53d9352..6b9391fa 100644 --- a/src/__generated__/resource-manager.graphql.ts +++ b/src/__generated__/resource-manager.graphql.ts @@ -25,9 +25,7 @@ export type AllocationStrategy = Node & { }; /** Supported languages for allocation strategy scripts */ -export type AllocationStrategyLang = - | 'js' - | 'py'; +export type AllocationStrategyLang = 'js' | 'py'; /** Input parameters for creating an allocation pool */ export type CreateAllocatingPoolInput = { @@ -241,14 +239,12 @@ export type Mutation = { UpdateTag: UpdateTagPayload; }; - export type MutationClaimResourceArgs = { description?: InputMaybe; poolId: Scalars['ID']; userInput: Scalars['Map']; }; - export type MutationClaimResourceWithAltIdArgs = { alternativeId: Scalars['Map']; description?: InputMaybe; @@ -256,83 +252,67 @@ export type MutationClaimResourceWithAltIdArgs = { userInput: Scalars['Map']; }; - export type MutationCreateAllocatingPoolArgs = { input?: InputMaybe; }; - export type MutationCreateAllocationStrategyArgs = { input?: InputMaybe; }; - export type MutationCreateNestedAllocatingPoolArgs = { input: CreateNestedAllocatingPoolInput; }; - export type MutationCreateNestedSetPoolArgs = { input: CreateNestedSetPoolInput; }; - export type MutationCreateNestedSingletonPoolArgs = { input: CreateNestedSingletonPoolInput; }; - export type MutationCreateResourceTypeArgs = { input: CreateResourceTypeInput; }; - export type MutationCreateSetPoolArgs = { input: CreateSetPoolInput; }; - export type MutationCreateSingletonPoolArgs = { input?: InputMaybe; }; - export type MutationCreateTagArgs = { input: CreateTagInput; }; - export type MutationDeleteAllocationStrategyArgs = { input?: InputMaybe; }; - export type MutationDeleteResourcePoolArgs = { input: DeleteResourcePoolInput; }; - export type MutationDeleteResourceTypeArgs = { input: DeleteResourceTypeInput; }; - export type MutationDeleteTagArgs = { input: DeleteTagInput; }; - export type MutationFreeResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; - export type MutationTagPoolArgs = { input: TagPoolInput; }; - export type MutationTestAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; currentResources: Array; @@ -340,24 +320,20 @@ export type MutationTestAllocationStrategyArgs = { userInput: Scalars['Map']; }; - export type MutationUntagPoolArgs = { input: UntagPoolInput; }; - export type MutationUpdateResourceAltIdArgs = { alternativeId: Scalars['Map']; input: Scalars['Map']; poolId: Scalars['ID']; }; - export type MutationUpdateResourceTypeNameArgs = { input: UpdateResourceTypeNameInput; }; - export type MutationUpdateTagArgs = { input: UpdateTagInput; }; @@ -391,10 +367,7 @@ export type PoolCapacityPayload = { }; /** Defines the type of pool */ -export type PoolType = - | 'allocating' - | 'set' - | 'singleton'; +export type PoolType = 'allocating' | 'set' | 'singleton'; /** Defines the type of the property */ export type PropertyType = Node & { @@ -431,17 +404,14 @@ export type Query = { node: Maybe; }; - export type QueryQueryAllocationStrategiesArgs = { byName?: InputMaybe; }; - export type QueryQueryAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; }; - export type QueryQueryEmptyResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -450,7 +420,6 @@ export type QueryQueryEmptyResourcePoolsArgs = { resourceTypeId?: InputMaybe; }; - export type QueryQueryLeafResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -461,12 +430,10 @@ export type QueryQueryLeafResourcePoolsArgs = { tags?: InputMaybe; }; - export type QueryQueryPoolCapacityArgs = { poolId: Scalars['ID']; }; - export type QueryQueryRecentlyActiveResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -476,28 +443,23 @@ export type QueryQueryRecentlyActiveResourcesArgs = { toDatetime?: InputMaybe; }; - export type QueryQueryRequiredPoolPropertiesArgs = { allocationStrategyName: Scalars['String']; }; - export type QueryQueryResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; - export type QueryQueryResourcePoolArgs = { poolId: Scalars['ID']; }; - export type QueryQueryResourcePoolHierarchyPathArgs = { poolId: Scalars['ID']; }; - export type QueryQueryResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -508,12 +470,10 @@ export type QueryQueryResourcePoolsArgs = { tags?: InputMaybe; }; - export type QueryQueryResourceTypesArgs = { byName?: InputMaybe; }; - export type QueryQueryResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -522,7 +482,6 @@ export type QueryQueryResourcesArgs = { poolId: Scalars['ID']; }; - export type QueryQueryResourcesByAltIdArgs = { after?: InputMaybe; before?: InputMaybe; @@ -532,7 +491,6 @@ export type QueryQueryResourcesByAltIdArgs = { poolId?: InputMaybe; }; - export type QueryQueryRootResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -543,7 +501,6 @@ export type QueryQueryRootResourcePoolsArgs = { tags?: InputMaybe; }; - export type QuerySearchPoolsByTagsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -552,7 +509,6 @@ export type QuerySearchPoolsByTagsArgs = { tags?: InputMaybe; }; - export type QueryNodeArgs = { id: Scalars['ID']; }; @@ -606,7 +562,6 @@ export type ResourcePool = Node & { id: Scalars['ID']; }; - /** A pool is an entity that contains allocated and free resources */ export type ResourcePoolAllocatedResourcesArgs = { after?: InputMaybe; @@ -710,14 +665,39 @@ export type UpdateTagPayload = { tag: Maybe; }; -export type PoolFragmentFragment = { __typename?: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }; +export type PoolFragmentFragment = { + __typename?: 'ResourcePool'; + id: string; + Name: string; + PoolType: PoolType; + PoolProperties: any; + Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; + ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; +}; export type GetPoolQueryVariables = Exact<{ nodeId: Scalars['ID']; }>; - -export type GetPoolQuery = { __typename?: 'Query', node: { __typename?: 'AllocationStrategy' } | { __typename?: 'PropertyType' } | { __typename?: 'Resource' } | { __typename?: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } } | { __typename?: 'ResourceType' } | { __typename?: 'Tag' } | null }; +export type GetPoolQuery = { + __typename?: 'Query'; + node: + | { __typename?: 'AllocationStrategy' } + | { __typename?: 'PropertyType' } + | { __typename?: 'Resource' } + | { + __typename?: 'ResourcePool'; + id: string; + Name: string; + PoolType: PoolType; + PoolProperties: any; + Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; + ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; + } + | { __typename?: 'ResourceType' } + | { __typename?: 'Tag' } + | null; +}; export type GetPoolsQueryVariables = Exact<{ resourceTypeId?: InputMaybe; @@ -728,5 +708,30 @@ export type GetPoolsQueryVariables = Exact<{ filterByResources?: InputMaybe; }>; - -export type GetPoolsQuery = { __typename?: 'Query', QueryRootResourcePools: { __typename?: 'ResourcePoolConnection', totalCount: number, edges: Array<{ __typename?: 'ResourcePoolEdge', node: { __typename?: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }, cursor: { __typename?: 'OutputCursor', ID: string } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: { __typename?: 'OutputCursor', ID: string } | null, endCursor: { __typename?: 'OutputCursor', ID: string } | null } } }; +export type GetPoolsQuery = { + __typename?: 'Query'; + QueryRootResourcePools: { + __typename?: 'ResourcePoolConnection'; + totalCount: number; + edges: Array<{ + __typename?: 'ResourcePoolEdge'; + node: { + __typename?: 'ResourcePool'; + id: string; + Name: string; + PoolType: PoolType; + PoolProperties: any; + Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; + ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; + }; + cursor: { __typename?: 'OutputCursor'; ID: string }; + } | null>; + pageInfo: { + __typename?: 'PageInfo'; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: { __typename?: 'OutputCursor'; ID: string } | null; + endCursor: { __typename?: 'OutputCursor'; ID: string } | null; + }; + }; +}; diff --git a/src/__generated__/scheduler.graphql.ts b/src/__generated__/scheduler.graphql.ts index af39c7c6..db014ee9 100644 --- a/src/__generated__/scheduler.graphql.ts +++ b/src/__generated__/scheduler.graphql.ts @@ -33,17 +33,14 @@ export type Mutation = { updateSchedule: Schedule; }; - export type MutationCreateScheduleArgs = { input: CreateScheduleInput; }; - export type MutationDeleteScheduleArgs = { name: Scalars['String']; }; - export type MutationUpdateScheduleArgs = { input: UpdateScheduleInput; name: Scalars['String']; @@ -63,12 +60,10 @@ export type Query = { schedules: Maybe; }; - export type QueryScheduleArgs = { name: Scalars['String']; }; - export type QuerySchedulesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -109,14 +104,7 @@ export type SchedulesFilterInput = { workflowVersion: Scalars['String']; }; -export type Status = - | 'COMPLETED' - | 'FAILED' - | 'PAUSED' - | 'RUNNING' - | 'TERMINATED' - | 'TIMED_OUT' - | 'UNKNOWN'; +export type Status = 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; export type UpdateScheduleInput = { cronString?: InputMaybe; @@ -133,30 +121,71 @@ export type DeleteScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; }>; - -export type DeleteScheduleMutation = { __typename?: 'Mutation', deleteSchedule: boolean }; +export type DeleteScheduleMutation = { __typename?: 'Mutation'; deleteSchedule: boolean }; export type UpdateScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; input: UpdateScheduleInput; }>; - -export type UpdateScheduleMutation = { __typename?: 'Mutation', updateSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; +export type UpdateScheduleMutation = { + __typename?: 'Mutation'; + updateSchedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; +}; export type CreateScheduleMutationVariables = Exact<{ input: CreateScheduleInput; }>; - -export type CreateScheduleMutation = { __typename?: 'Mutation', createSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; +export type CreateScheduleMutation = { + __typename?: 'Mutation'; + createSchedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; +}; export type GetScheduleQueryVariables = Exact<{ scheduleName: Scalars['String']; }>; - -export type GetScheduleQuery = { __typename?: 'Query', schedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } | null }; +export type GetScheduleQuery = { + __typename?: 'Query'; + schedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + } | null; +}; export type GetSchedulesQueryVariables = Exact<{ first?: InputMaybe; @@ -166,5 +195,34 @@ export type GetSchedulesQueryVariables = Exact<{ filter?: InputMaybe; }>; - -export type GetSchedulesQuery = { __typename?: 'Query', schedules: { __typename?: 'ScheduleConnection', totalCount: number, edges: Array<{ __typename?: 'ScheduleEdge', cursor: string, node: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null } } | null }; +export type GetSchedulesQuery = { + __typename?: 'Query'; + schedules: { + __typename?: 'ScheduleConnection'; + totalCount: number; + edges: Array<{ + __typename?: 'ScheduleEdge'; + cursor: string; + node: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; + } | null>; + pageInfo: { + __typename?: 'PageInfo'; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; + endCursor: string | null; + }; + } | null; +}; From 1fbc2ee50f81817dfca3186c12c42431b2b118f7 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Fri, 16 Jun 2023 16:08:02 +0200 Subject: [PATCH 28/69] README.md updated --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index ef1eee39..2bf168a2 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,9 @@ DATABASE_URL="postgresql://postgres:postgres@localhost:5432/frinx" UNICONFIG_API_PROTOCOL=http UNICONFIG_API_PORT=8181 UNICONFIG_LIST_URL=http://10.19.0.7/static/list/uniconfig +CONDUCTOR_API_URL="http:/10.19.0.7:8080/api" +SCHEDULER_API_URL="http://10.19.0.7:3001/query" +RESOURCE_MANAGER_API_URL="http://10.19.0.7/api/resource" X_TENANT_ID="frinx" ``` From 92850c927ca66f1260dc4a8c93cd99e510d9f470 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Tue, 20 Jun 2023 09:58:39 +0200 Subject: [PATCH 29/69] freeResource mutation added (#313) --- src/__generated__/resource-manager.graphql.ts | 117 +++++++++--------- src/__generated__/scheduler.graphql.ts | 104 ++++------------ src/external-api/resource-manager.ts | 18 +++ src/schema/api.graphql | 13 +- src/schema/nexus-typegen.ts | 27 +++- src/schema/pool.ts | 44 ++++++- 6 files changed, 180 insertions(+), 143 deletions(-) diff --git a/src/__generated__/resource-manager.graphql.ts b/src/__generated__/resource-manager.graphql.ts index 6b9391fa..1f793f5c 100644 --- a/src/__generated__/resource-manager.graphql.ts +++ b/src/__generated__/resource-manager.graphql.ts @@ -25,7 +25,9 @@ export type AllocationStrategy = Node & { }; /** Supported languages for allocation strategy scripts */ -export type AllocationStrategyLang = 'js' | 'py'; +export type AllocationStrategyLang = + | 'js' + | 'py'; /** Input parameters for creating an allocation pool */ export type CreateAllocatingPoolInput = { @@ -239,12 +241,14 @@ export type Mutation = { UpdateTag: UpdateTagPayload; }; + export type MutationClaimResourceArgs = { description?: InputMaybe; poolId: Scalars['ID']; userInput: Scalars['Map']; }; + export type MutationClaimResourceWithAltIdArgs = { alternativeId: Scalars['Map']; description?: InputMaybe; @@ -252,67 +256,83 @@ export type MutationClaimResourceWithAltIdArgs = { userInput: Scalars['Map']; }; + export type MutationCreateAllocatingPoolArgs = { input?: InputMaybe; }; + export type MutationCreateAllocationStrategyArgs = { input?: InputMaybe; }; + export type MutationCreateNestedAllocatingPoolArgs = { input: CreateNestedAllocatingPoolInput; }; + export type MutationCreateNestedSetPoolArgs = { input: CreateNestedSetPoolInput; }; + export type MutationCreateNestedSingletonPoolArgs = { input: CreateNestedSingletonPoolInput; }; + export type MutationCreateResourceTypeArgs = { input: CreateResourceTypeInput; }; + export type MutationCreateSetPoolArgs = { input: CreateSetPoolInput; }; + export type MutationCreateSingletonPoolArgs = { input?: InputMaybe; }; + export type MutationCreateTagArgs = { input: CreateTagInput; }; + export type MutationDeleteAllocationStrategyArgs = { input?: InputMaybe; }; + export type MutationDeleteResourcePoolArgs = { input: DeleteResourcePoolInput; }; + export type MutationDeleteResourceTypeArgs = { input: DeleteResourceTypeInput; }; + export type MutationDeleteTagArgs = { input: DeleteTagInput; }; + export type MutationFreeResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; + export type MutationTagPoolArgs = { input: TagPoolInput; }; + export type MutationTestAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; currentResources: Array; @@ -320,20 +340,24 @@ export type MutationTestAllocationStrategyArgs = { userInput: Scalars['Map']; }; + export type MutationUntagPoolArgs = { input: UntagPoolInput; }; + export type MutationUpdateResourceAltIdArgs = { alternativeId: Scalars['Map']; input: Scalars['Map']; poolId: Scalars['ID']; }; + export type MutationUpdateResourceTypeNameArgs = { input: UpdateResourceTypeNameInput; }; + export type MutationUpdateTagArgs = { input: UpdateTagInput; }; @@ -367,7 +391,10 @@ export type PoolCapacityPayload = { }; /** Defines the type of pool */ -export type PoolType = 'allocating' | 'set' | 'singleton'; +export type PoolType = + | 'allocating' + | 'set' + | 'singleton'; /** Defines the type of the property */ export type PropertyType = Node & { @@ -404,14 +431,17 @@ export type Query = { node: Maybe; }; + export type QueryQueryAllocationStrategiesArgs = { byName?: InputMaybe; }; + export type QueryQueryAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; }; + export type QueryQueryEmptyResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -420,6 +450,7 @@ export type QueryQueryEmptyResourcePoolsArgs = { resourceTypeId?: InputMaybe; }; + export type QueryQueryLeafResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -430,10 +461,12 @@ export type QueryQueryLeafResourcePoolsArgs = { tags?: InputMaybe; }; + export type QueryQueryPoolCapacityArgs = { poolId: Scalars['ID']; }; + export type QueryQueryRecentlyActiveResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -443,23 +476,28 @@ export type QueryQueryRecentlyActiveResourcesArgs = { toDatetime?: InputMaybe; }; + export type QueryQueryRequiredPoolPropertiesArgs = { allocationStrategyName: Scalars['String']; }; + export type QueryQueryResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; + export type QueryQueryResourcePoolArgs = { poolId: Scalars['ID']; }; + export type QueryQueryResourcePoolHierarchyPathArgs = { poolId: Scalars['ID']; }; + export type QueryQueryResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -470,10 +508,12 @@ export type QueryQueryResourcePoolsArgs = { tags?: InputMaybe; }; + export type QueryQueryResourceTypesArgs = { byName?: InputMaybe; }; + export type QueryQueryResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -482,6 +522,7 @@ export type QueryQueryResourcesArgs = { poolId: Scalars['ID']; }; + export type QueryQueryResourcesByAltIdArgs = { after?: InputMaybe; before?: InputMaybe; @@ -491,6 +532,7 @@ export type QueryQueryResourcesByAltIdArgs = { poolId?: InputMaybe; }; + export type QueryQueryRootResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -501,6 +543,7 @@ export type QueryQueryRootResourcePoolsArgs = { tags?: InputMaybe; }; + export type QuerySearchPoolsByTagsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -509,6 +552,7 @@ export type QuerySearchPoolsByTagsArgs = { tags?: InputMaybe; }; + export type QueryNodeArgs = { id: Scalars['ID']; }; @@ -562,6 +606,7 @@ export type ResourcePool = Node & { id: Scalars['ID']; }; + /** A pool is an entity that contains allocated and free resources */ export type ResourcePoolAllocatedResourcesArgs = { after?: InputMaybe; @@ -665,39 +710,14 @@ export type UpdateTagPayload = { tag: Maybe; }; -export type PoolFragmentFragment = { - __typename?: 'ResourcePool'; - id: string; - Name: string; - PoolType: PoolType; - PoolProperties: any; - Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; - ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; -}; +export type PoolFragmentFragment = { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }; export type GetPoolQueryVariables = Exact<{ nodeId: Scalars['ID']; }>; -export type GetPoolQuery = { - __typename?: 'Query'; - node: - | { __typename?: 'AllocationStrategy' } - | { __typename?: 'PropertyType' } - | { __typename?: 'Resource' } - | { - __typename?: 'ResourcePool'; - id: string; - Name: string; - PoolType: PoolType; - PoolProperties: any; - Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; - ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; - } - | { __typename?: 'ResourceType' } - | { __typename?: 'Tag' } - | null; -}; + +export type GetPoolQuery = { __typename?: 'Query', node: { __typename?: 'AllocationStrategy' } | { __typename?: 'PropertyType' } | { __typename?: 'Resource' } | { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } } | { __typename?: 'ResourceType' } | { __typename?: 'Tag' } | null }; export type GetPoolsQueryVariables = Exact<{ resourceTypeId?: InputMaybe; @@ -708,30 +728,13 @@ export type GetPoolsQueryVariables = Exact<{ filterByResources?: InputMaybe; }>; -export type GetPoolsQuery = { - __typename?: 'Query'; - QueryRootResourcePools: { - __typename?: 'ResourcePoolConnection'; - totalCount: number; - edges: Array<{ - __typename?: 'ResourcePoolEdge'; - node: { - __typename?: 'ResourcePool'; - id: string; - Name: string; - PoolType: PoolType; - PoolProperties: any; - Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; - ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; - }; - cursor: { __typename?: 'OutputCursor'; ID: string }; - } | null>; - pageInfo: { - __typename?: 'PageInfo'; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: { __typename?: 'OutputCursor'; ID: string } | null; - endCursor: { __typename?: 'OutputCursor'; ID: string } | null; - }; - }; -}; + +export type GetPoolsQuery = { __typename?: 'Query', QueryRootResourcePools: { __typename?: 'ResourcePoolConnection', totalCount: number, edges: Array<{ __typename?: 'ResourcePoolEdge', node: { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }, cursor: { __typename?: 'OutputCursor', ID: string } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: { __typename?: 'OutputCursor', ID: string } | null, endCursor: { __typename?: 'OutputCursor', ID: string } | null } } }; + +export type FreeResourceMutationVariables = Exact<{ + poolId: Scalars['ID']; + input: Scalars['Map']; +}>; + + +export type FreeResourceMutation = { __typename?: 'Mutation', FreeResource: string }; diff --git a/src/__generated__/scheduler.graphql.ts b/src/__generated__/scheduler.graphql.ts index db014ee9..af39c7c6 100644 --- a/src/__generated__/scheduler.graphql.ts +++ b/src/__generated__/scheduler.graphql.ts @@ -33,14 +33,17 @@ export type Mutation = { updateSchedule: Schedule; }; + export type MutationCreateScheduleArgs = { input: CreateScheduleInput; }; + export type MutationDeleteScheduleArgs = { name: Scalars['String']; }; + export type MutationUpdateScheduleArgs = { input: UpdateScheduleInput; name: Scalars['String']; @@ -60,10 +63,12 @@ export type Query = { schedules: Maybe; }; + export type QueryScheduleArgs = { name: Scalars['String']; }; + export type QuerySchedulesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -104,7 +109,14 @@ export type SchedulesFilterInput = { workflowVersion: Scalars['String']; }; -export type Status = 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; +export type Status = + | 'COMPLETED' + | 'FAILED' + | 'PAUSED' + | 'RUNNING' + | 'TERMINATED' + | 'TIMED_OUT' + | 'UNKNOWN'; export type UpdateScheduleInput = { cronString?: InputMaybe; @@ -121,71 +133,30 @@ export type DeleteScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; }>; -export type DeleteScheduleMutation = { __typename?: 'Mutation'; deleteSchedule: boolean }; + +export type DeleteScheduleMutation = { __typename?: 'Mutation', deleteSchedule: boolean }; export type UpdateScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; input: UpdateScheduleInput; }>; -export type UpdateScheduleMutation = { - __typename?: 'Mutation'; - updateSchedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; -}; + +export type UpdateScheduleMutation = { __typename?: 'Mutation', updateSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; export type CreateScheduleMutationVariables = Exact<{ input: CreateScheduleInput; }>; -export type CreateScheduleMutation = { - __typename?: 'Mutation'; - createSchedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; -}; + +export type CreateScheduleMutation = { __typename?: 'Mutation', createSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; export type GetScheduleQueryVariables = Exact<{ scheduleName: Scalars['String']; }>; -export type GetScheduleQuery = { - __typename?: 'Query'; - schedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - } | null; -}; + +export type GetScheduleQuery = { __typename?: 'Query', schedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } | null }; export type GetSchedulesQueryVariables = Exact<{ first?: InputMaybe; @@ -195,34 +166,5 @@ export type GetSchedulesQueryVariables = Exact<{ filter?: InputMaybe; }>; -export type GetSchedulesQuery = { - __typename?: 'Query'; - schedules: { - __typename?: 'ScheduleConnection'; - totalCount: number; - edges: Array<{ - __typename?: 'ScheduleEdge'; - cursor: string; - node: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; - } | null>; - pageInfo: { - __typename?: 'PageInfo'; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; - endCursor: string | null; - }; - } | null; -}; + +export type GetSchedulesQuery = { __typename?: 'Query', schedules: { __typename?: 'ScheduleConnection', totalCount: number, edges: Array<{ __typename?: 'ScheduleEdge', cursor: string, node: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null } } | null }; diff --git a/src/external-api/resource-manager.ts b/src/external-api/resource-manager.ts index b15b0736..de52a00b 100644 --- a/src/external-api/resource-manager.ts +++ b/src/external-api/resource-manager.ts @@ -2,6 +2,8 @@ import { PaginationArgs } from 'nexus/dist/plugins/connectionPlugin'; import { GraphQLClient, gql } from 'graphql-request'; import config from '../config'; import { + FreeResourceMutation, + FreeResourceMutationVariables, GetPoolQuery, GetPoolQueryVariables, GetPoolsQuery, @@ -81,6 +83,12 @@ const GET_POOLS_QUERY = gql` ${POOL_FRAGMENT} `; +const FREE_RESOURCE_MUTATION = gql` + mutation FreeResource($poolId: ID!, $input: Map!) { + FreeResource(poolId: $poolId, input: $input) + } +`; + async function getPool(nodeId: string): Promise { const response = await client.request(GET_POOL_QUERY, { nodeId, @@ -107,9 +115,19 @@ async function getPools( return response; } +async function freeResource(poolId: string, input: Record) { + const response = await client.request(FREE_RESOURCE_MUTATION, { + poolId, + input, + }); + + return response.FreeResource; +} + const resourceManagerAPI = { getPool, getPools, + freeResource, }; export type ResourceManagerAPI = typeof resourceManagerAPI; diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 15c7c7b7..0859e7aa 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -455,6 +455,11 @@ input FilterWorkflowsInput { labels: [String!] } +input FreeResourceInput { + poolId: String! + resource: Record! +} + type GraphEdge { id: ID! source: EdgeSourceTarget! @@ -580,6 +585,7 @@ type Mutation { editWorkflowSchedule(id: String!, input: EditWorkflowScheduleInput!): Schedule executeNewWorkflow(input: StartWorkflowRequestInput!): String executeWorkflowByName(input: ExecuteWorkflowByName!): String + freeResource(input: FreeResourceInput!): String importCSV(input: CSVImportInput!): CSVImport installDevice(id: String!): InstallDevicePayload! pauseWorkflow(id: String!): IsOkResponse @@ -656,7 +662,7 @@ type Pool implements Node { name: String! poolType: PoolType! resourceType: ResourceType! - tags: [Tag]! + tags: [Tag!]! version: Int } @@ -717,6 +723,11 @@ type Query { zones(after: String, before: String, first: Int, last: Int): ZonesConnection! } +""" +Graphql custom scalar record type +""" +scalar Record + input RemoveWorkflowInput { """ Default value is true diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index adaec8b3..70fcd308 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -15,6 +15,13 @@ declare global { fieldName: FieldName, opts?: core.CommonInputFieldConfig, ): void; // "Upload"; + /** + * Graphql custom scalar record type + */ + record( + fieldName: FieldName, + opts?: core.CommonInputFieldConfig, + ): void; // "Record"; } } declare global { @@ -23,6 +30,10 @@ declare global { * The `Upload` scalar type represents a file upload. */ upload(fieldName: FieldName, ...opts: core.ScalarOutSpread): void; // "Upload"; + /** + * Graphql custom scalar record type + */ + record(fieldName: FieldName, ...opts: core.ScalarOutSpread): void; // "Record"; } } @@ -187,6 +198,11 @@ export interface NexusGenInputs { keyword?: string | null; // String labels?: string[] | null; // [String!] }; + FreeResourceInput: { + // input type + poolId: string; // String! + resource: NexusGenScalars['Record']; // Record! + }; GraphNodeCoordinatesInput: { // input type deviceName: string; // String! @@ -371,6 +387,7 @@ export interface NexusGenScalars { Float: number; Boolean: boolean; ID: string; + Record: any; Upload: any; } @@ -647,7 +664,7 @@ export interface NexusGenObjects { name: string; // String! poolType: NexusGenEnums['PoolType']; // PoolType! resourceType: NexusGenRootTypes['ResourceType']; // ResourceType! - tags: Array; // [Tag]! + tags: NexusGenRootTypes['Tag'][]; // [Tag!]! version?: number | null; // Int }; PoolConnection: { @@ -1185,6 +1202,7 @@ export interface NexusGenFieldTypes { editWorkflowSchedule: NexusGenRootTypes['Schedule'] | null; // Schedule executeNewWorkflow: string | null; // String executeWorkflowByName: string | null; // String + freeResource: string | null; // String importCSV: NexusGenRootTypes['CSVImport'] | null; // CSVImport installDevice: NexusGenRootTypes['InstallDevicePayload']; // InstallDevicePayload! pauseWorkflow: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse @@ -1246,7 +1264,7 @@ export interface NexusGenFieldTypes { name: string; // String! poolType: NexusGenEnums['PoolType']; // PoolType! resourceType: NexusGenRootTypes['ResourceType']; // ResourceType! - tags: Array; // [Tag]! + tags: NexusGenRootTypes['Tag'][]; // [Tag!]! version: number | null; // Int }; PoolConnection: { @@ -1864,6 +1882,7 @@ export interface NexusGenFieldTypeNames { editWorkflowSchedule: 'Schedule'; executeNewWorkflow: 'String'; executeWorkflowByName: 'String'; + freeResource: 'String'; importCSV: 'CSVImport'; installDevice: 'InstallDevicePayload'; pauseWorkflow: 'IsOkResponse'; @@ -2296,6 +2315,10 @@ export interface NexusGenArgTypes { // args input: NexusGenInputs['ExecuteWorkflowByName']; // ExecuteWorkflowByName! }; + freeResource: { + // args + input: NexusGenInputs['FreeResourceInput']; // FreeResourceInput! + }; importCSV: { // args input: NexusGenInputs['CSVImportInput']; // CSVImportInput! diff --git a/src/schema/pool.ts b/src/schema/pool.ts index 09b51353..c01b6fdd 100644 --- a/src/schema/pool.ts +++ b/src/schema/pool.ts @@ -1,7 +1,25 @@ -import { enumType, extendType, inputObjectType, objectType, stringArg } from 'nexus'; +import { + arg, + enumType, + extendType, + inputObjectType, + mutationField, + nonNull, + objectType, + scalarType, + stringArg, +} from 'nexus'; import { Node, PageInfo, PaginationConnectionArgs } from './global-types'; import { apiPoolsToGraphqlPools } from '../helpers/resource-manager.helpers'; +export const GraphQLRecord = scalarType({ + name: 'Record', + description: 'Graphql custom scalar record type', + asNexusMethod: 'record', + parseValue: (serializedValue) => JSON.parse(serializedValue as string), + serialize: (value) => JSON.stringify(value), +}); + export const PoolType = enumType({ name: 'PoolType', members: ['allocating', 'set', 'singleton'], @@ -30,7 +48,7 @@ export const Pool = objectType({ t.nonNull.id('id'); t.nonNull.string('name'); t.nonNull.field('poolType', { type: PoolType }); - t.nonNull.list.field('tags', { type: Tag }); + t.nonNull.list.nonNull.field('tags', { type: Tag }); t.nonNull.field('resourceType', { type: ResourceType }); }, }); @@ -91,3 +109,25 @@ export const PoolQuery = extendType({ }); }, }); + +export const FreeResourceInput = inputObjectType({ + name: 'FreeResourceInput', + definition: (t) => { + t.nonNull.string('poolId'); + t.nonNull.field('resource', { + type: GraphQLRecord, + }); + }, +}); + +export const FreeResource = mutationField('freeResource', { + type: 'String', + args: { + input: nonNull(arg({ type: FreeResourceInput })), + }, + resolve: async (_, { input }, { resourceManagerAPI }) => { + const { poolId, resource } = input; + const result = await resourceManagerAPI.freeResource(poolId, resource); + return result; + }, +}); From 42586a250454fb52d1ee84298672537ab0624296 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Tue, 20 Jun 2023 10:23:03 +0200 Subject: [PATCH 30/69] fix formatter --- src/__generated__/resource-manager.graphql.ts | 112 +++++++++--------- src/__generated__/scheduler.graphql.ts | 104 ++++++++++++---- 2 files changed, 139 insertions(+), 77 deletions(-) diff --git a/src/__generated__/resource-manager.graphql.ts b/src/__generated__/resource-manager.graphql.ts index 1f793f5c..021d65fd 100644 --- a/src/__generated__/resource-manager.graphql.ts +++ b/src/__generated__/resource-manager.graphql.ts @@ -25,9 +25,7 @@ export type AllocationStrategy = Node & { }; /** Supported languages for allocation strategy scripts */ -export type AllocationStrategyLang = - | 'js' - | 'py'; +export type AllocationStrategyLang = 'js' | 'py'; /** Input parameters for creating an allocation pool */ export type CreateAllocatingPoolInput = { @@ -241,14 +239,12 @@ export type Mutation = { UpdateTag: UpdateTagPayload; }; - export type MutationClaimResourceArgs = { description?: InputMaybe; poolId: Scalars['ID']; userInput: Scalars['Map']; }; - export type MutationClaimResourceWithAltIdArgs = { alternativeId: Scalars['Map']; description?: InputMaybe; @@ -256,83 +252,67 @@ export type MutationClaimResourceWithAltIdArgs = { userInput: Scalars['Map']; }; - export type MutationCreateAllocatingPoolArgs = { input?: InputMaybe; }; - export type MutationCreateAllocationStrategyArgs = { input?: InputMaybe; }; - export type MutationCreateNestedAllocatingPoolArgs = { input: CreateNestedAllocatingPoolInput; }; - export type MutationCreateNestedSetPoolArgs = { input: CreateNestedSetPoolInput; }; - export type MutationCreateNestedSingletonPoolArgs = { input: CreateNestedSingletonPoolInput; }; - export type MutationCreateResourceTypeArgs = { input: CreateResourceTypeInput; }; - export type MutationCreateSetPoolArgs = { input: CreateSetPoolInput; }; - export type MutationCreateSingletonPoolArgs = { input?: InputMaybe; }; - export type MutationCreateTagArgs = { input: CreateTagInput; }; - export type MutationDeleteAllocationStrategyArgs = { input?: InputMaybe; }; - export type MutationDeleteResourcePoolArgs = { input: DeleteResourcePoolInput; }; - export type MutationDeleteResourceTypeArgs = { input: DeleteResourceTypeInput; }; - export type MutationDeleteTagArgs = { input: DeleteTagInput; }; - export type MutationFreeResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; - export type MutationTagPoolArgs = { input: TagPoolInput; }; - export type MutationTestAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; currentResources: Array; @@ -340,24 +320,20 @@ export type MutationTestAllocationStrategyArgs = { userInput: Scalars['Map']; }; - export type MutationUntagPoolArgs = { input: UntagPoolInput; }; - export type MutationUpdateResourceAltIdArgs = { alternativeId: Scalars['Map']; input: Scalars['Map']; poolId: Scalars['ID']; }; - export type MutationUpdateResourceTypeNameArgs = { input: UpdateResourceTypeNameInput; }; - export type MutationUpdateTagArgs = { input: UpdateTagInput; }; @@ -391,10 +367,7 @@ export type PoolCapacityPayload = { }; /** Defines the type of pool */ -export type PoolType = - | 'allocating' - | 'set' - | 'singleton'; +export type PoolType = 'allocating' | 'set' | 'singleton'; /** Defines the type of the property */ export type PropertyType = Node & { @@ -431,17 +404,14 @@ export type Query = { node: Maybe; }; - export type QueryQueryAllocationStrategiesArgs = { byName?: InputMaybe; }; - export type QueryQueryAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; }; - export type QueryQueryEmptyResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -450,7 +420,6 @@ export type QueryQueryEmptyResourcePoolsArgs = { resourceTypeId?: InputMaybe; }; - export type QueryQueryLeafResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -461,12 +430,10 @@ export type QueryQueryLeafResourcePoolsArgs = { tags?: InputMaybe; }; - export type QueryQueryPoolCapacityArgs = { poolId: Scalars['ID']; }; - export type QueryQueryRecentlyActiveResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -476,28 +443,23 @@ export type QueryQueryRecentlyActiveResourcesArgs = { toDatetime?: InputMaybe; }; - export type QueryQueryRequiredPoolPropertiesArgs = { allocationStrategyName: Scalars['String']; }; - export type QueryQueryResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; - export type QueryQueryResourcePoolArgs = { poolId: Scalars['ID']; }; - export type QueryQueryResourcePoolHierarchyPathArgs = { poolId: Scalars['ID']; }; - export type QueryQueryResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -508,12 +470,10 @@ export type QueryQueryResourcePoolsArgs = { tags?: InputMaybe; }; - export type QueryQueryResourceTypesArgs = { byName?: InputMaybe; }; - export type QueryQueryResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -522,7 +482,6 @@ export type QueryQueryResourcesArgs = { poolId: Scalars['ID']; }; - export type QueryQueryResourcesByAltIdArgs = { after?: InputMaybe; before?: InputMaybe; @@ -532,7 +491,6 @@ export type QueryQueryResourcesByAltIdArgs = { poolId?: InputMaybe; }; - export type QueryQueryRootResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -543,7 +501,6 @@ export type QueryQueryRootResourcePoolsArgs = { tags?: InputMaybe; }; - export type QuerySearchPoolsByTagsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -552,7 +509,6 @@ export type QuerySearchPoolsByTagsArgs = { tags?: InputMaybe; }; - export type QueryNodeArgs = { id: Scalars['ID']; }; @@ -606,7 +562,6 @@ export type ResourcePool = Node & { id: Scalars['ID']; }; - /** A pool is an entity that contains allocated and free resources */ export type ResourcePoolAllocatedResourcesArgs = { after?: InputMaybe; @@ -710,14 +665,39 @@ export type UpdateTagPayload = { tag: Maybe; }; -export type PoolFragmentFragment = { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }; +export type PoolFragmentFragment = { + __typename: 'ResourcePool'; + id: string; + Name: string; + PoolType: PoolType; + PoolProperties: any; + Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; + ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; +}; export type GetPoolQueryVariables = Exact<{ nodeId: Scalars['ID']; }>; - -export type GetPoolQuery = { __typename?: 'Query', node: { __typename?: 'AllocationStrategy' } | { __typename?: 'PropertyType' } | { __typename?: 'Resource' } | { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } } | { __typename?: 'ResourceType' } | { __typename?: 'Tag' } | null }; +export type GetPoolQuery = { + __typename?: 'Query'; + node: + | { __typename?: 'AllocationStrategy' } + | { __typename?: 'PropertyType' } + | { __typename?: 'Resource' } + | { + __typename: 'ResourcePool'; + id: string; + Name: string; + PoolType: PoolType; + PoolProperties: any; + Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; + ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; + } + | { __typename?: 'ResourceType' } + | { __typename?: 'Tag' } + | null; +}; export type GetPoolsQueryVariables = Exact<{ resourceTypeId?: InputMaybe; @@ -728,13 +708,37 @@ export type GetPoolsQueryVariables = Exact<{ filterByResources?: InputMaybe; }>; - -export type GetPoolsQuery = { __typename?: 'Query', QueryRootResourcePools: { __typename?: 'ResourcePoolConnection', totalCount: number, edges: Array<{ __typename?: 'ResourcePoolEdge', node: { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }, cursor: { __typename?: 'OutputCursor', ID: string } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: { __typename?: 'OutputCursor', ID: string } | null, endCursor: { __typename?: 'OutputCursor', ID: string } | null } } }; +export type GetPoolsQuery = { + __typename?: 'Query'; + QueryRootResourcePools: { + __typename?: 'ResourcePoolConnection'; + totalCount: number; + edges: Array<{ + __typename?: 'ResourcePoolEdge'; + node: { + __typename: 'ResourcePool'; + id: string; + Name: string; + PoolType: PoolType; + PoolProperties: any; + Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; + ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; + }; + cursor: { __typename?: 'OutputCursor'; ID: string }; + } | null>; + pageInfo: { + __typename?: 'PageInfo'; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: { __typename?: 'OutputCursor'; ID: string } | null; + endCursor: { __typename?: 'OutputCursor'; ID: string } | null; + }; + }; +}; export type FreeResourceMutationVariables = Exact<{ poolId: Scalars['ID']; input: Scalars['Map']; }>; - -export type FreeResourceMutation = { __typename?: 'Mutation', FreeResource: string }; +export type FreeResourceMutation = { __typename?: 'Mutation'; FreeResource: string }; diff --git a/src/__generated__/scheduler.graphql.ts b/src/__generated__/scheduler.graphql.ts index af39c7c6..db014ee9 100644 --- a/src/__generated__/scheduler.graphql.ts +++ b/src/__generated__/scheduler.graphql.ts @@ -33,17 +33,14 @@ export type Mutation = { updateSchedule: Schedule; }; - export type MutationCreateScheduleArgs = { input: CreateScheduleInput; }; - export type MutationDeleteScheduleArgs = { name: Scalars['String']; }; - export type MutationUpdateScheduleArgs = { input: UpdateScheduleInput; name: Scalars['String']; @@ -63,12 +60,10 @@ export type Query = { schedules: Maybe; }; - export type QueryScheduleArgs = { name: Scalars['String']; }; - export type QuerySchedulesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -109,14 +104,7 @@ export type SchedulesFilterInput = { workflowVersion: Scalars['String']; }; -export type Status = - | 'COMPLETED' - | 'FAILED' - | 'PAUSED' - | 'RUNNING' - | 'TERMINATED' - | 'TIMED_OUT' - | 'UNKNOWN'; +export type Status = 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; export type UpdateScheduleInput = { cronString?: InputMaybe; @@ -133,30 +121,71 @@ export type DeleteScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; }>; - -export type DeleteScheduleMutation = { __typename?: 'Mutation', deleteSchedule: boolean }; +export type DeleteScheduleMutation = { __typename?: 'Mutation'; deleteSchedule: boolean }; export type UpdateScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; input: UpdateScheduleInput; }>; - -export type UpdateScheduleMutation = { __typename?: 'Mutation', updateSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; +export type UpdateScheduleMutation = { + __typename?: 'Mutation'; + updateSchedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; +}; export type CreateScheduleMutationVariables = Exact<{ input: CreateScheduleInput; }>; - -export type CreateScheduleMutation = { __typename?: 'Mutation', createSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; +export type CreateScheduleMutation = { + __typename?: 'Mutation'; + createSchedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; +}; export type GetScheduleQueryVariables = Exact<{ scheduleName: Scalars['String']; }>; - -export type GetScheduleQuery = { __typename?: 'Query', schedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } | null }; +export type GetScheduleQuery = { + __typename?: 'Query'; + schedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + } | null; +}; export type GetSchedulesQueryVariables = Exact<{ first?: InputMaybe; @@ -166,5 +195,34 @@ export type GetSchedulesQueryVariables = Exact<{ filter?: InputMaybe; }>; - -export type GetSchedulesQuery = { __typename?: 'Query', schedules: { __typename?: 'ScheduleConnection', totalCount: number, edges: Array<{ __typename?: 'ScheduleEdge', cursor: string, node: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null } } | null }; +export type GetSchedulesQuery = { + __typename?: 'Query'; + schedules: { + __typename?: 'ScheduleConnection'; + totalCount: number; + edges: Array<{ + __typename?: 'ScheduleEdge'; + cursor: string; + node: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; + } | null>; + pageInfo: { + __typename?: 'PageInfo'; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; + endCursor: string | null; + }; + } | null; +}; From 4c909c3b316f95f8598d50184678a70bb0805ae7 Mon Sep 17 00:00:00 2001 From: plehocky <117287338+plehocky@users.noreply.github.com> Date: Fri, 14 Jul 2023 08:55:02 +0200 Subject: [PATCH 31/69] Add delete and create mutation for task definitions (#316) * added graphql task definitions mutation for deleting and creating * refactor input and output of create task definition mutation * remove redundant funciton and use static one instead for readability purposes * fix guard statement * refactored delete mutation and create mutation * formatting * changed tasks query to relay connection format * fixed realy connection resolver for taskDefinitionsQuery --------- Co-authored-by: PeterL Co-authored-by: marco.mruz --- .gitignore | 4 +- package-lock.json | 8950 +++++++++++++++++++ src/external-api/conductor-network-types.ts | 40 + src/external-api/conductor.ts | 19 + src/helpers/id-helper.ts | 2 + src/helpers/task-definition.helpers.ts | 63 + src/schema/api.graphql | 59 +- src/schema/nexus-typegen.ts | 102 +- src/schema/task-definitons.ts | 151 +- 9 files changed, 9370 insertions(+), 20 deletions(-) create mode 100644 package-lock.json create mode 100644 src/helpers/task-definition.helpers.ts diff --git a/.gitignore b/.gitignore index 463c5575..db674e01 100644 --- a/.gitignore +++ b/.gitignore @@ -96,4 +96,6 @@ build !/.yarn/plugins !/.yarn/sdks !/.yarn/versions -/.pnp.* \ No newline at end of file +/.pnp.* + +.idea \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..6f67025d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,8950 @@ +{ + "name": "@frinx/inventory-server", + "version": "1.9.2", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@frinx/inventory-server", + "version": "1.9.2", + "license": "MIT", + "dependencies": { + "@devoxa/prisma-relay-cursor-connection": "2.2.2", + "@graphql-tools/schema": "^9.0.9", + "@prisma/client": "4.2.1", + "@types/express": "4.17.13", + "@types/graphql-upload": "15.0.2", + "@types/json-templates": "3.0.0", + "@types/lodash": "4.14.194", + "@types/node": "16.18.32", + "@types/node-fetch": "2.6.4", + "@types/pino": "7.0.4", + "@types/ssh2": "^1.11.6", + "@types/url-join": "4.0.1", + "@types/uuid": "^9.0.0", + "@types/ws": "^8.5.3", + "apollo-server-core": "3.12.0", + "apollo-server-express": "3.12.0", + "base64url": "3.0.1", + "csv-parse": "5.3.10", + "express": "4.18.1", + "fp-ts": "2.15.0", + "graphql": "16.6.0", + "graphql-relay": "0.10.0", + "graphql-upload": "15.0.2", + "graphql-ws": "^5.11.2", + "i18n-iso-countries": "7.5.0", + "io-ts": "2.2.20", + "json-templates": "4.2.0", + "lodash": "4.17.21", + "nexus": "1.3.0", + "node-fetch": "2.6.11", + "node-ssh": "^13.0.0", + "pino": "8.11.0", + "pino-pretty": "9.4.0", + "prisma": "4.2.1", + "ssh2": "^1.11.0", + "url-join": "4.0.1", + "uuid": "^9.0.0", + "ws": "^8.11.0" + }, + "devDependencies": { + "@frinx/eslint-config-typescript-base": "15.0.0-build.1", + "@types/jest": "28.1.8", + "@types/ssh2": "^1.11.6", + "@typescript-eslint/eslint-plugin": "5.54.0", + "@typescript-eslint/parser": "5.54.0", + "@vercel/ncc": "0.36.1", + "apollo-server": "3.12.0", + "cross-env": "7.0.3", + "dotenv": "16.0.3", + "eslint": "8.35.0", + "eslint-config-prettier": "7.2.0", + "eslint-import-resolver-typescript": "3.5.5", + "eslint-plugin-import": "2.27.5", + "get-port": "5.1.1", + "glob": "8.1.0", + "graphql-request": "4.3.0", + "jest": "28.1.3", + "npm-run-all": "4.1.5", + "prettier": "2.8.8", + "rimraf": "3.0.2", + "ts-jest": "28.0.8", + "ts-node": "10.9.1", + "ts-node-dev": "2.0.0", + "typescript": "4.9.5" + }, + "engines": { + "node": "18" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", + "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@apollo/protobufjs": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.2.6.tgz", + "integrity": "sha512-Wqo1oSHNUj/jxmsVp4iR3I480p6qdqHikn38lKrFhfzcDJ7lwd7Ck7cHRl4JE81tWNArl77xhnG/OkZhxKBYOw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.0", + "@types/node": "^10.1.0", + "long": "^4.0.0" + }, + "bin": { + "apollo-pbjs": "bin/pbjs", + "apollo-pbts": "bin/pbts" + } + }, + "node_modules/@apollo/protobufjs/node_modules/@types/node": { + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" + }, + "node_modules/@apollo/utils.dropunuseddefinitions": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.dropunuseddefinitions/-/utils.dropunuseddefinitions-1.1.0.tgz", + "integrity": "sha512-jU1XjMr6ec9pPoL+BFWzEPW7VHHulVdGKMkPAMiCigpVIT11VmCbnij0bWob8uS3ODJ65tZLYKAh/55vLw2rbg==", + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "graphql": "14.x || 15.x || 16.x" + } + }, + "node_modules/@apollo/utils.keyvaluecache": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-1.0.1.tgz", + "integrity": "sha512-nLgYLomqjVimEzQ4cdvVQkcryi970NDvcRVPfd0OPeXhBfda38WjBq+WhQFk+czSHrmrSp34YHBxpat0EtiowA==", + "dependencies": { + "@apollo/utils.logger": "^1.0.0", + "lru-cache": "^7.10.1" + } + }, + "node_modules/@apollo/utils.keyvaluecache/node_modules/lru-cache": { + "version": "7.13.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.13.2.tgz", + "integrity": "sha512-VJL3nIpA79TodY/ctmZEfhASgqekbT574/c4j3jn4bKXbSCnTTCH/KltZyvL2GlV+tGSMtsWyem8DCX7qKTMBA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@apollo/utils.logger": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-1.0.0.tgz", + "integrity": "sha512-dx9XrjyisD2pOa+KsB5RcDbWIAdgC91gJfeyLCgy0ctJMjQe7yZK5kdWaWlaOoCeX0z6YI9iYlg7vMPyMpQF3Q==" + }, + "node_modules/@apollo/utils.printwithreducedwhitespace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.printwithreducedwhitespace/-/utils.printwithreducedwhitespace-1.1.0.tgz", + "integrity": "sha512-GfFSkAv3n1toDZ4V6u2d7L4xMwLA+lv+6hqXicMN9KELSJ9yy9RzuEXaX73c/Ry+GzRsBy/fdSUGayGqdHfT2Q==", + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "graphql": "14.x || 15.x || 16.x" + } + }, + "node_modules/@apollo/utils.removealiases": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.removealiases/-/utils.removealiases-1.0.0.tgz", + "integrity": "sha512-6cM8sEOJW2LaGjL/0vHV0GtRaSekrPQR4DiywaApQlL9EdROASZU5PsQibe2MWeZCOhNrPRuHh4wDMwPsWTn8A==", + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "graphql": "14.x || 15.x || 16.x" + } + }, + "node_modules/@apollo/utils.sortast": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.sortast/-/utils.sortast-1.1.0.tgz", + "integrity": "sha512-VPlTsmUnOwzPK5yGZENN069y6uUHgeiSlpEhRnLFYwYNoJHsuJq2vXVwIaSmts015WTPa2fpz1inkLYByeuRQA==", + "dependencies": { + "lodash.sortby": "^4.7.0" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "graphql": "14.x || 15.x || 16.x" + } + }, + "node_modules/@apollo/utils.stripsensitiveliterals": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.stripsensitiveliterals/-/utils.stripsensitiveliterals-1.2.0.tgz", + "integrity": "sha512-E41rDUzkz/cdikM5147d8nfCFVKovXxKBcjvLEQ7bjZm/cg9zEcXvS6vFY8ugTubI3fn6zoqo0CyU8zT+BGP9w==", + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "graphql": "14.x || 15.x || 16.x" + } + }, + "node_modules/@apollo/utils.usagereporting": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.usagereporting/-/utils.usagereporting-1.0.0.tgz", + "integrity": "sha512-5PL7hJMkTPmdo3oxPtigRrIyPxDk/ddrUryHPDaezL1lSFExpNzsDd2f1j0XJoHOg350GRd3LyD64caLA2PU1w==", + "dependencies": { + "@apollo/utils.dropunuseddefinitions": "^1.1.0", + "@apollo/utils.printwithreducedwhitespace": "^1.1.0", + "@apollo/utils.removealiases": "1.0.0", + "@apollo/utils.sortast": "^1.1.0", + "@apollo/utils.stripsensitiveliterals": "^1.2.0", + "apollo-reporting-protobuf": "^3.3.1" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "graphql": "14.x || 15.x || 16.x" + } + }, + "node_modules/@apollographql/apollo-tools": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.5.3.tgz", + "integrity": "sha512-VcsXHfTFoCodDAgJZxN04GdFK1kqOhZQnQY/9Fa147P+I8xfvOSz5d+lKAPB+hwSgBNyd7ncAKGIs4+utbL+yA==", + "engines": { + "node": ">=8", + "npm": ">=6" + }, + "peerDependencies": { + "graphql": "^14.2.1 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@apollographql/graphql-playground-html": { + "version": "1.6.29", + "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.29.tgz", + "integrity": "sha512-xCcXpoz52rI4ksJSdOCxeOCn2DLocxwHf9dVT/Q90Pte1LX+LY+91SFtJF3KXVHH8kEin+g1KKCQPKBjZJfWNA==", + "dependencies": { + "xss": "^1.0.8" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", + "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.2.tgz", + "integrity": "sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-compilation-targets": "^7.18.2", + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helpers": "^7.18.2", + "@babel/parser": "^7.18.0", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.2", + "@babel/types": "^7.18.2", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", + "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.2", + "@jridgewell/gen-mapping": "^0.3.0", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", + "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", + "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", + "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.0", + "@babel/types": "^7.18.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", + "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", + "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", + "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.2", + "@babel/types": "^7.18.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", + "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz", + "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.0.tgz", + "integrity": "sha512-Xv6mEXqVdaqCBfJFyeab0fH2DnUoMsDmhamxsSi4j8nLd4Vtw213WMJr55xxqipC/YVWyPY3K0blJncPYji+dQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.2.tgz", + "integrity": "sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-environment-visitor": "^7.18.2", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.18.0", + "@babel/types": "^7.18.2", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", + "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@devoxa/prisma-relay-cursor-connection": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@devoxa/prisma-relay-cursor-connection/-/prisma-relay-cursor-connection-2.2.2.tgz", + "integrity": "sha512-nR8/f8DQXNG6a1C3wNRs2YZa6eDCuygz/fzwt6a/ARMsr0asnMK95NhFkZ2jN+ksKHA/AtfvVZvG7UVtJOB09Q==", + "dependencies": { + "graphql-fields": "^2.0.3" + }, + "peerDependencies": { + "@prisma/client": "^2.0.0 || ^3.0.0 || ^4.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", + "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", + "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@frinx/eslint-config-typescript-base": { + "version": "15.0.0-build.1", + "resolved": "https://registry.npmjs.org/@frinx/eslint-config-typescript-base/-/eslint-config-typescript-base-15.0.0-build.1.tgz", + "integrity": "sha512-U3a1xvYxxk5CORATx+7J+2kwBefW3tLihBUKikGGXSh89PDjjAiSGrNkLz87/lk1s9Sh69iFaB3ozbIISS7N1A==", + "dev": true, + "dependencies": { + "eslint-config-airbnb-base": "^15.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.14.0", + "@typescript-eslint/parser": "^5.14.0", + "eslint": "^8.6.0", + "eslint-config-prettier": "^7.2.0", + "eslint-plugin-import": "^2.25.3", + "prettier": "^2.2.1" + } + }, + "node_modules/@graphql-tools/merge": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.2.tgz", + "integrity": "sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw==", + "dependencies": { + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/mock": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/mock/-/mock-8.4.2.tgz", + "integrity": "sha512-2v4v99mWUB1by+6Bk01PoJCUVnYoNSOT0E5VvFRf5oMwJPaRKLAbC+IjZaRoen1tWpVrg+3Coub7co8jyhvm/Q==", + "dependencies": { + "@graphql-tools/schema": "^8.3.1", + "@graphql-tools/utils": "^8.5.1", + "fast-json-stable-stringify": "^2.1.0", + "tslib": "~2.3.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-tools/mock/node_modules/@graphql-tools/schema": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.1.tgz", + "integrity": "sha512-3R0AJFe715p4GwF067G5i0KCr/XIdvSfDLvTLEiTDQ8V/hwbOHEKHKWlEBHGRQwkG5lwFQlW1aOn7VnlPERnWQ==", + "dependencies": { + "@graphql-tools/merge": "^8.2.1", + "@graphql-tools/utils": "^8.5.1", + "tslib": "~2.3.0", + "value-or-promise": "1.0.11" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-tools/mock/node_modules/@graphql-tools/utils": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.5.2.tgz", + "integrity": "sha512-wxA51td/759nQziPYh+HxE0WbURRufrp1lwfOYMgfK4e8Aa6gCa1P1p6ERogUIm423NrIfOVau19Q/BBpHdolw==", + "dependencies": { + "tslib": "~2.3.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/@graphql-tools/mock/node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "node_modules/@graphql-tools/mock/node_modules/value-or-promise": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz", + "integrity": "sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@graphql-tools/schema": { + "version": "9.0.19", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-9.0.19.tgz", + "integrity": "sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==", + "dependencies": { + "@graphql-tools/merge": "^8.4.1", + "@graphql-tools/utils": "^9.2.1", + "tslib": "^2.4.0", + "value-or-promise": "^1.0.12" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-tools/utils": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz", + "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==", + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/core": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.3.tgz", + "integrity": "sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA==", + "dev": true, + "dependencies": { + "@jest/console": "^28.1.3", + "@jest/reporters": "^28.1.3", + "@jest/test-result": "^28.1.3", + "@jest/transform": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^28.1.3", + "jest-config": "^28.1.3", + "jest-haste-map": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-regex-util": "^28.0.2", + "jest-resolve": "^28.1.3", + "jest-resolve-dependencies": "^28.1.3", + "jest-runner": "^28.1.3", + "jest-runtime": "^28.1.3", + "jest-snapshot": "^28.1.3", + "jest-util": "^28.1.3", + "jest-validate": "^28.1.3", + "jest-watcher": "^28.1.3", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.3.tgz", + "integrity": "sha512-1bf40cMFTEkKyEf585R9Iz1WayDjHoHqvts0XFYEqyKM3cFWDpeMoqKKTAF9LSYQModPUlh8FKptoM2YcMWAXA==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "jest-mock": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.3.tgz", + "integrity": "sha512-lzc8CpUbSoE4dqT0U+g1qODQjBRHPpCPXissXD4mS9+sWQdmmpeJ9zSH1rS1HEkrsMN0fb7nKrJ9giAR1d3wBw==", + "dev": true, + "dependencies": { + "expect": "^28.1.3", + "jest-snapshot": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.3.tgz", + "integrity": "sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==", + "dev": true, + "dependencies": { + "jest-get-type": "^28.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.3.tgz", + "integrity": "sha512-D/wOkL2POHv52h+ok5Oj/1gOG9HSywdoPtFsRCUmlCILXNn5eIWmcnd3DIiWlJnpGvQtmajqBP95Ei0EimxfLw==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@sinonjs/fake-timers": "^9.1.2", + "@types/node": "*", + "jest-message-util": "^28.1.3", + "jest-mock": "^28.1.3", + "jest-util": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.3.tgz", + "integrity": "sha512-XFU4P4phyryCXu1pbcqMO0GSQcYe1IsalYCDzRNyhetyeyxMcIxa11qPNDpVNLeretItNqEmYYQn1UYz/5x1NA==", + "dev": true, + "dependencies": { + "@jest/environment": "^28.1.3", + "@jest/expect": "^28.1.3", + "@jest/types": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.3.tgz", + "integrity": "sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^28.1.3", + "@jest/test-result": "^28.1.3", + "@jest/transform": "^28.1.3", + "@jest/types": "^28.1.3", + "@jridgewell/trace-mapping": "^0.3.13", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "jest-worker": "^28.1.3", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "28.1.2", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.1.2.tgz", + "integrity": "sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.13", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", + "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", + "dev": true, + "dependencies": { + "@jest/console": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-28.1.3.tgz", + "integrity": "sha512-NIMPEqqa59MWnDi1kvXXpYbqsfQmSJsIbnd85mdVGkiDfQ9WQQTXOLsvISUfonmnBT+w85WEgneCigEEdHDFxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^28.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.3", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.3.tgz", + "integrity": "sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^28.1.3", + "@jridgewell/trace-mapping": "^0.3.13", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.3", + "jest-regex-util": "^28.0.2", + "jest-util": "^28.1.3", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/@josephg/resolvable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@josephg/resolvable/-/resolvable-1.0.1.tgz", + "integrity": "sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg==" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", + "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", + "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", + "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgr/utils": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz", + "integrity": "sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "is-glob": "^4.0.3", + "open": "^8.4.0", + "picocolors": "^1.0.0", + "tiny-glob": "^0.2.9", + "tslib": "^2.4.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@prisma/client": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.2.1.tgz", + "integrity": "sha512-PZBkY60+k5oix+e6IUfl3ub8TbRLNsPLdfWrdy2eh80WcHTaT+/UfvXf/B7gXedH7FRtbPFHZXk1hZenJiJZFQ==", + "hasInstallScript": true, + "dependencies": { + "@prisma/engines-version": "4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/engines": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.2.1.tgz", + "integrity": "sha512-0KqBwREUOjBiHwITsQzw2DWfLHjntvbqzGRawj4sBMnIiL5CXwyDUKeHOwXzKMtNr1rEjxEsypM14g0CzLRK3g==", + "hasInstallScript": true + }, + "node_modules/@prisma/engines-version": { + "version": "4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826.tgz", + "integrity": "sha512-tktkqdiwqE4QhmE088boPt+FwPj1Jub/zk+5F6sEfcRHzO5yz9jyMD5HFVtiwxZPLx/8Xg9ElnuTi8E5lWVQFQ==" + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78= sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A= sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU= sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E= sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik= sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0= sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q= sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, + "node_modules/@sinclair/typebox": { + "version": "0.24.27", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.27.tgz", + "integrity": "sha512-K7C7IlQ3zLePEZleUN21ceBA2aLcMnLHTLph8QWk1JK37L90obdpY+QGY8bXMKxf1ht1Z0MNewvXxWv0oGDYFg==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", + "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, + "node_modules/@types/accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/babel__core": { + "version": "7.1.16", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.16.tgz", + "integrity": "sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.3.tgz", + "integrity": "sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz", + "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.3.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/busboy": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-1.5.0.tgz", + "integrity": "sha512-ncOOhwmyFDW76c/Tuvv9MA9VGYUCn8blzyWmzYELcNGDb0WXWLSmFi7hJq25YdRBYJrmMBB5jZZwUjlJe9HCjQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/content-disposition": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.5.tgz", + "integrity": "sha512-v6LCdKfK6BwcqMo+wYW05rLS12S0ZO0Fl4w1h4aaZMD7bqT3gVUns6FvLJKGZHQmYn3SX55JWGpziwJRwVgutA==" + }, + "node_modules/@types/cookies": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.7.tgz", + "integrity": "sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==", + "dependencies": { + "@types/connect": "*", + "@types/express": "*", + "@types/keygrip": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + }, + "node_modules/@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.31", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", + "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/graphql-upload": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/@types/graphql-upload/-/graphql-upload-15.0.2.tgz", + "integrity": "sha512-dK4GN/JbMmgHbsKZaUWVYwaLMCwIR0QMBcFz+jb4xj/cRLq1yo2VfnoFvnP5yCw7W4IgGgW7JRwEvM4jn0ahlA==", + "dependencies": { + "@types/express": "*", + "@types/koa": "*", + "fs-capacitor": "^8.0.0", + "graphql": "0.13.1 - 16" + } + }, + "node_modules/@types/http-assert": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.3.tgz", + "integrity": "sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA==" + }, + "node_modules/@types/http-errors": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.2.tgz", + "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "28.1.8", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-28.1.8.tgz", + "integrity": "sha512-8TJkV++s7B6XqnDrzR1m/TT0A0h948Pnl/097veySPN67VRAgQ4gZ7n2KfJo2rVq6njQjdxU3GCCyDvAeuHoiw==", + "dev": true, + "dependencies": { + "expect": "^28.0.0", + "pretty-format": "^28.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/json-templates": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/json-templates/-/json-templates-3.0.0.tgz", + "integrity": "sha512-oaCQfpgz/tL6s20Qs/UW4l1kBg8z48GbmwE74K2y6JG0Uud5BN36Fxev3HOhuJcbH+TpbfaK3cZuhuZ9bxrqeA==" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4= sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/keygrip": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", + "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==" + }, + "node_modules/@types/koa": { + "version": "2.13.5", + "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.13.5.tgz", + "integrity": "sha512-HSUOdzKz3by4fnqagwthW/1w/yJspTgppyyalPVbgZf8jQWvdIXcVW5h2DGtw4zYntOaeRGx49r1hxoPWrD4aA==", + "dependencies": { + "@types/accepts": "*", + "@types/content-disposition": "*", + "@types/cookies": "*", + "@types/http-assert": "*", + "@types/http-errors": "*", + "@types/keygrip": "*", + "@types/koa-compose": "*", + "@types/node": "*" + } + }, + "node_modules/@types/koa-compose": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", + "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", + "dependencies": { + "@types/koa": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.14.194", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.194.tgz", + "integrity": "sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==" + }, + "node_modules/@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "node_modules/@types/node": { + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==" + }, + "node_modules/@types/node-fetch": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", + "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/object-path": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@types/object-path/-/object-path-0.11.1.tgz", + "integrity": "sha512-219LSCO9HPcoXcRTC6DbCs0FRhZgBnEMzf16RRqkT40WbkKx3mOeQuz3e2XqbfhOz/AHfbru0kzB1n1RCAsIIg==" + }, + "node_modules/@types/pino": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@types/pino/-/pino-7.0.4.tgz", + "integrity": "sha512-yKw1UbZOTe7vP1xMQT+oz3FexwgIpBTrM+AC62vWgAkNRULgLTJWfYX+H5/sKPm8VXFbIcXkC3VZPyuaNioZFg==", + "dependencies": { + "pino": "*" + } + }, + "node_modules/@types/prettier": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.1.tgz", + "integrity": "sha512-Fo79ojj3vdEZOHg3wR9ksAMRz4P3S5fDB5e/YWZiFnyFQI1WY2Vftu9XoXVVtJfxB7Bpce/QTqWSSntkz2Znrw==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, + "node_modules/@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/ssh2": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.11.6.tgz", + "integrity": "sha512-8Mf6bhzYYBLEB/G6COux7DS/F5bCWwojv/qFo2yH/e4cLzAavJnxvFXrYW59iKfXdhG6OmzJcXDasgOb/s0rxw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I= sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", + "dev": true + }, + "node_modules/@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true + }, + "node_modules/@types/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-wDXw9LEEUHyV+7UWy7U315nrJGJ7p1BzaCxDpEoLr789Dk1WDVMMlf3iBfbG2F8NdWnYyFbtTxUn2ZNbm1Q4LQ==" + }, + "node_modules/@types/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==" + }, + "node_modules/@types/ws": { + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", + "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.10", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", + "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz", + "integrity": "sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.54.0", + "@typescript-eslint/type-utils": "5.54.0", + "@typescript-eslint/utils": "5.54.0", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.0.tgz", + "integrity": "sha512-aAVL3Mu2qTi+h/r04WI/5PfNWvO6pdhpeMRWk9R7rEV4mwJNzoWf5CCU5vDKBsPIFQFjEq1xg7XBI2rjiMXQbQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.54.0", + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/typescript-estree": "5.54.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz", + "integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/visitor-keys": "5.54.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.0.tgz", + "integrity": "sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.54.0", + "@typescript-eslint/utils": "5.54.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", + "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz", + "integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/visitor-keys": "5.54.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.0.tgz", + "integrity": "sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.54.0", + "@typescript-eslint/types": "5.54.0", + "@typescript-eslint/typescript-estree": "5.54.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.54.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", + "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.54.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vercel/ncc": { + "version": "0.36.1", + "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.36.1.tgz", + "integrity": "sha512-S4cL7Taa9yb5qbv+6wLgiKVZ03Qfkc4jGRuiUQMQ8HGBD5pcNRnHeYM33zBvJE4/zJGjJJ8GScB+WmTsn9mORw==", + "dev": true, + "bin": { + "ncc": "dist/ncc/cli.js" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/apollo-datasource": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-3.3.2.tgz", + "integrity": "sha512-L5TiS8E2Hn/Yz7SSnWIVbZw0ZfEIXZCa5VUiVxD9P53JvSrf4aStvsFDlGWPvpIdCR+aly2CfoB79B9/JjKFqg==", + "deprecated": "The `apollo-datasource` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "@apollo/utils.keyvaluecache": "^1.0.1", + "apollo-server-env": "^4.2.1" + }, + "engines": { + "node": ">=12.0" + } + }, + "node_modules/apollo-reporting-protobuf": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-3.4.0.tgz", + "integrity": "sha512-h0u3EbC/9RpihWOmcSsvTW2O6RXVaD/mPEjfrPkxRPTEPWqncsgOoRJw+wih4OqfH3PvTJvoEIf4LwKrUaqWog==", + "deprecated": "The `apollo-reporting-protobuf` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/usage-reporting-protobuf` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "@apollo/protobufjs": "1.2.6" + } + }, + "node_modules/apollo-server": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/apollo-server/-/apollo-server-3.12.0.tgz", + "integrity": "sha512-wZHLgBoIdGxr/YpPTG5RwNnS+B2y70T/nCegCnU6Yl+H3PXB92OIguLMhdJIZVjukIOhiQT12dNIehqLQ+1hMQ==", + "deprecated": "The `apollo-server` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dev": true, + "dependencies": { + "@types/express": "4.17.14", + "apollo-server-core": "^3.12.0", + "apollo-server-express": "^3.12.0", + "express": "^4.17.1" + }, + "peerDependencies": { + "graphql": "^15.3.0 || ^16.0.0" + } + }, + "node_modules/apollo-server-core": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-3.12.0.tgz", + "integrity": "sha512-hq7iH6Cgldgmnjs9FVSZeKWRpi0/ZR+iJ1arzeD2VXGxxgk1mAm/cz1Tx0TYgegZI+FvvrRl0UhKEx7sLnIxIg==", + "deprecated": "The `apollo-server-core` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "@apollo/utils.keyvaluecache": "^1.0.1", + "@apollo/utils.logger": "^1.0.0", + "@apollo/utils.usagereporting": "^1.0.0", + "@apollographql/apollo-tools": "^0.5.3", + "@apollographql/graphql-playground-html": "1.6.29", + "@graphql-tools/mock": "^8.1.2", + "@graphql-tools/schema": "^8.0.0", + "@josephg/resolvable": "^1.0.0", + "apollo-datasource": "^3.3.2", + "apollo-reporting-protobuf": "^3.4.0", + "apollo-server-env": "^4.2.1", + "apollo-server-errors": "^3.3.1", + "apollo-server-plugin-base": "^3.7.2", + "apollo-server-types": "^3.8.0", + "async-retry": "^1.2.1", + "fast-json-stable-stringify": "^2.1.0", + "graphql-tag": "^2.11.0", + "loglevel": "^1.6.8", + "lru-cache": "^6.0.0", + "node-abort-controller": "^3.0.1", + "sha.js": "^2.4.11", + "uuid": "^9.0.0", + "whatwg-mimetype": "^3.0.0" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "graphql": "^15.3.0 || ^16.0.0" + } + }, + "node_modules/apollo-server-core/node_modules/@graphql-tools/schema": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.1.tgz", + "integrity": "sha512-3R0AJFe715p4GwF067G5i0KCr/XIdvSfDLvTLEiTDQ8V/hwbOHEKHKWlEBHGRQwkG5lwFQlW1aOn7VnlPERnWQ==", + "dependencies": { + "@graphql-tools/merge": "^8.2.1", + "@graphql-tools/utils": "^8.5.1", + "tslib": "~2.3.0", + "value-or-promise": "1.0.11" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/apollo-server-core/node_modules/@graphql-tools/utils": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.5.2.tgz", + "integrity": "sha512-wxA51td/759nQziPYh+HxE0WbURRufrp1lwfOYMgfK4e8Aa6gCa1P1p6ERogUIm423NrIfOVau19Q/BBpHdolw==", + "dependencies": { + "tslib": "~2.3.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/apollo-server-core/node_modules/graphql-tag": { + "version": "2.12.5", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.5.tgz", + "integrity": "sha512-5xNhP4063d16Pz3HBtKprutsPrmHZi5IdUGOWRxA2B6VF7BIRGOHZ5WQvDmJXZuPcBg7rYwaFxvQYjqkSdR3TQ==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" + } + }, + "node_modules/apollo-server-core/node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "node_modules/apollo-server-core/node_modules/value-or-promise": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz", + "integrity": "sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/apollo-server-env": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-4.2.1.tgz", + "integrity": "sha512-vm/7c7ld+zFMxibzqZ7SSa5tBENc4B0uye9LTfjJwGoQFY5xsUPH5FpO5j0bMUDZ8YYNbrF9SNtzc5Cngcr90g==", + "deprecated": "The `apollo-server-env` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/utils.fetcher` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "node-fetch": "^2.6.7" + }, + "engines": { + "node": ">=12.0" + } + }, + "node_modules/apollo-server-errors": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-3.3.1.tgz", + "integrity": "sha512-xnZJ5QWs6FixHICXHxUfm+ZWqqxrNuPlQ+kj5m6RtEgIpekOPssH/SD9gf2B4HuWV0QozorrygwZnux8POvyPA==", + "deprecated": "The `apollo-server-errors` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "graphql": "^15.3.0 || ^16.0.0" + } + }, + "node_modules/apollo-server-express": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-3.12.0.tgz", + "integrity": "sha512-m8FaGPUfDOEGSm7QRWRmUUGjG/vqvpQoorkId9/FXkC57fz/A59kEdrzkMt9538Xgsa5AV+X4MEWLJhTvlW3LQ==", + "deprecated": "The `apollo-server-express` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "@types/accepts": "^1.3.5", + "@types/body-parser": "1.19.2", + "@types/cors": "2.8.12", + "@types/express": "4.17.14", + "@types/express-serve-static-core": "4.17.31", + "accepts": "^1.3.5", + "apollo-server-core": "^3.12.0", + "apollo-server-types": "^3.8.0", + "body-parser": "^1.19.0", + "cors": "^2.8.5", + "parseurl": "^1.3.3" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "express": "^4.17.1", + "graphql": "^15.3.0 || ^16.0.0" + } + }, + "node_modules/apollo-server-express/node_modules/@types/express": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", + "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/apollo-server-plugin-base": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-3.7.2.tgz", + "integrity": "sha512-wE8dwGDvBOGehSsPTRZ8P/33Jan6/PmL0y0aN/1Z5a5GcbFhDaaJCjK5cav6npbbGL2DPKK0r6MPXi3k3N45aw==", + "deprecated": "The `apollo-server-plugin-base` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "apollo-server-types": "^3.8.0" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "graphql": "^15.3.0 || ^16.0.0" + } + }, + "node_modules/apollo-server-types": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-3.8.0.tgz", + "integrity": "sha512-ZI/8rTE4ww8BHktsVpb91Sdq7Cb71rdSkXELSwdSR0eXu600/sY+1UXhTWdiJvk+Eq5ljqoHLwLbY2+Clq2b9A==", + "deprecated": "The `apollo-server-types` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", + "dependencies": { + "@apollo/utils.keyvaluecache": "^1.0.1", + "@apollo/utils.logger": "^1.0.0", + "apollo-reporting-protobuf": "^3.4.0", + "apollo-server-env": "^4.2.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "graphql": "^15.3.0 || ^16.0.0" + } + }, + "node_modules/apollo-server/node_modules/@types/express": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", + "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k= sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/babel-jest": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.3.tgz", + "integrity": "sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q==", + "dev": true, + "dependencies": { + "@jest/transform": "^28.1.3", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^28.1.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.3.tgz", + "integrity": "sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-28.1.3.tgz", + "integrity": "sha512-L+fupJvlWAHbQfn74coNX3zf60LXMJsezNvvx8eIh7iOR1luJ1poxYgQk1F8PYtNq/6QODDHCqsSnTFSWC491A==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^28.1.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.20.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.4.tgz", + "integrity": "sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001349", + "electron-to-chromium": "^1.4.147", + "escalade": "^3.1.1", + "node-releases": "^2.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/buildcheck": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.3.tgz", + "integrity": "sha512-pziaA+p/wdVImfcbsZLNF32EiWyujlQLwolMqUQE8xpKNOH7KmZQaY8sXN7DGOEzPAElo9QTaeNRfGnf3iOJbA==", + "optional": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001352", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001352.tgz", + "integrity": "sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ci-info": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", + "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", + "dev": true + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "dev": true + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", + "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/convert-source-map/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw= sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cpu-features": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.4.tgz", + "integrity": "sha512-fKiZ/zp1mUwQbnzb9IghXtHtDoTMtNeb8oYGx6kX2SYfhnG0HNdBEBIzB9b5KlXu5DQPhfy3mInbBxFcgwAr3A==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "buildcheck": "0.0.3", + "nan": "^2.15.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dev": true, + "dependencies": { + "node-fetch": "2.6.7" + } + }, + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssfilter": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", + "integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4= sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==" + }, + "node_modules/csv-parse": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.3.10.tgz", + "integrity": "sha512-cTXY6iy0gN5Ha/cGILeDgQE+nKiKDU2m0DjSRdJhr86BN3cM7oefBsTk2aH0LQeaYtL7Z7HvW+jYoadmdhzeDA==" + }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, + "node_modules/dedupe": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dedupe/-/dedupe-3.0.3.tgz", + "integrity": "sha512-ZSCmu4uLkBWTAPSz9LXtrTNusY2P6BoghZhokPBLzpQpLiBtU0B4QXNxVnwpy7yaqFc1jN30V5BkKMr/uXqf/w==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk= sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diacritics": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/diacritics/-/diacritics-1.3.0.tgz", + "integrity": "sha1-PvqHMj67hj5mls67AILUj/PW96E= sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA==" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", + "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/dynamic-dedupe": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", + "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE= sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", + "dev": true, + "dependencies": { + "xtend": "^4.0.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.150", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.150.tgz", + "integrity": "sha512-MP3oBer0X7ZeS9GJ0H6lmkn561UxiwOIY9TTkdxVY7lI9G6GVCKfgJaHaDcakwdKxBXA4T3ybeswH/WBIN/KTA==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.14.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz", + "integrity": "sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", + "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^2.0.0", + "@eslint/js": "8.35.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, + "node_modules/eslint-config-airbnb-base/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-config-prettier": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz", + "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz", + "integrity": "sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "get-tsconfig": "^4.5.0", + "globby": "^13.1.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "synckit": "^0.8.5" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/globby": { + "version": "13.1.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", + "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", + "dev": true, + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.11", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", + "has": "^1.0.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", + "tsconfig-paths": "^3.14.1" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.3.tgz", + "integrity": "sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^28.1.3", + "jest-get-type": "^28.0.2", + "jest-matcher-utils": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/extract-files": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz", + "integrity": "sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==", + "dev": true, + "engines": { + "node": "^10.17.0 || ^12.0.0 || >= 13.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/jaydenseric" + } + }, + "node_modules/fast-copy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", + "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-redact": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.1.tgz", + "integrity": "sha512-odVmjC8x8jNeMZ3C+rPMESzXVSEU8tSWSHv9HFxP2mm89G/1WwqhrerJDQm9Zus8X6aoRgQDThKqptdNA6bt+A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fp-ts": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.15.0.tgz", + "integrity": "sha512-3o6EllAvGuCsDgjM+frscLKDRPR9pqbrg13tJ13z86F4eni913kBV8h85rM6zpu2fEvJ8RWA0ouYlUWwHEmxTg==" + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-capacitor": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-8.0.0.tgz", + "integrity": "sha512-+Lk6iSKajdGw+7XYxUkwIzreJ2G1JFlYOdnKJv5PzwFLVsoJYBpCuS7WPIUSNT1IbQaEWT1nhYU63Ud03DyzLA==", + "engines": { + "node": "^14.17.0 || >=16.0.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8= sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.5.0.tgz", + "integrity": "sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globalyzer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", + "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", + "dev": true + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/graphql": { + "version": "16.6.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", + "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/graphql-fields": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/graphql-fields/-/graphql-fields-2.0.3.tgz", + "integrity": "sha512-x3VE5lUcR4XCOxPIqaO4CE+bTK8u6gVouOdpQX9+EKHr+scqtK5Pp/l8nIGqIpN1TUlkKE6jDCCycm/WtLRAwA==" + }, + "node_modules/graphql-relay": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/graphql-relay/-/graphql-relay-0.10.0.tgz", + "integrity": "sha512-44yBuw2/DLNEiMypbNZBt1yMDbBmyVPVesPywnteGGALiBmdyy1JP8jSg8ClLePg8ZZxk0O4BLhd1a6U/1jDOQ==", + "engines": { + "node": "^12.20.0 || ^14.15.0 || >= 15.9.0" + }, + "peerDependencies": { + "graphql": "^16.2.0" + } + }, + "node_modules/graphql-request": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-4.3.0.tgz", + "integrity": "sha512-2v6hQViJvSsifK606AliqiNiijb1uwWp6Re7o0RTyH+uRTv/u7Uqm2g4Fjq/LgZIzARB38RZEvVBFOQOVdlBow==", + "dev": true, + "dependencies": { + "cross-fetch": "^3.1.5", + "extract-files": "^9.0.0", + "form-data": "^3.0.0" + }, + "peerDependencies": { + "graphql": "14 - 16" + } + }, + "node_modules/graphql-upload": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-15.0.2.tgz", + "integrity": "sha512-ufJAkZJBKWRDD/4wJR3VZMy9QWTwqIYIciPtCEF5fCNgWF+V1p7uIgz+bP2YYLiS4OJBhCKR8rnqE/Wg3XPUiw==", + "dependencies": { + "@types/busboy": "^1.5.0", + "@types/node": "*", + "@types/object-path": "^0.11.1", + "busboy": "^1.6.0", + "fs-capacitor": "^6.2.0", + "http-errors": "^2.0.0", + "object-path": "^0.11.8" + }, + "engines": { + "node": "^14.17.0 || ^16.0.0 || >= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/jaydenseric" + }, + "peerDependencies": { + "@types/express": "^4.0.29", + "@types/koa": "^2.11.4", + "graphql": "^16.3.0" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + }, + "@types/koa": { + "optional": true + } + } + }, + "node_modules/graphql-upload/node_modules/fs-capacitor": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-6.2.0.tgz", + "integrity": "sha512-nKcE1UduoSKX27NSZlg879LdQc94OtbOsEmKMN2MBNudXREvijRKx2GEBsTMTfws+BrbkJoEuynbGSVRSpauvw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/graphql-ws": { + "version": "5.11.2", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.11.2.tgz", + "integrity": "sha512-4EiZ3/UXYcjm+xFGP544/yW1+DVI8ZpKASFbzrV5EDTFWJp0ZvLl4Dy2fSZAzz9imKp5pZMIcjB0x/H69Pv/6w==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": ">=0.11 <=16" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/help-me": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.0.1.tgz", + "integrity": "sha512-PLv01Z+OhEPKj2QPYB4kjoCUkopYNPUK3EROlaPIf5bib752fZ+VCvGDAoA+FXo/OwCyLEA4D2e0mX8+Zhcplw==", + "dependencies": { + "glob": "^8.0.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/help-me/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/i18n-iso-countries": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/i18n-iso-countries/-/i18n-iso-countries-7.5.0.tgz", + "integrity": "sha512-PtfKJNWLVhhU0KBX/8asmywjAcuyQk07mmmMwxFJcddTNBJJ1yvpY2qxVmyxbtVF+9+6eg9phgpv83XPUKU5CA==", + "dependencies": { + "diacritics": "1.3.0" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", + "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o= sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/io-ts": { + "version": "2.2.20", + "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.2.20.tgz", + "integrity": "sha512-Rq2BsYmtwS5vVttie4rqrOCIfHCS9TgpRLFpKQCM1wZBBRY9nWVGmEvm2FnDbSE2un1UE39DvFpTR5UL47YDcA==", + "peerDependencies": { + "fp-ts": "^2.5.0" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", + "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterall": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", + "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" + }, + "node_modules/jest": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.3.tgz", + "integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==", + "dev": true, + "dependencies": { + "@jest/core": "^28.1.3", + "@jest/types": "^28.1.3", + "import-local": "^3.0.2", + "jest-cli": "^28.1.3" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.1.3.tgz", + "integrity": "sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-circus": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.3.tgz", + "integrity": "sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow==", + "dev": true, + "dependencies": { + "@jest/environment": "^28.1.3", + "@jest/expect": "^28.1.3", + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^28.1.3", + "jest-matcher-utils": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-runtime": "^28.1.3", + "jest-snapshot": "^28.1.3", + "jest-util": "^28.1.3", + "p-limit": "^3.1.0", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-cli": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.3.tgz", + "integrity": "sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ==", + "dev": true, + "dependencies": { + "@jest/core": "^28.1.3", + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^28.1.3", + "jest-util": "^28.1.3", + "jest-validate": "^28.1.3", + "prompts": "^2.0.1", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.3.tgz", + "integrity": "sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^28.1.3", + "@jest/types": "^28.1.3", + "babel-jest": "^28.1.3", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^28.1.3", + "jest-environment-node": "^28.1.3", + "jest-get-type": "^28.0.2", + "jest-regex-util": "^28.0.2", + "jest-resolve": "^28.1.3", + "jest-runner": "^28.1.3", + "jest-util": "^28.1.3", + "jest-validate": "^28.1.3", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-diff": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", + "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^28.1.1", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.1.1.tgz", + "integrity": "sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-each": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.1.3.tgz", + "integrity": "sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "chalk": "^4.0.0", + "jest-get-type": "^28.0.2", + "jest-util": "^28.1.3", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.3.tgz", + "integrity": "sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A==", + "dev": true, + "dependencies": { + "@jest/environment": "^28.1.3", + "@jest/fake-timers": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "jest-mock": "^28.1.3", + "jest-util": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", + "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.3.tgz", + "integrity": "sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^28.0.2", + "jest-util": "^28.1.3", + "jest-worker": "^28.1.3", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.1.3.tgz", + "integrity": "sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA==", + "dev": true, + "dependencies": { + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", + "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^28.1.3", + "jest-get-type": "^28.0.2", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-mock": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-28.1.3.tgz", + "integrity": "sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "dev": true, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.1.3.tgz", + "integrity": "sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.3", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^28.1.3", + "jest-validate": "^28.1.3", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.3.tgz", + "integrity": "sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^28.0.2", + "jest-snapshot": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-runner": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.3.tgz", + "integrity": "sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA==", + "dev": true, + "dependencies": { + "@jest/console": "^28.1.3", + "@jest/environment": "^28.1.3", + "@jest/test-result": "^28.1.3", + "@jest/transform": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "graceful-fs": "^4.2.9", + "jest-docblock": "^28.1.1", + "jest-environment-node": "^28.1.3", + "jest-haste-map": "^28.1.3", + "jest-leak-detector": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-resolve": "^28.1.3", + "jest-runtime": "^28.1.3", + "jest-util": "^28.1.3", + "jest-watcher": "^28.1.3", + "jest-worker": "^28.1.3", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.3.tgz", + "integrity": "sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw==", + "dev": true, + "dependencies": { + "@jest/environment": "^28.1.3", + "@jest/fake-timers": "^28.1.3", + "@jest/globals": "^28.1.3", + "@jest/source-map": "^28.1.2", + "@jest/test-result": "^28.1.3", + "@jest/transform": "^28.1.3", + "@jest/types": "^28.1.3", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-mock": "^28.1.3", + "jest-regex-util": "^28.0.2", + "jest-resolve": "^28.1.3", + "jest-snapshot": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-snapshot": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.3.tgz", + "integrity": "sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^28.1.3", + "@jest/transform": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/babel__traverse": "^7.0.6", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^28.1.3", + "graceful-fs": "^4.2.9", + "jest-diff": "^28.1.3", + "jest-get-type": "^28.0.2", + "jest-haste-map": "^28.1.3", + "jest-matcher-utils": "^28.1.3", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "natural-compare": "^1.4.0", + "pretty-format": "^28.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-validate": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.1.3.tgz", + "integrity": "sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA==", + "dev": true, + "dependencies": { + "@jest/types": "^28.1.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^28.0.2", + "leven": "^3.1.0", + "pretty-format": "^28.1.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", + "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.3", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-worker": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", + "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json-templates": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/json-templates/-/json-templates-4.2.0.tgz", + "integrity": "sha512-NX0r9SEI2bsz17DJpKhZPymvlw/vcMcRqjqRC0jl7pofLwcpaSsfjweatMFt9QXaUv+dR5EBzInBp8y5lzluIQ==", + "dependencies": { + "dedupe": "^3.0.2", + "object-path": "^0.11.8" + } + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs= sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "node_modules/loglevel": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", + "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==", + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI= sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nan": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", + "optional": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nexus": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/nexus/-/nexus-1.3.0.tgz", + "integrity": "sha512-w/s19OiNOs0LrtP7pBmD9/FqJHvZLmCipVRt6v1PM8cRUYIbhEswyNKGHVoC4eHZGPSnD+bOf5A3+gnbt0A5/A==", + "dependencies": { + "iterall": "^1.3.0", + "tslib": "^2.0.3" + }, + "peerDependencies": { + "graphql": "15.x || 16.x" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/node-abort-controller": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", + "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" + }, + "node_modules/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", + "dev": true + }, + "node_modules/node-ssh": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/node-ssh/-/node-ssh-13.0.0.tgz", + "integrity": "sha512-8yfPvuB8z1M5rXFR8Z1Tl0a0M43N64VjZfjXRwOGCcImFphuXhMPniPksf1FkVj9djKbpHvLUMIVS399H9yCSQ==", + "dependencies": { + "is-stream": "^2.0.0", + "make-dir": "^3.1.0", + "sb-promise-queue": "^2.1.0", + "sb-scandir": "^3.1.0", + "shell-escape": "^0.2.0", + "ssh2": "^1.5.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm-run-all/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/npm-run-all/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/npm-run-all/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/npm-run-all/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-path": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.8.tgz", + "integrity": "sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==", + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", + "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E= sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18= sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pino": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.11.0.tgz", + "integrity": "sha512-Z2eKSvlrl2rH8p5eveNUnTdd4AjJk8tAsLkHYZQKGHP4WTh2Gi1cOSOs3eWPqaj+niS3gj4UkoreoaWgF3ZWYg==", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "v1.0.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^2.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.1.0", + "thread-stream": "^2.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz", + "integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-9.4.0.tgz", + "integrity": "sha512-NIudkNLxnl7MGj1XkvsqVyRgo6meFP82ECXF2PlOI+9ghmbGuBUUqKJ7IZPIxpJw4vhhSva0IuiDSAuGh6TV9g==", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.0", + "fast-safe-stringify": "^2.1.1", + "help-me": "^4.0.1", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-std-serializers": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.0.0.tgz", + "integrity": "sha512-mMMOwSKrmyl+Y12Ri2xhH1lbzQxwwpuru9VjyJpgFIH4asSj88F2csdMwN6+M5g1Ll4rmsYghHLQJw81tgZ7LQ==" + }, + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prisma": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.2.1.tgz", + "integrity": "sha512-HuYqnTDgH8atjPGtYmY0Ql9XrrJnfW7daG1PtAJRW0E6gJxc50lY3vrIDn0yjMR3TvRlypjTcspQX8DT+xD4Sg==", + "hasInstallScript": true, + "dependencies": { + "@prisma/engines": "4.2.1" + }, + "bin": { + "prisma": "build/index.js", + "prisma2": "build/index.js" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/process-warning": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.0.0.tgz", + "integrity": "sha512-+MmoAXoUX+VTHAlwns0h+kFUWFs/3FZy+ZuchkgjyOu3oioLAo2LB5aCfKPh2+P9O18i3m43tUEv3YqttSy0Ww==" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-is": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", + "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "dev": true + }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/readable-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.1.0.tgz", + "integrity": "sha512-sVisi3+P2lJ2t0BPbpK629j8wRW06yKGJUcaLAGXPAUhyUxVJm7VsCTit1PFgT4JHUDMrGNR+ZjSKpzGaRF3zw==", + "dependencies": { + "abort-controller": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I= sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dev": true, + "dependencies": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz", + "integrity": "sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sb-promise-queue": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sb-promise-queue/-/sb-promise-queue-2.1.0.tgz", + "integrity": "sha512-zwq4YuP1FQFkGx2Q7GIkZYZ6PqWpV+bg0nIO1sJhWOyGyhqbj0MsTvK6lCFo5TQwX5pZr6SCQ75e8PCDCuNvkg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/sb-scandir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/sb-scandir/-/sb-scandir-3.1.0.tgz", + "integrity": "sha512-70BVm2xz9jn94zSQdpvYrEG101/UV9TVGcfWr9T5iob3QhCK4lYXeculfBqPGFv3XTeKgx4dpWyYIDeZUqo4kg==", + "dependencies": { + "sb-promise-queue": "^2.1.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/secure-json-parse": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.4.0.tgz", + "integrity": "sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg==" + }, + "node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-escape": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/shell-escape/-/shell-escape-0.2.0.tgz", + "integrity": "sha512-uRRBT2MfEOyxuECseCZd28jC1AJ8hmqqneWQ4VWUTgCAFvb3wKU1jLqj6egC4Exrr88ogg3dp+zroH4wJuaXzw==" + }, + "node_modules/shell-quote": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", + "dev": true + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sonic-boom": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.2.0.tgz", + "integrity": "sha512-SbbZ+Kqj/XIunvIAgUZRlqd6CGQYq71tRRbXR92Za8J/R3Yh4Av+TWENiSiEgnlwckYLyP0YZQWVfyNC0dzLaA==", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", + "dev": true + }, + "node_modules/split2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", + "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/ssh2": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.11.0.tgz", + "integrity": "sha512-nfg0wZWGSsfUe/IBJkXVll3PEZ//YH2guww+mP88gTpuSU4FtZN7zu9JoeTGOyCNx2dTDtT9fOpWwlzyj4uOOw==", + "hasInstallScript": true, + "dependencies": { + "asn1": "^0.2.4", + "bcrypt-pbkdf": "^1.0.2" + }, + "engines": { + "node": ">=10.16.0" + }, + "optionalDependencies": { + "cpu-features": "~0.0.4", + "nan": "^2.16.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.padend": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz", + "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/synckit": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "dev": true, + "dependencies": { + "@pkgr/utils": "^2.3.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thread-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.0.1.tgz", + "integrity": "sha512-X7vWOdsHLkBq0si20ruEE2ttpS7WOVyD52xKu+TOjrRP9Qi9uB9ynHYpzZUbBptArBSuKYUn4mH+jEBnO2CRGg==", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/tiny-glob": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", + "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", + "dev": true, + "dependencies": { + "globalyzer": "0.1.0", + "globrex": "^0.1.2" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-jest": { + "version": "28.0.8", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-28.0.8.tgz", + "integrity": "sha512-5FaG0lXmRPzApix8oFG8RKjAz4ehtm8yMKOTy5HX3fY6W8kmvOrmcY0hKDElW52FJov+clhUbrKAqofnj4mXTg==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^28.0.0", + "json5": "^2.2.1", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "7.x", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^28.0.0", + "babel-jest": "^28.0.0", + "jest": "^28.0.0", + "typescript": ">=4.3" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node-dev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", + "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.1", + "dynamic-dedupe": "^0.3.0", + "minimist": "^1.2.6", + "mkdirp": "^1.0.4", + "resolve": "^1.0.0", + "rimraf": "^2.6.1", + "source-map-support": "^0.5.12", + "tree-kill": "^1.2.2", + "ts-node": "^10.4.0", + "tsconfig": "^7.0.0" + }, + "bin": { + "ts-node-dev": "lib/bin.js", + "tsnd": "lib/bin.js" + }, + "engines": { + "node": ">=0.8.0" + }, + "peerDependencies": { + "node-notifier": "*", + "typescript": "*" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/ts-node-dev/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ts-node-dev/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", + "dev": true, + "dependencies": { + "@types/strip-bom": "^3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", + "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tsconfig/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tsconfig/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo= sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tslib": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", + "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", + "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/value-or-promise": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz", + "integrity": "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==", + "engines": { + "node": ">=12" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0= sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.1.tgz", + "integrity": "sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xss": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.10.tgz", + "integrity": "sha512-qmoqrRksmzqSKvgqzN0055UFWY7OKx1/9JWeRswwEVX9fCG5jcYRxa/A2DHcmZX6VJvjzHRQ2STeeVcQkrmLSw==", + "dependencies": { + "commander": "^2.20.3", + "cssfilter": "0.0.10" + }, + "bin": { + "xss": "bin/xss" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index d6cc487e..55d43a4a 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -192,6 +192,39 @@ const ExecutedWorkflowsValidator = t.type({ results: t.array(ExecutedWorkflow), }); +const CreateTaskDefinitionInputRequired = t.type({ + name: t.string, + timeoutSeconds: t.number, +}); + +const CreateTaskDefinitionInputOptional = t.partial({ + ownerApp: optional(t.string), + createTime: optional(t.number), + updateTime: optional(t.number), + createdBy: optional(t.string), + updatedBy: optional(t.string), + accessPolicy: optional(t.UnknownRecord), + description: optional(t.string), + retryCount: optional(t.number), + inputKeys: optional(t.array(t.string)), + outputKeys: optional(t.array(t.string)), + timeoutPolicy: optional(t.union([t.literal('RETRY'), t.literal('TIME_OUT_WF'), t.literal('ALERT_ONLY')])), + retryLogic: optional(t.union([t.literal('FIXED'), t.literal('EXPONENTIAL_BACKOFF'), t.literal('LINEAR_BACKOFF')])), + retryDelaySeconds: optional(t.number), + responseTimeoutSeconds: optional(t.number), + concurrentExecLimit: optional(t.number), + inputTemplate: optional(t.UnknownRecord), + rateLimitPerFrequency: optional(t.number), + rateLimitFrequencyInSeconds: optional(t.number), + isolationGroupId: optional(t.string), + executionNameSpace: optional(t.string), + ownerEmail: optional(t.string), + pollTimeoutSeconds: optional(t.number), + backoffScaleFactor: optional(t.number), +}); + +const TaskDefinitionInput = t.intersection([CreateTaskDefinitionInputRequired, CreateTaskDefinitionInputOptional]); + const TaskDefinition = t.type({ name: t.string, timeoutSeconds: t.number, @@ -249,11 +282,18 @@ export function decodeExecutedWorkflowDetailOutput(value: unknown): ApiExecutedW } export type TaskDefinitionsOutput = t.TypeOf; +export type TaskDefinitionOutput = t.TypeOf; + +export type TaskDefinitionDetailInput = t.TypeOf; export function decodeTaskDefinitionsOutput(value: unknown): TaskDefinitionsOutput { return extractResult(TaskDefinitionsValidator.decode(value)); } +export function decodeTaskDefinitionOutput(value: unknown): TaskDefinitionOutput { + return extractResult(TaskDefinition.decode(value)); +} + export function decodeBulkTerminateOutput(value: unknown): BulkOperationOutput { return extractResult(BulkOperation.decode(value)); } diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts index 37107143..6774686b 100644 --- a/src/external-api/conductor.ts +++ b/src/external-api/conductor.ts @@ -17,6 +17,8 @@ import { decodeBulkTerminateOutput, decodeExecutedWorkflowTaskDetailOutput, ApiExecutedWorkflowTask, + decodeTaskDefinitionOutput, + TaskDefinitionDetailInput, } from './conductor-network-types'; import { sendDeleteRequest, sendGetRequest, sendPostRequest, sendPutRequest } from './helpers'; @@ -198,12 +200,26 @@ async function executeWorkflowByName( } } +async function getTaskDetail(baseURL: string, taskName: string) { + const json = await sendGetRequest([baseURL, `metadata/taskdefs/${taskName}`]); + const data = decodeTaskDefinitionOutput(json); + return data; +} + async function getTaskDefinitions(baseURL: string): Promise { const json = await sendGetRequest([baseURL, 'metadata/taskdefs']); const data = decodeTaskDefinitionsOutput(json); return data; } +async function deleteTaskDefinition(baseURL: string, name: string): Promise { + await sendDeleteRequest([baseURL, `metadata/taskdefs/${name}`]); +} + +async function createTaskDefinition(baseURL: string, taskDefinitionInput: TaskDefinitionDetailInput): Promise { + await sendPostRequest([baseURL, `metadata/taskdefs`], [taskDefinitionInput]); +} + async function getExecutedWorkflowTaskDetail(baseURL: string, taskId: string): Promise { const json = await sendGetRequest([baseURL, `/tasks/${taskId}`]); const data = decodeExecutedWorkflowTaskDetailOutput(json); @@ -231,7 +247,10 @@ const conductorAPI = { removeWorkflow, executeNewWorkflow, executeWorkflowByName, + getTaskDetail, getTaskDefinitions, + deleteTaskDefinition, + createTaskDefinition, getExecutedWorkflowTaskDetail, }; diff --git a/src/helpers/id-helper.ts b/src/helpers/id-helper.ts index b091ae31..bd67b4f7 100644 --- a/src/helpers/id-helper.ts +++ b/src/helpers/id-helper.ts @@ -13,6 +13,7 @@ export type DataType = | 'GraphNode' | 'GraphEdge' | 'Schedule' + | 'TaskDefinition' | 'Pool'; function isDataType(value: string): value is DataType { @@ -29,6 +30,7 @@ function isDataType(value: string): value is DataType { value === 'GraphNode' || value === 'GraphEdge' || value === 'Schedule' || + value === 'TaskDefinition' || value === 'Pool' ); } diff --git a/src/helpers/task-definition.helpers.ts b/src/helpers/task-definition.helpers.ts new file mode 100644 index 00000000..6376a60d --- /dev/null +++ b/src/helpers/task-definition.helpers.ts @@ -0,0 +1,63 @@ +import { TaskDefinition } from '../schema/source-types'; + +type TaskDefinitionDetailInput = { + name: string; + timeoutSeconds: number; + createdBy?: string | null | undefined; + updatedBy?: string | null | undefined; + retryCount?: number | null | undefined; + pollTimeoutSeconds?: number | null | undefined; + inputKeys?: string[] | null | undefined; + outputKeys?: string[] | null | undefined; + inputTemplate?: string | null | undefined; + timeoutPolicy?: 'RETRY' | 'TIME_OUT_WF' | 'ALERT_ONLY' | null | undefined; + retryLogic?: 'FIXED' | 'EXPONENTIAL_BACKOFF' | 'LINEAR_BACKOFF' | null | undefined; + retryDelaySeconds?: number | null | undefined; + responseTimeoutSeconds?: number | null | undefined; + concurrentExecLimit?: number | null | undefined; + rateLimitFrequencyInSeconds?: number | null | undefined; + rateLimitPerFrequency?: number | null | undefined; + ownerEmail?: string | null | undefined; + accessPolicy?: string | null | undefined; + ownerApp?: string | null | undefined; + description?: string | null | undefined; + isolationGroupId?: string | null | undefined; + executionNameSpace?: string | null | undefined; + backoffScaleFactor?: number | null | undefined; + createTime?: string | null | undefined; + updateTime?: string | null | undefined; +}; + +export const getTaskDefinitionInput = (input: TaskDefinitionDetailInput) => { + const taskDefinitionInput = { + ...input, + createdBy: input.createdBy ?? undefined, + updatedBy: input.updatedBy ?? undefined, + retryCount: input.retryCount ?? undefined, + pollTimeoutSeconds: input.pollTimeoutSeconds ?? undefined, + inputKeys: input.inputKeys ?? undefined, + outputKeys: input.outputKeys ?? undefined, + inputTemplate: input.inputTemplate ? JSON.parse(input.inputTemplate) : undefined, + timeoutPolicy: input.timeoutPolicy ?? undefined, + retryLogic: input.retryLogic ?? undefined, + retryDelaySeconds: input.retryDelaySeconds ?? undefined, + responseTimeoutSeconds: input.responseTimeoutSeconds ?? undefined, + concurrentExecLimit: input.concurrentExecLimit ?? undefined, + rateLimitFrequencyInSeconds: input.rateLimitFrequencyInSeconds ?? undefined, + rateLimitPerFrequency: input.rateLimitPerFrequency ?? undefined, + ownerEmail: input.ownerEmail ?? undefined, + accessPolicy: input.accessPolicy ? JSON.parse(input.accessPolicy) : undefined, + ownerApp: input.ownerApp ?? undefined, + description: input.description ?? undefined, + isolationGroupId: input.isolationGroupId ?? undefined, + executionNameSpace: input.executionNameSpace ?? undefined, + backoffScaleFactor: input.backoffScaleFactor ?? undefined, + createTime: Date.now(), + updateTime: Date.now(), + }; + return taskDefinitionInput; +}; + +export const getFilteredTaskDefinitions = (defs: T[], searchTerm: string): T[] => { + return defs.filter((df) => df.name.toLowerCase().includes(searchTerm.toLowerCase())); +}; diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 0859e7aa..664d2f68 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -187,6 +187,32 @@ input CreateScheduleInput { workflowVersion: String! } +input CreateTaskDefinitionInput { + accessPolicy: String + backoffScaleFactor: Int + concurrentExecLimit: Int + createdBy: String + description: String + executionNameSpace: String + inputKeys: [String!] + inputTemplate: String + isolationGroupId: String + name: String! + outputKeys: [String!] + ownerApp: String + ownerEmail: String + pollTimeoutSeconds: Int + rateLimitFrequencyInSeconds: Int + rateLimitPerFrequency: Int + responseTimeoutSeconds: Int + retryCount: Int + retryDelaySeconds: Int + retryLogic: RetryLogic + timeoutPolicy: TaskTimeoutPolicy + timeoutSeconds: Int! + updatedBy: String +} + type CreateTransactionPayload { transactionId: String } @@ -446,6 +472,10 @@ input FilterPoolsInput { poolName: String } +input FilterTaskDefinitionsInput { + keyword: String +} + input FilterTopologyInput { labels: [String!] } @@ -574,6 +604,7 @@ type Mutation { closeTransaction(deviceId: String!, transactionId: String!): CloseTransactionPayload! commitConfig(input: CommitConfigInput!, transactionId: String!): CommitConfigPayload! createLabel(input: CreateLabelInput!): CreateLabelPayload! + createTaskDefinition(input: CreateTaskDefinitionInput!): TaskDefinition createTransaction(deviceId: String!): CreateTransactionPayload! createWorkflow(input: CreateWorkflowInput!): CreateWorkflowPayload! deleteBlueprint(id: String!): DeleteBlueprintPayload! @@ -581,6 +612,7 @@ type Mutation { deleteLabel(id: String!): DeleteLabelPayload! deleteSchedule(id: String!): IsOkResponse deleteSnapshot(input: DeleteSnapshotInput!): DeleteSnapshotPayload + deleteTask(name: String!): IsOkResponse deleteWorkflow(input: DeleteWorkflowInput!): DeleteWorkflowPayload! editWorkflowSchedule(id: String!, input: EditWorkflowScheduleInput!): Schedule executeNewWorkflow(input: StartWorkflowRequestInput!): String @@ -710,7 +742,13 @@ type Query { resourceTypeId: String ): PoolConnection! schedules(after: String, before: String, filter: ScheduleFilterInput, first: Int, last: Int): ScheduleConnection! - taskDefinitions: [TaskDefinition!]! + taskDefinitions( + after: String + before: String + filter: FilterTaskDefinitionsInput + first: Int + last: Int + ): TaskDefinitionConnection! topology(filter: FilterTopologyInput): Topology topologyCommonNodes(nodes: [String!]!): TopologyCommonNodes topologyVersionData(version: String!): TopologyVersionData! @@ -853,11 +891,12 @@ type Tag { tag: String! } -type TaskDefinition { +type TaskDefinition implements Node { concurrentExecLimit: Int - createdAt: String + createTime: String createdBy: String description: String + id: ID! inputKeys: [String!] inputTemplate: String name: String! @@ -872,8 +911,20 @@ type TaskDefinition { retryLogic: RetryLogic timeoutPolicy: TaskTimeoutPolicy timeoutSeconds: Int! - updatedAt: String + updateTime: String updatedBy: String + version: Int +} + +type TaskDefinitionConnection { + edges: [TaskDefinitionEdge!]! + pageInfo: PageInfo! + totalCount: Int! +} + +type TaskDefinitionEdge { + cursor: String! + node: TaskDefinition! } input TaskInput { diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 70fcd308..b3e01b4c 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -114,6 +114,32 @@ export interface NexusGenInputs { workflowName: string; // String! workflowVersion: string; // String! }; + CreateTaskDefinitionInput: { + // input type + accessPolicy?: string | null; // String + backoffScaleFactor?: number | null; // Int + concurrentExecLimit?: number | null; // Int + createdBy?: string | null; // String + description?: string | null; // String + executionNameSpace?: string | null; // String + inputKeys?: string[] | null; // [String!] + inputTemplate?: string | null; // String + isolationGroupId?: string | null; // String + name: string; // String! + outputKeys?: string[] | null; // [String!] + ownerApp?: string | null; // String + ownerEmail?: string | null; // String + pollTimeoutSeconds?: number | null; // Int + rateLimitFrequencyInSeconds?: number | null; // Int + rateLimitPerFrequency?: number | null; // Int + responseTimeoutSeconds?: number | null; // Int + retryCount?: number | null; // Int + retryDelaySeconds?: number | null; // Int + retryLogic?: NexusGenEnums['RetryLogic'] | null; // RetryLogic + timeoutPolicy?: NexusGenEnums['TaskTimeoutPolicy'] | null; // TaskTimeoutPolicy + timeoutSeconds: number; // Int! + updatedBy?: string | null; // String + }; CreateWorkflowInput: { // input type workflow: NexusGenInputs['WorkflowInput']; // WorkflowInput! @@ -189,6 +215,10 @@ export interface NexusGenInputs { // input type poolName?: string | null; // String }; + FilterTaskDefinitionsInput: { + // input type + keyword?: string | null; // String + }; FilterTopologyInput: { // input type labels?: string[] | null; // [String!] @@ -726,6 +756,17 @@ export interface NexusGenObjects { tag: string; // String! }; TaskDefinition: SourceTypes.TaskDefinition; + TaskDefinitionConnection: { + // root type + edges: NexusGenRootTypes['TaskDefinitionEdge'][]; // [TaskDefinitionEdge!]! + pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! + totalCount: number; // Int! + }; + TaskDefinitionEdge: { + // root type + cursor: string; // String! + node: NexusGenRootTypes['TaskDefinition']; // TaskDefinition! + }; Topology: { // root type edges: NexusGenRootTypes['GraphEdge'][]; // [GraphEdge!]! @@ -829,6 +870,7 @@ export interface NexusGenInterfaces { | core.Discriminate<'Location', 'required'> | core.Discriminate<'Pool', 'required'> | core.Discriminate<'Schedule', 'required'> + | core.Discriminate<'TaskDefinition', 'required'> | core.Discriminate<'Workflow', 'required'> | core.Discriminate<'Zone', 'required'>; } @@ -1191,6 +1233,7 @@ export interface NexusGenFieldTypes { closeTransaction: NexusGenRootTypes['CloseTransactionPayload']; // CloseTransactionPayload! commitConfig: NexusGenRootTypes['CommitConfigPayload']; // CommitConfigPayload! createLabel: NexusGenRootTypes['CreateLabelPayload']; // CreateLabelPayload! + createTaskDefinition: NexusGenRootTypes['TaskDefinition'] | null; // TaskDefinition createTransaction: NexusGenRootTypes['CreateTransactionPayload']; // CreateTransactionPayload! createWorkflow: NexusGenRootTypes['CreateWorkflowPayload']; // CreateWorkflowPayload! deleteBlueprint: NexusGenRootTypes['DeleteBlueprintPayload']; // DeleteBlueprintPayload! @@ -1198,6 +1241,7 @@ export interface NexusGenFieldTypes { deleteLabel: NexusGenRootTypes['DeleteLabelPayload']; // DeleteLabelPayload! deleteSchedule: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse deleteSnapshot: NexusGenRootTypes['DeleteSnapshotPayload'] | null; // DeleteSnapshotPayload + deleteTask: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse deleteWorkflow: NexusGenRootTypes['DeleteWorkflowPayload']; // DeleteWorkflowPayload! editWorkflowSchedule: NexusGenRootTypes['Schedule'] | null; // Schedule executeNewWorkflow: string | null; // String @@ -1292,7 +1336,7 @@ export interface NexusGenFieldTypes { node: NexusGenRootTypes['Node'] | null; // Node pools: NexusGenRootTypes['PoolConnection']; // PoolConnection! schedules: NexusGenRootTypes['ScheduleConnection']; // ScheduleConnection! - taskDefinitions: NexusGenRootTypes['TaskDefinition'][]; // [TaskDefinition!]! + taskDefinitions: NexusGenRootTypes['TaskDefinitionConnection']; // TaskDefinitionConnection! topology: NexusGenRootTypes['Topology'] | null; // Topology topologyCommonNodes: NexusGenRootTypes['TopologyCommonNodes'] | null; // TopologyCommonNodes topologyVersionData: NexusGenRootTypes['TopologyVersionData']; // TopologyVersionData! @@ -1371,9 +1415,10 @@ export interface NexusGenFieldTypes { TaskDefinition: { // field return type concurrentExecLimit: number | null; // Int - createdAt: string | null; // String + createTime: string | null; // String createdBy: string | null; // String description: string | null; // String + id: string; // ID! inputKeys: string[] | null; // [String!] inputTemplate: string | null; // String name: string; // String! @@ -1388,8 +1433,20 @@ export interface NexusGenFieldTypes { retryLogic: NexusGenEnums['RetryLogic'] | null; // RetryLogic timeoutPolicy: NexusGenEnums['TaskTimeoutPolicy'] | null; // TaskTimeoutPolicy timeoutSeconds: number; // Int! - updatedAt: string | null; // String + updateTime: string | null; // String updatedBy: string | null; // String + version: number | null; // Int + }; + TaskDefinitionConnection: { + // field return type + edges: NexusGenRootTypes['TaskDefinitionEdge'][]; // [TaskDefinitionEdge!]! + pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! + totalCount: number; // Int! + }; + TaskDefinitionEdge: { + // field return type + cursor: string; // String! + node: NexusGenRootTypes['TaskDefinition']; // TaskDefinition! }; Topology: { // field return type @@ -1871,6 +1928,7 @@ export interface NexusGenFieldTypeNames { closeTransaction: 'CloseTransactionPayload'; commitConfig: 'CommitConfigPayload'; createLabel: 'CreateLabelPayload'; + createTaskDefinition: 'TaskDefinition'; createTransaction: 'CreateTransactionPayload'; createWorkflow: 'CreateWorkflowPayload'; deleteBlueprint: 'DeleteBlueprintPayload'; @@ -1878,6 +1936,7 @@ export interface NexusGenFieldTypeNames { deleteLabel: 'DeleteLabelPayload'; deleteSchedule: 'IsOkResponse'; deleteSnapshot: 'DeleteSnapshotPayload'; + deleteTask: 'IsOkResponse'; deleteWorkflow: 'DeleteWorkflowPayload'; editWorkflowSchedule: 'Schedule'; executeNewWorkflow: 'String'; @@ -1972,7 +2031,7 @@ export interface NexusGenFieldTypeNames { node: 'Node'; pools: 'PoolConnection'; schedules: 'ScheduleConnection'; - taskDefinitions: 'TaskDefinition'; + taskDefinitions: 'TaskDefinitionConnection'; topology: 'Topology'; topologyCommonNodes: 'TopologyCommonNodes'; topologyVersionData: 'TopologyVersionData'; @@ -2051,9 +2110,10 @@ export interface NexusGenFieldTypeNames { TaskDefinition: { // field return type name concurrentExecLimit: 'Int'; - createdAt: 'String'; + createTime: 'String'; createdBy: 'String'; description: 'String'; + id: 'ID'; inputKeys: 'String'; inputTemplate: 'String'; name: 'String'; @@ -2068,8 +2128,20 @@ export interface NexusGenFieldTypeNames { retryLogic: 'RetryLogic'; timeoutPolicy: 'TaskTimeoutPolicy'; timeoutSeconds: 'Int'; - updatedAt: 'String'; + updateTime: 'String'; updatedBy: 'String'; + version: 'Int'; + }; + TaskDefinitionConnection: { + // field return type name + edges: 'TaskDefinitionEdge'; + pageInfo: 'PageInfo'; + totalCount: 'Int'; + }; + TaskDefinitionEdge: { + // field return type name + cursor: 'String'; + node: 'TaskDefinition'; }; Topology: { // field return type name @@ -2270,6 +2342,10 @@ export interface NexusGenArgTypes { // args input: NexusGenInputs['CreateLabelInput']; // CreateLabelInput! }; + createTaskDefinition: { + // args + input: NexusGenInputs['CreateTaskDefinitionInput']; // CreateTaskDefinitionInput! + }; createTransaction: { // args deviceId: string; // String! @@ -2298,6 +2374,10 @@ export interface NexusGenArgTypes { // args input: NexusGenInputs['DeleteSnapshotInput']; // DeleteSnapshotInput! }; + deleteTask: { + // args + name: string; // String! + }; deleteWorkflow: { // args input: NexusGenInputs['DeleteWorkflowInput']; // DeleteWorkflowInput! @@ -2478,6 +2558,14 @@ export interface NexusGenArgTypes { first?: number | null; // Int last?: number | null; // Int }; + taskDefinitions: { + // args + after?: string | null; // String + before?: string | null; // String + filter?: NexusGenInputs['FilterTaskDefinitionsInput'] | null; // FilterTaskDefinitionsInput + first?: number | null; // Int + last?: number | null; // Int + }; topology: { // args filter?: NexusGenInputs['FilterTopologyInput'] | null; // FilterTopologyInput @@ -2537,6 +2625,7 @@ export interface NexusGenAbstractTypeMembers { | 'Location' | 'Pool' | 'Schedule' + | 'TaskDefinition' | 'Workflow' | 'Zone'; } @@ -2553,6 +2642,7 @@ export interface NexusGenTypeInterfaces { Location: 'Node'; Pool: 'Node'; Schedule: 'Node'; + TaskDefinition: 'Node'; Workflow: 'Node'; Zone: 'Node'; } diff --git a/src/schema/task-definitons.ts b/src/schema/task-definitons.ts index c6a63fe4..b01b86cb 100644 --- a/src/schema/task-definitons.ts +++ b/src/schema/task-definitons.ts @@ -1,5 +1,11 @@ -import { enumType, extendType, list, nonNull, objectType } from 'nexus'; +import { arg, enumType, extendType, inputObjectType, list, mutationField, nonNull, objectType, stringArg } from 'nexus'; import config from '../config'; +import { toGraphId } from '../helpers/id-helper'; +import { getTaskDefinitionInput } from '../helpers/task-definition.helpers'; +import { IsOkResponse, Node, PageInfo, PaginationConnectionArgs } from './global-types'; +import { getFilteredTaskDefinitions } from '../helpers/task-definition.helpers'; +import {connectionFromArray} from '../helpers/connection.helpers' +import { log } from 'console'; const TaskTimeoutPolicy = enumType({ name: 'TaskTimeoutPolicy', @@ -14,25 +20,33 @@ const RetryLogic = enumType({ export const TaskDefinition = objectType({ name: 'TaskDefinition', definition: (t) => { + t.implements(Node); + t.nonNull.id('id', { + resolve: (taskDefinition) => toGraphId('TaskDefinition', taskDefinition.name), + }); t.nonNull.string('name'); t.nonNull.int('timeoutSeconds'); - t.string('createdAt', { + t.string('createTime', { resolve: (taskDefinition) => taskDefinition.createTime ? new Date(taskDefinition.createTime).toISOString() : new Date().toISOString(), }); - t.string('updatedAt', { + t.string('updateTime', { resolve: (taskDefinition) => taskDefinition.updateTime ? new Date(taskDefinition.updateTime).toISOString() : new Date().toISOString(), }); - t.string('createdBy'); - t.string('updatedBy'); + t.string('createdBy', { + resolve: (taskDefinition) => taskDefinition.createdBy ?? null, + }); + t.string('updatedBy', { + resolve: (taskDefinition) => taskDefinition.updatedBy ?? null, + }); t.string('description'); t.int('retryCount'); t.int('pollTimeoutSeconds'); t.list.nonNull.string('inputKeys'); t.list.nonNull.string('outputKeys'); t.string('inputTemplate', { - resolve: (taskDefinition) => JSON.stringify(taskDefinition.inputTemplate), + resolve: (taskDefinition) => JSON.stringify(taskDefinition.inputTemplate) ?? null, }); t.field('timeoutPolicy', { type: TaskTimeoutPolicy }); t.field('retryLogic', { type: RetryLogic }); @@ -45,16 +59,135 @@ export const TaskDefinition = objectType({ }, }); +export const TaskDefinitionEdge = objectType({ + name: 'TaskDefinitionEdge', + definition: (t) => { + t.nonNull.field('node', { + type: TaskDefinition, + }); + t.nonNull.string('cursor'); + }, +}); + +export const TaskDefinitionConnection = objectType({ + name: 'TaskDefinitionConnection', + definition: (t) => { + t.nonNull.list.nonNull.field('edges', { + type: TaskDefinitionEdge, + }); + t.nonNull.field('pageInfo', { + type: PageInfo, + }); + t.nonNull.int('totalCount'); + }, +}); + +export const FilterTaskDefinitionsInput = inputObjectType({ + name: 'FilterTaskDefinitionsInput', + definition: (t) => { + t.string('keyword'); + }, +}); + + + export const TaskDefinitionsQuery = extendType({ type: 'Query', definition: (t) => { t.nonNull.field('taskDefinitions', { - type: list(nonNull(TaskDefinition)), - resolve: async (_, _args, { conductorAPI }) => { + type: TaskDefinitionConnection, + args: { + ...PaginationConnectionArgs, + filter: arg({ type: FilterTaskDefinitionsInput }), + }, + resolve: async (_, args, { conductorAPI }) => { + const { filter, ...paginationArgs } = args; const taskDefinitions = await conductorAPI.getTaskDefinitions(config.conductorApiURL); + const filteredTaskDefs = filter?.keyword + ? getFilteredTaskDefinitions(taskDefinitions, filter.keyword) + : taskDefinitions; - return taskDefinitions; + const tasksWithId = filteredTaskDefs.map((task) => ({ + ...task, + id: task.name, + })); + return { + ...connectionFromArray(tasksWithId, paginationArgs), + totalCount: filteredTaskDefs.length, + }; }, }); }, }); + + +export const DeleteTaskDefinitionMutation = mutationField('deleteTask', { + type: IsOkResponse, + args: { + name: nonNull(stringArg()), + }, + resolve: async (_, { name }, { conductorAPI }) => { + try { + await conductorAPI.deleteTaskDefinition(config.conductorApiURL, name); + return { + isOk: true, + }; + } catch (error) { + return { + isOk: false, + }; + } + }, +}); + +const CreateTaskDefinitionInput = inputObjectType({ + name: 'CreateTaskDefinitionInput', + definition: (t) => { + t.string('ownerApp'); + t.string('createdBy'); + t.string('updatedBy'); + t.string('accessPolicy'); + t.nonNull.string('name'); + t.string('description'); + t.int('retryCount'); + t.nonNull.int('timeoutSeconds'); + t.list.nonNull.string('inputKeys'); + t.list.nonNull.string('outputKeys'); + t.field('timeoutPolicy', { type: TaskTimeoutPolicy }); + t.field('retryLogic', { type: RetryLogic }); + t.int('retryDelaySeconds'); + t.int('responseTimeoutSeconds'); + t.int('concurrentExecLimit'); + t.string('inputTemplate'); + t.int('rateLimitPerFrequency'); + t.int('rateLimitFrequencyInSeconds'); + t.string('isolationGroupId'); + t.string('executionNameSpace'); + t.string('ownerEmail'); + t.int('pollTimeoutSeconds'); + t.int('backoffScaleFactor'); + }, +}); + +export const CreateTaskDefinitionMutation = mutationField('createTaskDefinition', { + type: TaskDefinition, + args: { + input: nonNull(arg({ type: CreateTaskDefinitionInput })), + }, + resolve: async (_, { input }, { conductorAPI }) => { + if (input.responseTimeoutSeconds == null || input.responseTimeoutSeconds > input.timeoutSeconds) { + throw new Error( + 'Response timeout cannot be greater than task timeout. Default value for responseTimeoutSeconds is 3600', + ); + } + + const taskDefinitionInput = getTaskDefinitionInput(input); + + await conductorAPI.createTaskDefinition(config.conductorApiURL, taskDefinitionInput); + + return { + ...taskDefinitionInput, + id: toGraphId('TaskDefinition', input.name), + }; + }, +}); From 35b85e5b3dbba4181ec331f16d0c131ac8d5a2ec Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Fri, 14 Jul 2023 15:07:49 +0200 Subject: [PATCH 32/69] Add event listener graphql support (#318) * add API typings and CRUD operation * add event handler queries * add event handler mutations for CRUD operations * format and lint files * add typings for converter functions * fix typings of converter functions * refactor update mutation of event handler because of terrible netflix conductor logic * refactor inputs needed to update event handler * add query to get event handlers by event and event handler detail query * fix JSON validation and decoding * add ID to event handlers action * generate graphql schema typings --- src/__generated__/resource-manager.graphql.ts | 112 +++--- src/__generated__/scheduler.graphql.ts | 104 ++---- src/external-api/conductor-network-types.ts | 47 +++ src/external-api/conductor.ts | 49 +++ src/helpers/event-handler.helpers.ts | 173 +++++++++ src/helpers/id-helper.ts | 3 + src/schema/api.graphql | 144 ++++++++ src/schema/event-handler.ts | 339 ++++++++++++++++++ src/schema/global-types.ts | 1 + src/schema/index.ts | 2 + src/schema/nexus-typegen.ts | 254 +++++++++++++ 11 files changed, 1089 insertions(+), 139 deletions(-) create mode 100644 src/helpers/event-handler.helpers.ts create mode 100644 src/schema/event-handler.ts diff --git a/src/__generated__/resource-manager.graphql.ts b/src/__generated__/resource-manager.graphql.ts index 021d65fd..1f793f5c 100644 --- a/src/__generated__/resource-manager.graphql.ts +++ b/src/__generated__/resource-manager.graphql.ts @@ -25,7 +25,9 @@ export type AllocationStrategy = Node & { }; /** Supported languages for allocation strategy scripts */ -export type AllocationStrategyLang = 'js' | 'py'; +export type AllocationStrategyLang = + | 'js' + | 'py'; /** Input parameters for creating an allocation pool */ export type CreateAllocatingPoolInput = { @@ -239,12 +241,14 @@ export type Mutation = { UpdateTag: UpdateTagPayload; }; + export type MutationClaimResourceArgs = { description?: InputMaybe; poolId: Scalars['ID']; userInput: Scalars['Map']; }; + export type MutationClaimResourceWithAltIdArgs = { alternativeId: Scalars['Map']; description?: InputMaybe; @@ -252,67 +256,83 @@ export type MutationClaimResourceWithAltIdArgs = { userInput: Scalars['Map']; }; + export type MutationCreateAllocatingPoolArgs = { input?: InputMaybe; }; + export type MutationCreateAllocationStrategyArgs = { input?: InputMaybe; }; + export type MutationCreateNestedAllocatingPoolArgs = { input: CreateNestedAllocatingPoolInput; }; + export type MutationCreateNestedSetPoolArgs = { input: CreateNestedSetPoolInput; }; + export type MutationCreateNestedSingletonPoolArgs = { input: CreateNestedSingletonPoolInput; }; + export type MutationCreateResourceTypeArgs = { input: CreateResourceTypeInput; }; + export type MutationCreateSetPoolArgs = { input: CreateSetPoolInput; }; + export type MutationCreateSingletonPoolArgs = { input?: InputMaybe; }; + export type MutationCreateTagArgs = { input: CreateTagInput; }; + export type MutationDeleteAllocationStrategyArgs = { input?: InputMaybe; }; + export type MutationDeleteResourcePoolArgs = { input: DeleteResourcePoolInput; }; + export type MutationDeleteResourceTypeArgs = { input: DeleteResourceTypeInput; }; + export type MutationDeleteTagArgs = { input: DeleteTagInput; }; + export type MutationFreeResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; + export type MutationTagPoolArgs = { input: TagPoolInput; }; + export type MutationTestAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; currentResources: Array; @@ -320,20 +340,24 @@ export type MutationTestAllocationStrategyArgs = { userInput: Scalars['Map']; }; + export type MutationUntagPoolArgs = { input: UntagPoolInput; }; + export type MutationUpdateResourceAltIdArgs = { alternativeId: Scalars['Map']; input: Scalars['Map']; poolId: Scalars['ID']; }; + export type MutationUpdateResourceTypeNameArgs = { input: UpdateResourceTypeNameInput; }; + export type MutationUpdateTagArgs = { input: UpdateTagInput; }; @@ -367,7 +391,10 @@ export type PoolCapacityPayload = { }; /** Defines the type of pool */ -export type PoolType = 'allocating' | 'set' | 'singleton'; +export type PoolType = + | 'allocating' + | 'set' + | 'singleton'; /** Defines the type of the property */ export type PropertyType = Node & { @@ -404,14 +431,17 @@ export type Query = { node: Maybe; }; + export type QueryQueryAllocationStrategiesArgs = { byName?: InputMaybe; }; + export type QueryQueryAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; }; + export type QueryQueryEmptyResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -420,6 +450,7 @@ export type QueryQueryEmptyResourcePoolsArgs = { resourceTypeId?: InputMaybe; }; + export type QueryQueryLeafResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -430,10 +461,12 @@ export type QueryQueryLeafResourcePoolsArgs = { tags?: InputMaybe; }; + export type QueryQueryPoolCapacityArgs = { poolId: Scalars['ID']; }; + export type QueryQueryRecentlyActiveResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -443,23 +476,28 @@ export type QueryQueryRecentlyActiveResourcesArgs = { toDatetime?: InputMaybe; }; + export type QueryQueryRequiredPoolPropertiesArgs = { allocationStrategyName: Scalars['String']; }; + export type QueryQueryResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; + export type QueryQueryResourcePoolArgs = { poolId: Scalars['ID']; }; + export type QueryQueryResourcePoolHierarchyPathArgs = { poolId: Scalars['ID']; }; + export type QueryQueryResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -470,10 +508,12 @@ export type QueryQueryResourcePoolsArgs = { tags?: InputMaybe; }; + export type QueryQueryResourceTypesArgs = { byName?: InputMaybe; }; + export type QueryQueryResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -482,6 +522,7 @@ export type QueryQueryResourcesArgs = { poolId: Scalars['ID']; }; + export type QueryQueryResourcesByAltIdArgs = { after?: InputMaybe; before?: InputMaybe; @@ -491,6 +532,7 @@ export type QueryQueryResourcesByAltIdArgs = { poolId?: InputMaybe; }; + export type QueryQueryRootResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -501,6 +543,7 @@ export type QueryQueryRootResourcePoolsArgs = { tags?: InputMaybe; }; + export type QuerySearchPoolsByTagsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -509,6 +552,7 @@ export type QuerySearchPoolsByTagsArgs = { tags?: InputMaybe; }; + export type QueryNodeArgs = { id: Scalars['ID']; }; @@ -562,6 +606,7 @@ export type ResourcePool = Node & { id: Scalars['ID']; }; + /** A pool is an entity that contains allocated and free resources */ export type ResourcePoolAllocatedResourcesArgs = { after?: InputMaybe; @@ -665,39 +710,14 @@ export type UpdateTagPayload = { tag: Maybe; }; -export type PoolFragmentFragment = { - __typename: 'ResourcePool'; - id: string; - Name: string; - PoolType: PoolType; - PoolProperties: any; - Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; - ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; -}; +export type PoolFragmentFragment = { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }; export type GetPoolQueryVariables = Exact<{ nodeId: Scalars['ID']; }>; -export type GetPoolQuery = { - __typename?: 'Query'; - node: - | { __typename?: 'AllocationStrategy' } - | { __typename?: 'PropertyType' } - | { __typename?: 'Resource' } - | { - __typename: 'ResourcePool'; - id: string; - Name: string; - PoolType: PoolType; - PoolProperties: any; - Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; - ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; - } - | { __typename?: 'ResourceType' } - | { __typename?: 'Tag' } - | null; -}; + +export type GetPoolQuery = { __typename?: 'Query', node: { __typename?: 'AllocationStrategy' } | { __typename?: 'PropertyType' } | { __typename?: 'Resource' } | { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } } | { __typename?: 'ResourceType' } | { __typename?: 'Tag' } | null }; export type GetPoolsQueryVariables = Exact<{ resourceTypeId?: InputMaybe; @@ -708,37 +728,13 @@ export type GetPoolsQueryVariables = Exact<{ filterByResources?: InputMaybe; }>; -export type GetPoolsQuery = { - __typename?: 'Query'; - QueryRootResourcePools: { - __typename?: 'ResourcePoolConnection'; - totalCount: number; - edges: Array<{ - __typename?: 'ResourcePoolEdge'; - node: { - __typename: 'ResourcePool'; - id: string; - Name: string; - PoolType: PoolType; - PoolProperties: any; - Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; - ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; - }; - cursor: { __typename?: 'OutputCursor'; ID: string }; - } | null>; - pageInfo: { - __typename?: 'PageInfo'; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: { __typename?: 'OutputCursor'; ID: string } | null; - endCursor: { __typename?: 'OutputCursor'; ID: string } | null; - }; - }; -}; + +export type GetPoolsQuery = { __typename?: 'Query', QueryRootResourcePools: { __typename?: 'ResourcePoolConnection', totalCount: number, edges: Array<{ __typename?: 'ResourcePoolEdge', node: { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }, cursor: { __typename?: 'OutputCursor', ID: string } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: { __typename?: 'OutputCursor', ID: string } | null, endCursor: { __typename?: 'OutputCursor', ID: string } | null } } }; export type FreeResourceMutationVariables = Exact<{ poolId: Scalars['ID']; input: Scalars['Map']; }>; -export type FreeResourceMutation = { __typename?: 'Mutation'; FreeResource: string }; + +export type FreeResourceMutation = { __typename?: 'Mutation', FreeResource: string }; diff --git a/src/__generated__/scheduler.graphql.ts b/src/__generated__/scheduler.graphql.ts index db014ee9..af39c7c6 100644 --- a/src/__generated__/scheduler.graphql.ts +++ b/src/__generated__/scheduler.graphql.ts @@ -33,14 +33,17 @@ export type Mutation = { updateSchedule: Schedule; }; + export type MutationCreateScheduleArgs = { input: CreateScheduleInput; }; + export type MutationDeleteScheduleArgs = { name: Scalars['String']; }; + export type MutationUpdateScheduleArgs = { input: UpdateScheduleInput; name: Scalars['String']; @@ -60,10 +63,12 @@ export type Query = { schedules: Maybe; }; + export type QueryScheduleArgs = { name: Scalars['String']; }; + export type QuerySchedulesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -104,7 +109,14 @@ export type SchedulesFilterInput = { workflowVersion: Scalars['String']; }; -export type Status = 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; +export type Status = + | 'COMPLETED' + | 'FAILED' + | 'PAUSED' + | 'RUNNING' + | 'TERMINATED' + | 'TIMED_OUT' + | 'UNKNOWN'; export type UpdateScheduleInput = { cronString?: InputMaybe; @@ -121,71 +133,30 @@ export type DeleteScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; }>; -export type DeleteScheduleMutation = { __typename?: 'Mutation'; deleteSchedule: boolean }; + +export type DeleteScheduleMutation = { __typename?: 'Mutation', deleteSchedule: boolean }; export type UpdateScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; input: UpdateScheduleInput; }>; -export type UpdateScheduleMutation = { - __typename?: 'Mutation'; - updateSchedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; -}; + +export type UpdateScheduleMutation = { __typename?: 'Mutation', updateSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; export type CreateScheduleMutationVariables = Exact<{ input: CreateScheduleInput; }>; -export type CreateScheduleMutation = { - __typename?: 'Mutation'; - createSchedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; -}; + +export type CreateScheduleMutation = { __typename?: 'Mutation', createSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; export type GetScheduleQueryVariables = Exact<{ scheduleName: Scalars['String']; }>; -export type GetScheduleQuery = { - __typename?: 'Query'; - schedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - } | null; -}; + +export type GetScheduleQuery = { __typename?: 'Query', schedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } | null }; export type GetSchedulesQueryVariables = Exact<{ first?: InputMaybe; @@ -195,34 +166,5 @@ export type GetSchedulesQueryVariables = Exact<{ filter?: InputMaybe; }>; -export type GetSchedulesQuery = { - __typename?: 'Query'; - schedules: { - __typename?: 'ScheduleConnection'; - totalCount: number; - edges: Array<{ - __typename?: 'ScheduleEdge'; - cursor: string; - node: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; - } | null>; - pageInfo: { - __typename?: 'PageInfo'; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; - endCursor: string | null; - }; - } | null; -}; + +export type GetSchedulesQuery = { __typename?: 'Query', schedules: { __typename?: 'ScheduleConnection', totalCount: number, edges: Array<{ __typename?: 'ScheduleEdge', cursor: string, node: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null } } | null }; diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index 55d43a4a..41540c43 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -248,6 +248,47 @@ const TaskDefinition = t.type({ }); const TaskDefinitionsValidator = t.array(TaskDefinition); +const ActionStartWorkflow = t.type({ + name: optional(t.string), + version: optional(t.number), + input: optional(t.UnknownRecord), + correlationId: optional(t.string), + taskToDomain: optional(t.record(t.string, t.string)), +}); + +const ActionCompleteTask = t.type({ + workflowId: optional(t.string), + taskId: optional(t.string), + output: optional(t.UnknownRecord), + taskRefName: optional(t.string), +}); + +const ActionFailTask = t.type({ + workflowId: optional(t.string), + taskId: optional(t.string), + output: optional(t.UnknownRecord), + taskRefName: optional(t.string), +}); + +const EventHandlerAction = t.type({ + action: optional(t.union([t.literal('start_workflow'), t.literal('complete_task'), t.literal('fail_task')])), + start_workflow: optional(ActionStartWorkflow), + complete_task: optional(ActionCompleteTask), + fail_task: optional(ActionFailTask), + expandInlineJSON: optional(t.boolean), +}); +export type ApiEventHandlerAction = t.TypeOf; + +const EventHandler = t.type({ + name: t.string, + event: t.string, + condition: optional(t.string), + actions: t.array(EventHandlerAction), + active: optional(t.boolean), + evaluatorType: optional(t.string), +}); +const EventHandlersValidator = t.array(EventHandler); + export type ExecutedWorkflowsOutput = t.TypeOf; export type WorfklowMetadataOutput = t.TypeOf; export type WorkflowMetadataOutput = t.TypeOf; @@ -255,6 +296,8 @@ export type ApiWorkflow = t.TypeOf; export type ApiExecutedWorkflow = t.TypeOf; export type ApiExecutedWorkflowTask = t.TypeOf; export type ApiTaskDefinition = t.TypeOf; +export type ApiEventHandlersOutput = t.TypeOf; +export type ApiEventHandler = t.TypeOf; export function decodeWorkflowMetadataOutput(value: unknown): WorkflowMetadataOutput { return extractResult(WorkflowMetadataValidator.decode(value)); @@ -309,3 +352,7 @@ export function decodeBulkRestartOutput(value: unknown): BulkOperationOutput { export function decodeExecutedWorkflowTaskDetailOutput(value: unknown): ApiExecutedWorkflowTask { return extractResult(ExecutedWorkflowTask.decode(value)); } + +export function decodeEventHandlersOutput(value: unknown): ApiEventHandlersOutput { + return extractResult(EventHandlersValidator.decode(value)); +} diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts index 6774686b..922a7be1 100644 --- a/src/external-api/conductor.ts +++ b/src/external-api/conductor.ts @@ -17,6 +17,9 @@ import { decodeBulkTerminateOutput, decodeExecutedWorkflowTaskDetailOutput, ApiExecutedWorkflowTask, + ApiEventHandlersOutput, + decodeEventHandlersOutput, + ApiEventHandler, decodeTaskDefinitionOutput, TaskDefinitionDetailInput, } from './conductor-network-types'; @@ -226,6 +229,46 @@ async function getExecutedWorkflowTaskDetail(baseURL: string, taskId: string): P return data; } +async function getEventHandlers(baseURL: string): Promise { + const json = await sendGetRequest([baseURL, '/event']); + const data = decodeEventHandlersOutput(json); + return data; +} + +async function updateEventHandler(baseURL: string, eventHandler: ApiEventHandler): Promise { + await sendPutRequest([baseURL, `/event`], eventHandler); +} + +async function deleteEventHandler(baseURL: string, eventHandlerName: string): Promise { + await sendDeleteRequest([baseURL, `/event/${eventHandlerName}`]); +} + +async function createEventHandler(baseURL: string, eventHandler: ApiEventHandler): Promise { + await sendPostRequest([baseURL, '/event'], eventHandler); +} + +async function getEventHandler(baseURL: string, event: string, eventName: string): Promise { + const json = await sendGetRequest([baseURL, `/event/${event}?activeOnly=false`]); + const data = decodeEventHandlersOutput(json); + const eventHandler = data.find((eh) => eh.name === eventName); + + if (eventHandler == null) { + throw new Error(`Event handler ${eventName} not found`); + } + + return eventHandler; +} + +async function getEventHandlersByEvent( + baseURL: string, + event: string, + activeOnly: boolean, +): Promise { + const json = await sendGetRequest([baseURL, `/event/${event}?activeOnly=${activeOnly}`]); + const data = decodeEventHandlersOutput(json); + return data; +} + const conductorAPI = { getWorkflowMetadata, getWorkflowDetail, @@ -252,6 +295,12 @@ const conductorAPI = { deleteTaskDefinition, createTaskDefinition, getExecutedWorkflowTaskDetail, + getEventHandlers, + updateEventHandler, + deleteEventHandler, + createEventHandler, + getEventHandler, + getEventHandlersByEvent, }; export type ConductorAPI = typeof conductorAPI; diff --git a/src/helpers/event-handler.helpers.ts b/src/helpers/event-handler.helpers.ts new file mode 100644 index 00000000..cae13a00 --- /dev/null +++ b/src/helpers/event-handler.helpers.ts @@ -0,0 +1,173 @@ +import { ApiEventHandler, ApiEventHandlerAction } from '../external-api/conductor-network-types'; + +type StartWorkflowGraphQL = { + name?: string | null; + version?: number | null; + input?: string | null; + correlationId?: string | null; + taskToDomain?: string | null; +}; + +type CompleteTaskGraphQL = { + workflowId?: string | null; + taskId?: string | null; + output?: string | null; + taskRefName?: string | null; +}; + +type FailTaskGraphQL = { + workflowId?: string | null; + taskId?: string | null; + output?: string | null; + taskRefName?: string | null; +}; + +type EventHandlerActionGraphQL = { + action?: 'start_workflow' | 'complete_task' | 'fail_task' | null; + startWorkflow?: StartWorkflowGraphQL | null; + completeTask?: CompleteTaskGraphQL | null; + failTask?: FailTaskGraphQL | null; + expandInlineJSON?: boolean | null; +}; + +type EventHandlerGraphQL = { + name: string; + event: string; + isActive?: boolean | null; + condition?: string | null; + actions: EventHandlerActionGraphQL[]; + evaluatorType?: string | null; +}; + +function makeFromApiToGraphQLActionStartWorkflow(actionStartWorkflow: ApiEventHandlerAction['start_workflow']) { + if (actionStartWorkflow == null) { + return undefined; + } + + return { + name: actionStartWorkflow.name || undefined, + version: actionStartWorkflow.version || undefined, + input: actionStartWorkflow != null ? JSON.stringify(actionStartWorkflow.input) : undefined, + correlationId: actionStartWorkflow.correlationId || undefined, + taskToDomain: actionStartWorkflow != null ? JSON.stringify(actionStartWorkflow.taskToDomain) : undefined, + }; +} + +function makeFromApiToGraphQLActionCompleteTask(actionCompleteTask: ApiEventHandlerAction['complete_task']) { + if (actionCompleteTask == null) { + return undefined; + } + + return { + workflowId: actionCompleteTask.workflowId || undefined, + taskId: actionCompleteTask.taskId || undefined, + output: actionCompleteTask != null ? JSON.stringify(actionCompleteTask.output) : undefined, + taskRefName: actionCompleteTask.taskRefName || undefined, + }; +} + +function makeFromApiToGraphQLActionFailTask(actionFailTask: ApiEventHandlerAction['fail_task']) { + if (actionFailTask == null) { + return undefined; + } + + return { + workflowId: actionFailTask.workflowId || undefined, + taskId: actionFailTask.taskId || undefined, + output: actionFailTask != null ? JSON.stringify(actionFailTask.output) : undefined, + taskRefName: actionFailTask.taskRefName || undefined, + }; +} + +export function makeFromApiToGraphQLEventHandlerAction(eventHandlerAction: ApiEventHandlerAction) { + return { + action: eventHandlerAction.action || undefined, + startWorkflow: makeFromApiToGraphQLActionStartWorkflow(eventHandlerAction.start_workflow) || undefined, + completeTask: makeFromApiToGraphQLActionCompleteTask(eventHandlerAction.complete_task) || undefined, + failTask: makeFromApiToGraphQLActionFailTask(eventHandlerAction.fail_task) || undefined, + expandInlineJSON: eventHandlerAction.expandInlineJSON || undefined, + }; +} + +export function makeFromApiToGraphQLEventHandler(eventHandler: ApiEventHandler) { + return { + name: eventHandler.name, + event: eventHandler.event, + isActive: eventHandler.active || false, + condition: eventHandler.condition || undefined, + actions: eventHandler.actions.map(makeFromApiToGraphQLEventHandlerAction), + evaluatorType: eventHandler.evaluatorType || undefined, + }; +} + +// add function that will convert from GraphQL to API + +function makeFromGraphQLToApiActionStartWorkflow( + actionStartWorkflow?: StartWorkflowGraphQL | null, +): ApiEventHandlerAction['start_workflow'] { + if (actionStartWorkflow == null) { + return undefined; + } + + return { + name: actionStartWorkflow.name || undefined, + version: actionStartWorkflow.version || undefined, + input: actionStartWorkflow.input != null ? JSON.parse(actionStartWorkflow.input) : undefined, + correlationId: actionStartWorkflow.correlationId || undefined, + taskToDomain: actionStartWorkflow.taskToDomain != null ? JSON.parse(actionStartWorkflow.taskToDomain) : undefined, + }; +} + +function makeFromGraphQLToApiActionCompleteTask( + actionCompleteTask?: CompleteTaskGraphQL | null, +): ApiEventHandlerAction['complete_task'] { + if (actionCompleteTask == null) { + return undefined; + } + + return { + workflowId: actionCompleteTask.workflowId || undefined, + taskId: actionCompleteTask.taskId || undefined, + output: actionCompleteTask.output != null ? JSON.parse(actionCompleteTask.output) : undefined, + taskRefName: actionCompleteTask.taskRefName || undefined, + }; +} + +function makeFromGraphQLToApiActionFailTask( + actionFailTask?: FailTaskGraphQL | null, +): ApiEventHandlerAction['fail_task'] { + if (actionFailTask == null) { + return undefined; + } + + return { + workflowId: actionFailTask.workflowId || undefined, + taskId: actionFailTask.taskId || undefined, + output: actionFailTask.output != null ? JSON.parse(actionFailTask.output) : undefined, + taskRefName: actionFailTask.taskRefName || undefined, + }; +} + +function makeFromGraphQLToApiEventHandlerAction(eventHandlerAction: EventHandlerActionGraphQL): ApiEventHandlerAction { + return { + action: eventHandlerAction.action || undefined, + // eslint-disable-next-line @typescript-eslint/naming-convention + start_workflow: makeFromGraphQLToApiActionStartWorkflow(eventHandlerAction.startWorkflow) || undefined, + // eslint-disable-next-line @typescript-eslint/naming-convention + complete_task: makeFromGraphQLToApiActionCompleteTask(eventHandlerAction.completeTask) || undefined, + // eslint-disable-next-line @typescript-eslint/naming-convention + fail_task: makeFromGraphQLToApiActionFailTask(eventHandlerAction.failTask) || undefined, + expandInlineJSON: eventHandlerAction.expandInlineJSON || undefined, + }; +} + +export function makeFromGraphQLToApiEventHandler(eventHandler: EventHandlerGraphQL): ApiEventHandler { + return { + name: eventHandler.name, + event: eventHandler.event, + active: eventHandler.isActive || undefined, + condition: eventHandler.condition || undefined, + actions: eventHandler.actions.map(makeFromGraphQLToApiEventHandlerAction), + evaluatorType: eventHandler.evaluatorType || undefined, + }; +} diff --git a/src/helpers/id-helper.ts b/src/helpers/id-helper.ts index bd67b4f7..bcf31d06 100644 --- a/src/helpers/id-helper.ts +++ b/src/helpers/id-helper.ts @@ -13,6 +13,9 @@ export type DataType = | 'GraphNode' | 'GraphEdge' | 'Schedule' + | 'Pool' + | 'EventHandler' + | 'EventHandlerAction' | 'TaskDefinition' | 'Pool'; diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 664d2f68..7ecab4b5 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -1,6 +1,50 @@ ### This file was generated by Nexus Schema ### Do not make changes to this file directly +type ActionCompleteTask { + output: String + taskId: String + taskRefName: String + workflowId: String +} + +input ActionCompleteTaskInput { + output: String + taskId: String + taskRefName: String + workflowId: String +} + +type ActionFailTask { + output: String + taskId: String + taskRefName: String + workflowId: String +} + +input ActionFailTaskInput { + output: String + taskId: String + taskRefName: String + workflowId: String +} + +type ActionStartWorkflow { + correlationId: String + input: String + name: String + taskToDomain: String + version: Int +} + +input ActionStartWorkflowInput { + correlationId: String + input: String + name: String + taskToDomain: String + version: Int +} + input AddBlueprintInput { name: String! template: String! @@ -167,6 +211,23 @@ type CountryEdge { node: Country! } +input CreateEventHandlerInput { + actions: [EventHandlerActionInput!]! + condition: String + evaluatorType: String + + """ + The event is immutable and cannot be changed. + """ + event: String! + isActive: Boolean + + """ + The name is immutable and cannot be changed. Also it must be unique. + """ + name: String! +} + input CreateLabelInput { name: String! } @@ -338,6 +399,57 @@ input EditWorkflowScheduleInput { workflowVersion: String } +type EventHandler { + actions: [EventHandlerAction!]! + condition: String + evaluatorType: String + + """ + The event is immutable and cannot be changed. + """ + event: String! + id: ID! + isActive: Boolean + + """ + The name is immutable and cannot be changed. Also it must be unique. + """ + name: String! +} + +type EventHandlerAction { + action: EventHandlerActionEnum + completeTask: ActionCompleteTask + expandInlineJSON: Boolean + failTask: ActionFailTask + id: ID! + startWorkflow: ActionStartWorkflow +} + +enum EventHandlerActionEnum { + complete_task + fail_task + start_workflow +} + +input EventHandlerActionInput { + action: EventHandlerActionEnum + completeTask: ActionCompleteTaskInput + expandInlineJSON: Boolean + failTask: ActionFailTaskInput + startWorkflow: ActionStartWorkflowInput +} + +type EventHandlerConnection { + edges: [EventHandlerEdge!] + pageInfo: PageInfo! +} + +type EventHandlerEdge { + cursor: String! + node: EventHandler! +} + input ExecuteNewWorkflowInput { correlationId: String externalInputPayloadStoragePath: String @@ -468,6 +580,12 @@ input FilterDevicesInput { labels: [String!] } +input FilterEventHandlerInput { + evaluatorType: String + event: String + isActive: Boolean +} + input FilterPoolsInput { poolName: String } @@ -603,12 +721,14 @@ type Mutation { bulkTerminateWorkflow(input: BulkOperationInput!): BulkOperationResponse closeTransaction(deviceId: String!, transactionId: String!): CloseTransactionPayload! commitConfig(input: CommitConfigInput!, transactionId: String!): CommitConfigPayload! + createEventHandler(input: CreateEventHandlerInput!): EventHandler createLabel(input: CreateLabelInput!): CreateLabelPayload! createTaskDefinition(input: CreateTaskDefinitionInput!): TaskDefinition createTransaction(deviceId: String!): CreateTransactionPayload! createWorkflow(input: CreateWorkflowInput!): CreateWorkflowPayload! deleteBlueprint(id: String!): DeleteBlueprintPayload! deleteDevice(id: String!): DeleteDevicePayload! + deleteEventHandler(id: String!): IsOkResponse deleteLabel(id: String!): DeleteLabelPayload! deleteSchedule(id: String!): IsOkResponse deleteSnapshot(input: DeleteSnapshotInput!): DeleteSnapshotPayload @@ -634,6 +754,7 @@ type Mutation { updateBlueprint(id: String!, input: UpdateBlueprintInput!): UpdateBlueprintPayload! updateDataStore(deviceId: String!, input: UpdateDataStoreInput!, transactionId: String!): UpdateDataStorePayload! updateDevice(id: String!, input: UpdateDeviceInput!): UpdateDevicePayload! + updateEventHandler(event: String!, input: UpdateEventHandlerInput!, name: String!): EventHandler updateGraphNodeCoordinates(input: [GraphNodeCoordinatesInput!]!): UpdateGraphNodeCoordinatesPayload! updateWorkflow(id: String!, input: UpdateWorkflowInput!): UpdateWorkflowPayload! } @@ -728,6 +849,22 @@ type Query { last: Int orderBy: DeviceOrderByInput ): DeviceConnection! + eventHandler(event: String!, name: String!): EventHandler + eventHandlers( + after: String + before: String + filter: FilterEventHandlerInput + first: Int + last: Int + ): EventHandlerConnection + eventHandlersByEvent( + activeOnly: Boolean + after: String + before: String + event: String! + first: Int + last: Int + ): EventHandlerConnection executedWorkflows(pagination: PaginationArgs, searchQuery: ExecutedWorkflowSearchInput): ExecutedWorkflowConnection labels(after: String, before: String, first: Int, last: Int): LabelConnection! locations(after: String, before: String, first: Int, last: Int): LocationConnection! @@ -1036,6 +1173,13 @@ type UpdateDevicePayload { device: Device } +input UpdateEventHandlerInput { + actions: [EventHandlerActionInput!] + condition: String + evaluatorType: String + isActive: Boolean +} + type UpdateGraphNodeCoordinatesPayload { deviceNames: [String!]! } diff --git a/src/schema/event-handler.ts b/src/schema/event-handler.ts new file mode 100644 index 00000000..1904616a --- /dev/null +++ b/src/schema/event-handler.ts @@ -0,0 +1,339 @@ +import { + arg, + booleanArg, + enumType, + inputObjectType, + mutationField, + nonNull, + objectType, + queryField, + stringArg, +} from 'nexus'; +import { connectionFromArray } from 'graphql-relay'; +import { v4 as uuid } from 'uuid'; +import { IsOkResponse, PaginationConnectionArgs } from './global-types'; +import config from '../config'; +import { makeFromApiToGraphQLEventHandler, makeFromGraphQLToApiEventHandler } from '../helpers/event-handler.helpers'; +import { fromGraphId, toGraphId } from '../helpers/id-helper'; + +export const EventHandlerActionEnum = enumType({ + name: 'EventHandlerActionEnum', + members: ['start_workflow', 'complete_task', 'fail_task'], +}); + +export const ActionStartWorkflow = objectType({ + name: 'ActionStartWorkflow', + definition(t) { + t.string('name'); + t.int('version'); + t.string('input'); + t.string('correlationId'); + t.string('taskToDomain'); + }, +}); + +export const ActionCompleteTask = objectType({ + name: 'ActionCompleteTask', + definition(t) { + t.string('workflowId'); + t.string('taskId'); + t.string('output'); + t.string('taskRefName'); + }, +}); + +export const ActionFailTask = objectType({ + name: 'ActionFailTask', + definition(t) { + t.string('workflowId'); + t.string('taskId'); + t.string('output'); + t.string('taskRefName'); + }, +}); + +export const EventHandlerAction = objectType({ + name: 'EventHandlerAction', + definition(t) { + t.nonNull.id('id'); + t.field('action', { type: EventHandlerActionEnum }); + t.field('startWorkflow', { type: ActionStartWorkflow }); + t.field('completeTask', { type: ActionCompleteTask }); + t.field('failTask', { type: ActionFailTask }); + t.boolean('expandInlineJSON'); + }, +}); + +export const EventHandler = objectType({ + name: 'EventHandler', + definition(t) { + t.nonNull.id('id'); + t.nonNull.string('name', { description: 'The name is immutable and cannot be changed. Also it must be unique.' }); + t.nonNull.string('event', { description: 'The event is immutable and cannot be changed.' }); + t.string('condition'); + t.nonNull.list.nonNull.field('actions', { type: EventHandlerAction }); + t.boolean('isActive'); + t.string('evaluatorType'); + }, +}); + +export const EventHandlerEdge = objectType({ + name: 'EventHandlerEdge', + definition(t) { + t.nonNull.field('node', { type: EventHandler }); + t.nonNull.string('cursor'); + }, +}); + +export const EventHandlerConnection = objectType({ + name: 'EventHandlerConnection', + definition(t) { + t.list.nonNull.field('edges', { type: EventHandlerEdge }); + t.nonNull.field('pageInfo', { type: 'PageInfo' }); + }, +}); + +export const FilterEventHandlerInput = inputObjectType({ + name: 'FilterEventHandlerInput', + definition(t) { + t.boolean('isActive'); + t.string('event'); + t.string('evaluatorType'); + }, +}); + +export const EventHandlerQuery = queryField('eventHandlers', { + type: EventHandlerConnection, + args: { + filter: arg({ type: FilterEventHandlerInput }), + ...PaginationConnectionArgs, + }, + resolve: async (_, args, { conductorAPI }) => { + const { filter, ...paginationArgs } = args; + const eventHandlers = await conductorAPI.getEventHandlers(config.conductorApiURL); + + const filteredEventHandlers = eventHandlers.filter((eventHandler) => { + if (filter?.isActive != null && eventHandler.active !== filter.isActive) { + return false; + } + + if (filter?.event != null && eventHandler.event !== filter.event) { + return false; + } + + if (filter?.evaluatorType != null && eventHandler.evaluatorType !== filter.evaluatorType) { + return false; + } + + return true; + }); + + const mappedEventHandlersWithId = filteredEventHandlers.map((eventHandler) => ({ + id: toGraphId('EventHandler', eventHandler.name), + ...makeFromApiToGraphQLEventHandler(eventHandler), + })); + + const mappedEventHandlers = mappedEventHandlersWithId.map((eventHandler) => ({ + ...eventHandler, + actions: eventHandler.actions.map((action) => ({ + ...action, + id: toGraphId('EventHandlerAction', uuid()), + })), + })); + return connectionFromArray(mappedEventHandlers, paginationArgs); + }, +}); + +export const ActionStartWorkflowInput = inputObjectType({ + name: 'ActionStartWorkflowInput', + definition(t) { + t.string('name'); + t.int('version'); + t.string('input'); + t.string('correlationId'); + t.string('taskToDomain'); + }, +}); + +export const ActionCompleteTaskInput = inputObjectType({ + name: 'ActionCompleteTaskInput', + definition(t) { + t.string('workflowId'); + t.string('taskId'); + t.string('output'); + t.string('taskRefName'); + }, +}); + +export const ActionFailTaskInput = inputObjectType({ + name: 'ActionFailTaskInput', + definition(t) { + t.string('workflowId'); + t.string('taskId'); + t.string('output'); + t.string('taskRefName'); + }, +}); + +export const EventHandlerActionInput = inputObjectType({ + name: 'EventHandlerActionInput', + definition(t) { + t.field('action', { type: EventHandlerActionEnum }); + t.field('startWorkflow', { type: ActionStartWorkflowInput }); + t.field('completeTask', { type: ActionCompleteTaskInput }); + t.field('failTask', { type: ActionFailTaskInput }); + t.boolean('expandInlineJSON'); + }, +}); + +export const CreateEventHandlerInput = inputObjectType({ + name: 'CreateEventHandlerInput', + definition(t) { + t.nonNull.string('name', { description: 'The name is immutable and cannot be changed. Also it must be unique.' }); + t.nonNull.string('event', { description: 'The event is immutable and cannot be changed.' }); + t.string('condition'); + t.nonNull.list.nonNull.field('actions', { type: EventHandlerActionInput }); + t.boolean('isActive'); + t.string('evaluatorType'); + }, +}); + +export const UpdateEventHandlerInput = inputObjectType({ + name: 'UpdateEventHandlerInput', + definition(t) { + t.string('condition'); + t.list.nonNull.field('actions', { type: EventHandlerActionInput }); + t.boolean('isActive'); + t.string('evaluatorType'); + }, +}); + +export const CreateEventHandlerMutation = mutationField('createEventHandler', { + type: EventHandler, + args: { + input: nonNull(arg({ type: CreateEventHandlerInput })), + }, + resolve: async (_, args, { conductorAPI }) => { + const { input } = args; + await conductorAPI.createEventHandler(config.conductorApiURL, makeFromGraphQLToApiEventHandler(input)); + return { + id: toGraphId('EventHandler', input.name), + ...input, + }; + }, +}); + +export const UpdateEventHandlerMutation = mutationField('updateEventHandler', { + type: EventHandler, + args: { + event: nonNull(stringArg()), + name: nonNull(stringArg()), + input: nonNull(arg({ type: UpdateEventHandlerInput })), + }, + resolve: async (_, args, { conductorAPI }) => { + const { input, event, name } = args; + const oldEventHandler = await conductorAPI.getEventHandler(config.conductorApiURL, event, name); + + if (input.actions == null || input.actions.length === 0) { + await conductorAPI.updateEventHandler(config.conductorApiURL, { + ...oldEventHandler, + ...makeFromGraphQLToApiEventHandler({ + ...input, + actions: [], + name, + event, + }), + actions: oldEventHandler.actions, + }); + } else { + await conductorAPI.updateEventHandler(config.conductorApiURL, { + ...oldEventHandler, + ...makeFromGraphQLToApiEventHandler({ + ...input, + actions: input.actions, + name, + event, + }), + }); + } + + const mappedEventHandler = makeFromApiToGraphQLEventHandler(oldEventHandler); + + return { + id: toGraphId('EventHandler', name), + ...mappedEventHandler, + ...input, + actions: input.actions == null ? mappedEventHandler.actions : input.actions, + }; + }, +}); + +export const DeleteEventHandlerMutation = mutationField('deleteEventHandler', { + type: IsOkResponse, + args: { + id: nonNull(stringArg()), + }, + resolve: async (_, args, { conductorAPI }) => { + const { id } = args; + const name = fromGraphId('EventHandler', id); + await conductorAPI.deleteEventHandler(config.conductorApiURL, name); + + return { + isOk: true, + }; + }, +}); + +export const GetEventHandler = queryField('eventHandler', { + type: EventHandler, + args: { + event: nonNull(stringArg()), + name: nonNull(stringArg()), + }, + resolve: async (_, args, { conductorAPI }) => { + const { event, name } = args; + const eventHandler = await conductorAPI.getEventHandler(config.conductorApiURL, event, name); + + const eventHandlerWithId = { + id: toGraphId('EventHandler', name), + ...makeFromApiToGraphQLEventHandler(eventHandler), + }; + + return { + ...eventHandlerWithId, + actions: eventHandlerWithId.actions.map((action) => ({ + ...action, + id: toGraphId('EventHandlerAction', uuid()), + })), + }; + }, +}); + +export const GetEventHandlersByEvent = queryField('eventHandlersByEvent', { + type: 'EventHandlerConnection', + args: { + event: nonNull(stringArg()), + activeOnly: booleanArg(), + ...PaginationConnectionArgs, + }, + resolve: async (_, args, { conductorAPI }) => { + const { event } = args; + const eventHandlers = await conductorAPI.getEventHandlersByEvent( + config.conductorApiURL, + event, + args.activeOnly || false, + ); + + const mappedEventHandlers = eventHandlers.map((eventHandler) => ({ + id: toGraphId('EventHandler', eventHandler.name), + ...makeFromApiToGraphQLEventHandler(eventHandler), + })); + + return connectionFromArray(mappedEventHandlers, { + first: args.first, + after: args.after, + last: args.last, + before: args.before, + }); + }, +}); diff --git a/src/schema/global-types.ts b/src/schema/global-types.ts index 5794c64a..0fb16d27 100644 --- a/src/schema/global-types.ts +++ b/src/schema/global-types.ts @@ -6,6 +6,7 @@ import { fromGraphId, getType } from '../helpers/id-helper'; import schedulerAPI from '../external-api/scheduler'; import resourceManagerAPI from '../external-api/resource-manager'; import { apiPoolEdgeToGraphqlPoolEdge } from '../helpers/resource-manager.helpers'; +import { makeFromApiToGraphQLEventHandler } from '../helpers/event-handler.helpers'; export const Node = interfaceType({ name: 'Node', diff --git a/src/schema/index.ts b/src/schema/index.ts index c9090491..231da89c 100644 --- a/src/schema/index.ts +++ b/src/schema/index.ts @@ -14,6 +14,7 @@ import * as executedWorkflowTask from './task'; import * as workflowLabels from './workflow-labels'; import * as taskDefintions from './task-definitons'; import * as pool from './pool'; +import * as eventHandler from './event-handler'; export default makeSchema({ features: { @@ -46,6 +47,7 @@ export default makeSchema({ executedWorkflowTask, taskDefintions, pool, + eventHandler, ], sourceTypes: { modules: [ diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index b3e01b4c..4e776686 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -42,6 +42,28 @@ declare global { } export interface NexusGenInputs { + ActionCompleteTaskInput: { + // input type + output?: string | null; // String + taskId?: string | null; // String + taskRefName?: string | null; // String + workflowId?: string | null; // String + }; + ActionFailTaskInput: { + // input type + output?: string | null; // String + taskId?: string | null; // String + taskRefName?: string | null; // String + workflowId?: string | null; // String + }; + ActionStartWorkflowInput: { + // input type + correlationId?: string | null; // String + input?: string | null; // String + name?: string | null; // String + taskToDomain?: string | null; // String + version?: number | null; // Int + }; AddBlueprintInput: { // input type name: string; // String! @@ -98,6 +120,15 @@ export interface NexusGenInputs { deviceId: string; // String! shouldDryRun?: boolean | null; // Boolean }; + CreateEventHandlerInput: { + // input type + actions: NexusGenInputs['EventHandlerActionInput'][]; // [EventHandlerActionInput!]! + condition?: string | null; // String + evaluatorType?: string | null; // String + event: string; // String! + isActive?: boolean | null; // Boolean + name: string; // String! + }; CreateLabelInput: { // input type name: string; // String! @@ -171,6 +202,14 @@ export interface NexusGenInputs { workflowName?: string | null; // String workflowVersion?: string | null; // String }; + EventHandlerActionInput: { + // input type + action?: NexusGenEnums['EventHandlerActionEnum'] | null; // EventHandlerActionEnum + completeTask?: NexusGenInputs['ActionCompleteTaskInput'] | null; // ActionCompleteTaskInput + expandInlineJSON?: boolean | null; // Boolean + failTask?: NexusGenInputs['ActionFailTaskInput'] | null; // ActionFailTaskInput + startWorkflow?: NexusGenInputs['ActionStartWorkflowInput'] | null; // ActionStartWorkflowInput + }; ExecuteNewWorkflowInput: { // input type correlationId?: string | null; // String @@ -211,6 +250,12 @@ export interface NexusGenInputs { deviceName?: string | null; // String labels?: string[] | null; // [String!] }; + FilterEventHandlerInput: { + // input type + evaluatorType?: string | null; // String + event?: string | null; // String + isActive?: boolean | null; // Boolean + }; FilterPoolsInput: { // input type poolName?: string | null; // String @@ -322,6 +367,13 @@ export interface NexusGenInputs { vendor?: string | null; // String version?: string | null; // String }; + UpdateEventHandlerInput: { + // input type + actions?: NexusGenInputs['EventHandlerActionInput'][] | null; // [EventHandlerActionInput!] + condition?: string | null; // String + evaluatorType?: string | null; // String + isActive?: boolean | null; // Boolean + }; UpdateWorkflowInput: { // input type workflow: NexusGenInputs['WorkflowInput']; // WorkflowInput! @@ -367,6 +419,7 @@ export interface NexusGenEnums { DeviceServiceState: 'IN_SERVICE' | 'OUT_OF_SERVICE' | 'PLANNING'; DeviceSize: 'LARGE' | 'MEDIUM' | 'SMALL'; DeviceSource: 'DISCOVERED' | 'IMPORTED' | 'MANUAL'; + EventHandlerActionEnum: 'complete_task' | 'fail_task' | 'start_workflow'; ExecutedWorkflowStatus: 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT'; ExecutedWorkflowTaskStatus: | 'CANCELED' @@ -422,6 +475,28 @@ export interface NexusGenScalars { } export interface NexusGenObjects { + ActionCompleteTask: { + // root type + output?: string | null; // String + taskId?: string | null; // String + taskRefName?: string | null; // String + workflowId?: string | null; // String + }; + ActionFailTask: { + // root type + output?: string | null; // String + taskId?: string | null; // String + taskRefName?: string | null; // String + workflowId?: string | null; // String + }; + ActionStartWorkflow: { + // root type + correlationId?: string | null; // String + input?: string | null; // String + name?: string | null; // String + taskToDomain?: string | null; // String + version?: number | null; // Int + }; AddBlueprintPayload: { // root type blueprint: NexusGenRootTypes['Blueprint']; // Blueprint! @@ -565,6 +640,35 @@ export interface NexusGenObjects { interface: string; // String! nodeId: string; // String! }; + EventHandler: { + // root type + actions: NexusGenRootTypes['EventHandlerAction'][]; // [EventHandlerAction!]! + condition?: string | null; // String + evaluatorType?: string | null; // String + event: string; // String! + id: string; // ID! + isActive?: boolean | null; // Boolean + name: string; // String! + }; + EventHandlerAction: { + // root type + action?: NexusGenEnums['EventHandlerActionEnum'] | null; // EventHandlerActionEnum + completeTask?: NexusGenRootTypes['ActionCompleteTask'] | null; // ActionCompleteTask + expandInlineJSON?: boolean | null; // Boolean + failTask?: NexusGenRootTypes['ActionFailTask'] | null; // ActionFailTask + id: string; // ID! + startWorkflow?: NexusGenRootTypes['ActionStartWorkflow'] | null; // ActionStartWorkflow + }; + EventHandlerConnection: { + // root type + edges?: NexusGenRootTypes['EventHandlerEdge'][] | null; // [EventHandlerEdge!] + pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! + }; + EventHandlerEdge: { + // root type + cursor: string; // String! + node: NexusGenRootTypes['EventHandler']; // EventHandler! + }; ExecutedWorkflow: SourceTypes.ExecutedWorkflow; ExecutedWorkflowConnection: { // root type @@ -882,6 +986,28 @@ export type NexusGenRootTypes = NexusGenInterfaces & NexusGenObjects; export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars & NexusGenEnums; export interface NexusGenFieldTypes { + ActionCompleteTask: { + // field return type + output: string | null; // String + taskId: string | null; // String + taskRefName: string | null; // String + workflowId: string | null; // String + }; + ActionFailTask: { + // field return type + output: string | null; // String + taskId: string | null; // String + taskRefName: string | null; // String + workflowId: string | null; // String + }; + ActionStartWorkflow: { + // field return type + correlationId: string | null; // String + input: string | null; // String + name: string | null; // String + taskToDomain: string | null; // String + version: number | null; // Int + }; AddBlueprintPayload: { // field return type blueprint: NexusGenRootTypes['Blueprint']; // Blueprint! @@ -1064,6 +1190,35 @@ export interface NexusGenFieldTypes { interface: string; // String! nodeId: string; // String! }; + EventHandler: { + // field return type + actions: NexusGenRootTypes['EventHandlerAction'][]; // [EventHandlerAction!]! + condition: string | null; // String + evaluatorType: string | null; // String + event: string; // String! + id: string; // ID! + isActive: boolean | null; // Boolean + name: string; // String! + }; + EventHandlerAction: { + // field return type + action: NexusGenEnums['EventHandlerActionEnum'] | null; // EventHandlerActionEnum + completeTask: NexusGenRootTypes['ActionCompleteTask'] | null; // ActionCompleteTask + expandInlineJSON: boolean | null; // Boolean + failTask: NexusGenRootTypes['ActionFailTask'] | null; // ActionFailTask + id: string; // ID! + startWorkflow: NexusGenRootTypes['ActionStartWorkflow'] | null; // ActionStartWorkflow + }; + EventHandlerConnection: { + // field return type + edges: NexusGenRootTypes['EventHandlerEdge'][] | null; // [EventHandlerEdge!] + pageInfo: NexusGenRootTypes['PageInfo']; // PageInfo! + }; + EventHandlerEdge: { + // field return type + cursor: string; // String! + node: NexusGenRootTypes['EventHandler']; // EventHandler! + }; ExecutedWorkflow: { // field return type correlationId: string | null; // String @@ -1232,12 +1387,14 @@ export interface NexusGenFieldTypes { bulkTerminateWorkflow: NexusGenRootTypes['BulkOperationResponse'] | null; // BulkOperationResponse closeTransaction: NexusGenRootTypes['CloseTransactionPayload']; // CloseTransactionPayload! commitConfig: NexusGenRootTypes['CommitConfigPayload']; // CommitConfigPayload! + createEventHandler: NexusGenRootTypes['EventHandler'] | null; // EventHandler createLabel: NexusGenRootTypes['CreateLabelPayload']; // CreateLabelPayload! createTaskDefinition: NexusGenRootTypes['TaskDefinition'] | null; // TaskDefinition createTransaction: NexusGenRootTypes['CreateTransactionPayload']; // CreateTransactionPayload! createWorkflow: NexusGenRootTypes['CreateWorkflowPayload']; // CreateWorkflowPayload! deleteBlueprint: NexusGenRootTypes['DeleteBlueprintPayload']; // DeleteBlueprintPayload! deleteDevice: NexusGenRootTypes['DeleteDevicePayload']; // DeleteDevicePayload! + deleteEventHandler: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse deleteLabel: NexusGenRootTypes['DeleteLabelPayload']; // DeleteLabelPayload! deleteSchedule: NexusGenRootTypes['IsOkResponse'] | null; // IsOkResponse deleteSnapshot: NexusGenRootTypes['DeleteSnapshotPayload'] | null; // DeleteSnapshotPayload @@ -1263,6 +1420,7 @@ export interface NexusGenFieldTypes { updateBlueprint: NexusGenRootTypes['UpdateBlueprintPayload']; // UpdateBlueprintPayload! updateDataStore: NexusGenRootTypes['UpdateDataStorePayload']; // UpdateDataStorePayload! updateDevice: NexusGenRootTypes['UpdateDevicePayload']; // UpdateDevicePayload! + updateEventHandler: NexusGenRootTypes['EventHandler'] | null; // EventHandler updateGraphNodeCoordinates: NexusGenRootTypes['UpdateGraphNodeCoordinatesPayload']; // UpdateGraphNodeCoordinatesPayload! updateWorkflow: NexusGenRootTypes['UpdateWorkflowPayload']; // UpdateWorkflowPayload! }; @@ -1329,6 +1487,9 @@ export interface NexusGenFieldTypes { countries: NexusGenRootTypes['CountryConnection']; // CountryConnection! dataStore: NexusGenRootTypes['DataStore'] | null; // DataStore devices: NexusGenRootTypes['DeviceConnection']; // DeviceConnection! + eventHandler: NexusGenRootTypes['EventHandler'] | null; // EventHandler + eventHandlers: NexusGenRootTypes['EventHandlerConnection'] | null; // EventHandlerConnection + eventHandlersByEvent: NexusGenRootTypes['EventHandlerConnection'] | null; // EventHandlerConnection executedWorkflows: NexusGenRootTypes['ExecutedWorkflowConnection'] | null; // ExecutedWorkflowConnection labels: NexusGenRootTypes['LabelConnection']; // LabelConnection! locations: NexusGenRootTypes['LocationConnection']; // LocationConnection! @@ -1577,6 +1738,28 @@ export interface NexusGenFieldTypes { } export interface NexusGenFieldTypeNames { + ActionCompleteTask: { + // field return type name + output: 'String'; + taskId: 'String'; + taskRefName: 'String'; + workflowId: 'String'; + }; + ActionFailTask: { + // field return type name + output: 'String'; + taskId: 'String'; + taskRefName: 'String'; + workflowId: 'String'; + }; + ActionStartWorkflow: { + // field return type name + correlationId: 'String'; + input: 'String'; + name: 'String'; + taskToDomain: 'String'; + version: 'Int'; + }; AddBlueprintPayload: { // field return type name blueprint: 'Blueprint'; @@ -1759,6 +1942,35 @@ export interface NexusGenFieldTypeNames { interface: 'String'; nodeId: 'String'; }; + EventHandler: { + // field return type name + actions: 'EventHandlerAction'; + condition: 'String'; + evaluatorType: 'String'; + event: 'String'; + id: 'ID'; + isActive: 'Boolean'; + name: 'String'; + }; + EventHandlerAction: { + // field return type name + action: 'EventHandlerActionEnum'; + completeTask: 'ActionCompleteTask'; + expandInlineJSON: 'Boolean'; + failTask: 'ActionFailTask'; + id: 'ID'; + startWorkflow: 'ActionStartWorkflow'; + }; + EventHandlerConnection: { + // field return type name + edges: 'EventHandlerEdge'; + pageInfo: 'PageInfo'; + }; + EventHandlerEdge: { + // field return type name + cursor: 'String'; + node: 'EventHandler'; + }; ExecutedWorkflow: { // field return type name correlationId: 'String'; @@ -1927,12 +2139,14 @@ export interface NexusGenFieldTypeNames { bulkTerminateWorkflow: 'BulkOperationResponse'; closeTransaction: 'CloseTransactionPayload'; commitConfig: 'CommitConfigPayload'; + createEventHandler: 'EventHandler'; createLabel: 'CreateLabelPayload'; createTaskDefinition: 'TaskDefinition'; createTransaction: 'CreateTransactionPayload'; createWorkflow: 'CreateWorkflowPayload'; deleteBlueprint: 'DeleteBlueprintPayload'; deleteDevice: 'DeleteDevicePayload'; + deleteEventHandler: 'IsOkResponse'; deleteLabel: 'DeleteLabelPayload'; deleteSchedule: 'IsOkResponse'; deleteSnapshot: 'DeleteSnapshotPayload'; @@ -1958,6 +2172,7 @@ export interface NexusGenFieldTypeNames { updateBlueprint: 'UpdateBlueprintPayload'; updateDataStore: 'UpdateDataStorePayload'; updateDevice: 'UpdateDevicePayload'; + updateEventHandler: 'EventHandler'; updateGraphNodeCoordinates: 'UpdateGraphNodeCoordinatesPayload'; updateWorkflow: 'UpdateWorkflowPayload'; }; @@ -2024,6 +2239,9 @@ export interface NexusGenFieldTypeNames { countries: 'CountryConnection'; dataStore: 'DataStore'; devices: 'DeviceConnection'; + eventHandler: 'EventHandler'; + eventHandlers: 'EventHandlerConnection'; + eventHandlersByEvent: 'EventHandlerConnection'; executedWorkflows: 'ExecutedWorkflowConnection'; labels: 'LabelConnection'; locations: 'LocationConnection'; @@ -2338,6 +2556,10 @@ export interface NexusGenArgTypes { input: NexusGenInputs['CommitConfigInput']; // CommitConfigInput! transactionId: string; // String! }; + createEventHandler: { + // args + input: NexusGenInputs['CreateEventHandlerInput']; // CreateEventHandlerInput! + }; createLabel: { // args input: NexusGenInputs['CreateLabelInput']; // CreateLabelInput! @@ -2362,6 +2584,10 @@ export interface NexusGenArgTypes { // args id: string; // String! }; + deleteEventHandler: { + // args + id: string; // String! + }; deleteLabel: { // args id: string; // String! @@ -2473,6 +2699,12 @@ export interface NexusGenArgTypes { id: string; // String! input: NexusGenInputs['UpdateDeviceInput']; // UpdateDeviceInput! }; + updateEventHandler: { + // args + event: string; // String! + input: NexusGenInputs['UpdateEventHandlerInput']; // UpdateEventHandlerInput! + name: string; // String! + }; updateGraphNodeCoordinates: { // args input: NexusGenInputs['GraphNodeCoordinatesInput'][]; // [GraphNodeCoordinatesInput!]! @@ -2517,6 +2749,28 @@ export interface NexusGenArgTypes { last?: number | null; // Int orderBy?: NexusGenInputs['DeviceOrderByInput'] | null; // DeviceOrderByInput }; + eventHandler: { + // args + event: string; // String! + name: string; // String! + }; + eventHandlers: { + // args + after?: string | null; // String + before?: string | null; // String + filter?: NexusGenInputs['FilterEventHandlerInput'] | null; // FilterEventHandlerInput + first?: number | null; // Int + last?: number | null; // Int + }; + eventHandlersByEvent: { + // args + activeOnly?: boolean | null; // Boolean + after?: string | null; // String + before?: string | null; // String + event: string; // String! + first?: number | null; // Int + last?: number | null; // Int + }; executedWorkflows: { // args pagination?: NexusGenInputs['PaginationArgs'] | null; // PaginationArgs From a2aa828c029afbbb63172cec4ea3177ecce0e45d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Mr=C3=BAz?= Date: Mon, 17 Jul 2023 13:32:34 +0200 Subject: [PATCH 33/69] remove generated id of event handler actions --- src/schema/api.graphql | 1 - src/schema/event-handler.ts | 1 - src/schema/nexus-typegen.ts | 3 --- 3 files changed, 5 deletions(-) diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 7ecab4b5..df2e50b9 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -422,7 +422,6 @@ type EventHandlerAction { completeTask: ActionCompleteTask expandInlineJSON: Boolean failTask: ActionFailTask - id: ID! startWorkflow: ActionStartWorkflow } diff --git a/src/schema/event-handler.ts b/src/schema/event-handler.ts index 1904616a..73b59fbb 100644 --- a/src/schema/event-handler.ts +++ b/src/schema/event-handler.ts @@ -55,7 +55,6 @@ export const ActionFailTask = objectType({ export const EventHandlerAction = objectType({ name: 'EventHandlerAction', definition(t) { - t.nonNull.id('id'); t.field('action', { type: EventHandlerActionEnum }); t.field('startWorkflow', { type: ActionStartWorkflow }); t.field('completeTask', { type: ActionCompleteTask }); diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 4e776686..e98c23cc 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -656,7 +656,6 @@ export interface NexusGenObjects { completeTask?: NexusGenRootTypes['ActionCompleteTask'] | null; // ActionCompleteTask expandInlineJSON?: boolean | null; // Boolean failTask?: NexusGenRootTypes['ActionFailTask'] | null; // ActionFailTask - id: string; // ID! startWorkflow?: NexusGenRootTypes['ActionStartWorkflow'] | null; // ActionStartWorkflow }; EventHandlerConnection: { @@ -1206,7 +1205,6 @@ export interface NexusGenFieldTypes { completeTask: NexusGenRootTypes['ActionCompleteTask'] | null; // ActionCompleteTask expandInlineJSON: boolean | null; // Boolean failTask: NexusGenRootTypes['ActionFailTask'] | null; // ActionFailTask - id: string; // ID! startWorkflow: NexusGenRootTypes['ActionStartWorkflow'] | null; // ActionStartWorkflow }; EventHandlerConnection: { @@ -1958,7 +1956,6 @@ export interface NexusGenFieldTypeNames { completeTask: 'ActionCompleteTask'; expandInlineJSON: 'Boolean'; failTask: 'ActionFailTask'; - id: 'ID'; startWorkflow: 'ActionStartWorkflow'; }; EventHandlerConnection: { From 5a3c8f955805a9f6bd1a933fa72e81ccd3d835d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Mr=C3=BAz?= Date: Mon, 17 Jul 2023 13:37:38 +0200 Subject: [PATCH 34/69] fix lint and formatting --- src/__generated__/resource-manager.graphql.ts | 112 +++++++++--------- src/__generated__/scheduler.graphql.ts | 104 ++++++++++++---- src/helpers/task-definition.helpers.ts | 7 +- src/schema/global-types.ts | 1 - src/schema/task-definitons.ts | 19 ++- 5 files changed, 148 insertions(+), 95 deletions(-) diff --git a/src/__generated__/resource-manager.graphql.ts b/src/__generated__/resource-manager.graphql.ts index 1f793f5c..021d65fd 100644 --- a/src/__generated__/resource-manager.graphql.ts +++ b/src/__generated__/resource-manager.graphql.ts @@ -25,9 +25,7 @@ export type AllocationStrategy = Node & { }; /** Supported languages for allocation strategy scripts */ -export type AllocationStrategyLang = - | 'js' - | 'py'; +export type AllocationStrategyLang = 'js' | 'py'; /** Input parameters for creating an allocation pool */ export type CreateAllocatingPoolInput = { @@ -241,14 +239,12 @@ export type Mutation = { UpdateTag: UpdateTagPayload; }; - export type MutationClaimResourceArgs = { description?: InputMaybe; poolId: Scalars['ID']; userInput: Scalars['Map']; }; - export type MutationClaimResourceWithAltIdArgs = { alternativeId: Scalars['Map']; description?: InputMaybe; @@ -256,83 +252,67 @@ export type MutationClaimResourceWithAltIdArgs = { userInput: Scalars['Map']; }; - export type MutationCreateAllocatingPoolArgs = { input?: InputMaybe; }; - export type MutationCreateAllocationStrategyArgs = { input?: InputMaybe; }; - export type MutationCreateNestedAllocatingPoolArgs = { input: CreateNestedAllocatingPoolInput; }; - export type MutationCreateNestedSetPoolArgs = { input: CreateNestedSetPoolInput; }; - export type MutationCreateNestedSingletonPoolArgs = { input: CreateNestedSingletonPoolInput; }; - export type MutationCreateResourceTypeArgs = { input: CreateResourceTypeInput; }; - export type MutationCreateSetPoolArgs = { input: CreateSetPoolInput; }; - export type MutationCreateSingletonPoolArgs = { input?: InputMaybe; }; - export type MutationCreateTagArgs = { input: CreateTagInput; }; - export type MutationDeleteAllocationStrategyArgs = { input?: InputMaybe; }; - export type MutationDeleteResourcePoolArgs = { input: DeleteResourcePoolInput; }; - export type MutationDeleteResourceTypeArgs = { input: DeleteResourceTypeInput; }; - export type MutationDeleteTagArgs = { input: DeleteTagInput; }; - export type MutationFreeResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; - export type MutationTagPoolArgs = { input: TagPoolInput; }; - export type MutationTestAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; currentResources: Array; @@ -340,24 +320,20 @@ export type MutationTestAllocationStrategyArgs = { userInput: Scalars['Map']; }; - export type MutationUntagPoolArgs = { input: UntagPoolInput; }; - export type MutationUpdateResourceAltIdArgs = { alternativeId: Scalars['Map']; input: Scalars['Map']; poolId: Scalars['ID']; }; - export type MutationUpdateResourceTypeNameArgs = { input: UpdateResourceTypeNameInput; }; - export type MutationUpdateTagArgs = { input: UpdateTagInput; }; @@ -391,10 +367,7 @@ export type PoolCapacityPayload = { }; /** Defines the type of pool */ -export type PoolType = - | 'allocating' - | 'set' - | 'singleton'; +export type PoolType = 'allocating' | 'set' | 'singleton'; /** Defines the type of the property */ export type PropertyType = Node & { @@ -431,17 +404,14 @@ export type Query = { node: Maybe; }; - export type QueryQueryAllocationStrategiesArgs = { byName?: InputMaybe; }; - export type QueryQueryAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; }; - export type QueryQueryEmptyResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -450,7 +420,6 @@ export type QueryQueryEmptyResourcePoolsArgs = { resourceTypeId?: InputMaybe; }; - export type QueryQueryLeafResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -461,12 +430,10 @@ export type QueryQueryLeafResourcePoolsArgs = { tags?: InputMaybe; }; - export type QueryQueryPoolCapacityArgs = { poolId: Scalars['ID']; }; - export type QueryQueryRecentlyActiveResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -476,28 +443,23 @@ export type QueryQueryRecentlyActiveResourcesArgs = { toDatetime?: InputMaybe; }; - export type QueryQueryRequiredPoolPropertiesArgs = { allocationStrategyName: Scalars['String']; }; - export type QueryQueryResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; - export type QueryQueryResourcePoolArgs = { poolId: Scalars['ID']; }; - export type QueryQueryResourcePoolHierarchyPathArgs = { poolId: Scalars['ID']; }; - export type QueryQueryResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -508,12 +470,10 @@ export type QueryQueryResourcePoolsArgs = { tags?: InputMaybe; }; - export type QueryQueryResourceTypesArgs = { byName?: InputMaybe; }; - export type QueryQueryResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -522,7 +482,6 @@ export type QueryQueryResourcesArgs = { poolId: Scalars['ID']; }; - export type QueryQueryResourcesByAltIdArgs = { after?: InputMaybe; before?: InputMaybe; @@ -532,7 +491,6 @@ export type QueryQueryResourcesByAltIdArgs = { poolId?: InputMaybe; }; - export type QueryQueryRootResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -543,7 +501,6 @@ export type QueryQueryRootResourcePoolsArgs = { tags?: InputMaybe; }; - export type QuerySearchPoolsByTagsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -552,7 +509,6 @@ export type QuerySearchPoolsByTagsArgs = { tags?: InputMaybe; }; - export type QueryNodeArgs = { id: Scalars['ID']; }; @@ -606,7 +562,6 @@ export type ResourcePool = Node & { id: Scalars['ID']; }; - /** A pool is an entity that contains allocated and free resources */ export type ResourcePoolAllocatedResourcesArgs = { after?: InputMaybe; @@ -710,14 +665,39 @@ export type UpdateTagPayload = { tag: Maybe; }; -export type PoolFragmentFragment = { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }; +export type PoolFragmentFragment = { + __typename: 'ResourcePool'; + id: string; + Name: string; + PoolType: PoolType; + PoolProperties: any; + Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; + ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; +}; export type GetPoolQueryVariables = Exact<{ nodeId: Scalars['ID']; }>; - -export type GetPoolQuery = { __typename?: 'Query', node: { __typename?: 'AllocationStrategy' } | { __typename?: 'PropertyType' } | { __typename?: 'Resource' } | { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } } | { __typename?: 'ResourceType' } | { __typename?: 'Tag' } | null }; +export type GetPoolQuery = { + __typename?: 'Query'; + node: + | { __typename?: 'AllocationStrategy' } + | { __typename?: 'PropertyType' } + | { __typename?: 'Resource' } + | { + __typename: 'ResourcePool'; + id: string; + Name: string; + PoolType: PoolType; + PoolProperties: any; + Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; + ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; + } + | { __typename?: 'ResourceType' } + | { __typename?: 'Tag' } + | null; +}; export type GetPoolsQueryVariables = Exact<{ resourceTypeId?: InputMaybe; @@ -728,13 +708,37 @@ export type GetPoolsQueryVariables = Exact<{ filterByResources?: InputMaybe; }>; - -export type GetPoolsQuery = { __typename?: 'Query', QueryRootResourcePools: { __typename?: 'ResourcePoolConnection', totalCount: number, edges: Array<{ __typename?: 'ResourcePoolEdge', node: { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }, cursor: { __typename?: 'OutputCursor', ID: string } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: { __typename?: 'OutputCursor', ID: string } | null, endCursor: { __typename?: 'OutputCursor', ID: string } | null } } }; +export type GetPoolsQuery = { + __typename?: 'Query'; + QueryRootResourcePools: { + __typename?: 'ResourcePoolConnection'; + totalCount: number; + edges: Array<{ + __typename?: 'ResourcePoolEdge'; + node: { + __typename: 'ResourcePool'; + id: string; + Name: string; + PoolType: PoolType; + PoolProperties: any; + Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; + ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; + }; + cursor: { __typename?: 'OutputCursor'; ID: string }; + } | null>; + pageInfo: { + __typename?: 'PageInfo'; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: { __typename?: 'OutputCursor'; ID: string } | null; + endCursor: { __typename?: 'OutputCursor'; ID: string } | null; + }; + }; +}; export type FreeResourceMutationVariables = Exact<{ poolId: Scalars['ID']; input: Scalars['Map']; }>; - -export type FreeResourceMutation = { __typename?: 'Mutation', FreeResource: string }; +export type FreeResourceMutation = { __typename?: 'Mutation'; FreeResource: string }; diff --git a/src/__generated__/scheduler.graphql.ts b/src/__generated__/scheduler.graphql.ts index af39c7c6..db014ee9 100644 --- a/src/__generated__/scheduler.graphql.ts +++ b/src/__generated__/scheduler.graphql.ts @@ -33,17 +33,14 @@ export type Mutation = { updateSchedule: Schedule; }; - export type MutationCreateScheduleArgs = { input: CreateScheduleInput; }; - export type MutationDeleteScheduleArgs = { name: Scalars['String']; }; - export type MutationUpdateScheduleArgs = { input: UpdateScheduleInput; name: Scalars['String']; @@ -63,12 +60,10 @@ export type Query = { schedules: Maybe; }; - export type QueryScheduleArgs = { name: Scalars['String']; }; - export type QuerySchedulesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -109,14 +104,7 @@ export type SchedulesFilterInput = { workflowVersion: Scalars['String']; }; -export type Status = - | 'COMPLETED' - | 'FAILED' - | 'PAUSED' - | 'RUNNING' - | 'TERMINATED' - | 'TIMED_OUT' - | 'UNKNOWN'; +export type Status = 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; export type UpdateScheduleInput = { cronString?: InputMaybe; @@ -133,30 +121,71 @@ export type DeleteScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; }>; - -export type DeleteScheduleMutation = { __typename?: 'Mutation', deleteSchedule: boolean }; +export type DeleteScheduleMutation = { __typename?: 'Mutation'; deleteSchedule: boolean }; export type UpdateScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; input: UpdateScheduleInput; }>; - -export type UpdateScheduleMutation = { __typename?: 'Mutation', updateSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; +export type UpdateScheduleMutation = { + __typename?: 'Mutation'; + updateSchedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; +}; export type CreateScheduleMutationVariables = Exact<{ input: CreateScheduleInput; }>; - -export type CreateScheduleMutation = { __typename?: 'Mutation', createSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; +export type CreateScheduleMutation = { + __typename?: 'Mutation'; + createSchedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; +}; export type GetScheduleQueryVariables = Exact<{ scheduleName: Scalars['String']; }>; - -export type GetScheduleQuery = { __typename?: 'Query', schedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } | null }; +export type GetScheduleQuery = { + __typename?: 'Query'; + schedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + } | null; +}; export type GetSchedulesQueryVariables = Exact<{ first?: InputMaybe; @@ -166,5 +195,34 @@ export type GetSchedulesQueryVariables = Exact<{ filter?: InputMaybe; }>; - -export type GetSchedulesQuery = { __typename?: 'Query', schedules: { __typename?: 'ScheduleConnection', totalCount: number, edges: Array<{ __typename?: 'ScheduleEdge', cursor: string, node: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null } } | null }; +export type GetSchedulesQuery = { + __typename?: 'Query'; + schedules: { + __typename?: 'ScheduleConnection'; + totalCount: number; + edges: Array<{ + __typename?: 'ScheduleEdge'; + cursor: string; + node: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; + } | null>; + pageInfo: { + __typename?: 'PageInfo'; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; + endCursor: string | null; + }; + } | null; +}; diff --git a/src/helpers/task-definition.helpers.ts b/src/helpers/task-definition.helpers.ts index 6376a60d..3e3db298 100644 --- a/src/helpers/task-definition.helpers.ts +++ b/src/helpers/task-definition.helpers.ts @@ -1,5 +1,3 @@ -import { TaskDefinition } from '../schema/source-types'; - type TaskDefinitionDetailInput = { name: string; timeoutSeconds: number; @@ -58,6 +56,5 @@ export const getTaskDefinitionInput = (input: TaskDefinitionDetailInput) => { return taskDefinitionInput; }; -export const getFilteredTaskDefinitions = (defs: T[], searchTerm: string): T[] => { - return defs.filter((df) => df.name.toLowerCase().includes(searchTerm.toLowerCase())); -}; +export const getFilteredTaskDefinitions = (defs: T[], searchTerm: string): T[] => + defs.filter((df) => df.name.toLowerCase().includes(searchTerm.toLowerCase())); diff --git a/src/schema/global-types.ts b/src/schema/global-types.ts index 0fb16d27..5794c64a 100644 --- a/src/schema/global-types.ts +++ b/src/schema/global-types.ts @@ -6,7 +6,6 @@ import { fromGraphId, getType } from '../helpers/id-helper'; import schedulerAPI from '../external-api/scheduler'; import resourceManagerAPI from '../external-api/resource-manager'; import { apiPoolEdgeToGraphqlPoolEdge } from '../helpers/resource-manager.helpers'; -import { makeFromApiToGraphQLEventHandler } from '../helpers/event-handler.helpers'; export const Node = interfaceType({ name: 'Node', diff --git a/src/schema/task-definitons.ts b/src/schema/task-definitons.ts index b01b86cb..0a12c8a2 100644 --- a/src/schema/task-definitons.ts +++ b/src/schema/task-definitons.ts @@ -1,11 +1,9 @@ -import { arg, enumType, extendType, inputObjectType, list, mutationField, nonNull, objectType, stringArg } from 'nexus'; +import { arg, enumType, extendType, inputObjectType, mutationField, nonNull, objectType, stringArg } from 'nexus'; import config from '../config'; import { toGraphId } from '../helpers/id-helper'; -import { getTaskDefinitionInput } from '../helpers/task-definition.helpers'; +import { getTaskDefinitionInput, getFilteredTaskDefinitions } from '../helpers/task-definition.helpers'; import { IsOkResponse, Node, PageInfo, PaginationConnectionArgs } from './global-types'; -import { getFilteredTaskDefinitions } from '../helpers/task-definition.helpers'; -import {connectionFromArray} from '../helpers/connection.helpers' -import { log } from 'console'; +import { connectionFromArray } from '../helpers/connection.helpers'; const TaskTimeoutPolicy = enumType({ name: 'TaskTimeoutPolicy', @@ -89,8 +87,6 @@ export const FilterTaskDefinitionsInput = inputObjectType({ }, }); - - export const TaskDefinitionsQuery = extendType({ type: 'Query', definition: (t) => { @@ -107,10 +103,10 @@ export const TaskDefinitionsQuery = extendType({ ? getFilteredTaskDefinitions(taskDefinitions, filter.keyword) : taskDefinitions; - const tasksWithId = filteredTaskDefs.map((task) => ({ - ...task, - id: task.name, - })); + const tasksWithId = filteredTaskDefs.map((task) => ({ + ...task, + id: task.name, + })); return { ...connectionFromArray(tasksWithId, paginationArgs), totalCount: filteredTaskDefs.length, @@ -120,7 +116,6 @@ export const TaskDefinitionsQuery = extendType({ }, }); - export const DeleteTaskDefinitionMutation = mutationField('deleteTask', { type: IsOkResponse, args: { From 6a1be8d374ed4e58e1fa253350ed854c910abf21 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Tue, 18 Jul 2023 14:01:39 +0200 Subject: [PATCH 35/69] output parameters fix (#319) --- src/external-api/conductor-network-types.ts | 4 ++-- src/schema/workflow.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index 41540c43..ad2433f7 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -73,14 +73,14 @@ const WorkflowMetadataOptional = t.partial({ description: optional(t.string), version: optional(t.number), inputParameters: optional(t.array(t.string)), - outputParameters: optional(t.record(t.string, t.string)), + outputParameters: optional(t.record(t.string, t.unknown)), failureWorkflow: optional(t.string), schemaVersion: optional(t.number), restartable: optional(t.boolean), workflowStatusListenerEnabled: optional(t.boolean), ownerEmail: optional(t.string), timeoutPolicy: optional(t.union([t.literal('TIME_OUT_WF'), t.literal('ALERT_ONLY')])), - variables: optional(t.record(t.string, t.UnknownRecord)), + variables: optional(t.UnknownRecord), inputTemplate: optional(t.record(t.string, t.UnknownRecord)), }); diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index f1acb5a3..e92647c1 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -82,7 +82,7 @@ export const Workflow = objectType({ w.outputParameters ? Object.entries(w.outputParameters).map((e) => ({ key: e[0], - value: e[1], + value: JSON.stringify(e[1]), })) : null, }); From 3b52493053b3550cc7986a8443df6053f38120fd Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Tue, 18 Jul 2023 16:04:29 +0200 Subject: [PATCH 36/69] Typegen fix (#321) * type checks fix * remove unused code * add story branch to pr-check * workflow node type changes * make workflow id as stringified object of name and version properties --- .github/workflows/pr-check.yml | 1 + src/helpers/event-handler.helpers.ts | 2 ++ src/helpers/workflow.helpers.ts | 16 ++++++++++++++++ src/schema/api.graphql | 14 +------------- src/schema/event-handler.ts | 11 +++++------ src/schema/global-types.ts | 24 ++++++++++++++++++------ src/schema/nexus-typegen.ts | 28 +++------------------------- src/schema/task-definitons.ts | 2 +- src/schema/workflow.ts | 11 ++++++----- 9 files changed, 53 insertions(+), 56 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 729d2cfc..fc0992c6 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -3,6 +3,7 @@ on: pull_request: branches: - master + - story-new-conductor-api jobs: pr-check: runs-on: ubuntu-latest diff --git a/src/helpers/event-handler.helpers.ts b/src/helpers/event-handler.helpers.ts index cae13a00..a0f5e6a9 100644 --- a/src/helpers/event-handler.helpers.ts +++ b/src/helpers/event-handler.helpers.ts @@ -1,4 +1,5 @@ import { ApiEventHandler, ApiEventHandlerAction } from '../external-api/conductor-network-types'; +import { toGraphId } from './id-helper'; type StartWorkflowGraphQL = { name?: string | null; @@ -91,6 +92,7 @@ export function makeFromApiToGraphQLEventHandlerAction(eventHandlerAction: ApiEv export function makeFromApiToGraphQLEventHandler(eventHandler: ApiEventHandler) { return { + id: toGraphId('EventHandler', eventHandler.name), name: eventHandler.name, event: eventHandler.event, isActive: eventHandler.active || false, diff --git a/src/helpers/workflow.helpers.ts b/src/helpers/workflow.helpers.ts index 30347ba7..42035cf0 100644 --- a/src/helpers/workflow.helpers.ts +++ b/src/helpers/workflow.helpers.ts @@ -178,3 +178,19 @@ export function convertToApiOutputParameters( }; }, {}); } + +export type WorkflowCompositeID = { + name: string; + version?: number; +}; + +export function parseWorkflowId(id: string): WorkflowCompositeID { + return JSON.parse(id); +} + +export function getWorkflowId(name: string, version?: number): string { + return JSON.stringify({ + name, + version, + }); +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index df2e50b9..33a031ac 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -126,7 +126,6 @@ type Blueprint implements Node { name: String! template: String! updatedAt: String! - version: Int } type BlueprintConnection { @@ -197,7 +196,6 @@ type Country implements Node { code: String! id: ID! name: String! - version: Int } type CountryConnection { @@ -340,7 +338,6 @@ type Device implements Node { source: DeviceSource! updatedAt: String! vendor: String - version: Int zone: Zone! } @@ -399,7 +396,7 @@ input EditWorkflowScheduleInput { workflowVersion: String } -type EventHandler { +type EventHandler implements Node { actions: [EventHandlerAction!]! condition: String evaluatorType: String @@ -490,7 +487,6 @@ type ExecutedWorkflow implements Node { updatedAt: String updatedBy: String variables: String - version: Int workflowDefinition: Workflow workflowId: String! workflowName: String @@ -558,7 +554,6 @@ type ExecutedWorkflowTask implements Node { taskId: String taskType: String updateTime: String - version: Int workflowType: String } @@ -672,7 +667,6 @@ type Label implements Node { id: ID! name: String! updatedAt: String! - version: Int } type LabelConnection { @@ -692,7 +686,6 @@ type Location implements Node { id: ID! name: String! updatedAt: String! - version: Int } type LocationConnection { @@ -784,7 +777,6 @@ type NetTopology { interface Node { id: ID! - version: Int } type OutputParameter { @@ -815,7 +807,6 @@ type Pool implements Node { poolType: PoolType! resourceType: ResourceType! tags: [Tag!]! - version: Int } type PoolConnection { @@ -955,7 +946,6 @@ type Schedule implements Node { performFromDate: String! performTillDate: String! status: ScheduleStatus! - version: Int workflowContext: String! workflowName: String! workflowVersion: String! @@ -1049,7 +1039,6 @@ type TaskDefinition implements Node { timeoutSeconds: Int! updateTime: String updatedBy: String - version: Int } type TaskDefinitionConnection { @@ -1296,7 +1285,6 @@ type Zone implements Node { id: ID! name: String! updatedAt: String! - version: Int } type ZoneEdge { diff --git a/src/schema/event-handler.ts b/src/schema/event-handler.ts index 73b59fbb..aa7fbff1 100644 --- a/src/schema/event-handler.ts +++ b/src/schema/event-handler.ts @@ -11,7 +11,7 @@ import { } from 'nexus'; import { connectionFromArray } from 'graphql-relay'; import { v4 as uuid } from 'uuid'; -import { IsOkResponse, PaginationConnectionArgs } from './global-types'; +import { IsOkResponse, Node, PaginationConnectionArgs } from './global-types'; import config from '../config'; import { makeFromApiToGraphQLEventHandler, makeFromGraphQLToApiEventHandler } from '../helpers/event-handler.helpers'; import { fromGraphId, toGraphId } from '../helpers/id-helper'; @@ -66,6 +66,7 @@ export const EventHandlerAction = objectType({ export const EventHandler = objectType({ name: 'EventHandler', definition(t) { + t.implements(Node); t.nonNull.id('id'); t.nonNull.string('name', { description: 'The name is immutable and cannot be changed. Also it must be unique.' }); t.nonNull.string('event', { description: 'The event is immutable and cannot be changed.' }); @@ -128,7 +129,6 @@ export const EventHandlerQuery = queryField('eventHandlers', { }); const mappedEventHandlersWithId = filteredEventHandlers.map((eventHandler) => ({ - id: toGraphId('EventHandler', eventHandler.name), ...makeFromApiToGraphQLEventHandler(eventHandler), })); @@ -216,8 +216,8 @@ export const CreateEventHandlerMutation = mutationField('createEventHandler', { const { input } = args; await conductorAPI.createEventHandler(config.conductorApiURL, makeFromGraphQLToApiEventHandler(input)); return { - id: toGraphId('EventHandler', input.name), ...input, + id: toGraphId('EventHandler', input.name), }; }, }); @@ -259,10 +259,10 @@ export const UpdateEventHandlerMutation = mutationField('updateEventHandler', { const mappedEventHandler = makeFromApiToGraphQLEventHandler(oldEventHandler); return { - id: toGraphId('EventHandler', name), ...mappedEventHandler, ...input, actions: input.actions == null ? mappedEventHandler.actions : input.actions, + id: toGraphId('EventHandler', name), }; }, }); @@ -294,7 +294,6 @@ export const GetEventHandler = queryField('eventHandler', { const eventHandler = await conductorAPI.getEventHandler(config.conductorApiURL, event, name); const eventHandlerWithId = { - id: toGraphId('EventHandler', name), ...makeFromApiToGraphQLEventHandler(eventHandler), }; @@ -324,8 +323,8 @@ export const GetEventHandlersByEvent = queryField('eventHandlersByEvent', { ); const mappedEventHandlers = eventHandlers.map((eventHandler) => ({ - id: toGraphId('EventHandler', eventHandler.name), ...makeFromApiToGraphQLEventHandler(eventHandler), + // id: toGraphId('EventHandler', eventHandler.name), })); return connectionFromArray(mappedEventHandlers, { diff --git a/src/schema/global-types.ts b/src/schema/global-types.ts index 5794c64a..c77ea728 100644 --- a/src/schema/global-types.ts +++ b/src/schema/global-types.ts @@ -6,12 +6,15 @@ import { fromGraphId, getType } from '../helpers/id-helper'; import schedulerAPI from '../external-api/scheduler'; import resourceManagerAPI from '../external-api/resource-manager'; import { apiPoolEdgeToGraphqlPoolEdge } from '../helpers/resource-manager.helpers'; +import { parseWorkflowId } from '../helpers/workflow.helpers'; export const Node = interfaceType({ name: 'Node', definition: (t) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + // TODO: once TypeDefinition implements Node, type-check fails at this line t.nonNull.id('id'); - t.int('version'); // this is only used for Workflow, because it has composite id (name/version) }, }); export const PageInfo = objectType({ @@ -104,11 +107,8 @@ export const NodeQuery = extendType({ } case 'Workflow': { const id = fromGraphId('Workflow', args.id); - const workflow = await conductorAPI.getWorkflowDetail( - config.conductorApiURL, - id, - args.version ?? undefined, - ); + const { name, version } = parseWorkflowId(id); + const workflow = await conductorAPI.getWorkflowDetail(config.conductorApiURL, name, version); if (workflow == null) { return null; } @@ -153,6 +153,18 @@ export const NodeQuery = extendType({ return { ...task, id: args.id, __typename: 'ExecutedWorkflowTask' }; } + case 'TaskDefinition': { + const id = fromGraphId('TaskDefinition', args.id); + const taskDefinition = await conductorAPI.getTaskDetail(config.conductorApiURL, id); + if (taskDefinition == null) { + return null; + } + return { + ...taskDefinition, + id: args.id, + __typename: 'TaskDefinition', + }; + } /* eslint-enable */ default: return null; diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index e98c23cc..2ff80c88 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -798,7 +798,6 @@ export interface NexusGenObjects { poolType: NexusGenEnums['PoolType']; // PoolType! resourceType: NexusGenRootTypes['ResourceType']; // ResourceType! tags: NexusGenRootTypes['Tag'][]; // [Tag!]! - version?: number | null; // Int }; PoolConnection: { // root type @@ -967,6 +966,7 @@ export interface NexusGenInterfaces { | core.Discriminate<'Blueprint', 'required'> | core.Discriminate<'Country', 'required'> | core.Discriminate<'Device', 'required'> + | core.Discriminate<'EventHandler', 'required'> | core.Discriminate<'ExecutedWorkflow', 'required'> | core.Discriminate<'ExecutedWorkflowTask', 'required'> | core.Discriminate<'Label', 'required'> @@ -1039,7 +1039,6 @@ export interface NexusGenFieldTypes { name: string; // String! template: string; // String! updatedAt: string; // String! - version: number | null; // Int }; BlueprintConnection: { // field return type @@ -1096,7 +1095,6 @@ export interface NexusGenFieldTypes { code: string; // String! id: string; // ID! name: string; // String! - version: number | null; // Int }; CountryConnection: { // field return type @@ -1165,7 +1163,6 @@ export interface NexusGenFieldTypes { source: NexusGenEnums['DeviceSource']; // DeviceSource! updatedAt: string; // String! vendor: string | null; // String - version: number | null; // Int zone: NexusGenRootTypes['Zone']; // Zone! }; DeviceConnection: { @@ -1237,7 +1234,6 @@ export interface NexusGenFieldTypes { updatedAt: string | null; // String updatedBy: string | null; // String variables: string | null; // String - version: number | null; // Int workflowDefinition: NexusGenRootTypes['Workflow'] | null; // Workflow workflowId: string; // String! workflowName: string | null; // String @@ -1279,7 +1275,6 @@ export interface NexusGenFieldTypes { taskId: string | null; // String taskType: string | null; // String updateTime: string | null; // String - version: number | null; // Int workflowType: string | null; // String }; GraphEdge: { @@ -1337,7 +1332,6 @@ export interface NexusGenFieldTypes { id: string; // ID! name: string; // String! updatedAt: string; // String! - version: number | null; // Int }; LabelConnection: { // field return type @@ -1357,7 +1351,6 @@ export interface NexusGenFieldTypes { id: string; // ID! name: string; // String! updatedAt: string; // String! - version: number | null; // Int }; LocationConnection: { // field return type @@ -1465,7 +1458,6 @@ export interface NexusGenFieldTypes { poolType: NexusGenEnums['PoolType']; // PoolType! resourceType: NexusGenRootTypes['ResourceType']; // ResourceType! tags: NexusGenRootTypes['Tag'][]; // [Tag!]! - version: number | null; // Int }; PoolConnection: { // field return type @@ -1530,7 +1522,6 @@ export interface NexusGenFieldTypes { performFromDate: string; // String! performTillDate: string; // String! status: NexusGenEnums['ScheduleStatus']; // ScheduleStatus! - version: number | null; // Int workflowContext: string; // String! workflowName: string; // String! workflowVersion: string; // String! @@ -1594,7 +1585,6 @@ export interface NexusGenFieldTypes { timeoutSeconds: number; // Int! updateTime: string | null; // String updatedBy: string | null; // String - version: number | null; // Int }; TaskDefinitionConnection: { // field return type @@ -1707,7 +1697,6 @@ export interface NexusGenFieldTypes { id: string; // ID! name: string; // String! updatedAt: string; // String! - version: number | null; // Int }; ZoneEdge: { // field return type @@ -1731,7 +1720,6 @@ export interface NexusGenFieldTypes { Node: { // field return type id: string; // ID! - version: number | null; // Int }; } @@ -1790,7 +1778,6 @@ export interface NexusGenFieldTypeNames { name: 'String'; template: 'String'; updatedAt: 'String'; - version: 'Int'; }; BlueprintConnection: { // field return type name @@ -1847,7 +1834,6 @@ export interface NexusGenFieldTypeNames { code: 'String'; id: 'ID'; name: 'String'; - version: 'Int'; }; CountryConnection: { // field return type name @@ -1916,7 +1902,6 @@ export interface NexusGenFieldTypeNames { source: 'DeviceSource'; updatedAt: 'String'; vendor: 'String'; - version: 'Int'; zone: 'Zone'; }; DeviceConnection: { @@ -1988,7 +1973,6 @@ export interface NexusGenFieldTypeNames { updatedAt: 'String'; updatedBy: 'String'; variables: 'String'; - version: 'Int'; workflowDefinition: 'Workflow'; workflowId: 'String'; workflowName: 'String'; @@ -2030,7 +2014,6 @@ export interface NexusGenFieldTypeNames { taskId: 'String'; taskType: 'String'; updateTime: 'String'; - version: 'Int'; workflowType: 'String'; }; GraphEdge: { @@ -2088,7 +2071,6 @@ export interface NexusGenFieldTypeNames { id: 'ID'; name: 'String'; updatedAt: 'String'; - version: 'Int'; }; LabelConnection: { // field return type name @@ -2108,7 +2090,6 @@ export interface NexusGenFieldTypeNames { id: 'ID'; name: 'String'; updatedAt: 'String'; - version: 'Int'; }; LocationConnection: { // field return type name @@ -2216,7 +2197,6 @@ export interface NexusGenFieldTypeNames { poolType: 'PoolType'; resourceType: 'ResourceType'; tags: 'Tag'; - version: 'Int'; }; PoolConnection: { // field return type name @@ -2281,7 +2261,6 @@ export interface NexusGenFieldTypeNames { performFromDate: 'String'; performTillDate: 'String'; status: 'ScheduleStatus'; - version: 'Int'; workflowContext: 'String'; workflowName: 'String'; workflowVersion: 'String'; @@ -2345,7 +2324,6 @@ export interface NexusGenFieldTypeNames { timeoutSeconds: 'Int'; updateTime: 'String'; updatedBy: 'String'; - version: 'Int'; }; TaskDefinitionConnection: { // field return type name @@ -2458,7 +2436,6 @@ export interface NexusGenFieldTypeNames { id: 'ID'; name: 'String'; updatedAt: 'String'; - version: 'Int'; }; ZoneEdge: { // field return type name @@ -2482,7 +2459,6 @@ export interface NexusGenFieldTypeNames { Node: { // field return type name id: 'ID'; - version: 'Int'; }; } @@ -2870,6 +2846,7 @@ export interface NexusGenAbstractTypeMembers { | 'Blueprint' | 'Country' | 'Device' + | 'EventHandler' | 'ExecutedWorkflow' | 'ExecutedWorkflowTask' | 'Label' @@ -2885,6 +2862,7 @@ export interface NexusGenTypeInterfaces { Blueprint: 'Node'; Country: 'Node'; Device: 'Node'; + EventHandler: 'Node'; ExecutedWorkflow: 'Node'; ExecutedWorkflowTask: 'Node'; GraphNode: 'BaseGraphNode'; diff --git a/src/schema/task-definitons.ts b/src/schema/task-definitons.ts index 0a12c8a2..67d5886e 100644 --- a/src/schema/task-definitons.ts +++ b/src/schema/task-definitons.ts @@ -105,7 +105,7 @@ export const TaskDefinitionsQuery = extendType({ const tasksWithId = filteredTaskDefs.map((task) => ({ ...task, - id: task.name, + id: toGraphId('TaskDefinition', task.name), })); return { ...connectionFromArray(tasksWithId, paginationArgs), diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index e92647c1..bb998fa3 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -23,6 +23,7 @@ import { convertToApiOutputParameters, getFilteredWorkflows, getSubworkflows, + getWorkflowId, makePaginationFromArgs, makeSearchQueryFromArgs, validateTasks, @@ -60,7 +61,7 @@ export const Workflow = objectType({ definition: (t) => { t.implements(Node); t.nonNull.id('id', { - resolve: (workflow) => toGraphId('Workflow', workflow.name), + resolve: (workflow) => toGraphId('Workflow', getWorkflowId(workflow.name, workflow.version ?? undefined)), }); t.nonNull.int('timeoutSeconds'); t.nonNull.string('name'); @@ -396,7 +397,7 @@ export const WorkflowInstanceQuery = queryField('workflowInstanceDetail', { return { result: { ...result, id: toGraphId('ExecutedWorkflow', uuid()) }, - meta: meta ? { ...meta, id: toGraphId('Workflow', meta.name) } : null, + meta: meta ? { ...meta, id: toGraphId('Workflow', getWorkflowId(meta.name, meta.version ?? undefined)) } : null, subworkflows, }; }, @@ -531,7 +532,7 @@ export const CreateWorkflowMutation = extendType({ await conductorAPI.createWorkflow(config.conductorApiURL, apiWorkflow); return { workflow: { - id: toGraphId('Workflow', apiWorkflow.name), + id: toGraphId('Workflow', getWorkflowId(apiWorkflow.name, apiWorkflow.version ?? undefined)), ...apiWorkflow, }, }; @@ -592,7 +593,7 @@ export const UpdateWorkflowMutation = extendType({ return { workflow: { - id: toGraphId('Workflow', apiWorkflow.name), + id: toGraphId('Workflow', getWorkflowId(apiWorkflow.name, apiWorkflow.version ?? undefined)), ...apiWorkflow, }, }; @@ -633,7 +634,7 @@ export const DeleteWorkflowMutation = extendType({ return { workflow: { ...workflowToDelete, - id: toGraphId('Workflow', workflowToDelete.name), + id: toGraphId('Workflow', getWorkflowId(workflowToDelete.name, workflowToDelete.version ?? undefined)), }, }; }, From 101cd0b85fc3f21025f9870a5867e7ee400205e7 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Tue, 18 Jul 2023 18:25:55 +0200 Subject: [PATCH 37/69] add poll data query (#317) * add poll data query * format changed files and add ID to poll data query * generate schema typings * refactor input parms for filtering poll data and add handlers for filters * formatter fixes --- src/__generated__/resource-manager.graphql.ts | 112 +++++++++--------- src/__generated__/scheduler.graphql.ts | 104 ++++------------ src/external-api/conductor-network-types.ts | 14 +++ src/external-api/conductor.ts | 9 ++ src/helpers/id-helper.ts | 4 +- src/helpers/task.helpers.ts | 69 +++++++++++ src/helpers/utils.helpers.ts | 8 ++ src/schema/api.graphql | 28 +++++ src/schema/event-handler.ts | 2 +- src/schema/nexus-typegen.ts | 75 ++++++++++++ src/schema/task-definitons.ts | 65 +++++++++- 11 files changed, 347 insertions(+), 143 deletions(-) create mode 100644 src/helpers/task.helpers.ts diff --git a/src/__generated__/resource-manager.graphql.ts b/src/__generated__/resource-manager.graphql.ts index 021d65fd..1f793f5c 100644 --- a/src/__generated__/resource-manager.graphql.ts +++ b/src/__generated__/resource-manager.graphql.ts @@ -25,7 +25,9 @@ export type AllocationStrategy = Node & { }; /** Supported languages for allocation strategy scripts */ -export type AllocationStrategyLang = 'js' | 'py'; +export type AllocationStrategyLang = + | 'js' + | 'py'; /** Input parameters for creating an allocation pool */ export type CreateAllocatingPoolInput = { @@ -239,12 +241,14 @@ export type Mutation = { UpdateTag: UpdateTagPayload; }; + export type MutationClaimResourceArgs = { description?: InputMaybe; poolId: Scalars['ID']; userInput: Scalars['Map']; }; + export type MutationClaimResourceWithAltIdArgs = { alternativeId: Scalars['Map']; description?: InputMaybe; @@ -252,67 +256,83 @@ export type MutationClaimResourceWithAltIdArgs = { userInput: Scalars['Map']; }; + export type MutationCreateAllocatingPoolArgs = { input?: InputMaybe; }; + export type MutationCreateAllocationStrategyArgs = { input?: InputMaybe; }; + export type MutationCreateNestedAllocatingPoolArgs = { input: CreateNestedAllocatingPoolInput; }; + export type MutationCreateNestedSetPoolArgs = { input: CreateNestedSetPoolInput; }; + export type MutationCreateNestedSingletonPoolArgs = { input: CreateNestedSingletonPoolInput; }; + export type MutationCreateResourceTypeArgs = { input: CreateResourceTypeInput; }; + export type MutationCreateSetPoolArgs = { input: CreateSetPoolInput; }; + export type MutationCreateSingletonPoolArgs = { input?: InputMaybe; }; + export type MutationCreateTagArgs = { input: CreateTagInput; }; + export type MutationDeleteAllocationStrategyArgs = { input?: InputMaybe; }; + export type MutationDeleteResourcePoolArgs = { input: DeleteResourcePoolInput; }; + export type MutationDeleteResourceTypeArgs = { input: DeleteResourceTypeInput; }; + export type MutationDeleteTagArgs = { input: DeleteTagInput; }; + export type MutationFreeResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; + export type MutationTagPoolArgs = { input: TagPoolInput; }; + export type MutationTestAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; currentResources: Array; @@ -320,20 +340,24 @@ export type MutationTestAllocationStrategyArgs = { userInput: Scalars['Map']; }; + export type MutationUntagPoolArgs = { input: UntagPoolInput; }; + export type MutationUpdateResourceAltIdArgs = { alternativeId: Scalars['Map']; input: Scalars['Map']; poolId: Scalars['ID']; }; + export type MutationUpdateResourceTypeNameArgs = { input: UpdateResourceTypeNameInput; }; + export type MutationUpdateTagArgs = { input: UpdateTagInput; }; @@ -367,7 +391,10 @@ export type PoolCapacityPayload = { }; /** Defines the type of pool */ -export type PoolType = 'allocating' | 'set' | 'singleton'; +export type PoolType = + | 'allocating' + | 'set' + | 'singleton'; /** Defines the type of the property */ export type PropertyType = Node & { @@ -404,14 +431,17 @@ export type Query = { node: Maybe; }; + export type QueryQueryAllocationStrategiesArgs = { byName?: InputMaybe; }; + export type QueryQueryAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; }; + export type QueryQueryEmptyResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -420,6 +450,7 @@ export type QueryQueryEmptyResourcePoolsArgs = { resourceTypeId?: InputMaybe; }; + export type QueryQueryLeafResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -430,10 +461,12 @@ export type QueryQueryLeafResourcePoolsArgs = { tags?: InputMaybe; }; + export type QueryQueryPoolCapacityArgs = { poolId: Scalars['ID']; }; + export type QueryQueryRecentlyActiveResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -443,23 +476,28 @@ export type QueryQueryRecentlyActiveResourcesArgs = { toDatetime?: InputMaybe; }; + export type QueryQueryRequiredPoolPropertiesArgs = { allocationStrategyName: Scalars['String']; }; + export type QueryQueryResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; + export type QueryQueryResourcePoolArgs = { poolId: Scalars['ID']; }; + export type QueryQueryResourcePoolHierarchyPathArgs = { poolId: Scalars['ID']; }; + export type QueryQueryResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -470,10 +508,12 @@ export type QueryQueryResourcePoolsArgs = { tags?: InputMaybe; }; + export type QueryQueryResourceTypesArgs = { byName?: InputMaybe; }; + export type QueryQueryResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -482,6 +522,7 @@ export type QueryQueryResourcesArgs = { poolId: Scalars['ID']; }; + export type QueryQueryResourcesByAltIdArgs = { after?: InputMaybe; before?: InputMaybe; @@ -491,6 +532,7 @@ export type QueryQueryResourcesByAltIdArgs = { poolId?: InputMaybe; }; + export type QueryQueryRootResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -501,6 +543,7 @@ export type QueryQueryRootResourcePoolsArgs = { tags?: InputMaybe; }; + export type QuerySearchPoolsByTagsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -509,6 +552,7 @@ export type QuerySearchPoolsByTagsArgs = { tags?: InputMaybe; }; + export type QueryNodeArgs = { id: Scalars['ID']; }; @@ -562,6 +606,7 @@ export type ResourcePool = Node & { id: Scalars['ID']; }; + /** A pool is an entity that contains allocated and free resources */ export type ResourcePoolAllocatedResourcesArgs = { after?: InputMaybe; @@ -665,39 +710,14 @@ export type UpdateTagPayload = { tag: Maybe; }; -export type PoolFragmentFragment = { - __typename: 'ResourcePool'; - id: string; - Name: string; - PoolType: PoolType; - PoolProperties: any; - Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; - ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; -}; +export type PoolFragmentFragment = { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }; export type GetPoolQueryVariables = Exact<{ nodeId: Scalars['ID']; }>; -export type GetPoolQuery = { - __typename?: 'Query'; - node: - | { __typename?: 'AllocationStrategy' } - | { __typename?: 'PropertyType' } - | { __typename?: 'Resource' } - | { - __typename: 'ResourcePool'; - id: string; - Name: string; - PoolType: PoolType; - PoolProperties: any; - Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; - ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; - } - | { __typename?: 'ResourceType' } - | { __typename?: 'Tag' } - | null; -}; + +export type GetPoolQuery = { __typename?: 'Query', node: { __typename?: 'AllocationStrategy' } | { __typename?: 'PropertyType' } | { __typename?: 'Resource' } | { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } } | { __typename?: 'ResourceType' } | { __typename?: 'Tag' } | null }; export type GetPoolsQueryVariables = Exact<{ resourceTypeId?: InputMaybe; @@ -708,37 +728,13 @@ export type GetPoolsQueryVariables = Exact<{ filterByResources?: InputMaybe; }>; -export type GetPoolsQuery = { - __typename?: 'Query'; - QueryRootResourcePools: { - __typename?: 'ResourcePoolConnection'; - totalCount: number; - edges: Array<{ - __typename?: 'ResourcePoolEdge'; - node: { - __typename: 'ResourcePool'; - id: string; - Name: string; - PoolType: PoolType; - PoolProperties: any; - Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; - ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; - }; - cursor: { __typename?: 'OutputCursor'; ID: string }; - } | null>; - pageInfo: { - __typename?: 'PageInfo'; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: { __typename?: 'OutputCursor'; ID: string } | null; - endCursor: { __typename?: 'OutputCursor'; ID: string } | null; - }; - }; -}; + +export type GetPoolsQuery = { __typename?: 'Query', QueryRootResourcePools: { __typename?: 'ResourcePoolConnection', totalCount: number, edges: Array<{ __typename?: 'ResourcePoolEdge', node: { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }, cursor: { __typename?: 'OutputCursor', ID: string } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: { __typename?: 'OutputCursor', ID: string } | null, endCursor: { __typename?: 'OutputCursor', ID: string } | null } } }; export type FreeResourceMutationVariables = Exact<{ poolId: Scalars['ID']; input: Scalars['Map']; }>; -export type FreeResourceMutation = { __typename?: 'Mutation'; FreeResource: string }; + +export type FreeResourceMutation = { __typename?: 'Mutation', FreeResource: string }; diff --git a/src/__generated__/scheduler.graphql.ts b/src/__generated__/scheduler.graphql.ts index db014ee9..af39c7c6 100644 --- a/src/__generated__/scheduler.graphql.ts +++ b/src/__generated__/scheduler.graphql.ts @@ -33,14 +33,17 @@ export type Mutation = { updateSchedule: Schedule; }; + export type MutationCreateScheduleArgs = { input: CreateScheduleInput; }; + export type MutationDeleteScheduleArgs = { name: Scalars['String']; }; + export type MutationUpdateScheduleArgs = { input: UpdateScheduleInput; name: Scalars['String']; @@ -60,10 +63,12 @@ export type Query = { schedules: Maybe; }; + export type QueryScheduleArgs = { name: Scalars['String']; }; + export type QuerySchedulesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -104,7 +109,14 @@ export type SchedulesFilterInput = { workflowVersion: Scalars['String']; }; -export type Status = 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; +export type Status = + | 'COMPLETED' + | 'FAILED' + | 'PAUSED' + | 'RUNNING' + | 'TERMINATED' + | 'TIMED_OUT' + | 'UNKNOWN'; export type UpdateScheduleInput = { cronString?: InputMaybe; @@ -121,71 +133,30 @@ export type DeleteScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; }>; -export type DeleteScheduleMutation = { __typename?: 'Mutation'; deleteSchedule: boolean }; + +export type DeleteScheduleMutation = { __typename?: 'Mutation', deleteSchedule: boolean }; export type UpdateScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; input: UpdateScheduleInput; }>; -export type UpdateScheduleMutation = { - __typename?: 'Mutation'; - updateSchedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; -}; + +export type UpdateScheduleMutation = { __typename?: 'Mutation', updateSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; export type CreateScheduleMutationVariables = Exact<{ input: CreateScheduleInput; }>; -export type CreateScheduleMutation = { - __typename?: 'Mutation'; - createSchedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; -}; + +export type CreateScheduleMutation = { __typename?: 'Mutation', createSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; export type GetScheduleQueryVariables = Exact<{ scheduleName: Scalars['String']; }>; -export type GetScheduleQuery = { - __typename?: 'Query'; - schedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - } | null; -}; + +export type GetScheduleQuery = { __typename?: 'Query', schedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } | null }; export type GetSchedulesQueryVariables = Exact<{ first?: InputMaybe; @@ -195,34 +166,5 @@ export type GetSchedulesQueryVariables = Exact<{ filter?: InputMaybe; }>; -export type GetSchedulesQuery = { - __typename?: 'Query'; - schedules: { - __typename?: 'ScheduleConnection'; - totalCount: number; - edges: Array<{ - __typename?: 'ScheduleEdge'; - cursor: string; - node: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; - } | null>; - pageInfo: { - __typename?: 'PageInfo'; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; - endCursor: string | null; - }; - } | null; -}; + +export type GetSchedulesQuery = { __typename?: 'Query', schedules: { __typename?: 'ScheduleConnection', totalCount: number, edges: Array<{ __typename?: 'ScheduleEdge', cursor: string, node: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null } } | null }; diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index ad2433f7..22884afc 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -248,6 +248,14 @@ const TaskDefinition = t.type({ }); const TaskDefinitionsValidator = t.array(TaskDefinition); +const PollData = t.type({ + queueName: optional(t.string), + domain: optional(t.string), + workerId: optional(t.string), + lastPollTime: optional(t.number), +}); +const PollDataArray = t.array(PollData); + const ActionStartWorkflow = t.type({ name: optional(t.string), version: optional(t.number), @@ -296,6 +304,8 @@ export type ApiWorkflow = t.TypeOf; export type ApiExecutedWorkflow = t.TypeOf; export type ApiExecutedWorkflowTask = t.TypeOf; export type ApiTaskDefinition = t.TypeOf; +export type ApiPollData = t.TypeOf; +export type ApiPollDataArray = t.TypeOf; export type ApiEventHandlersOutput = t.TypeOf; export type ApiEventHandler = t.TypeOf; @@ -353,6 +363,10 @@ export function decodeExecutedWorkflowTaskDetailOutput(value: unknown): ApiExecu return extractResult(ExecutedWorkflowTask.decode(value)); } +export function decodePollDataOutput(value: unknown): ApiPollDataArray { + return extractResult(PollDataArray.decode(value)); +} + export function decodeEventHandlersOutput(value: unknown): ApiEventHandlersOutput { return extractResult(EventHandlersValidator.decode(value)); } diff --git a/src/external-api/conductor.ts b/src/external-api/conductor.ts index 922a7be1..006f15a0 100644 --- a/src/external-api/conductor.ts +++ b/src/external-api/conductor.ts @@ -17,6 +17,8 @@ import { decodeBulkTerminateOutput, decodeExecutedWorkflowTaskDetailOutput, ApiExecutedWorkflowTask, + decodePollDataOutput, + ApiPollDataArray, ApiEventHandlersOutput, decodeEventHandlersOutput, ApiEventHandler, @@ -229,6 +231,12 @@ async function getExecutedWorkflowTaskDetail(baseURL: string, taskId: string): P return data; } +async function getPollData(baseURL: string): Promise { + const json = await sendGetRequest([baseURL, '/tasks/queue/polldata/all']); + const data = decodePollDataOutput(json); + return data; +} + async function getEventHandlers(baseURL: string): Promise { const json = await sendGetRequest([baseURL, '/event']); const data = decodeEventHandlersOutput(json); @@ -295,6 +303,7 @@ const conductorAPI = { deleteTaskDefinition, createTaskDefinition, getExecutedWorkflowTaskDetail, + getPollData, getEventHandlers, updateEventHandler, deleteEventHandler, diff --git a/src/helpers/id-helper.ts b/src/helpers/id-helper.ts index bcf31d06..2e4bfb87 100644 --- a/src/helpers/id-helper.ts +++ b/src/helpers/id-helper.ts @@ -14,10 +14,10 @@ export type DataType = | 'GraphEdge' | 'Schedule' | 'Pool' + | 'PollData' | 'EventHandler' | 'EventHandlerAction' - | 'TaskDefinition' - | 'Pool'; + | 'TaskDefinition'; function isDataType(value: string): value is DataType { return ( diff --git a/src/helpers/task.helpers.ts b/src/helpers/task.helpers.ts new file mode 100644 index 00000000..2daa1ec3 --- /dev/null +++ b/src/helpers/task.helpers.ts @@ -0,0 +1,69 @@ +import { v4 as uuid } from 'uuid'; +import { isAfterDate, isBeforeDate } from './utils.helpers'; +import { ApiPollDataArray } from '../external-api/conductor-network-types'; +import { toGraphId } from './id-helper'; + +type FilterPollDataArgs = { + queueName?: string | null; + workerId?: string | null; + domain?: string | null; + afterDate?: string | null; + beforeDate?: string | null; +}; +export function filterPollData(pollData: ApiPollDataArray, filters?: FilterPollDataArgs | null): ApiPollDataArray { + if (filters == null) return pollData; + + const { queueName, workerId, domain, beforeDate, afterDate } = filters; + const beforeDateFormat = beforeDate != null ? new Date(beforeDate) : null; + const afterDateFormat = afterDate != null ? new Date(afterDate) : null; + + if (afterDateFormat != null && beforeDateFormat != null && afterDateFormat.getTime() >= beforeDateFormat.getTime()) + throw new Error('afterDate must be smaller than beforeDate'); + + return pollData.filter((polldata) => { + if ( + queueName != null && + polldata.queueName != null && + queueName.length !== 0 && + !polldata.queueName.toLowerCase().includes(queueName.toLowerCase()) + ) + return false; + + if (workerId != null && workerId.length !== 0 && polldata.workerId != null && polldata.workerId !== workerId) + return false; + + if ( + domain != null && + polldata.domain != null && + domain.length !== 0 && + !polldata.domain.toLowerCase().includes(domain.toLowerCase()) + ) + return false; + + if ( + beforeDateFormat != null && + polldata.lastPollTime != null && + !isBeforeDate(new Date(polldata.lastPollTime), beforeDateFormat) + ) + return false; + + if ( + afterDateFormat != null && + polldata.lastPollTime != null && + !isAfterDate(new Date(polldata.lastPollTime), afterDateFormat) + ) + return false; + + return true; + }); +} + +export function makeFromApiToGraphQLPollData(pollData: ApiPollDataArray) { + return pollData.map((polldata) => ({ + id: toGraphId('PollData', uuid()), + ...(polldata.lastPollTime != null && { lastPollTime: new Date(polldata.lastPollTime).toISOString() }), + ...(polldata.queueName != null && { queueName: polldata.queueName }), + ...(polldata.workerId != null && { workerId: polldata.workerId }), + ...(polldata.domain != null && { domain: polldata.domain }), + })); +} diff --git a/src/helpers/utils.helpers.ts b/src/helpers/utils.helpers.ts index 9d5d2e3a..9269ba5c 100644 --- a/src/helpers/utils.helpers.ts +++ b/src/helpers/utils.helpers.ts @@ -36,3 +36,11 @@ export function parseJson(json?: string | null, throwError = true): T { } } } + +export function isBeforeDate(date: Date, other: Date): boolean { + return date.getTime() < other.getTime(); +} + +export function isAfterDate(date: Date, other: Date): boolean { + return date.getTime() > other.getTime(); +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 33a031ac..88750db6 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -580,6 +580,14 @@ input FilterEventHandlerInput { isActive: Boolean } +input FilterPollDataInput { + afterDate: String + beforeDate: String + domain: String + queueName: String + workerId: String +} + input FilterPoolsInput { poolName: String } @@ -801,6 +809,25 @@ input PaginationArgs { start: Int! } +type PollData { + domain: String + id: ID! + lastPollTime: String + queueName: String + workerId: String +} + +type PollDataConnection { + edges: [PollDataEdge] + pageInfo: PageInfo + totalCount: Int +} + +type PollDataEdge { + cursor: String + node: PollData +} + type Pool implements Node { id: ID! name: String! @@ -860,6 +887,7 @@ type Query { locations(after: String, before: String, first: Int, last: Int): LocationConnection! netTopology: NetTopology node(id: ID!, version: Int): Node + pollData(after: String, before: String, filter: FilterPollDataInput, first: Int, last: Int): PollDataConnection pools( after: String before: String diff --git a/src/schema/event-handler.ts b/src/schema/event-handler.ts index aa7fbff1..53fafb2c 100644 --- a/src/schema/event-handler.ts +++ b/src/schema/event-handler.ts @@ -9,12 +9,12 @@ import { queryField, stringArg, } from 'nexus'; -import { connectionFromArray } from 'graphql-relay'; import { v4 as uuid } from 'uuid'; import { IsOkResponse, Node, PaginationConnectionArgs } from './global-types'; import config from '../config'; import { makeFromApiToGraphQLEventHandler, makeFromGraphQLToApiEventHandler } from '../helpers/event-handler.helpers'; import { fromGraphId, toGraphId } from '../helpers/id-helper'; +import { connectionFromArray } from '../helpers/connection.helpers'; export const EventHandlerActionEnum = enumType({ name: 'EventHandlerActionEnum', diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 2ff80c88..3d53ad0c 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -256,6 +256,14 @@ export interface NexusGenInputs { event?: string | null; // String isActive?: boolean | null; // Boolean }; + FilterPollDataInput: { + // input type + afterDate?: string | null; // String + beforeDate?: string | null; // String + domain?: string | null; // String + queueName?: string | null; // String + workerId?: string | null; // String + }; FilterPoolsInput: { // input type poolName?: string | null; // String @@ -791,6 +799,25 @@ export interface NexusGenObjects { hasPreviousPage: boolean; // Boolean! startCursor?: string | null; // String }; + PollData: { + // root type + domain?: string | null; // String + id: string; // ID! + lastPollTime?: string | null; // String + queueName?: string | null; // String + workerId?: string | null; // String + }; + PollDataConnection: { + // root type + edges?: Array | null; // [PollDataEdge] + pageInfo?: NexusGenRootTypes['PageInfo'] | null; // PageInfo + totalCount?: number | null; // Int + }; + PollDataEdge: { + // root type + cursor?: string | null; // String + node?: NexusGenRootTypes['PollData'] | null; // PollData + }; Pool: { // root type id: string; // ID! @@ -1451,6 +1478,25 @@ export interface NexusGenFieldTypes { hasPreviousPage: boolean; // Boolean! startCursor: string | null; // String }; + PollData: { + // field return type + domain: string | null; // String + id: string; // ID! + lastPollTime: string | null; // String + queueName: string | null; // String + workerId: string | null; // String + }; + PollDataConnection: { + // field return type + edges: Array | null; // [PollDataEdge] + pageInfo: NexusGenRootTypes['PageInfo'] | null; // PageInfo + totalCount: number | null; // Int + }; + PollDataEdge: { + // field return type + cursor: string | null; // String + node: NexusGenRootTypes['PollData'] | null; // PollData + }; Pool: { // field return type id: string; // ID! @@ -1485,6 +1531,7 @@ export interface NexusGenFieldTypes { locations: NexusGenRootTypes['LocationConnection']; // LocationConnection! netTopology: NexusGenRootTypes['NetTopology'] | null; // NetTopology node: NexusGenRootTypes['Node'] | null; // Node + pollData: NexusGenRootTypes['PollDataConnection'] | null; // PollDataConnection pools: NexusGenRootTypes['PoolConnection']; // PoolConnection! schedules: NexusGenRootTypes['ScheduleConnection']; // ScheduleConnection! taskDefinitions: NexusGenRootTypes['TaskDefinitionConnection']; // TaskDefinitionConnection! @@ -2190,6 +2237,25 @@ export interface NexusGenFieldTypeNames { hasPreviousPage: 'Boolean'; startCursor: 'String'; }; + PollData: { + // field return type name + domain: 'String'; + id: 'ID'; + lastPollTime: 'String'; + queueName: 'String'; + workerId: 'String'; + }; + PollDataConnection: { + // field return type name + edges: 'PollDataEdge'; + pageInfo: 'PageInfo'; + totalCount: 'Int'; + }; + PollDataEdge: { + // field return type name + cursor: 'String'; + node: 'PollData'; + }; Pool: { // field return type name id: 'ID'; @@ -2224,6 +2290,7 @@ export interface NexusGenFieldTypeNames { locations: 'LocationConnection'; netTopology: 'NetTopology'; node: 'Node'; + pollData: 'PollDataConnection'; pools: 'PoolConnection'; schedules: 'ScheduleConnection'; taskDefinitions: 'TaskDefinitionConnection'; @@ -2768,6 +2835,14 @@ export interface NexusGenArgTypes { id: string; // ID! version?: number | null; // Int }; + pollData: { + // args + after?: string | null; // String + before?: string | null; // String + filter?: NexusGenInputs['FilterPollDataInput'] | null; // FilterPollDataInput + first?: number | null; // Int + last?: number | null; // Int + }; pools: { // args after?: string | null; // String diff --git a/src/schema/task-definitons.ts b/src/schema/task-definitons.ts index 67d5886e..c756c9dc 100644 --- a/src/schema/task-definitons.ts +++ b/src/schema/task-definitons.ts @@ -1,5 +1,16 @@ -import { arg, enumType, extendType, inputObjectType, mutationField, nonNull, objectType, stringArg } from 'nexus'; +import { + arg, + enumType, + extendType, + inputObjectType, + mutationField, + nonNull, + objectType, + queryField, + stringArg, +} from 'nexus'; import config from '../config'; +import { filterPollData, makeFromApiToGraphQLPollData } from '../helpers/task.helpers'; import { toGraphId } from '../helpers/id-helper'; import { getTaskDefinitionInput, getFilteredTaskDefinitions } from '../helpers/task-definition.helpers'; import { IsOkResponse, Node, PageInfo, PaginationConnectionArgs } from './global-types'; @@ -116,6 +127,58 @@ export const TaskDefinitionsQuery = extendType({ }, }); +export const PollData = objectType({ + name: 'PollData', + definition: (t) => { + t.nonNull.id('id'); + t.string('queueName'); + t.string('workerId'); + t.string('domain'); + t.string('lastPollTime'); + }, +}); + +export const PollDataEdge = objectType({ + name: 'PollDataEdge', + definition: (t) => { + t.string('cursor'); + t.field('node', { type: PollData }); + }, +}); + +export const PollDataConnection = objectType({ + name: 'PollDataConnection', + definition: (t) => { + t.int('totalCount'); + t.list.field('edges', { type: PollDataEdge }); + t.field('pageInfo', { type: 'PageInfo' }); + }, +}); + +export const FilterPollDataInput = inputObjectType({ + name: 'FilterPollDataInput', + definition: (t) => { + t.string('queueName'); + t.string('workerId'); + t.string('domain'); + t.string('afterDate'); + t.string('beforeDate'); + }, +}); + +export const PollDataQuery = queryField('pollData', { + type: PollDataConnection, + args: { + filter: arg({ type: FilterPollDataInput }), + ...PaginationConnectionArgs, + }, + resolve: async (_, args, { conductorAPI }) => { + const { filter, ...pagination } = args; + const pollData = await conductorAPI.getPollData(config.conductorApiURL); + return connectionFromArray(makeFromApiToGraphQLPollData(filterPollData(pollData, filter)), pagination); + }, +}); + export const DeleteTaskDefinitionMutation = mutationField('deleteTask', { type: IsOkResponse, args: { From 00df639c0b8bf0286b87443e82c48df6a5adba86 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Mon, 24 Jul 2023 12:47:03 +0200 Subject: [PATCH 38/69] shortest path endpoint implementation (#324) * shortest path endpoint implementation * formatter fix --- .env.example | 1 + .prettierignore | 3 +- codegen-topology-discovery.yml | 15 ++ package.json | 1 + .../topology-discovery.graphql.ts | 255 ++++++++++++++++++ src/config.ts | 11 +- src/context.ts | 3 + .../topology-discovery-graphql.ts | 40 +++ src/helpers/task.helpers.ts | 2 +- src/schema/api.graphql | 6 + src/schema/nexus-typegen.ts | 22 ++ src/schema/topology.ts | 40 ++- 12 files changed, 392 insertions(+), 7 deletions(-) create mode 100644 codegen-topology-discovery.yml create mode 100644 src/__generated__/topology-discovery.graphql.ts create mode 100644 src/external-api/topology-discovery-graphql.ts diff --git a/.env.example b/.env.example index 8461c225..74df2e81 100644 --- a/.env.example +++ b/.env.example @@ -15,3 +15,4 @@ TOPOLOGY_ENABLED=true # if TOPOLOGY_ENABLED=false they are ignored # either define all of them or do not define them at all TOPOLOGY_DISCOVERY_API_URL=http://10.19.0.5:8080/api/topology/data +TOPOLOGY_DISCOVERY_GRAPHQL_API_URL=http://localhost:5000/api/graphql diff --git a/.prettierignore b/.prettierignore index 227b71fe..895a518d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,2 +1,3 @@ build -coverage \ No newline at end of file +coverage +src/__generated__ \ No newline at end of file diff --git a/codegen-topology-discovery.yml b/codegen-topology-discovery.yml new file mode 100644 index 00000000..00ce2761 --- /dev/null +++ b/codegen-topology-discovery.yml @@ -0,0 +1,15 @@ +schema: + - 'http://localhost:5000/api/graphql' +documents: + - './src/external-api/topology-discovery-graphql.ts' +generates: + src/__generated__/topology-discovery.graphql.ts: + plugins: + - 'typescript' + - 'typescript-operations' + config: + enumsAsTypes: true + avoidOptionals: + field: true + object: false + inputValue: false diff --git a/package.json b/package.json index 0857c205..0ad51c9b 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "test": "run-s test:generate jest", "codegen:scheduler": "graphql-codegen --config codegen-scheduler.yml", "codegen:resource-manager": "graphql-codegen --config codegen-resource-manager.yml", + "codegen:topology-discovery": "graphql-codegen --config codegen-topology-discovery.yml", "codegen": "yarn codegen:scheduler && yarn codegen:resource-manager" }, "devDependencies": { diff --git a/src/__generated__/topology-discovery.graphql.ts b/src/__generated__/topology-discovery.graphql.ts new file mode 100644 index 00000000..78eb839c --- /dev/null +++ b/src/__generated__/topology-discovery.graphql.ts @@ -0,0 +1,255 @@ +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 }; +/** All built-in and custom scalars, mapped to their actual values */ +export type Scalars = { + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; +}; + +export type AlternativePaths = { + __typename?: 'AlternativePaths'; + edges: Maybe>>>; +}; + +export type Coordinates = { + __typename?: 'Coordinates'; + x: Scalars['Float']; + y: Scalars['Float']; +}; + +export type NetDevice = Node & { + __typename?: 'NetDevice'; + id: Scalars['ID']; + netInterfaces: NetInterfaceConnection; + netNetworks: NetNetworkConnection; + ospfAreaId: Scalars['String']; + phyDevice: Maybe; + routerId: Scalars['String']; +}; + + +export type NetDeviceNetInterfacesArgs = { + cursor?: InputMaybe; + filter?: InputMaybe; + first: Scalars['Int']; +}; + + +export type NetDeviceNetNetworksArgs = { + cursor?: InputMaybe; + filter?: InputMaybe; + first: Scalars['Int']; +}; + +export type NetDeviceConnection = { + __typename?: 'NetDeviceConnection'; + edges: Maybe>>; + pageInfo: PageInfo; +}; + +export type NetDeviceEdge = { + __typename?: 'NetDeviceEdge'; + cursor: Scalars['String']; + node: Maybe; +}; + +export type NetDeviceFilter = { + ospfAreaId?: InputMaybe; + routerId?: InputMaybe; +}; + +export type NetInterface = Node & { + __typename?: 'NetInterface'; + id: Scalars['ID']; + ipAddress: Scalars['String']; + netDevice: Maybe; + netLink: Maybe; +}; + +export type NetInterfaceConnection = { + __typename?: 'NetInterfaceConnection'; + edges: Maybe>>; + pageInfo: PageInfo; +}; + +export type NetInterfaceEdge = { + __typename?: 'NetInterfaceEdge'; + cursor: Scalars['String']; + node: Maybe; +}; + +export type NetInterfaceFilter = { + ipAddress?: InputMaybe; +}; + +export type NetNetwork = Node & { + __typename?: 'NetNetwork'; + coordinates: Coordinates; + id: Scalars['ID']; + ospfRouteType: Scalars['Int']; + subnet: Scalars['String']; +}; + +export type NetNetworkConnection = { + __typename?: 'NetNetworkConnection'; + edges: Maybe>>; + pageInfo: Maybe; +}; + +export type NetNetworkEdge = { + __typename?: 'NetNetworkEdge'; + cursor: Scalars['String']; + node: Maybe; +}; + +export type NetNetworkFilter = { + ospfRouteType?: InputMaybe; + subnet?: InputMaybe; +}; + +export type NetRoutingPathConnection = { + __typename?: 'NetRoutingPathConnection'; + alternativePaths: Maybe; + shortestPath: Maybe; +}; + +export type NetRoutingPathOutputCollections = + | 'NetDevice' + | 'NetInterface'; + +export type Node = { + id: Scalars['ID']; +}; + +export type NodeStatus = + | 'ok' + | 'unknown'; + +export type PageInfo = { + __typename?: 'PageInfo'; + endCursor: Maybe; + hasNextPage: Scalars['Boolean']; +}; + +export type PhyDevice = Node & { + __typename?: 'PhyDevice'; + coordinates: Coordinates; + details: PhyDeviceDetails; + id: Scalars['ID']; + labels: Maybe>; + name: Scalars['String']; + netDevice: Maybe; + phyInterfaces: PhyInterfaceConnection; + routerId: Maybe; + status: NodeStatus; +}; + + +export type PhyDevicePhyInterfacesArgs = { + cursor?: InputMaybe; + filter?: InputMaybe; + first: Scalars['Int']; +}; + +export type PhyDeviceConnection = { + __typename?: 'PhyDeviceConnection'; + edges: Maybe>>; + pageInfo: PageInfo; +}; + +export type PhyDeviceDetails = { + __typename?: 'PhyDeviceDetails'; + device_type: Scalars['String']; + sw_version: Scalars['String']; +}; + +export type PhyDeviceEdge = { + __typename?: 'PhyDeviceEdge'; + cursor: Scalars['String']; + node: Maybe; +}; + +export type PhyDeviceFilter = { + label?: InputMaybe; + name?: InputMaybe; +}; + +export type PhyInterface = Node & { + __typename?: 'PhyInterface'; + id: Scalars['ID']; + name: Scalars['String']; + phyDevice: Maybe; + phyLink: Maybe; + status: Scalars['String']; +}; + +export type PhyInterfaceConnection = { + __typename?: 'PhyInterfaceConnection'; + edges: Maybe>>; + pageInfo: PageInfo; +}; + +export type PhyInterfaceEdge = { + __typename?: 'PhyInterfaceEdge'; + cursor: Scalars['String']; + node: Maybe; +}; + +export type PhyInterfaceFilter = { + name?: InputMaybe; + status?: InputMaybe; +}; + +export type Query = { + __typename?: 'Query'; + netDevices: NetDeviceConnection; + netRoutingPaths: Maybe; + node: Maybe; + phyDevices: PhyDeviceConnection; +}; + + +export type QueryNetDevicesArgs = { + cursor?: InputMaybe; + filter?: InputMaybe; + first: Scalars['Int']; +}; + + +export type QueryNetRoutingPathsArgs = { + deviceFrom: Scalars['ID']; + deviceTo: Scalars['ID']; + outputCollection?: InputMaybe; +}; + + +export type QueryNodeArgs = { + id: Scalars['ID']; +}; + + +export type QueryPhyDevicesArgs = { + cursor?: InputMaybe; + filter?: InputMaybe; + first: Scalars['Int']; +}; + +export type ShortestPath = { + __typename?: 'ShortestPath'; + edges: Maybe>; +}; + +export type GetShortestPathQueryVariables = Exact<{ + deviceFrom: Scalars['ID']; + deviceTo: Scalars['ID']; + collection?: InputMaybe; +}>; + + +export type GetShortestPathQuery = { __typename?: 'Query', netRoutingPaths: { __typename?: 'NetRoutingPathConnection', shortestPath: { __typename?: 'ShortestPath', edges: Array | null } | null, alternativePaths: { __typename?: 'AlternativePaths', edges: Array | null> | null } | null } | null }; diff --git a/src/config.ts b/src/config.ts index 7cefd7a5..a9d9771e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -31,7 +31,8 @@ function optionalEnvString(key: string): string | null { type TopologyConfigEnabled = { topologyEnabled: true; - topologyDiscoveryURL: string | null; + topologyDiscoveryURL: string; + topologyDiscoveryGraphqlURL: string; }; type TopologyConfigDisabled = { @@ -44,19 +45,23 @@ type TopologyConfig = TopologyConfigDisabled | TopologyConfigEnabled; function getTopologyConfig(): TopologyConfig { const topologyEnabled = stringToBoolean(envString('TOPOLOGY_ENABLED')); const topologyDiscoveryURL = optionalEnvString('TOPOLOGY_DISCOVERY_API_URL'); + const topologyDiscoveryGraphqlURL = optionalEnvString('TOPOLOGY_DISCOVERY_GRAPHQL_API_URL'); if (!topologyEnabled) { return { topologyEnabled: false, }; } - if (!topologyDiscoveryURL) { - throw new Error('Not all mandatory topology discovery url were found.'); + if (!topologyDiscoveryURL || !topologyDiscoveryGraphqlURL) { + throw new Error( + 'Not all mandatory topology discovery url (TOPOLOGY_DISCOVERY_API_URL, TOPOLOGY_DISCOVERY_GRAPHQL_API_URL) were found.', + ); } return { topologyEnabled: true, topologyDiscoveryURL, + topologyDiscoveryGraphqlURL, }; } diff --git a/src/context.ts b/src/context.ts index e2daa4ff..bc8e14d0 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,6 +1,7 @@ import { PrismaClient } from '@prisma/client'; import { ExpressContext } from 'apollo-server-express'; import topologyDiscoveryAPI, { TopologyDiscoveryAPI } from './external-api/topology-discovery'; +import getTopologyDiscoveryApi, { TopologyDiscoveryGraphQLAPI } from './external-api/topology-discovery-graphql'; import conductorAPI, { ConductorAPI } from './external-api/conductor'; import uniconfigAPI, { UniConfigAPI } from './external-api/uniconfig'; import schedulerAPI, { SchedulerAPI } from './external-api/scheduler'; @@ -12,6 +13,7 @@ export type Context = { tenantId: string; uniconfigAPI: UniConfigAPI; topologyDiscoveryAPI: TopologyDiscoveryAPI; + topologyDiscoveryGraphQLAPI?: TopologyDiscoveryGraphQLAPI; conductorAPI: ConductorAPI; schedulerAPI: SchedulerAPI; resourceManagerAPI: ResourceManagerAPI; @@ -33,6 +35,7 @@ export default function createContext(context: ExpressContext): Context { tenantId, uniconfigAPI, topologyDiscoveryAPI, + topologyDiscoveryGraphQLAPI: getTopologyDiscoveryApi(), conductorAPI, schedulerAPI, resourceManagerAPI, diff --git a/src/external-api/topology-discovery-graphql.ts b/src/external-api/topology-discovery-graphql.ts new file mode 100644 index 00000000..a17748b3 --- /dev/null +++ b/src/external-api/topology-discovery-graphql.ts @@ -0,0 +1,40 @@ +import { GraphQLClient, gql } from 'graphql-request'; +import config from '../config'; +import { GetShortestPathQuery, GetShortestPathQueryVariables } from '../__generated__/topology-discovery.graphql'; + +const GET_SHORTEST_PATH = gql` + query GetShortestPath($deviceFrom: ID!, $deviceTo: ID!, $collection: NetRoutingPathOutputCollections) { + netRoutingPaths(deviceFrom: $deviceFrom, deviceTo: $deviceTo, outputCollection: $collection) { + shortestPath { + edges + } + alternativePaths { + edges + } + } + } +`; + +function getTopologyDiscoveryApi() { + if (!config.topologyEnabled) { + return undefined; + } + + const client = new GraphQLClient(config.topologyDiscoveryGraphqlURL); + + async function getShortestPath(from: string, to: string): Promise { + const response = await client.request(GET_SHORTEST_PATH, { + deviceFrom: from, + deviceTo: to, + }); + + return response; + } + + return { + getShortestPath, + }; +} + +export type TopologyDiscoveryGraphQLAPI = ReturnType; +export default getTopologyDiscoveryApi; diff --git a/src/helpers/task.helpers.ts b/src/helpers/task.helpers.ts index 2daa1ec3..141b20a8 100644 --- a/src/helpers/task.helpers.ts +++ b/src/helpers/task.helpers.ts @@ -60,10 +60,10 @@ export function filterPollData(pollData: ApiPollDataArray, filters?: FilterPollD export function makeFromApiToGraphQLPollData(pollData: ApiPollDataArray) { return pollData.map((polldata) => ({ - id: toGraphId('PollData', uuid()), ...(polldata.lastPollTime != null && { lastPollTime: new Date(polldata.lastPollTime).toISOString() }), ...(polldata.queueName != null && { queueName: polldata.queueName }), ...(polldata.workerId != null && { workerId: polldata.workerId }), ...(polldata.domain != null && { domain: polldata.domain }), + id: toGraphId('PollData', uuid()), })); } diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 88750db6..956e0bc5 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -778,6 +778,11 @@ type NetNode { networks: [NetNetwork!]! } +type NetRoutingPaths { + alternativePaths: [[String!]!]! + shortestPath: [String!]! +} + type NetTopology { edges: [GraphEdge!]! nodes: [NetNode!]! @@ -897,6 +902,7 @@ type Query { resourceTypeId: String ): PoolConnection! schedules(after: String, before: String, filter: ScheduleFilterInput, first: Int, last: Int): ScheduleConnection! + shortestPath(from: String!, to: String!): NetRoutingPaths taskDefinitions( after: String before: String diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 3d53ad0c..c729cdcc 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -782,6 +782,11 @@ export interface NexusGenObjects { name: string; // String! networks: NexusGenRootTypes['NetNetwork'][]; // [NetNetwork!]! }; + NetRoutingPaths: { + // root type + alternativePaths: string[][]; // [[String!]!]! + shortestPath: string[]; // [String!]! + }; NetTopology: { // root type edges: NexusGenRootTypes['GraphEdge'][]; // [GraphEdge!]! @@ -1461,6 +1466,11 @@ export interface NexusGenFieldTypes { name: string; // String! networks: NexusGenRootTypes['NetNetwork'][]; // [NetNetwork!]! }; + NetRoutingPaths: { + // field return type + alternativePaths: string[][]; // [[String!]!]! + shortestPath: string[]; // [String!]! + }; NetTopology: { // field return type edges: NexusGenRootTypes['GraphEdge'][]; // [GraphEdge!]! @@ -1534,6 +1544,7 @@ export interface NexusGenFieldTypes { pollData: NexusGenRootTypes['PollDataConnection'] | null; // PollDataConnection pools: NexusGenRootTypes['PoolConnection']; // PoolConnection! schedules: NexusGenRootTypes['ScheduleConnection']; // ScheduleConnection! + shortestPath: NexusGenRootTypes['NetRoutingPaths'] | null; // NetRoutingPaths taskDefinitions: NexusGenRootTypes['TaskDefinitionConnection']; // TaskDefinitionConnection! topology: NexusGenRootTypes['Topology'] | null; // Topology topologyCommonNodes: NexusGenRootTypes['TopologyCommonNodes'] | null; // TopologyCommonNodes @@ -2220,6 +2231,11 @@ export interface NexusGenFieldTypeNames { name: 'String'; networks: 'NetNetwork'; }; + NetRoutingPaths: { + // field return type name + alternativePaths: 'String'; + shortestPath: 'String'; + }; NetTopology: { // field return type name edges: 'GraphEdge'; @@ -2293,6 +2309,7 @@ export interface NexusGenFieldTypeNames { pollData: 'PollDataConnection'; pools: 'PoolConnection'; schedules: 'ScheduleConnection'; + shortestPath: 'NetRoutingPaths'; taskDefinitions: 'TaskDefinitionConnection'; topology: 'Topology'; topologyCommonNodes: 'TopologyCommonNodes'; @@ -2860,6 +2877,11 @@ export interface NexusGenArgTypes { first?: number | null; // Int last?: number | null; // Int }; + shortestPath: { + // args + from: string; // String! + to: string; // String! + }; taskDefinitions: { // args after?: string | null; // String diff --git a/src/schema/topology.ts b/src/schema/topology.ts index 753b781d..c6b8efe6 100644 --- a/src/schema/topology.ts +++ b/src/schema/topology.ts @@ -1,6 +1,6 @@ import { extendType, inputObjectType, nonNull, list, objectType, stringArg, enumType, arg, interfaceType } from 'nexus'; import config from '../config'; -import { toGraphId } from '../helpers/id-helper'; +import { fromGraphId, toGraphId } from '../helpers/id-helper'; import { getFilterQuery, getOldTopologyConnectedEdges, @@ -401,7 +401,7 @@ export const NetTopologyQuery = extendType({ return { nodes: nodes.map((n) => ({ - id: toGraphId('GraphNode', n._key), + id: toGraphId('GraphNode', n._id), name: n.router_id, interfaces: interfaceMap[n._id] ?? [], coordinates: n.coordinates, @@ -429,3 +429,39 @@ export const NetTopologyQuery = extendType({ }); }, }); + +export const NetRoutingsPaths = objectType({ + name: 'NetRoutingPaths', + definition: (t) => { + t.nonNull.field('shortestPath', { type: nonNull(list(nonNull('String'))) }); + t.nonNull.field('alternativePaths', { type: nonNull(list(nonNull(list(nonNull('String'))))) }); + }, +}); + +export const ShortestPathQuery = extendType({ + type: 'Query', + definition: (t) => { + t.field('shortestPath', { + type: NetRoutingsPaths, + args: { + from: nonNull(stringArg()), + to: nonNull(stringArg()), + }, + resolve: async (_, args, { topologyDiscoveryGraphQLAPI }) => { + const { from, to } = args; + const fromNodeNativeId = fromGraphId('GraphNode', from); + const toNodeNativeId = fromGraphId('GraphNode', to); + + const shortestPathResult = await topologyDiscoveryGraphQLAPI?.getShortestPath(fromNodeNativeId, toNodeNativeId); + const shortestPath = shortestPathResult?.netRoutingPaths?.shortestPath?.edges ?? []; + const alternativePaths = + shortestPathResult?.netRoutingPaths?.alternativePaths?.edges?.filter(omitNullValue) ?? []; + + return { + shortestPath, + alternativePaths, + }; + }, + }); + }, +}); From d6d72e753e4133ab400c2d92e7722d330ce12d2b Mon Sep 17 00:00:00 2001 From: plehocky <117287338+plehocky@users.noreply.github.com> Date: Mon, 24 Jul 2023 13:46:32 +0200 Subject: [PATCH 39/69] Update poll data sorting (#323) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix incorrect blueprintId sent to database - change it to native db id (#314) * add poll data query * format changed files and add ID to poll data query * generate schema typings * refactor input parms for filtering poll data and add handlers for filters * formatter fixes * added sorting to PollDataQuery * formatting * linter fixes * fixed ts error * formatting * sorting refactoring * ordering refactoring --------- Co-authored-by: Pavol Porubský Co-authored-by: marco.mruz Co-authored-by: PeterL --- src/__generated__/resource-manager.graphql.ts | 112 +++++++++--------- src/__generated__/scheduler.graphql.ts | 104 ++++++++++++---- src/schema/api.graphql | 25 +++- src/schema/device.ts | 3 +- src/schema/nexus-typegen.ts | 8 ++ src/schema/task-definitons.ts | 29 ++++- 6 files changed, 200 insertions(+), 81 deletions(-) diff --git a/src/__generated__/resource-manager.graphql.ts b/src/__generated__/resource-manager.graphql.ts index 1f793f5c..021d65fd 100644 --- a/src/__generated__/resource-manager.graphql.ts +++ b/src/__generated__/resource-manager.graphql.ts @@ -25,9 +25,7 @@ export type AllocationStrategy = Node & { }; /** Supported languages for allocation strategy scripts */ -export type AllocationStrategyLang = - | 'js' - | 'py'; +export type AllocationStrategyLang = 'js' | 'py'; /** Input parameters for creating an allocation pool */ export type CreateAllocatingPoolInput = { @@ -241,14 +239,12 @@ export type Mutation = { UpdateTag: UpdateTagPayload; }; - export type MutationClaimResourceArgs = { description?: InputMaybe; poolId: Scalars['ID']; userInput: Scalars['Map']; }; - export type MutationClaimResourceWithAltIdArgs = { alternativeId: Scalars['Map']; description?: InputMaybe; @@ -256,83 +252,67 @@ export type MutationClaimResourceWithAltIdArgs = { userInput: Scalars['Map']; }; - export type MutationCreateAllocatingPoolArgs = { input?: InputMaybe; }; - export type MutationCreateAllocationStrategyArgs = { input?: InputMaybe; }; - export type MutationCreateNestedAllocatingPoolArgs = { input: CreateNestedAllocatingPoolInput; }; - export type MutationCreateNestedSetPoolArgs = { input: CreateNestedSetPoolInput; }; - export type MutationCreateNestedSingletonPoolArgs = { input: CreateNestedSingletonPoolInput; }; - export type MutationCreateResourceTypeArgs = { input: CreateResourceTypeInput; }; - export type MutationCreateSetPoolArgs = { input: CreateSetPoolInput; }; - export type MutationCreateSingletonPoolArgs = { input?: InputMaybe; }; - export type MutationCreateTagArgs = { input: CreateTagInput; }; - export type MutationDeleteAllocationStrategyArgs = { input?: InputMaybe; }; - export type MutationDeleteResourcePoolArgs = { input: DeleteResourcePoolInput; }; - export type MutationDeleteResourceTypeArgs = { input: DeleteResourceTypeInput; }; - export type MutationDeleteTagArgs = { input: DeleteTagInput; }; - export type MutationFreeResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; - export type MutationTagPoolArgs = { input: TagPoolInput; }; - export type MutationTestAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; currentResources: Array; @@ -340,24 +320,20 @@ export type MutationTestAllocationStrategyArgs = { userInput: Scalars['Map']; }; - export type MutationUntagPoolArgs = { input: UntagPoolInput; }; - export type MutationUpdateResourceAltIdArgs = { alternativeId: Scalars['Map']; input: Scalars['Map']; poolId: Scalars['ID']; }; - export type MutationUpdateResourceTypeNameArgs = { input: UpdateResourceTypeNameInput; }; - export type MutationUpdateTagArgs = { input: UpdateTagInput; }; @@ -391,10 +367,7 @@ export type PoolCapacityPayload = { }; /** Defines the type of pool */ -export type PoolType = - | 'allocating' - | 'set' - | 'singleton'; +export type PoolType = 'allocating' | 'set' | 'singleton'; /** Defines the type of the property */ export type PropertyType = Node & { @@ -431,17 +404,14 @@ export type Query = { node: Maybe; }; - export type QueryQueryAllocationStrategiesArgs = { byName?: InputMaybe; }; - export type QueryQueryAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; }; - export type QueryQueryEmptyResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -450,7 +420,6 @@ export type QueryQueryEmptyResourcePoolsArgs = { resourceTypeId?: InputMaybe; }; - export type QueryQueryLeafResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -461,12 +430,10 @@ export type QueryQueryLeafResourcePoolsArgs = { tags?: InputMaybe; }; - export type QueryQueryPoolCapacityArgs = { poolId: Scalars['ID']; }; - export type QueryQueryRecentlyActiveResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -476,28 +443,23 @@ export type QueryQueryRecentlyActiveResourcesArgs = { toDatetime?: InputMaybe; }; - export type QueryQueryRequiredPoolPropertiesArgs = { allocationStrategyName: Scalars['String']; }; - export type QueryQueryResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; - export type QueryQueryResourcePoolArgs = { poolId: Scalars['ID']; }; - export type QueryQueryResourcePoolHierarchyPathArgs = { poolId: Scalars['ID']; }; - export type QueryQueryResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -508,12 +470,10 @@ export type QueryQueryResourcePoolsArgs = { tags?: InputMaybe; }; - export type QueryQueryResourceTypesArgs = { byName?: InputMaybe; }; - export type QueryQueryResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -522,7 +482,6 @@ export type QueryQueryResourcesArgs = { poolId: Scalars['ID']; }; - export type QueryQueryResourcesByAltIdArgs = { after?: InputMaybe; before?: InputMaybe; @@ -532,7 +491,6 @@ export type QueryQueryResourcesByAltIdArgs = { poolId?: InputMaybe; }; - export type QueryQueryRootResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -543,7 +501,6 @@ export type QueryQueryRootResourcePoolsArgs = { tags?: InputMaybe; }; - export type QuerySearchPoolsByTagsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -552,7 +509,6 @@ export type QuerySearchPoolsByTagsArgs = { tags?: InputMaybe; }; - export type QueryNodeArgs = { id: Scalars['ID']; }; @@ -606,7 +562,6 @@ export type ResourcePool = Node & { id: Scalars['ID']; }; - /** A pool is an entity that contains allocated and free resources */ export type ResourcePoolAllocatedResourcesArgs = { after?: InputMaybe; @@ -710,14 +665,39 @@ export type UpdateTagPayload = { tag: Maybe; }; -export type PoolFragmentFragment = { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }; +export type PoolFragmentFragment = { + __typename: 'ResourcePool'; + id: string; + Name: string; + PoolType: PoolType; + PoolProperties: any; + Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; + ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; +}; export type GetPoolQueryVariables = Exact<{ nodeId: Scalars['ID']; }>; - -export type GetPoolQuery = { __typename?: 'Query', node: { __typename?: 'AllocationStrategy' } | { __typename?: 'PropertyType' } | { __typename?: 'Resource' } | { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } } | { __typename?: 'ResourceType' } | { __typename?: 'Tag' } | null }; +export type GetPoolQuery = { + __typename?: 'Query'; + node: + | { __typename?: 'AllocationStrategy' } + | { __typename?: 'PropertyType' } + | { __typename?: 'Resource' } + | { + __typename: 'ResourcePool'; + id: string; + Name: string; + PoolType: PoolType; + PoolProperties: any; + Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; + ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; + } + | { __typename?: 'ResourceType' } + | { __typename?: 'Tag' } + | null; +}; export type GetPoolsQueryVariables = Exact<{ resourceTypeId?: InputMaybe; @@ -728,13 +708,37 @@ export type GetPoolsQueryVariables = Exact<{ filterByResources?: InputMaybe; }>; - -export type GetPoolsQuery = { __typename?: 'Query', QueryRootResourcePools: { __typename?: 'ResourcePoolConnection', totalCount: number, edges: Array<{ __typename?: 'ResourcePoolEdge', node: { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }, cursor: { __typename?: 'OutputCursor', ID: string } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: { __typename?: 'OutputCursor', ID: string } | null, endCursor: { __typename?: 'OutputCursor', ID: string } | null } } }; +export type GetPoolsQuery = { + __typename?: 'Query'; + QueryRootResourcePools: { + __typename?: 'ResourcePoolConnection'; + totalCount: number; + edges: Array<{ + __typename?: 'ResourcePoolEdge'; + node: { + __typename: 'ResourcePool'; + id: string; + Name: string; + PoolType: PoolType; + PoolProperties: any; + Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; + ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; + }; + cursor: { __typename?: 'OutputCursor'; ID: string }; + } | null>; + pageInfo: { + __typename?: 'PageInfo'; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: { __typename?: 'OutputCursor'; ID: string } | null; + endCursor: { __typename?: 'OutputCursor'; ID: string } | null; + }; + }; +}; export type FreeResourceMutationVariables = Exact<{ poolId: Scalars['ID']; input: Scalars['Map']; }>; - -export type FreeResourceMutation = { __typename?: 'Mutation', FreeResource: string }; +export type FreeResourceMutation = { __typename?: 'Mutation'; FreeResource: string }; diff --git a/src/__generated__/scheduler.graphql.ts b/src/__generated__/scheduler.graphql.ts index af39c7c6..db014ee9 100644 --- a/src/__generated__/scheduler.graphql.ts +++ b/src/__generated__/scheduler.graphql.ts @@ -33,17 +33,14 @@ export type Mutation = { updateSchedule: Schedule; }; - export type MutationCreateScheduleArgs = { input: CreateScheduleInput; }; - export type MutationDeleteScheduleArgs = { name: Scalars['String']; }; - export type MutationUpdateScheduleArgs = { input: UpdateScheduleInput; name: Scalars['String']; @@ -63,12 +60,10 @@ export type Query = { schedules: Maybe; }; - export type QueryScheduleArgs = { name: Scalars['String']; }; - export type QuerySchedulesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -109,14 +104,7 @@ export type SchedulesFilterInput = { workflowVersion: Scalars['String']; }; -export type Status = - | 'COMPLETED' - | 'FAILED' - | 'PAUSED' - | 'RUNNING' - | 'TERMINATED' - | 'TIMED_OUT' - | 'UNKNOWN'; +export type Status = 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; export type UpdateScheduleInput = { cronString?: InputMaybe; @@ -133,30 +121,71 @@ export type DeleteScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; }>; - -export type DeleteScheduleMutation = { __typename?: 'Mutation', deleteSchedule: boolean }; +export type DeleteScheduleMutation = { __typename?: 'Mutation'; deleteSchedule: boolean }; export type UpdateScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; input: UpdateScheduleInput; }>; - -export type UpdateScheduleMutation = { __typename?: 'Mutation', updateSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; +export type UpdateScheduleMutation = { + __typename?: 'Mutation'; + updateSchedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; +}; export type CreateScheduleMutationVariables = Exact<{ input: CreateScheduleInput; }>; - -export type CreateScheduleMutation = { __typename?: 'Mutation', createSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; +export type CreateScheduleMutation = { + __typename?: 'Mutation'; + createSchedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; +}; export type GetScheduleQueryVariables = Exact<{ scheduleName: Scalars['String']; }>; - -export type GetScheduleQuery = { __typename?: 'Query', schedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } | null }; +export type GetScheduleQuery = { + __typename?: 'Query'; + schedule: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + } | null; +}; export type GetSchedulesQueryVariables = Exact<{ first?: InputMaybe; @@ -166,5 +195,34 @@ export type GetSchedulesQueryVariables = Exact<{ filter?: InputMaybe; }>; - -export type GetSchedulesQuery = { __typename?: 'Query', schedules: { __typename?: 'ScheduleConnection', totalCount: number, edges: Array<{ __typename?: 'ScheduleEdge', cursor: string, node: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null } } | null }; +export type GetSchedulesQuery = { + __typename?: 'Query'; + schedules: { + __typename?: 'ScheduleConnection'; + totalCount: number; + edges: Array<{ + __typename?: 'ScheduleEdge'; + cursor: string; + node: { + __typename?: 'Schedule'; + name: string; + enabled: boolean; + parallelRuns: boolean; + workflowName: string; + workflowVersion: string; + cronString: string; + workflowContext: string; + fromDate: any; + toDate: any; + status: Status; + }; + } | null>; + pageInfo: { + __typename?: 'PageInfo'; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; + endCursor: string | null; + }; + } | null; +}; diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 956e0bc5..04c03408 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -833,6 +833,11 @@ type PollDataEdge { node: PollData } +input PollsOrderByInput { + direction: SortPollsDirection! + sortKey: SortPollsBy! +} + type Pool implements Node { id: ID! name: String! @@ -892,7 +897,14 @@ type Query { locations(after: String, before: String, first: Int, last: Int): LocationConnection! netTopology: NetTopology node(id: ID!, version: Int): Node - pollData(after: String, before: String, filter: FilterPollDataInput, first: Int, last: Int): PollDataConnection + pollData( + after: String + before: String + filter: FilterPollDataInput + first: Int + last: Int + orderBy: PollsOrderByInput! + ): PollDataConnection pools( after: String before: String @@ -1026,6 +1038,17 @@ enum SortDirection { DESC } +enum SortPollsBy { + lastPollTime + queueName + workerId +} + +enum SortPollsDirection { + asc + desc +} + input StartWorkflowRequestInput { workflow: ExecuteNewWorkflowInput! workflowDefinition: WorkflowDefinitionInput diff --git a/src/schema/device.ts b/src/schema/device.ts index 5e577f4b..62a5d328 100644 --- a/src/schema/device.ts +++ b/src/schema/device.ts @@ -260,6 +260,7 @@ export const AddDeviceMutation = extendType({ } const labelIds = input.labelIds ? [...new Set(input.labelIds)] : null; try { + const nativeBlueprintId = input.blueprintId != null ? fromGraphId('Blueprint', input.blueprintId) : undefined; const device = await prisma.device.create({ data: { name: input.name, @@ -276,7 +277,7 @@ export const AddDeviceMutation = extendType({ mountParameters: input.mountParameters != null ? JSON.parse(input.mountParameters) : undefined, source: 'MANUAL', serviceState: input.serviceState ?? undefined, - blueprintId: input.blueprintId ?? undefined, + blueprintId: nativeBlueprintId, label: labelIds ? { createMany: { data: labelIds.map((id) => ({ labelId: fromGraphId('Label', id) })) } } : undefined, diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index c729cdcc..57c0758f 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -302,6 +302,11 @@ export interface NexusGenInputs { size: number; // Int! start: number; // Int! }; + PollsOrderByInput: { + // input type + direction: NexusGenEnums['SortPollsDirection']; // SortPollsDirection! + sortKey: NexusGenEnums['SortPollsBy']; // SortPollsBy! + }; RemoveWorkflowInput: { // input type shouldArchiveWorkflow?: boolean | null; // Boolean @@ -445,6 +450,8 @@ export interface NexusGenEnums { ScheduleStatus: 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; SortDeviceBy: 'CREATED_AT' | 'NAME'; SortDirection: 'ASC' | 'DESC'; + SortPollsBy: 'lastPollTime' | 'queueName' | 'workerId'; + SortPollsDirection: 'asc' | 'desc'; TaskTimeoutPolicy: 'ALERT_ONLY' | 'RETRY' | 'TIME_OUT_WF'; TimeoutPolicy: 'ALERT_ONLY' | 'TIME_OUT_WF'; WorkflowTaskType: @@ -2859,6 +2866,7 @@ export interface NexusGenArgTypes { filter?: NexusGenInputs['FilterPollDataInput'] | null; // FilterPollDataInput first?: number | null; // Int last?: number | null; // Int + orderBy: NexusGenInputs['PollsOrderByInput']; // PollsOrderByInput! }; pools: { // args diff --git a/src/schema/task-definitons.ts b/src/schema/task-definitons.ts index c756c9dc..57f6be06 100644 --- a/src/schema/task-definitons.ts +++ b/src/schema/task-definitons.ts @@ -9,6 +9,7 @@ import { queryField, stringArg, } from 'nexus'; +import { orderBy } from 'lodash'; import config from '../config'; import { filterPollData, makeFromApiToGraphQLPollData } from '../helpers/task.helpers'; import { toGraphId } from '../helpers/id-helper'; @@ -166,16 +167,40 @@ export const FilterPollDataInput = inputObjectType({ }, }); +export const SortPollsBy = enumType({ + name: 'SortPollsBy', + members: ['queueName', 'workerId', 'lastPollTime'], +}); + +export const SortPollsDirection = enumType({ + name: 'SortPollsDirection', + members: ['asc', 'desc'], +}); + +export const PollsOrderByInput = inputObjectType({ + name: 'PollsOrderByInput', + definition: (t) => { + t.nonNull.field('sortKey', { type: SortPollsBy }); + t.nonNull.field('direction', { type: SortPollsDirection }); + }, +}); + export const PollDataQuery = queryField('pollData', { type: PollDataConnection, args: { filter: arg({ type: FilterPollDataInput }), + orderBy: nonNull(arg({ type: PollsOrderByInput })), ...PaginationConnectionArgs, }, resolve: async (_, args, { conductorAPI }) => { - const { filter, ...pagination } = args; + const { filter, orderBy: orderingArgs, ...pagination } = args; + const pollData = await conductorAPI.getPollData(config.conductorApiURL); - return connectionFromArray(makeFromApiToGraphQLPollData(filterPollData(pollData, filter)), pagination); + const filteredData = filterPollData(pollData, filter); + + const orderedData = orderBy(filteredData, [orderingArgs.sortKey], [orderingArgs.direction]); + + return connectionFromArray(makeFromApiToGraphQLPollData(orderedData), pagination); }, }); From 83447e8a625387bcff2673c79cad49c24eb71d23 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Mon, 24 Jul 2023 14:05:22 +0200 Subject: [PATCH 40/69] add new data types for validation (#325) --- src/helpers/id-helper.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/helpers/id-helper.ts b/src/helpers/id-helper.ts index 2e4bfb87..d3b6526a 100644 --- a/src/helpers/id-helper.ts +++ b/src/helpers/id-helper.ts @@ -34,7 +34,10 @@ function isDataType(value: string): value is DataType { value === 'GraphEdge' || value === 'Schedule' || value === 'TaskDefinition' || - value === 'Pool' + value === 'Pool' || + value === 'PollData' || + value === 'EventHandler' || + value === 'EventHandlerAction' ); } From 3f9237a38fff4c9b10290c0ab740772354ebaa66 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Wed, 26 Jul 2023 14:10:16 +0200 Subject: [PATCH 41/69] add name to event handlers filter (#326) * add name to event handlers filter * format file * move filter logic to helper functions * handle also when string is of 0 length * change logic so that every handler must fulfill statements --- src/helpers/event-handler.helpers.ts | 50 ++++++++++++++++++++++++++++ src/schema/api.graphql | 1 + src/schema/event-handler.ts | 24 ++++--------- src/schema/nexus-typegen.ts | 1 + 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/src/helpers/event-handler.helpers.ts b/src/helpers/event-handler.helpers.ts index a0f5e6a9..8ad6cd55 100644 --- a/src/helpers/event-handler.helpers.ts +++ b/src/helpers/event-handler.helpers.ts @@ -173,3 +173,53 @@ export function makeFromGraphQLToApiEventHandler(eventHandler: EventHandlerGraph evaluatorType: eventHandler.evaluatorType || undefined, }; } + +export const filterByName = (name: string) => (eventHandler: ApiEventHandler) => + eventHandler.name.toLowerCase().includes(name.toLowerCase()); + +export const filterByEvaluatorType = (evaluatorType: string) => (eventHandler: ApiEventHandler) => + eventHandler.evaluatorType != null && eventHandler.evaluatorType.toLowerCase().includes(evaluatorType.toLowerCase()); + +export const filterByEvent = (event: string) => (eventHandler: ApiEventHandler) => + eventHandler.event.toLowerCase().includes(event.toLowerCase()); + +export const filterByIsActive = (isActive: boolean) => (eventHandler: ApiEventHandler) => + eventHandler.active != null && eventHandler.active === isActive; + +export function filterEventHandlers( + eventHandlers: ApiEventHandler[], + filters?: { + name?: string | null; + evaluatorType?: string | null; + event?: string | null; + isActive?: boolean | null; + } | null, +) { + if (eventHandlers == null) { + return []; + } + + return eventHandlers.filter((eventHandler) => { + if (filters == null) { + return true; + } + + if (filters.name != null && !filterByName(filters.name)(eventHandler)) { + return false; + } + + if (filters.evaluatorType != null && !filterByEvaluatorType(filters.evaluatorType)(eventHandler)) { + return false; + } + + if (filters.event != null && !filterByEvent(filters.event)(eventHandler)) { + return false; + } + + if (filters.isActive != null && !filterByIsActive(filters.isActive)(eventHandler)) { + return false; + } + + return true; + }); +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 04c03408..b9b5b0f8 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -578,6 +578,7 @@ input FilterEventHandlerInput { evaluatorType: String event: String isActive: Boolean + name: String } input FilterPollDataInput { diff --git a/src/schema/event-handler.ts b/src/schema/event-handler.ts index 53fafb2c..11254e78 100644 --- a/src/schema/event-handler.ts +++ b/src/schema/event-handler.ts @@ -12,7 +12,11 @@ import { import { v4 as uuid } from 'uuid'; import { IsOkResponse, Node, PaginationConnectionArgs } from './global-types'; import config from '../config'; -import { makeFromApiToGraphQLEventHandler, makeFromGraphQLToApiEventHandler } from '../helpers/event-handler.helpers'; +import { + filterEventHandlers, + makeFromApiToGraphQLEventHandler, + makeFromGraphQLToApiEventHandler, +} from '../helpers/event-handler.helpers'; import { fromGraphId, toGraphId } from '../helpers/id-helper'; import { connectionFromArray } from '../helpers/connection.helpers'; @@ -99,6 +103,7 @@ export const FilterEventHandlerInput = inputObjectType({ t.boolean('isActive'); t.string('event'); t.string('evaluatorType'); + t.string('name'); }, }); @@ -112,22 +117,7 @@ export const EventHandlerQuery = queryField('eventHandlers', { const { filter, ...paginationArgs } = args; const eventHandlers = await conductorAPI.getEventHandlers(config.conductorApiURL); - const filteredEventHandlers = eventHandlers.filter((eventHandler) => { - if (filter?.isActive != null && eventHandler.active !== filter.isActive) { - return false; - } - - if (filter?.event != null && eventHandler.event !== filter.event) { - return false; - } - - if (filter?.evaluatorType != null && eventHandler.evaluatorType !== filter.evaluatorType) { - return false; - } - - return true; - }); - + const filteredEventHandlers = filterEventHandlers(eventHandlers, filter); const mappedEventHandlersWithId = filteredEventHandlers.map((eventHandler) => ({ ...makeFromApiToGraphQLEventHandler(eventHandler), })); diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 57c0758f..16e12020 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -255,6 +255,7 @@ export interface NexusGenInputs { evaluatorType?: string | null; // String event?: string | null; // String isActive?: boolean | null; // Boolean + name?: string | null; // String }; FilterPollDataInput: { // input type From b6278b2590c02ce38ccb3f60aff923c895b4b9a6 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 27 Jul 2023 13:36:47 +0200 Subject: [PATCH 42/69] task definitions createdAt, updatedAt fix (#328) --- src/schema/api.graphql | 4 ++-- src/schema/nexus-typegen.ts | 8 ++++---- src/schema/task-definitons.ts | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/schema/api.graphql b/src/schema/api.graphql index b9b5b0f8..7d6f08ef 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -1077,7 +1077,7 @@ type Tag { type TaskDefinition implements Node { concurrentExecLimit: Int - createTime: String + createdAt: String createdBy: String description: String id: ID! @@ -1095,7 +1095,7 @@ type TaskDefinition implements Node { retryLogic: RetryLogic timeoutPolicy: TaskTimeoutPolicy timeoutSeconds: Int! - updateTime: String + updatedAt: String updatedBy: String } diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 16e12020..3afa40d6 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -1631,7 +1631,7 @@ export interface NexusGenFieldTypes { TaskDefinition: { // field return type concurrentExecLimit: number | null; // Int - createTime: string | null; // String + createdAt: string | null; // String createdBy: string | null; // String description: string | null; // String id: string; // ID! @@ -1649,7 +1649,7 @@ export interface NexusGenFieldTypes { retryLogic: NexusGenEnums['RetryLogic'] | null; // RetryLogic timeoutPolicy: NexusGenEnums['TaskTimeoutPolicy'] | null; // TaskTimeoutPolicy timeoutSeconds: number; // Int! - updateTime: string | null; // String + updatedAt: string | null; // String updatedBy: string | null; // String }; TaskDefinitionConnection: { @@ -2396,7 +2396,7 @@ export interface NexusGenFieldTypeNames { TaskDefinition: { // field return type name concurrentExecLimit: 'Int'; - createTime: 'String'; + createdAt: 'String'; createdBy: 'String'; description: 'String'; id: 'ID'; @@ -2414,7 +2414,7 @@ export interface NexusGenFieldTypeNames { retryLogic: 'RetryLogic'; timeoutPolicy: 'TaskTimeoutPolicy'; timeoutSeconds: 'Int'; - updateTime: 'String'; + updatedAt: 'String'; updatedBy: 'String'; }; TaskDefinitionConnection: { diff --git a/src/schema/task-definitons.ts b/src/schema/task-definitons.ts index 57f6be06..c0fb7bf6 100644 --- a/src/schema/task-definitons.ts +++ b/src/schema/task-definitons.ts @@ -36,11 +36,11 @@ export const TaskDefinition = objectType({ }); t.nonNull.string('name'); t.nonNull.int('timeoutSeconds'); - t.string('createTime', { + t.string('createdAt', { resolve: (taskDefinition) => taskDefinition.createTime ? new Date(taskDefinition.createTime).toISOString() : new Date().toISOString(), }); - t.string('updateTime', { + t.string('updatedAt', { resolve: (taskDefinition) => taskDefinition.updateTime ? new Date(taskDefinition.updateTime).toISOString() : new Date().toISOString(), }); From 446b6765eb058961ba86675775e701179716b09f Mon Sep 17 00:00:00 2001 From: plehocky <117287338+plehocky@users.noreply.github.com> Date: Wed, 2 Aug 2023 13:34:53 +0200 Subject: [PATCH 43/69] refactored executed workflows query to support sorting (#329) * refactored executed workflows query to support sorting * lint fixing --------- Co-authored-by: PeterL --- src/__generated__/scheduler.graphql.ts | 104 ++++++------------------- src/schema/api.graphql | 24 +++++- src/schema/nexus-typegen.ts | 8 ++ src/schema/workflow.ts | 23 +++++- 4 files changed, 76 insertions(+), 83 deletions(-) diff --git a/src/__generated__/scheduler.graphql.ts b/src/__generated__/scheduler.graphql.ts index db014ee9..af39c7c6 100644 --- a/src/__generated__/scheduler.graphql.ts +++ b/src/__generated__/scheduler.graphql.ts @@ -33,14 +33,17 @@ export type Mutation = { updateSchedule: Schedule; }; + export type MutationCreateScheduleArgs = { input: CreateScheduleInput; }; + export type MutationDeleteScheduleArgs = { name: Scalars['String']; }; + export type MutationUpdateScheduleArgs = { input: UpdateScheduleInput; name: Scalars['String']; @@ -60,10 +63,12 @@ export type Query = { schedules: Maybe; }; + export type QueryScheduleArgs = { name: Scalars['String']; }; + export type QuerySchedulesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -104,7 +109,14 @@ export type SchedulesFilterInput = { workflowVersion: Scalars['String']; }; -export type Status = 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; +export type Status = + | 'COMPLETED' + | 'FAILED' + | 'PAUSED' + | 'RUNNING' + | 'TERMINATED' + | 'TIMED_OUT' + | 'UNKNOWN'; export type UpdateScheduleInput = { cronString?: InputMaybe; @@ -121,71 +133,30 @@ export type DeleteScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; }>; -export type DeleteScheduleMutation = { __typename?: 'Mutation'; deleteSchedule: boolean }; + +export type DeleteScheduleMutation = { __typename?: 'Mutation', deleteSchedule: boolean }; export type UpdateScheduleMutationVariables = Exact<{ scheduleName: Scalars['String']; input: UpdateScheduleInput; }>; -export type UpdateScheduleMutation = { - __typename?: 'Mutation'; - updateSchedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; -}; + +export type UpdateScheduleMutation = { __typename?: 'Mutation', updateSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; export type CreateScheduleMutationVariables = Exact<{ input: CreateScheduleInput; }>; -export type CreateScheduleMutation = { - __typename?: 'Mutation'; - createSchedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; -}; + +export type CreateScheduleMutation = { __typename?: 'Mutation', createSchedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } }; export type GetScheduleQueryVariables = Exact<{ scheduleName: Scalars['String']; }>; -export type GetScheduleQuery = { - __typename?: 'Query'; - schedule: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - } | null; -}; + +export type GetScheduleQuery = { __typename?: 'Query', schedule: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } | null }; export type GetSchedulesQueryVariables = Exact<{ first?: InputMaybe; @@ -195,34 +166,5 @@ export type GetSchedulesQueryVariables = Exact<{ filter?: InputMaybe; }>; -export type GetSchedulesQuery = { - __typename?: 'Query'; - schedules: { - __typename?: 'ScheduleConnection'; - totalCount: number; - edges: Array<{ - __typename?: 'ScheduleEdge'; - cursor: string; - node: { - __typename?: 'Schedule'; - name: string; - enabled: boolean; - parallelRuns: boolean; - workflowName: string; - workflowVersion: string; - cronString: string; - workflowContext: string; - fromDate: any; - toDate: any; - status: Status; - }; - } | null>; - pageInfo: { - __typename?: 'PageInfo'; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; - endCursor: string | null; - }; - } | null; -}; + +export type GetSchedulesQuery = { __typename?: 'Query', schedules: { __typename?: 'ScheduleConnection', totalCount: number, edges: Array<{ __typename?: 'ScheduleEdge', cursor: string, node: { __typename?: 'Schedule', name: string, enabled: boolean, parallelRuns: boolean, workflowName: string, workflowVersion: string, cronString: string, workflowContext: string, fromDate: any, toDate: any, status: Status } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null, endCursor: string | null } } | null }; diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 7d6f08ef..6b24adda 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -569,6 +569,11 @@ enum ExecutedWorkflowTaskStatus { TIMED_OUT } +input ExecutedWorkflowsOrderByInput { + direction: SortExecutedWorkflowsDirection! + sortKey: SortExecutedWorkflowsBy! +} + input FilterDevicesInput { deviceName: String labels: [String!] @@ -893,7 +898,11 @@ type Query { first: Int last: Int ): EventHandlerConnection - executedWorkflows(pagination: PaginationArgs, searchQuery: ExecutedWorkflowSearchInput): ExecutedWorkflowConnection + executedWorkflows( + orderBy: ExecutedWorkflowsOrderByInput! + pagination: PaginationArgs + searchQuery: ExecutedWorkflowSearchInput + ): ExecutedWorkflowConnection labels(after: String, before: String, first: Int, last: Int): LabelConnection! locations(after: String, before: String, first: Int, last: Int): LocationConnection! netTopology: NetTopology @@ -1039,6 +1048,19 @@ enum SortDirection { DESC } +enum SortExecutedWorkflowsBy { + endTime + startTime + status + workflowId + workflowName +} + +enum SortExecutedWorkflowsDirection { + asc + desc +} + enum SortPollsBy { lastPollTime queueName diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 3afa40d6..0f9693c0 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -245,6 +245,11 @@ export interface NexusGenInputs { from: string; // String! to?: string | null; // String }; + ExecutedWorkflowsOrderByInput: { + // input type + direction: NexusGenEnums['SortExecutedWorkflowsDirection']; // SortExecutedWorkflowsDirection! + sortKey: NexusGenEnums['SortExecutedWorkflowsBy']; // SortExecutedWorkflowsBy! + }; FilterDevicesInput: { // input type deviceName?: string | null; // String @@ -451,6 +456,8 @@ export interface NexusGenEnums { ScheduleStatus: 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; SortDeviceBy: 'CREATED_AT' | 'NAME'; SortDirection: 'ASC' | 'DESC'; + SortExecutedWorkflowsBy: 'endTime' | 'startTime' | 'status' | 'workflowId' | 'workflowName'; + SortExecutedWorkflowsDirection: 'asc' | 'desc'; SortPollsBy: 'lastPollTime' | 'queueName' | 'workerId'; SortPollsDirection: 'asc' | 'desc'; TaskTimeoutPolicy: 'ALERT_ONLY' | 'RETRY' | 'TIME_OUT_WF'; @@ -2838,6 +2845,7 @@ export interface NexusGenArgTypes { }; executedWorkflows: { // args + orderBy: NexusGenInputs['ExecutedWorkflowsOrderByInput']; // ExecutedWorkflowsOrderByInput! pagination?: NexusGenInputs['PaginationArgs'] | null; // PaginationArgs searchQuery?: NexusGenInputs['ExecutedWorkflowSearchInput'] | null; // ExecutedWorkflowSearchInput }; diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index bb998fa3..e3e839a5 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -13,6 +13,7 @@ import { stringArg, subscriptionField, } from 'nexus'; +import { orderBy } from 'lodash'; import config from '../config'; import { WorkflowDetailInput } from '../external-api/conductor-network-types'; import { fromGraphId, toGraphId } from '../helpers/id-helper'; @@ -309,20 +310,40 @@ export const PaginationArgs = inputObjectType({ }, }); +export const SortExecutedWorkflowsBy = enumType({ + name: 'SortExecutedWorkflowsBy', + members: ['workflowId', 'workflowName', 'startTime', 'endTime', 'status'], +}); +export const SortExecutedWorkflowsDirection = enumType({ + name: 'SortExecutedWorkflowsDirection', + members: ['asc', 'desc'], +}); +export const ExecutedWorkflowsOrderByInput = inputObjectType({ + name: 'ExecutedWorkflowsOrderByInput', + definition: (t) => { + t.nonNull.field('sortKey', { type: SortExecutedWorkflowsBy }); + t.nonNull.field('direction', { type: SortExecutedWorkflowsDirection }); + }, +}); + export const ExecutedWorkflowsQuery = queryField('executedWorkflows', { type: ExecutedWorkflowConnection, args: { pagination: arg({ type: PaginationArgs }), searchQuery: arg({ type: ExecutedWorkflowSearchInput }), + orderBy: nonNull(ExecutedWorkflowsOrderByInput), }, resolve: async (_, args, { conductorAPI }) => { + const { orderBy: orderingArgs } = args; const { results: executedWorkflows } = await conductorAPI.getExecutedWorkflows( config.conductorApiURL, makeSearchQueryFromArgs(args.searchQuery), makePaginationFromArgs(args.pagination), ); - const executedWorkflowsWithId = executedWorkflows + const orderedData = orderBy(executedWorkflows, [orderingArgs.sortKey], [orderingArgs.direction]); + + const executedWorkflowsWithId = orderedData .map((w) => ({ ...w, id: toGraphId('ExecutedWorkflow', w.workflowId), From 727da25b1171ccbbac45651d57115e9488345e7c Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 3 Aug 2023 08:56:19 +0200 Subject: [PATCH 44/69] make executed workflow order input optional (#334) --- src/schema/api.graphql | 2 +- src/schema/nexus-typegen.ts | 2 +- src/schema/workflow.ts | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 6b24adda..c330a44b 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -899,7 +899,7 @@ type Query { last: Int ): EventHandlerConnection executedWorkflows( - orderBy: ExecutedWorkflowsOrderByInput! + orderBy: ExecutedWorkflowsOrderByInput pagination: PaginationArgs searchQuery: ExecutedWorkflowSearchInput ): ExecutedWorkflowConnection diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 0f9693c0..45b1723f 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -2845,7 +2845,7 @@ export interface NexusGenArgTypes { }; executedWorkflows: { // args - orderBy: NexusGenInputs['ExecutedWorkflowsOrderByInput']; // ExecutedWorkflowsOrderByInput! + orderBy?: NexusGenInputs['ExecutedWorkflowsOrderByInput'] | null; // ExecutedWorkflowsOrderByInput pagination?: NexusGenInputs['PaginationArgs'] | null; // PaginationArgs searchQuery?: NexusGenInputs['ExecutedWorkflowSearchInput'] | null; // ExecutedWorkflowSearchInput }; diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index e3e839a5..c0b86eb9 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -331,7 +331,7 @@ export const ExecutedWorkflowsQuery = queryField('executedWorkflows', { args: { pagination: arg({ type: PaginationArgs }), searchQuery: arg({ type: ExecutedWorkflowSearchInput }), - orderBy: nonNull(ExecutedWorkflowsOrderByInput), + orderBy: ExecutedWorkflowsOrderByInput, }, resolve: async (_, args, { conductorAPI }) => { const { orderBy: orderingArgs } = args; @@ -341,7 +341,9 @@ export const ExecutedWorkflowsQuery = queryField('executedWorkflows', { makePaginationFromArgs(args.pagination), ); - const orderedData = orderBy(executedWorkflows, [orderingArgs.sortKey], [orderingArgs.direction]); + const orderSortKeyArg = orderingArgs ? [orderingArgs.sortKey] : undefined; + const orderDirectionArg = orderingArgs ? [orderingArgs.direction] : undefined; + const orderedData = orderBy(executedWorkflows, orderSortKeyArg, orderDirectionArg); const executedWorkflowsWithId = orderedData .map((w) => ({ From 878c705862365a56d8f7a4f5e61f740fd90e05a4 Mon Sep 17 00:00:00 2001 From: plehocky <117287338+plehocky@users.noreply.github.com> Date: Fri, 4 Aug 2023 08:18:53 +0200 Subject: [PATCH 45/69] updated workflow list to sort by name (#332) * updated workflow list to sort by name * lint fix * use shared sort direction type --------- Co-authored-by: PeterL Co-authored-by: Martin Sottnik --- src/schema/api.graphql | 18 +++++++++++++++++- src/schema/device.ts | 6 +----- src/schema/global-types.ts | 7 ++++++- src/schema/nexus-typegen.ts | 7 +++++++ src/schema/workflow.ts | 26 +++++++++++++++++++++++--- 5 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/schema/api.graphql b/src/schema/api.graphql index c330a44b..392738cf 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -940,7 +940,14 @@ type Query { uniconfigShellSession: String workflowInstanceDetail(shouldIncludeTasks: Boolean, workflowId: String!): WorkflowInstanceDetail workflowLabels: [String!]! - workflows(after: String, before: String, filter: FilterWorkflowsInput, first: Int, last: Int): WorkflowConnection! + workflows( + after: String + before: String + filter: FilterWorkflowsInput + first: Int + last: Int + orderBy: WorkflowsOrderByInput! + ): WorkflowConnection! zones(after: String, before: String, first: Int, last: Int): ZonesConnection! } @@ -1072,6 +1079,10 @@ enum SortPollsDirection { desc } +enum SortWorkflowsBy { + name +} + input StartWorkflowRequestInput { workflow: ExecuteNewWorkflowInput! workflowDefinition: WorkflowDefinitionInput @@ -1360,6 +1371,11 @@ enum WorkflowTaskType { WAIT } +input WorkflowsOrderByInput { + direction: SortDirection! + sortKey: SortWorkflowsBy! +} + type Zone implements Node { createdAt: String! id: ID! diff --git a/src/schema/device.ts b/src/schema/device.ts index 62a5d328..525ef660 100644 --- a/src/schema/device.ts +++ b/src/schema/device.ts @@ -30,7 +30,7 @@ import { CSVParserToPromise, CSVValuesToJSON, isHeaderValid } from '../helpers/i import { getUniconfigURL } from '../helpers/zone.helpers'; import { sshClient } from '../uniconfig-shell'; import { Blueprint } from './blueprint'; -import { Node, PageInfo, PaginationConnectionArgs } from './global-types'; +import { Node, PageInfo, PaginationConnectionArgs, SortDirection } from './global-types'; import { LabelConnection } from './label'; import { Location } from './location'; import { Zone } from './zone'; @@ -177,10 +177,6 @@ export const SortDeviceBy = enumType({ name: 'SortDeviceBy', members: ['NAME', 'CREATED_AT'], }); -export const SortDirection = enumType({ - name: 'SortDirection', - members: ['ASC', 'DESC'], -}); export const DeviceOrderByInput = inputObjectType({ name: 'DeviceOrderByInput', definition: (t) => { diff --git a/src/schema/global-types.ts b/src/schema/global-types.ts index c77ea728..a63b30e2 100644 --- a/src/schema/global-types.ts +++ b/src/schema/global-types.ts @@ -1,5 +1,5 @@ import countries from 'i18n-iso-countries'; -import { extendType, idArg, intArg, interfaceType, nonNull, objectType, stringArg } from 'nexus'; +import { enumType, extendType, idArg, intArg, interfaceType, nonNull, objectType, stringArg } from 'nexus'; import config from '../config'; import conductorAPI from '../external-api/conductor'; import { fromGraphId, getType } from '../helpers/id-helper'; @@ -180,3 +180,8 @@ export const IsOkResponse = objectType({ t.nonNull.boolean('isOk'); }, }); + +export const SortDirection = enumType({ + name: 'SortDirection', + members: ['ASC', 'DESC'], +}); diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 45b1723f..43fc5f49 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -432,6 +432,11 @@ export interface NexusGenInputs { updatedAt?: string | null; // String version?: number | null; // Int }; + WorkflowsOrderByInput: { + // input type + direction: NexusGenEnums['SortDirection']; // SortDirection! + sortKey: NexusGenEnums['SortWorkflowsBy']; // SortWorkflowsBy! + }; } export interface NexusGenEnums { @@ -460,6 +465,7 @@ export interface NexusGenEnums { SortExecutedWorkflowsDirection: 'asc' | 'desc'; SortPollsBy: 'lastPollTime' | 'queueName' | 'workerId'; SortPollsDirection: 'asc' | 'desc'; + SortWorkflowsBy: 'name'; TaskTimeoutPolicy: 'ALERT_ONLY' | 'RETRY' | 'TIME_OUT_WF'; TimeoutPolicy: 'ALERT_ONLY' | 'TIME_OUT_WF'; WorkflowTaskType: @@ -2931,6 +2937,7 @@ export interface NexusGenArgTypes { filter?: NexusGenInputs['FilterWorkflowsInput'] | null; // FilterWorkflowsInput first?: number | null; // Int last?: number | null; // Int + orderBy: NexusGenInputs['WorkflowsOrderByInput']; // WorkflowsOrderByInput! }; zones: { // args diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index c0b86eb9..66e426ff 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -18,7 +18,7 @@ import config from '../config'; import { WorkflowDetailInput } from '../external-api/conductor-network-types'; import { fromGraphId, toGraphId } from '../helpers/id-helper'; import getLogger from '../get-logger'; -import { IsOkResponse, Node, PageInfo, PaginationConnectionArgs } from './global-types'; +import { IsOkResponse, Node, PageInfo, PaginationConnectionArgs, SortDirection } from './global-types'; import { TaskInput, ExecutedWorkflowTask } from './task'; import { convertToApiOutputParameters, @@ -146,6 +146,19 @@ export const FilterWorkflowsInput = inputObjectType({ }, }); +export const SortWorkflowsBy = enumType({ + name: 'SortWorkflowsBy', + members: ['name'], +}); + +export const WorkflowsOrderByInput = inputObjectType({ + name: 'WorkflowsOrderByInput', + definition: (t) => { + t.nonNull.field('sortKey', { type: SortWorkflowsBy }); + t.nonNull.field('direction', { type: SortDirection }); + }, +}); + export const WorkflowsQuery = extendType({ type: 'Query', definition: (t) => { @@ -154,15 +167,22 @@ export const WorkflowsQuery = extendType({ args: { ...PaginationConnectionArgs, filter: FilterWorkflowsInput, + orderBy: nonNull(WorkflowsOrderByInput), }, resolve: async (_, args, { conductorAPI }) => { - const { filter, ...paginationArgs } = args; + const { filter, orderBy: orderingArgs, ...paginationArgs } = args; const workflows = await conductorAPI.getWorkflowMetadata(config.conductorApiURL); const filteredWorkflows = filter?.labels || filter?.keyword ? getFilteredWorkflows(workflows, filter) : workflows; - const workflowsWithId = filteredWorkflows.map((w) => ({ + const orderedData = orderBy( + filteredWorkflows, + [orderingArgs.sortKey], + [orderingArgs.direction === 'ASC' ? 'asc' : 'desc'], + ); + + const workflowsWithId = orderedData.map((w) => ({ ...w, id: w.name, })); From 20d4958468e18255e87bc6ad9cef583edf0eb5ec Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Fri, 4 Aug 2023 14:45:03 +0200 Subject: [PATCH 46/69] shortest path (#327) * add nodeId to netRoutingPath * remove package-lock.json --- package-lock.json | 8950 ----------------------------------- src/schema/api.graphql | 1 + src/schema/nexus-typegen.ts | 3 + src/schema/topology.ts | 2 + 4 files changed, 6 insertions(+), 8950 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 6f67025d..00000000 --- a/package-lock.json +++ /dev/null @@ -1,8950 +0,0 @@ -{ - "name": "@frinx/inventory-server", - "version": "1.9.2", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@frinx/inventory-server", - "version": "1.9.2", - "license": "MIT", - "dependencies": { - "@devoxa/prisma-relay-cursor-connection": "2.2.2", - "@graphql-tools/schema": "^9.0.9", - "@prisma/client": "4.2.1", - "@types/express": "4.17.13", - "@types/graphql-upload": "15.0.2", - "@types/json-templates": "3.0.0", - "@types/lodash": "4.14.194", - "@types/node": "16.18.32", - "@types/node-fetch": "2.6.4", - "@types/pino": "7.0.4", - "@types/ssh2": "^1.11.6", - "@types/url-join": "4.0.1", - "@types/uuid": "^9.0.0", - "@types/ws": "^8.5.3", - "apollo-server-core": "3.12.0", - "apollo-server-express": "3.12.0", - "base64url": "3.0.1", - "csv-parse": "5.3.10", - "express": "4.18.1", - "fp-ts": "2.15.0", - "graphql": "16.6.0", - "graphql-relay": "0.10.0", - "graphql-upload": "15.0.2", - "graphql-ws": "^5.11.2", - "i18n-iso-countries": "7.5.0", - "io-ts": "2.2.20", - "json-templates": "4.2.0", - "lodash": "4.17.21", - "nexus": "1.3.0", - "node-fetch": "2.6.11", - "node-ssh": "^13.0.0", - "pino": "8.11.0", - "pino-pretty": "9.4.0", - "prisma": "4.2.1", - "ssh2": "^1.11.0", - "url-join": "4.0.1", - "uuid": "^9.0.0", - "ws": "^8.11.0" - }, - "devDependencies": { - "@frinx/eslint-config-typescript-base": "15.0.0-build.1", - "@types/jest": "28.1.8", - "@types/ssh2": "^1.11.6", - "@typescript-eslint/eslint-plugin": "5.54.0", - "@typescript-eslint/parser": "5.54.0", - "@vercel/ncc": "0.36.1", - "apollo-server": "3.12.0", - "cross-env": "7.0.3", - "dotenv": "16.0.3", - "eslint": "8.35.0", - "eslint-config-prettier": "7.2.0", - "eslint-import-resolver-typescript": "3.5.5", - "eslint-plugin-import": "2.27.5", - "get-port": "5.1.1", - "glob": "8.1.0", - "graphql-request": "4.3.0", - "jest": "28.1.3", - "npm-run-all": "4.1.5", - "prettier": "2.8.8", - "rimraf": "3.0.2", - "ts-jest": "28.0.8", - "ts-node": "10.9.1", - "ts-node-dev": "2.0.0", - "typescript": "4.9.5" - }, - "engines": { - "node": "18" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", - "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@apollo/protobufjs": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.2.6.tgz", - "integrity": "sha512-Wqo1oSHNUj/jxmsVp4iR3I480p6qdqHikn38lKrFhfzcDJ7lwd7Ck7cHRl4JE81tWNArl77xhnG/OkZhxKBYOw==", - "hasInstallScript": true, - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.0", - "@types/node": "^10.1.0", - "long": "^4.0.0" - }, - "bin": { - "apollo-pbjs": "bin/pbjs", - "apollo-pbts": "bin/pbts" - } - }, - "node_modules/@apollo/protobufjs/node_modules/@types/node": { - "version": "10.17.60", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", - "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" - }, - "node_modules/@apollo/utils.dropunuseddefinitions": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.dropunuseddefinitions/-/utils.dropunuseddefinitions-1.1.0.tgz", - "integrity": "sha512-jU1XjMr6ec9pPoL+BFWzEPW7VHHulVdGKMkPAMiCigpVIT11VmCbnij0bWob8uS3ODJ65tZLYKAh/55vLw2rbg==", - "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "graphql": "14.x || 15.x || 16.x" - } - }, - "node_modules/@apollo/utils.keyvaluecache": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-1.0.1.tgz", - "integrity": "sha512-nLgYLomqjVimEzQ4cdvVQkcryi970NDvcRVPfd0OPeXhBfda38WjBq+WhQFk+czSHrmrSp34YHBxpat0EtiowA==", - "dependencies": { - "@apollo/utils.logger": "^1.0.0", - "lru-cache": "^7.10.1" - } - }, - "node_modules/@apollo/utils.keyvaluecache/node_modules/lru-cache": { - "version": "7.13.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.13.2.tgz", - "integrity": "sha512-VJL3nIpA79TodY/ctmZEfhASgqekbT574/c4j3jn4bKXbSCnTTCH/KltZyvL2GlV+tGSMtsWyem8DCX7qKTMBA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/@apollo/utils.logger": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-1.0.0.tgz", - "integrity": "sha512-dx9XrjyisD2pOa+KsB5RcDbWIAdgC91gJfeyLCgy0ctJMjQe7yZK5kdWaWlaOoCeX0z6YI9iYlg7vMPyMpQF3Q==" - }, - "node_modules/@apollo/utils.printwithreducedwhitespace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.printwithreducedwhitespace/-/utils.printwithreducedwhitespace-1.1.0.tgz", - "integrity": "sha512-GfFSkAv3n1toDZ4V6u2d7L4xMwLA+lv+6hqXicMN9KELSJ9yy9RzuEXaX73c/Ry+GzRsBy/fdSUGayGqdHfT2Q==", - "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "graphql": "14.x || 15.x || 16.x" - } - }, - "node_modules/@apollo/utils.removealiases": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.removealiases/-/utils.removealiases-1.0.0.tgz", - "integrity": "sha512-6cM8sEOJW2LaGjL/0vHV0GtRaSekrPQR4DiywaApQlL9EdROASZU5PsQibe2MWeZCOhNrPRuHh4wDMwPsWTn8A==", - "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "graphql": "14.x || 15.x || 16.x" - } - }, - "node_modules/@apollo/utils.sortast": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.sortast/-/utils.sortast-1.1.0.tgz", - "integrity": "sha512-VPlTsmUnOwzPK5yGZENN069y6uUHgeiSlpEhRnLFYwYNoJHsuJq2vXVwIaSmts015WTPa2fpz1inkLYByeuRQA==", - "dependencies": { - "lodash.sortby": "^4.7.0" - }, - "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "graphql": "14.x || 15.x || 16.x" - } - }, - "node_modules/@apollo/utils.stripsensitiveliterals": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.stripsensitiveliterals/-/utils.stripsensitiveliterals-1.2.0.tgz", - "integrity": "sha512-E41rDUzkz/cdikM5147d8nfCFVKovXxKBcjvLEQ7bjZm/cg9zEcXvS6vFY8ugTubI3fn6zoqo0CyU8zT+BGP9w==", - "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "graphql": "14.x || 15.x || 16.x" - } - }, - "node_modules/@apollo/utils.usagereporting": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.usagereporting/-/utils.usagereporting-1.0.0.tgz", - "integrity": "sha512-5PL7hJMkTPmdo3oxPtigRrIyPxDk/ddrUryHPDaezL1lSFExpNzsDd2f1j0XJoHOg350GRd3LyD64caLA2PU1w==", - "dependencies": { - "@apollo/utils.dropunuseddefinitions": "^1.1.0", - "@apollo/utils.printwithreducedwhitespace": "^1.1.0", - "@apollo/utils.removealiases": "1.0.0", - "@apollo/utils.sortast": "^1.1.0", - "@apollo/utils.stripsensitiveliterals": "^1.2.0", - "apollo-reporting-protobuf": "^3.3.1" - }, - "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "graphql": "14.x || 15.x || 16.x" - } - }, - "node_modules/@apollographql/apollo-tools": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.5.3.tgz", - "integrity": "sha512-VcsXHfTFoCodDAgJZxN04GdFK1kqOhZQnQY/9Fa147P+I8xfvOSz5d+lKAPB+hwSgBNyd7ncAKGIs4+utbL+yA==", - "engines": { - "node": ">=8", - "npm": ">=6" - }, - "peerDependencies": { - "graphql": "^14.2.1 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@apollographql/graphql-playground-html": { - "version": "1.6.29", - "resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.29.tgz", - "integrity": "sha512-xCcXpoz52rI4ksJSdOCxeOCn2DLocxwHf9dVT/Q90Pte1LX+LY+91SFtJF3KXVHH8kEin+g1KKCQPKBjZJfWNA==", - "dependencies": { - "xss": "^1.0.8" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", - "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.2.tgz", - "integrity": "sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.18.2", - "@babel/helper-compilation-targets": "^7.18.2", - "@babel/helper-module-transforms": "^7.18.0", - "@babel/helpers": "^7.18.2", - "@babel/parser": "^7.18.0", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.2", - "@babel/types": "^7.18.2", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", - "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.2", - "@jridgewell/gen-mapping": "^0.3.0", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", - "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.20.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", - "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", - "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", - "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.0", - "@babel/types": "^7.18.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", - "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", - "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.18.2", - "@babel/types": "^7.18.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.18.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz", - "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.0.tgz", - "integrity": "sha512-Xv6mEXqVdaqCBfJFyeab0fH2DnUoMsDmhamxsSi4j8nLd4Vtw213WMJr55xxqipC/YVWyPY3K0blJncPYji+dQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.2.tgz", - "integrity": "sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.18.2", - "@babel/helper-environment-visitor": "^7.18.2", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.18.0", - "@babel/types": "^7.18.2", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.18.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", - "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@devoxa/prisma-relay-cursor-connection": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@devoxa/prisma-relay-cursor-connection/-/prisma-relay-cursor-connection-2.2.2.tgz", - "integrity": "sha512-nR8/f8DQXNG6a1C3wNRs2YZa6eDCuygz/fzwt6a/ARMsr0asnMK95NhFkZ2jN+ksKHA/AtfvVZvG7UVtJOB09Q==", - "dependencies": { - "graphql-fields": "^2.0.3" - }, - "peerDependencies": { - "@prisma/client": "^2.0.0 || ^3.0.0 || ^4.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", - "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", - "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@frinx/eslint-config-typescript-base": { - "version": "15.0.0-build.1", - "resolved": "https://registry.npmjs.org/@frinx/eslint-config-typescript-base/-/eslint-config-typescript-base-15.0.0-build.1.tgz", - "integrity": "sha512-U3a1xvYxxk5CORATx+7J+2kwBefW3tLihBUKikGGXSh89PDjjAiSGrNkLz87/lk1s9Sh69iFaB3ozbIISS7N1A==", - "dev": true, - "dependencies": { - "eslint-config-airbnb-base": "^15.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.14.0", - "@typescript-eslint/parser": "^5.14.0", - "eslint": "^8.6.0", - "eslint-config-prettier": "^7.2.0", - "eslint-plugin-import": "^2.25.3", - "prettier": "^2.2.1" - } - }, - "node_modules/@graphql-tools/merge": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.2.tgz", - "integrity": "sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw==", - "dependencies": { - "@graphql-tools/utils": "^9.2.1", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/mock": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/mock/-/mock-8.4.2.tgz", - "integrity": "sha512-2v4v99mWUB1by+6Bk01PoJCUVnYoNSOT0E5VvFRf5oMwJPaRKLAbC+IjZaRoen1tWpVrg+3Coub7co8jyhvm/Q==", - "dependencies": { - "@graphql-tools/schema": "^8.3.1", - "@graphql-tools/utils": "^8.5.1", - "fast-json-stable-stringify": "^2.1.0", - "tslib": "~2.3.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-tools/mock/node_modules/@graphql-tools/schema": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.1.tgz", - "integrity": "sha512-3R0AJFe715p4GwF067G5i0KCr/XIdvSfDLvTLEiTDQ8V/hwbOHEKHKWlEBHGRQwkG5lwFQlW1aOn7VnlPERnWQ==", - "dependencies": { - "@graphql-tools/merge": "^8.2.1", - "@graphql-tools/utils": "^8.5.1", - "tslib": "~2.3.0", - "value-or-promise": "1.0.11" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-tools/mock/node_modules/@graphql-tools/utils": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.5.2.tgz", - "integrity": "sha512-wxA51td/759nQziPYh+HxE0WbURRufrp1lwfOYMgfK4e8Aa6gCa1P1p6ERogUIm423NrIfOVau19Q/BBpHdolw==", - "dependencies": { - "tslib": "~2.3.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-tools/mock/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/@graphql-tools/mock/node_modules/value-or-promise": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz", - "integrity": "sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==", - "engines": { - "node": ">=12" - } - }, - "node_modules/@graphql-tools/schema": { - "version": "9.0.19", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-9.0.19.tgz", - "integrity": "sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==", - "dependencies": { - "@graphql-tools/merge": "^8.4.1", - "@graphql-tools/utils": "^9.2.1", - "tslib": "^2.4.0", - "value-or-promise": "^1.0.12" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/utils": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz", - "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==", - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-typed-document-node/core": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", - "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", - "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", - "dev": true, - "dependencies": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "slash": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/@jest/core": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.3.tgz", - "integrity": "sha512-CIKBrlaKOzA7YG19BEqCw3SLIsEwjZkeJzf5bdooVnW4bH5cktqe3JX+G2YV1aK5vP8N9na1IGWFzYaTp6k6NA==", - "dev": true, - "dependencies": { - "@jest/console": "^28.1.3", - "@jest/reporters": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^28.1.3", - "jest-config": "^28.1.3", - "jest-haste-map": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.3", - "jest-resolve-dependencies": "^28.1.3", - "jest-runner": "^28.1.3", - "jest-runtime": "^28.1.3", - "jest-snapshot": "^28.1.3", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "jest-watcher": "^28.1.3", - "micromatch": "^4.0.4", - "pretty-format": "^28.1.3", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/environment": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.3.tgz", - "integrity": "sha512-1bf40cMFTEkKyEf585R9Iz1WayDjHoHqvts0XFYEqyKM3cFWDpeMoqKKTAF9LSYQModPUlh8FKptoM2YcMWAXA==", - "dev": true, - "dependencies": { - "@jest/fake-timers": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "jest-mock": "^28.1.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.3.tgz", - "integrity": "sha512-lzc8CpUbSoE4dqT0U+g1qODQjBRHPpCPXissXD4mS9+sWQdmmpeJ9zSH1rS1HEkrsMN0fb7nKrJ9giAR1d3wBw==", - "dev": true, - "dependencies": { - "expect": "^28.1.3", - "jest-snapshot": "^28.1.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.3.tgz", - "integrity": "sha512-wvbi9LUrHJLn3NlDW6wF2hvIMtd4JUl2QNVrjq+IBSHirgfrR3o9RnVtxzdEGO2n9JyIWwHnLfby5KzqBGg2YA==", - "dev": true, - "dependencies": { - "jest-get-type": "^28.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.3.tgz", - "integrity": "sha512-D/wOkL2POHv52h+ok5Oj/1gOG9HSywdoPtFsRCUmlCILXNn5eIWmcnd3DIiWlJnpGvQtmajqBP95Ei0EimxfLw==", - "dev": true, - "dependencies": { - "@jest/types": "^28.1.3", - "@sinonjs/fake-timers": "^9.1.2", - "@types/node": "*", - "jest-message-util": "^28.1.3", - "jest-mock": "^28.1.3", - "jest-util": "^28.1.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.3.tgz", - "integrity": "sha512-XFU4P4phyryCXu1pbcqMO0GSQcYe1IsalYCDzRNyhetyeyxMcIxa11qPNDpVNLeretItNqEmYYQn1UYz/5x1NA==", - "dev": true, - "dependencies": { - "@jest/environment": "^28.1.3", - "@jest/expect": "^28.1.3", - "@jest/types": "^28.1.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.3.tgz", - "integrity": "sha512-JuAy7wkxQZVNU/V6g9xKzCGC5LVXx9FDcABKsSXp5MiKPEE2144a/vXTEDoyzjUpZKfVwp08Wqg5A4WfTMAzjg==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@jridgewell/trace-mapping": "^0.3.13", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "jest-worker": "^28.1.3", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@jest/schemas": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", - "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.24.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "28.1.2", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.1.2.tgz", - "integrity": "sha512-cV8Lx3BeStJb8ipPHnqVw/IM2VCMWO3crWZzYodSIkxXnRcXJipCdx1JCK0K5MsJJouZQTH73mzf4vgxRaH9ww==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.13", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", - "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", - "dev": true, - "dependencies": { - "@jest/console": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-28.1.3.tgz", - "integrity": "sha512-NIMPEqqa59MWnDi1kvXXpYbqsfQmSJsIbnd85mdVGkiDfQ9WQQTXOLsvISUfonmnBT+w85WEgneCigEEdHDFxw==", - "dev": true, - "dependencies": { - "@jest/test-result": "^28.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", - "slash": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.3.tgz", - "integrity": "sha512-u5dT5di+oFI6hfcLOHGTAfmUxFRrjK+vnaP0kkVow9Md/M7V/MxqQMOz/VV25UZO8pzeA9PjfTpOu6BDuwSPQA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^28.1.3", - "@jridgewell/trace-mapping": "^0.3.13", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.1.3", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/@jest/types": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", - "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/@josephg/resolvable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@josephg/resolvable/-/resolvable-1.0.1.tgz", - "integrity": "sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg==" - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", - "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", - "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.11", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", - "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgr/utils": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz", - "integrity": "sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "is-glob": "^4.0.3", - "open": "^8.4.0", - "picocolors": "^1.0.0", - "tiny-glob": "^0.2.9", - "tslib": "^2.4.0" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@prisma/client": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-4.2.1.tgz", - "integrity": "sha512-PZBkY60+k5oix+e6IUfl3ub8TbRLNsPLdfWrdy2eh80WcHTaT+/UfvXf/B7gXedH7FRtbPFHZXk1hZenJiJZFQ==", - "hasInstallScript": true, - "dependencies": { - "@prisma/engines-version": "4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826" - }, - "engines": { - "node": ">=14.17" - }, - "peerDependencies": { - "prisma": "*" - }, - "peerDependenciesMeta": { - "prisma": { - "optional": true - } - } - }, - "node_modules/@prisma/engines": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-4.2.1.tgz", - "integrity": "sha512-0KqBwREUOjBiHwITsQzw2DWfLHjntvbqzGRawj4sBMnIiL5CXwyDUKeHOwXzKMtNr1rEjxEsypM14g0CzLRK3g==", - "hasInstallScript": true - }, - "node_modules/@prisma/engines-version": { - "version": "4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826.tgz", - "integrity": "sha512-tktkqdiwqE4QhmE088boPt+FwPj1Jub/zk+5F6sEfcRHzO5yz9jyMD5HFVtiwxZPLx/8Xg9ElnuTi8E5lWVQFQ==" - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78= sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A= sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU= sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E= sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik= sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0= sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q= sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" - }, - "node_modules/@sinclair/typebox": { - "version": "0.24.27", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.27.tgz", - "integrity": "sha512-K7C7IlQ3zLePEZleUN21ceBA2aLcMnLHTLph8QWk1JK37L90obdpY+QGY8bXMKxf1ht1Z0MNewvXxWv0oGDYFg==", - "dev": true - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", - "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", - "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", - "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", - "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", - "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true - }, - "node_modules/@types/accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/babel__core": { - "version": "7.1.16", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.16.tgz", - "integrity": "sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.3.tgz", - "integrity": "sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz", - "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.3.0" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/busboy": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-1.5.0.tgz", - "integrity": "sha512-ncOOhwmyFDW76c/Tuvv9MA9VGYUCn8blzyWmzYELcNGDb0WXWLSmFi7hJq25YdRBYJrmMBB5jZZwUjlJe9HCjQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/content-disposition": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.5.tgz", - "integrity": "sha512-v6LCdKfK6BwcqMo+wYW05rLS12S0ZO0Fl4w1h4aaZMD7bqT3gVUns6FvLJKGZHQmYn3SX55JWGpziwJRwVgutA==" - }, - "node_modules/@types/cookies": { - "version": "0.7.7", - "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.7.tgz", - "integrity": "sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==", - "dependencies": { - "@types/connect": "*", - "@types/express": "*", - "@types/keygrip": "*", - "@types/node": "*" - } - }, - "node_modules/@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" - }, - "node_modules/@types/express": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", - "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.31", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", - "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/graphql-upload": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@types/graphql-upload/-/graphql-upload-15.0.2.tgz", - "integrity": "sha512-dK4GN/JbMmgHbsKZaUWVYwaLMCwIR0QMBcFz+jb4xj/cRLq1yo2VfnoFvnP5yCw7W4IgGgW7JRwEvM4jn0ahlA==", - "dependencies": { - "@types/express": "*", - "@types/koa": "*", - "fs-capacitor": "^8.0.0", - "graphql": "0.13.1 - 16" - } - }, - "node_modules/@types/http-assert": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.3.tgz", - "integrity": "sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA==" - }, - "node_modules/@types/http-errors": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.2.tgz", - "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==" - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", - "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "28.1.8", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-28.1.8.tgz", - "integrity": "sha512-8TJkV++s7B6XqnDrzR1m/TT0A0h948Pnl/097veySPN67VRAgQ4gZ7n2KfJo2rVq6njQjdxU3GCCyDvAeuHoiw==", - "dev": true, - "dependencies": { - "expect": "^28.0.0", - "pretty-format": "^28.0.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/json-templates": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/json-templates/-/json-templates-3.0.0.tgz", - "integrity": "sha512-oaCQfpgz/tL6s20Qs/UW4l1kBg8z48GbmwE74K2y6JG0Uud5BN36Fxev3HOhuJcbH+TpbfaK3cZuhuZ9bxrqeA==" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4= sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/keygrip": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", - "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==" - }, - "node_modules/@types/koa": { - "version": "2.13.5", - "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.13.5.tgz", - "integrity": "sha512-HSUOdzKz3by4fnqagwthW/1w/yJspTgppyyalPVbgZf8jQWvdIXcVW5h2DGtw4zYntOaeRGx49r1hxoPWrD4aA==", - "dependencies": { - "@types/accepts": "*", - "@types/content-disposition": "*", - "@types/cookies": "*", - "@types/http-assert": "*", - "@types/http-errors": "*", - "@types/keygrip": "*", - "@types/koa-compose": "*", - "@types/node": "*" - } - }, - "node_modules/@types/koa-compose": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", - "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", - "dependencies": { - "@types/koa": "*" - } - }, - "node_modules/@types/lodash": { - "version": "4.14.194", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.194.tgz", - "integrity": "sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==" - }, - "node_modules/@types/long": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", - "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" - }, - "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" - }, - "node_modules/@types/node": { - "version": "16.18.32", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", - "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==" - }, - "node_modules/@types/node-fetch": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", - "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", - "dependencies": { - "@types/node": "*", - "form-data": "^3.0.0" - } - }, - "node_modules/@types/object-path": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/@types/object-path/-/object-path-0.11.1.tgz", - "integrity": "sha512-219LSCO9HPcoXcRTC6DbCs0FRhZgBnEMzf16RRqkT40WbkKx3mOeQuz3e2XqbfhOz/AHfbru0kzB1n1RCAsIIg==" - }, - "node_modules/@types/pino": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@types/pino/-/pino-7.0.4.tgz", - "integrity": "sha512-yKw1UbZOTe7vP1xMQT+oz3FexwgIpBTrM+AC62vWgAkNRULgLTJWfYX+H5/sKPm8VXFbIcXkC3VZPyuaNioZFg==", - "dependencies": { - "pino": "*" - } - }, - "node_modules/@types/prettier": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.1.tgz", - "integrity": "sha512-Fo79ojj3vdEZOHg3wR9ksAMRz4P3S5fDB5e/YWZiFnyFQI1WY2Vftu9XoXVVtJfxB7Bpce/QTqWSSntkz2Znrw==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" - }, - "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true - }, - "node_modules/@types/serve-static": { - "version": "1.13.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", - "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/ssh2": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.11.6.tgz", - "integrity": "sha512-8Mf6bhzYYBLEB/G6COux7DS/F5bCWwojv/qFo2yH/e4cLzAavJnxvFXrYW59iKfXdhG6OmzJcXDasgOb/s0rxw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "node_modules/@types/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I= sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", - "dev": true - }, - "node_modules/@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", - "dev": true - }, - "node_modules/@types/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-wDXw9LEEUHyV+7UWy7U315nrJGJ7p1BzaCxDpEoLr789Dk1WDVMMlf3iBfbG2F8NdWnYyFbtTxUn2ZNbm1Q4LQ==" - }, - "node_modules/@types/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==" - }, - "node_modules/@types/ws": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", - "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/yargs": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", - "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "20.2.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", - "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz", - "integrity": "sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.54.0", - "@typescript-eslint/type-utils": "5.54.0", - "@typescript-eslint/utils": "5.54.0", - "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.0.tgz", - "integrity": "sha512-aAVL3Mu2qTi+h/r04WI/5PfNWvO6pdhpeMRWk9R7rEV4mwJNzoWf5CCU5vDKBsPIFQFjEq1xg7XBI2rjiMXQbQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.54.0", - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/typescript-estree": "5.54.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz", - "integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.0.tgz", - "integrity": "sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "5.54.0", - "@typescript-eslint/utils": "5.54.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", - "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz", - "integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.0.tgz", - "integrity": "sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.54.0", - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/typescript-estree": "5.54.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", - "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.54.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@vercel/ncc": { - "version": "0.36.1", - "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.36.1.tgz", - "integrity": "sha512-S4cL7Taa9yb5qbv+6wLgiKVZ03Qfkc4jGRuiUQMQ8HGBD5pcNRnHeYM33zBvJE4/zJGjJJ8GScB+WmTsn9mORw==", - "dev": true, - "bin": { - "ncc": "dist/ncc/cli.js" - } - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/apollo-datasource": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-3.3.2.tgz", - "integrity": "sha512-L5TiS8E2Hn/Yz7SSnWIVbZw0ZfEIXZCa5VUiVxD9P53JvSrf4aStvsFDlGWPvpIdCR+aly2CfoB79B9/JjKFqg==", - "deprecated": "The `apollo-datasource` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", - "dependencies": { - "@apollo/utils.keyvaluecache": "^1.0.1", - "apollo-server-env": "^4.2.1" - }, - "engines": { - "node": ">=12.0" - } - }, - "node_modules/apollo-reporting-protobuf": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-3.4.0.tgz", - "integrity": "sha512-h0u3EbC/9RpihWOmcSsvTW2O6RXVaD/mPEjfrPkxRPTEPWqncsgOoRJw+wih4OqfH3PvTJvoEIf4LwKrUaqWog==", - "deprecated": "The `apollo-reporting-protobuf` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/usage-reporting-protobuf` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", - "dependencies": { - "@apollo/protobufjs": "1.2.6" - } - }, - "node_modules/apollo-server": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/apollo-server/-/apollo-server-3.12.0.tgz", - "integrity": "sha512-wZHLgBoIdGxr/YpPTG5RwNnS+B2y70T/nCegCnU6Yl+H3PXB92OIguLMhdJIZVjukIOhiQT12dNIehqLQ+1hMQ==", - "deprecated": "The `apollo-server` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", - "dev": true, - "dependencies": { - "@types/express": "4.17.14", - "apollo-server-core": "^3.12.0", - "apollo-server-express": "^3.12.0", - "express": "^4.17.1" - }, - "peerDependencies": { - "graphql": "^15.3.0 || ^16.0.0" - } - }, - "node_modules/apollo-server-core": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-3.12.0.tgz", - "integrity": "sha512-hq7iH6Cgldgmnjs9FVSZeKWRpi0/ZR+iJ1arzeD2VXGxxgk1mAm/cz1Tx0TYgegZI+FvvrRl0UhKEx7sLnIxIg==", - "deprecated": "The `apollo-server-core` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", - "dependencies": { - "@apollo/utils.keyvaluecache": "^1.0.1", - "@apollo/utils.logger": "^1.0.0", - "@apollo/utils.usagereporting": "^1.0.0", - "@apollographql/apollo-tools": "^0.5.3", - "@apollographql/graphql-playground-html": "1.6.29", - "@graphql-tools/mock": "^8.1.2", - "@graphql-tools/schema": "^8.0.0", - "@josephg/resolvable": "^1.0.0", - "apollo-datasource": "^3.3.2", - "apollo-reporting-protobuf": "^3.4.0", - "apollo-server-env": "^4.2.1", - "apollo-server-errors": "^3.3.1", - "apollo-server-plugin-base": "^3.7.2", - "apollo-server-types": "^3.8.0", - "async-retry": "^1.2.1", - "fast-json-stable-stringify": "^2.1.0", - "graphql-tag": "^2.11.0", - "loglevel": "^1.6.8", - "lru-cache": "^6.0.0", - "node-abort-controller": "^3.0.1", - "sha.js": "^2.4.11", - "uuid": "^9.0.0", - "whatwg-mimetype": "^3.0.0" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "graphql": "^15.3.0 || ^16.0.0" - } - }, - "node_modules/apollo-server-core/node_modules/@graphql-tools/schema": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.1.tgz", - "integrity": "sha512-3R0AJFe715p4GwF067G5i0KCr/XIdvSfDLvTLEiTDQ8V/hwbOHEKHKWlEBHGRQwkG5lwFQlW1aOn7VnlPERnWQ==", - "dependencies": { - "@graphql-tools/merge": "^8.2.1", - "@graphql-tools/utils": "^8.5.1", - "tslib": "~2.3.0", - "value-or-promise": "1.0.11" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/apollo-server-core/node_modules/@graphql-tools/utils": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.5.2.tgz", - "integrity": "sha512-wxA51td/759nQziPYh+HxE0WbURRufrp1lwfOYMgfK4e8Aa6gCa1P1p6ERogUIm423NrIfOVau19Q/BBpHdolw==", - "dependencies": { - "tslib": "~2.3.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/apollo-server-core/node_modules/graphql-tag": { - "version": "2.12.5", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.5.tgz", - "integrity": "sha512-5xNhP4063d16Pz3HBtKprutsPrmHZi5IdUGOWRxA2B6VF7BIRGOHZ5WQvDmJXZuPcBg7rYwaFxvQYjqkSdR3TQ==", - "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0" - } - }, - "node_modules/apollo-server-core/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "node_modules/apollo-server-core/node_modules/value-or-promise": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz", - "integrity": "sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==", - "engines": { - "node": ">=12" - } - }, - "node_modules/apollo-server-env": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-4.2.1.tgz", - "integrity": "sha512-vm/7c7ld+zFMxibzqZ7SSa5tBENc4B0uye9LTfjJwGoQFY5xsUPH5FpO5j0bMUDZ8YYNbrF9SNtzc5Cngcr90g==", - "deprecated": "The `apollo-server-env` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/utils.fetcher` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", - "dependencies": { - "node-fetch": "^2.6.7" - }, - "engines": { - "node": ">=12.0" - } - }, - "node_modules/apollo-server-errors": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-3.3.1.tgz", - "integrity": "sha512-xnZJ5QWs6FixHICXHxUfm+ZWqqxrNuPlQ+kj5m6RtEgIpekOPssH/SD9gf2B4HuWV0QozorrygwZnux8POvyPA==", - "deprecated": "The `apollo-server-errors` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "graphql": "^15.3.0 || ^16.0.0" - } - }, - "node_modules/apollo-server-express": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-3.12.0.tgz", - "integrity": "sha512-m8FaGPUfDOEGSm7QRWRmUUGjG/vqvpQoorkId9/FXkC57fz/A59kEdrzkMt9538Xgsa5AV+X4MEWLJhTvlW3LQ==", - "deprecated": "The `apollo-server-express` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", - "dependencies": { - "@types/accepts": "^1.3.5", - "@types/body-parser": "1.19.2", - "@types/cors": "2.8.12", - "@types/express": "4.17.14", - "@types/express-serve-static-core": "4.17.31", - "accepts": "^1.3.5", - "apollo-server-core": "^3.12.0", - "apollo-server-types": "^3.8.0", - "body-parser": "^1.19.0", - "cors": "^2.8.5", - "parseurl": "^1.3.3" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "express": "^4.17.1", - "graphql": "^15.3.0 || ^16.0.0" - } - }, - "node_modules/apollo-server-express/node_modules/@types/express": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", - "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/apollo-server-plugin-base": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-3.7.2.tgz", - "integrity": "sha512-wE8dwGDvBOGehSsPTRZ8P/33Jan6/PmL0y0aN/1Z5a5GcbFhDaaJCjK5cav6npbbGL2DPKK0r6MPXi3k3N45aw==", - "deprecated": "The `apollo-server-plugin-base` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", - "dependencies": { - "apollo-server-types": "^3.8.0" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "graphql": "^15.3.0 || ^16.0.0" - } - }, - "node_modules/apollo-server-types": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-3.8.0.tgz", - "integrity": "sha512-ZI/8rTE4ww8BHktsVpb91Sdq7Cb71rdSkXELSwdSR0eXu600/sY+1UXhTWdiJvk+Eq5ljqoHLwLbY2+Clq2b9A==", - "deprecated": "The `apollo-server-types` package is part of Apollo Server v2 and v3, which are now deprecated (end-of-life October 22nd 2023). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details.", - "dependencies": { - "@apollo/utils.keyvaluecache": "^1.0.1", - "@apollo/utils.logger": "^1.0.0", - "apollo-reporting-protobuf": "^3.4.0", - "apollo-server-env": "^4.2.1" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "graphql": "^15.3.0 || ^16.0.0" - } - }, - "node_modules/apollo-server/node_modules/@types/express": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", - "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/async-retry": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", - "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", - "dependencies": { - "retry": "0.13.1" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k= sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/babel-jest": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.3.tgz", - "integrity": "sha512-epUaPOEWMk3cWX0M/sPvCHHCe9fMFAa/9hXEgKP8nFfNl/jlGkE9ucq9NqkZGXLDduCJYS0UvSlPUwC0S+rH6Q==", - "dev": true, - "dependencies": { - "@jest/transform": "^28.1.3", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^28.1.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.3.tgz", - "integrity": "sha512-Ys3tUKAmfnkRUpPdpa98eYrAR0nV+sSFUZZEGuQ2EbFd1y4SOLtD5QDNHAq+bb9a+bbXvYQC4b+ID/THIMcU6Q==", - "dev": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-28.1.3.tgz", - "integrity": "sha512-L+fupJvlWAHbQfn74coNX3zf60LXMJsezNvvx8eIh7iOR1luJ1poxYgQk1F8PYtNq/6QODDHCqsSnTFSWC491A==", - "dev": true, - "dependencies": { - "babel-plugin-jest-hoist": "^28.1.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base64url": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", - "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.10.3", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.20.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.4.tgz", - "integrity": "sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001349", - "electron-to-chromium": "^1.4.147", - "escalade": "^3.1.1", - "node-releases": "^2.0.5", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/buildcheck": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.3.tgz", - "integrity": "sha512-pziaA+p/wdVImfcbsZLNF32EiWyujlQLwolMqUQE8xpKNOH7KmZQaY8sXN7DGOEzPAElo9QTaeNRfGnf3iOJbA==", - "optional": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001352", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001352.tgz", - "integrity": "sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ] - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ci-info": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", - "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", - "dev": true - }, - "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", - "dev": true - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/confusing-browser-globals": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", - "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", - "dev": true - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/convert-source-map/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw= sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cpu-features": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.4.tgz", - "integrity": "sha512-fKiZ/zp1mUwQbnzb9IghXtHtDoTMtNeb8oYGx6kX2SYfhnG0HNdBEBIzB9b5KlXu5DQPhfy3mInbBxFcgwAr3A==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "buildcheck": "0.0.3", - "nan": "^2.15.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dev": true, - "dependencies": { - "node-fetch": "2.6.7" - } - }, - "node_modules/cross-fetch/node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cssfilter": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", - "integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4= sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==" - }, - "node_modules/csv-parse": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.3.10.tgz", - "integrity": "sha512-cTXY6iy0gN5Ha/cGILeDgQE+nKiKDU2m0DjSRdJhr86BN3cM7oefBsTk2aH0LQeaYtL7Z7HvW+jYoadmdhzeDA==" - }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "engines": { - "node": "*" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true - }, - "node_modules/dedupe": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dedupe/-/dedupe-3.0.3.tgz", - "integrity": "sha512-ZSCmu4uLkBWTAPSz9LXtrTNusY2P6BoghZhokPBLzpQpLiBtU0B4QXNxVnwpy7yaqFc1jN30V5BkKMr/uXqf/w==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dev": true, - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk= sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/diacritics": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/diacritics/-/diacritics-1.3.0.tgz", - "integrity": "sha1-PvqHMj67hj5mls67AILUj/PW96E= sha512-wlwEkqcsaxvPJML+rDh/2iS824jbREk6DUMUKkEaSlxdYHeS43cClJtsWglvw2RfeXGm6ohKDqsXteJ5sP5enA==" - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-sequences": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", - "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", - "dev": true, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/dynamic-dedupe": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", - "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE= sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ==", - "dev": true, - "dependencies": { - "xtend": "^4.0.0" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/electron-to-chromium": { - "version": "1.4.150", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.150.tgz", - "integrity": "sha512-MP3oBer0X7ZeS9GJ0H6lmkn561UxiwOIY9TTkdxVY7lI9G6GVCKfgJaHaDcakwdKxBXA4T3ybeswH/WBIN/KTA==", - "dev": true - }, - "node_modules/emittery": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", - "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.14.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz", - "integrity": "sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", - "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^2.0.0", - "@eslint/js": "8.35.0", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-airbnb-base": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", - "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", - "dev": true, - "dependencies": { - "confusing-browser-globals": "^1.0.10", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5", - "semver": "^6.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.2" - } - }, - "node_modules/eslint-config-airbnb-base/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-config-prettier": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz", - "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz", - "integrity": "sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==", - "dev": true, - "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "get-tsconfig": "^4.5.0", - "globby": "^13.1.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "synckit": "^0.8.5" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/globby": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", - "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", - "dev": true, - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/espree": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", - "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", - "dev": true, - "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.3.tgz", - "integrity": "sha512-eEh0xn8HlsuOBxFgIss+2mX85VAS4Qy3OSkjV7rlBWljtA4oWH37glVGyOZSZvErDT/yBywZdPGwCXuTvSG85g==", - "dev": true, - "dependencies": { - "@jest/expect-utils": "^28.1.3", - "jest-get-type": "^28.0.2", - "jest-matcher-utils": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.0", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.10.3", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/extract-files": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz", - "integrity": "sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==", - "dev": true, - "engines": { - "node": "^10.17.0 || ^12.0.0 || >= 13.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/jaydenseric" - } - }, - "node_modules/fast-copy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", - "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fast-redact": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.1.tgz", - "integrity": "sha512-odVmjC8x8jNeMZ3C+rPMESzXVSEU8tSWSHv9HFxP2mm89G/1WwqhrerJDQm9Zus8X6aoRgQDThKqptdNA6bt+A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==" - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", - "dev": true, - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", - "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", - "dev": true - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fp-ts": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-2.15.0.tgz", - "integrity": "sha512-3o6EllAvGuCsDgjM+frscLKDRPR9pqbrg13tJ13z86F4eni913kBV8h85rM6zpu2fEvJ8RWA0ouYlUWwHEmxTg==" - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-capacitor": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-8.0.0.tgz", - "integrity": "sha512-+Lk6iSKajdGw+7XYxUkwIzreJ2G1JFlYOdnKJv5PzwFLVsoJYBpCuS7WPIUSNT1IbQaEWT1nhYU63Ud03DyzLA==", - "engines": { - "node": "^14.17.0 || >=16.0.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8= sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.5.0.tgz", - "integrity": "sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==", - "dev": true, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globalyzer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", - "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", - "dev": true - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globrex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", - "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", - "dev": true - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "node_modules/graphql": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", - "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==", - "engines": { - "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" - } - }, - "node_modules/graphql-fields": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/graphql-fields/-/graphql-fields-2.0.3.tgz", - "integrity": "sha512-x3VE5lUcR4XCOxPIqaO4CE+bTK8u6gVouOdpQX9+EKHr+scqtK5Pp/l8nIGqIpN1TUlkKE6jDCCycm/WtLRAwA==" - }, - "node_modules/graphql-relay": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/graphql-relay/-/graphql-relay-0.10.0.tgz", - "integrity": "sha512-44yBuw2/DLNEiMypbNZBt1yMDbBmyVPVesPywnteGGALiBmdyy1JP8jSg8ClLePg8ZZxk0O4BLhd1a6U/1jDOQ==", - "engines": { - "node": "^12.20.0 || ^14.15.0 || >= 15.9.0" - }, - "peerDependencies": { - "graphql": "^16.2.0" - } - }, - "node_modules/graphql-request": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-4.3.0.tgz", - "integrity": "sha512-2v6hQViJvSsifK606AliqiNiijb1uwWp6Re7o0RTyH+uRTv/u7Uqm2g4Fjq/LgZIzARB38RZEvVBFOQOVdlBow==", - "dev": true, - "dependencies": { - "cross-fetch": "^3.1.5", - "extract-files": "^9.0.0", - "form-data": "^3.0.0" - }, - "peerDependencies": { - "graphql": "14 - 16" - } - }, - "node_modules/graphql-upload": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/graphql-upload/-/graphql-upload-15.0.2.tgz", - "integrity": "sha512-ufJAkZJBKWRDD/4wJR3VZMy9QWTwqIYIciPtCEF5fCNgWF+V1p7uIgz+bP2YYLiS4OJBhCKR8rnqE/Wg3XPUiw==", - "dependencies": { - "@types/busboy": "^1.5.0", - "@types/node": "*", - "@types/object-path": "^0.11.1", - "busboy": "^1.6.0", - "fs-capacitor": "^6.2.0", - "http-errors": "^2.0.0", - "object-path": "^0.11.8" - }, - "engines": { - "node": "^14.17.0 || ^16.0.0 || >= 18.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/jaydenseric" - }, - "peerDependencies": { - "@types/express": "^4.0.29", - "@types/koa": "^2.11.4", - "graphql": "^16.3.0" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - }, - "@types/koa": { - "optional": true - } - } - }, - "node_modules/graphql-upload/node_modules/fs-capacitor": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/fs-capacitor/-/fs-capacitor-6.2.0.tgz", - "integrity": "sha512-nKcE1UduoSKX27NSZlg879LdQc94OtbOsEmKMN2MBNudXREvijRKx2GEBsTMTfws+BrbkJoEuynbGSVRSpauvw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/graphql-ws": { - "version": "5.11.2", - "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.11.2.tgz", - "integrity": "sha512-4EiZ3/UXYcjm+xFGP544/yW1+DVI8ZpKASFbzrV5EDTFWJp0ZvLl4Dy2fSZAzz9imKp5pZMIcjB0x/H69Pv/6w==", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": ">=0.11 <=16" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/help-me": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.0.1.tgz", - "integrity": "sha512-PLv01Z+OhEPKj2QPYB4kjoCUkopYNPUK3EROlaPIf5bib752fZ+VCvGDAoA+FXo/OwCyLEA4D2e0mX8+Zhcplw==", - "dependencies": { - "glob": "^8.0.0", - "readable-stream": "^3.6.0" - } - }, - "node_modules/help-me/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/i18n-iso-countries": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/i18n-iso-countries/-/i18n-iso-countries-7.5.0.tgz", - "integrity": "sha512-PtfKJNWLVhhU0KBX/8asmywjAcuyQk07mmmMwxFJcddTNBJJ1yvpY2qxVmyxbtVF+9+6eg9phgpv83XPUKU5CA==", - "dependencies": { - "diacritics": "1.3.0" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", - "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o= sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/io-ts": { - "version": "2.2.20", - "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-2.2.20.tgz", - "integrity": "sha512-Rq2BsYmtwS5vVttie4rqrOCIfHCS9TgpRLFpKQCM1wZBBRY9nWVGmEvm2FnDbSE2un1UE39DvFpTR5UL47YDcA==", - "peerDependencies": { - "fp-ts": "^2.5.0" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", - "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", - "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/iterall": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", - "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==" - }, - "node_modules/jest": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.3.tgz", - "integrity": "sha512-N4GT5on8UkZgH0O5LUavMRV1EDEhNTL0KEfRmDIeZHSV7p2XgLoY9t9VDUgL6o+yfdgYHVxuz81G8oB9VG5uyA==", - "dev": true, - "dependencies": { - "@jest/core": "^28.1.3", - "@jest/types": "^28.1.3", - "import-local": "^3.0.2", - "jest-cli": "^28.1.3" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.1.3.tgz", - "integrity": "sha512-esaOfUWJXk2nfZt9SPyC8gA1kNfdKLkQWyzsMlqq8msYSlNKfmZxfRgZn4Cd4MGVUF+7v6dBs0d5TOAKa7iIiA==", - "dev": true, - "dependencies": { - "execa": "^5.0.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-circus": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.3.tgz", - "integrity": "sha512-cZ+eS5zc79MBwt+IhQhiEp0OeBddpc1n8MBo1nMB8A7oPMKEO+Sre+wHaLJexQUj9Ya/8NOBY0RESUgYjB6fow==", - "dev": true, - "dependencies": { - "@jest/environment": "^28.1.3", - "@jest/expect": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^28.1.3", - "jest-matcher-utils": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-runtime": "^28.1.3", - "jest-snapshot": "^28.1.3", - "jest-util": "^28.1.3", - "p-limit": "^3.1.0", - "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-cli": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.3.tgz", - "integrity": "sha512-roY3kvrv57Azn1yPgdTebPAXvdR2xfezaKKYzVxZ6It/5NCxzJym6tUI5P1zkdWhfUYkxEI9uZWcQdaFLo8mJQ==", - "dev": true, - "dependencies": { - "@jest/core": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^28.1.3", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "prompts": "^2.0.1", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-config": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.3.tgz", - "integrity": "sha512-MG3INjByJ0J4AsNBm7T3hsuxKQqFIiRo/AUqb1q9LRKI5UU6Aar9JHbr9Ivn1TVwfUD9KirRoM/T6u8XlcQPHQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^28.1.3", - "@jest/types": "^28.1.3", - "babel-jest": "^28.1.3", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^28.1.3", - "jest-environment-node": "^28.1.3", - "jest-get-type": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.3", - "jest-runner": "^28.1.3", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-config/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-diff": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.3.tgz", - "integrity": "sha512-8RqP1B/OXzjjTWkqMX67iqgwBVJRgCyKD3L9nq+6ZqJMdvjE8RgHktqZ6jNrkdMT+dJuYNI3rhQpxaz7drJHfw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^28.1.1", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.1.1.tgz", - "integrity": "sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==", - "dev": true, - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-each": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.1.3.tgz", - "integrity": "sha512-arT1z4sg2yABU5uogObVPvSlSMQlDA48owx07BDPAiasW0yYpYHYOo4HHLz9q0BVzDVU4hILFjzJw0So9aCL/g==", - "dev": true, - "dependencies": { - "@jest/types": "^28.1.3", - "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", - "jest-util": "^28.1.3", - "pretty-format": "^28.1.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-environment-node": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.3.tgz", - "integrity": "sha512-ugP6XOhEpjAEhGYvp5Xj989ns5cB1K6ZdjBYuS30umT4CQEETaxSiPcZ/E1kFktX4GkrcM4qu07IIlDYX1gp+A==", - "dev": true, - "dependencies": { - "@jest/environment": "^28.1.3", - "@jest/fake-timers": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "jest-mock": "^28.1.3", - "jest-util": "^28.1.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", - "dev": true, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.3.tgz", - "integrity": "sha512-3S+RQWDXccXDKSWnkHa/dPwt+2qwA8CJzR61w3FoYCvoo3Pn8tvGcysmMF0Bj0EX5RYvAI2EIvC57OmotfdtKA==", - "dev": true, - "dependencies": { - "@jest/types": "^28.1.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.1.3", - "jest-worker": "^28.1.3", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-leak-detector": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.1.3.tgz", - "integrity": "sha512-WFVJhnQsiKtDEo5lG2mM0v40QWnBM+zMdHHyJs8AWZ7J0QZJS59MsyKeJHWhpBZBH32S48FOVvGyOFT1h0DlqA==", - "dev": true, - "dependencies": { - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.3.tgz", - "integrity": "sha512-kQeJ7qHemKfbzKoGjHHrRKH6atgxMk8Enkk2iPQ3XwO6oE/KYD8lMYOziCkeSB9G4adPM4nR1DE8Tf5JeWH6Bw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^28.1.3", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^28.1.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-mock": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-28.1.3.tgz", - "integrity": "sha512-o3J2jr6dMMWYVH4Lh/NKmDXdosrsJgi4AviS8oXLujcjpCMBb1FMsblDnOXKZKfSiHLxYub1eS0IHuRXsio9eA==", - "dev": true, - "dependencies": { - "@jest/types": "^28.1.3", - "@types/node": "*" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", - "dev": true, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.1.3.tgz", - "integrity": "sha512-Z1W3tTjE6QaNI90qo/BJpfnvpxtaFTFw5CDgwpyE/Kz8U/06N1Hjf4ia9quUhCh39qIGWF1ZuxFiBiJQwSEYKQ==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.1.3", - "jest-validate": "^28.1.3", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.3.tgz", - "integrity": "sha512-qa0QO2Q0XzQoNPouMbCc7Bvtsem8eQgVPNkwn9LnS+R2n8DaVDPL/U1gngC0LTl1RYXJU0uJa2BMC2DbTfFrHA==", - "dev": true, - "dependencies": { - "jest-regex-util": "^28.0.2", - "jest-snapshot": "^28.1.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-runner": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.3.tgz", - "integrity": "sha512-GkMw4D/0USd62OVO0oEgjn23TM+YJa2U2Wu5zz9xsQB1MxWKDOlrnykPxnMsN0tnJllfLPinHTka61u0QhaxBA==", - "dev": true, - "dependencies": { - "@jest/console": "^28.1.3", - "@jest/environment": "^28.1.3", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.10.2", - "graceful-fs": "^4.2.9", - "jest-docblock": "^28.1.1", - "jest-environment-node": "^28.1.3", - "jest-haste-map": "^28.1.3", - "jest-leak-detector": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-resolve": "^28.1.3", - "jest-runtime": "^28.1.3", - "jest-util": "^28.1.3", - "jest-watcher": "^28.1.3", - "jest-worker": "^28.1.3", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.3.tgz", - "integrity": "sha512-NU+881ScBQQLc1JHG5eJGU7Ui3kLKrmwCPPtYsJtBykixrM2OhVQlpMmFWJjMyDfdkGgBMNjXCGB/ebzsgNGQw==", - "dev": true, - "dependencies": { - "@jest/environment": "^28.1.3", - "@jest/fake-timers": "^28.1.3", - "@jest/globals": "^28.1.3", - "@jest/source-map": "^28.1.2", - "@jest/test-result": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-mock": "^28.1.3", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.3", - "jest-snapshot": "^28.1.3", - "jest-util": "^28.1.3", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-runtime/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-snapshot": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.3.tgz", - "integrity": "sha512-4lzMgtiNlc3DU/8lZfmqxN3AYD6GGLbl+72rdBpXvcV+whX7mDrREzkPdp2RnmfIiWBg1YbuFSkXduF2JcafJg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^28.1.3", - "@jest/transform": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^28.1.3", - "graceful-fs": "^4.2.9", - "jest-diff": "^28.1.3", - "jest-get-type": "^28.0.2", - "jest-haste-map": "^28.1.3", - "jest-matcher-utils": "^28.1.3", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "natural-compare": "^1.4.0", - "pretty-format": "^28.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", - "dev": true, - "dependencies": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-validate": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.1.3.tgz", - "integrity": "sha512-SZbOGBWEsaTxBGCOpsRWlXlvNkvTkY0XxRfh7zYmvd8uL5Qzyg0CHAXiXKROflh801quA6+/DsT4ODDthOC/OA==", - "dev": true, - "dependencies": { - "@jest/types": "^28.1.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", - "leven": "^3.1.0", - "pretty-format": "^28.1.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watcher": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", - "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", - "dev": true, - "dependencies": { - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.10.2", - "jest-util": "^28.1.3", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-worker": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", - "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/js-sdsl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", - "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json-templates": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/json-templates/-/json-templates-4.2.0.tgz", - "integrity": "sha512-NX0r9SEI2bsz17DJpKhZPymvlw/vcMcRqjqRC0jl7pofLwcpaSsfjweatMFt9QXaUv+dR5EBzInBp8y5lzluIQ==", - "dependencies": { - "dedupe": "^3.0.2", - "object-path": "^0.11.8" - } - }, - "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs= sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" - }, - "node_modules/loglevel": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", - "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==", - "engines": { - "node": ">= 0.6.0" - }, - "funding": { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/loglevel" - } - }, - "node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI= sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", - "dev": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", - "optional": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/nexus": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/nexus/-/nexus-1.3.0.tgz", - "integrity": "sha512-w/s19OiNOs0LrtP7pBmD9/FqJHvZLmCipVRt6v1PM8cRUYIbhEswyNKGHVoC4eHZGPSnD+bOf5A3+gnbt0A5/A==", - "dependencies": { - "iterall": "^1.3.0", - "tslib": "^2.0.3" - }, - "peerDependencies": { - "graphql": "15.x || 16.x" - } - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/node-abort-controller": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", - "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" - }, - "node_modules/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", - "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", - "dev": true - }, - "node_modules/node-ssh": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/node-ssh/-/node-ssh-13.0.0.tgz", - "integrity": "sha512-8yfPvuB8z1M5rXFR8Z1Tl0a0M43N64VjZfjXRwOGCcImFphuXhMPniPksf1FkVj9djKbpHvLUMIVS399H9yCSQ==", - "dependencies": { - "is-stream": "^2.0.0", - "make-dir": "^3.1.0", - "sb-promise-queue": "^2.1.0", - "sb-scandir": "^3.1.0", - "shell-escape": "^0.2.0", - "ssh2": "^1.5.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-all": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", - "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" - }, - "bin": { - "npm-run-all": "bin/npm-run-all/index.js", - "run-p": "bin/run-p/index.js", - "run-s": "bin/run-s/index.js" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/npm-run-all/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/npm-run-all/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/npm-run-all/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/npm-run-all/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/npm-run-all/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/npm-run-all/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-all/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-all/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-path": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.8.tgz", - "integrity": "sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==", - "engines": { - "node": ">= 10.12.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", - "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-exit-leak-free": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", - "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==" - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E= sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", - "dev": true, - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18= sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidtree": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", - "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", - "dev": true, - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/pino": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-8.11.0.tgz", - "integrity": "sha512-Z2eKSvlrl2rH8p5eveNUnTdd4AjJk8tAsLkHYZQKGHP4WTh2Gi1cOSOs3eWPqaj+niS3gj4UkoreoaWgF3ZWYg==", - "dependencies": { - "atomic-sleep": "^1.0.0", - "fast-redact": "^3.1.1", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "v1.0.0", - "pino-std-serializers": "^6.0.0", - "process-warning": "^2.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^3.1.0", - "thread-stream": "^2.0.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/pino-abstract-transport": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz", - "integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==", - "dependencies": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - } - }, - "node_modules/pino-pretty": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-9.4.0.tgz", - "integrity": "sha512-NIudkNLxnl7MGj1XkvsqVyRgo6meFP82ECXF2PlOI+9ghmbGuBUUqKJ7IZPIxpJw4vhhSva0IuiDSAuGh6TV9g==", - "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.0", - "fast-safe-stringify": "^2.1.1", - "help-me": "^4.0.1", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", - "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/pino-std-serializers": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.0.0.tgz", - "integrity": "sha512-mMMOwSKrmyl+Y12Ri2xhH1lbzQxwwpuru9VjyJpgFIH4asSj88F2csdMwN6+M5g1Ll4rmsYghHLQJw81tgZ7LQ==" - }, - "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "dependencies": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/prisma": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-4.2.1.tgz", - "integrity": "sha512-HuYqnTDgH8atjPGtYmY0Ql9XrrJnfW7daG1PtAJRW0E6gJxc50lY3vrIDn0yjMR3TvRlypjTcspQX8DT+xD4Sg==", - "hasInstallScript": true, - "dependencies": { - "@prisma/engines": "4.2.1" - }, - "bin": { - "prisma": "build/index.js", - "prisma2": "build/index.js" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/process-warning": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-2.0.0.tgz", - "integrity": "sha512-+MmoAXoUX+VTHAlwns0h+kFUWFs/3FZy+ZuchkgjyOu3oioLAo2LB5aCfKPh2+P9O18i3m43tUEv3YqttSy0Ww==" - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-format-unescaped": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==" - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", - "dev": true - }, - "node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", - "dev": true, - "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/readable-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.1.0.tgz", - "integrity": "sha512-sVisi3+P2lJ2t0BPbpK629j8wRW06yKGJUcaLAGXPAUhyUxVJm7VsCTit1PFgT4JHUDMrGNR+ZjSKpzGaRF3zw==", - "dependencies": { - "abort-controller": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/real-require": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", - "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I= sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", - "dev": true, - "dependencies": { - "is-core-module": "^2.11.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve.exports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", - "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-stable-stringify": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz", - "integrity": "sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==", - "engines": { - "node": ">=10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sb-promise-queue": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sb-promise-queue/-/sb-promise-queue-2.1.0.tgz", - "integrity": "sha512-zwq4YuP1FQFkGx2Q7GIkZYZ6PqWpV+bg0nIO1sJhWOyGyhqbj0MsTvK6lCFo5TQwX5pZr6SCQ75e8PCDCuNvkg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/sb-scandir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/sb-scandir/-/sb-scandir-3.1.0.tgz", - "integrity": "sha512-70BVm2xz9jn94zSQdpvYrEG101/UV9TVGcfWr9T5iob3QhCK4lYXeculfBqPGFv3XTeKgx4dpWyYIDeZUqo4kg==", - "dependencies": { - "sb-promise-queue": "^2.1.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/secure-json-parse": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.4.0.tgz", - "integrity": "sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg==" - }, - "node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-escape": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/shell-escape/-/shell-escape-0.2.0.tgz", - "integrity": "sha512-uRRBT2MfEOyxuECseCZd28jC1AJ8hmqqneWQ4VWUTgCAFvb3wKU1jLqj6egC4Exrr88ogg3dp+zroH4wJuaXzw==" - }, - "node_modules/shell-quote": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", - "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", - "dev": true - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sonic-boom": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.2.0.tgz", - "integrity": "sha512-SbbZ+Kqj/XIunvIAgUZRlqd6CGQYq71tRRbXR92Za8J/R3Yh4Av+TWENiSiEgnlwckYLyP0YZQWVfyNC0dzLaA==", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", - "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", - "dev": true - }, - "node_modules/split2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", - "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/ssh2": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.11.0.tgz", - "integrity": "sha512-nfg0wZWGSsfUe/IBJkXVll3PEZ//YH2guww+mP88gTpuSU4FtZN7zu9JoeTGOyCNx2dTDtT9fOpWwlzyj4uOOw==", - "hasInstallScript": true, - "dependencies": { - "asn1": "^0.2.4", - "bcrypt-pbkdf": "^1.0.2" - }, - "engines": { - "node": ">=10.16.0" - }, - "optionalDependencies": { - "cpu-features": "~0.0.4", - "nan": "^2.16.0" - } - }, - "node_modules/stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string.prototype.padend": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz", - "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/synckit": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", - "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", - "dev": true, - "dependencies": { - "@pkgr/utils": "^2.3.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/thread-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.0.1.tgz", - "integrity": "sha512-X7vWOdsHLkBq0si20ruEE2ttpS7WOVyD52xKu+TOjrRP9Qi9uB9ynHYpzZUbBptArBSuKYUn4mH+jEBnO2CRGg==", - "dependencies": { - "real-require": "^0.2.0" - } - }, - "node_modules/tiny-glob": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", - "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", - "dev": true, - "dependencies": { - "globalyzer": "0.1.0", - "globrex": "^0.1.2" - } - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/ts-jest": { - "version": "28.0.8", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-28.0.8.tgz", - "integrity": "sha512-5FaG0lXmRPzApix8oFG8RKjAz4ehtm8yMKOTy5HX3fY6W8kmvOrmcY0hKDElW52FJov+clhUbrKAqofnj4mXTg==", - "dev": true, - "dependencies": { - "bs-logger": "0.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^28.0.0", - "json5": "^2.2.1", - "lodash.memoize": "4.x", - "make-error": "1.x", - "semver": "7.x", - "yargs-parser": "^21.0.1" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/types": "^28.0.0", - "babel-jest": "^28.0.0", - "jest": "^28.0.0", - "typescript": ">=4.3" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } - } - }, - "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-node-dev": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz", - "integrity": "sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w==", - "dev": true, - "dependencies": { - "chokidar": "^3.5.1", - "dynamic-dedupe": "^0.3.0", - "minimist": "^1.2.6", - "mkdirp": "^1.0.4", - "resolve": "^1.0.0", - "rimraf": "^2.6.1", - "source-map-support": "^0.5.12", - "tree-kill": "^1.2.2", - "ts-node": "^10.4.0", - "tsconfig": "^7.0.0" - }, - "bin": { - "ts-node-dev": "lib/bin.js", - "tsnd": "lib/bin.js" - }, - "engines": { - "node": ">=0.8.0" - }, - "peerDependencies": { - "node-notifier": "*", - "typescript": "*" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/ts-node-dev/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ts-node-dev/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/tsconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", - "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", - "dev": true, - "dependencies": { - "@types/strip-bom": "^3.0.0", - "@types/strip-json-comments": "0.0.30", - "strip-bom": "^3.0.0", - "strip-json-comments": "^2.0.0" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/tsconfig/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/tsconfig/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo= sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tslib": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", - "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "node_modules/v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/value-or-promise": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz", - "integrity": "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==", - "engines": { - "node": ">=12" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0= sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/write-file-atomic": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.1.tgz", - "integrity": "sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" - } - }, - "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xss": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.10.tgz", - "integrity": "sha512-qmoqrRksmzqSKvgqzN0055UFWY7OKx1/9JWeRswwEVX9fCG5jcYRxa/A2DHcmZX6VJvjzHRQ2STeeVcQkrmLSw==", - "dependencies": { - "commander": "^2.20.3", - "cssfilter": "0.0.10" - }, - "bin": { - "xss": "bin/xss" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 392738cf..3300907e 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -782,6 +782,7 @@ type NetNode { interfaces: [NetInterface!]! name: String! networks: [NetNetwork!]! + nodeId: String! } type NetRoutingPaths { diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 43fc5f49..c5502a6d 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -802,6 +802,7 @@ export interface NexusGenObjects { interfaces: NexusGenRootTypes['NetInterface'][]; // [NetInterface!]! name: string; // String! networks: NexusGenRootTypes['NetNetwork'][]; // [NetNetwork!]! + nodeId: string; // String! }; NetRoutingPaths: { // root type @@ -1486,6 +1487,7 @@ export interface NexusGenFieldTypes { interfaces: NexusGenRootTypes['NetInterface'][]; // [NetInterface!]! name: string; // String! networks: NexusGenRootTypes['NetNetwork'][]; // [NetNetwork!]! + nodeId: string; // String! }; NetRoutingPaths: { // field return type @@ -2251,6 +2253,7 @@ export interface NexusGenFieldTypeNames { interfaces: 'NetInterface'; name: 'String'; networks: 'NetNetwork'; + nodeId: 'String'; }; NetRoutingPaths: { // field return type name diff --git a/src/schema/topology.ts b/src/schema/topology.ts index c6b8efe6..e0bfb66a 100644 --- a/src/schema/topology.ts +++ b/src/schema/topology.ts @@ -354,6 +354,7 @@ export const NetNode = objectType({ name: 'NetNode', definition: (t) => { t.nonNull.id('id'); + t.nonNull.string('nodeId'); t.nonNull.string('name'); t.nonNull.list.nonNull.field('interfaces', { type: nonNull(NetInterface) }); t.nonNull.list.nonNull.field('networks', { type: nonNull(NetNetwork) }); @@ -402,6 +403,7 @@ export const NetTopologyQuery = extendType({ return { nodes: nodes.map((n) => ({ id: toGraphId('GraphNode', n._id), + nodeId: n._id, name: n.router_id, interfaces: interfaceMap[n._id] ?? [], coordinates: n.coordinates, From 1235672277a36606c5ebb3b78e874c0369e1352d Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Wed, 9 Aug 2023 16:01:52 +0200 Subject: [PATCH 47/69] update logic of how to handle update of event handler (#337) --- src/helpers/event-handler.helpers.ts | 28 ++++++++++++++++++++----- src/schema/event-handler.ts | 31 ++++++++++++++++------------ 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/helpers/event-handler.helpers.ts b/src/helpers/event-handler.helpers.ts index 8ad6cd55..6dbf88cc 100644 --- a/src/helpers/event-handler.helpers.ts +++ b/src/helpers/event-handler.helpers.ts @@ -163,14 +163,32 @@ function makeFromGraphQLToApiEventHandlerAction(eventHandlerAction: EventHandler }; } -export function makeFromGraphQLToApiEventHandler(eventHandler: EventHandlerGraphQL): ApiEventHandler { +export function makeFromGraphQLToApiEventHandler( + eventHandler: EventHandlerGraphQL, + oldEventHandler: ApiEventHandler | null = null, +): ApiEventHandler { + if (oldEventHandler == null) { + return { + name: eventHandler.name, + event: eventHandler.event, + actions: eventHandler.actions.map(makeFromGraphQLToApiEventHandlerAction), + condition: eventHandler.condition || undefined, + active: eventHandler.isActive || undefined, + evaluatorType: eventHandler.evaluatorType || undefined, + }; + } + return { name: eventHandler.name, event: eventHandler.event, - active: eventHandler.isActive || undefined, - condition: eventHandler.condition || undefined, - actions: eventHandler.actions.map(makeFromGraphQLToApiEventHandlerAction), - evaluatorType: eventHandler.evaluatorType || undefined, + actions: + eventHandler.actions == null || eventHandler.actions.length === 0 + ? oldEventHandler.actions + : eventHandler.actions.map(makeFromGraphQLToApiEventHandlerAction), + condition: eventHandler.condition == null ? oldEventHandler.condition || undefined : eventHandler.condition, + active: eventHandler.isActive == null ? oldEventHandler.active || undefined : eventHandler.isActive, + evaluatorType: + eventHandler.evaluatorType == null ? oldEventHandler.evaluatorType || undefined : eventHandler.evaluatorType, }; } diff --git a/src/schema/event-handler.ts b/src/schema/event-handler.ts index 11254e78..a070a1e3 100644 --- a/src/schema/event-handler.ts +++ b/src/schema/event-handler.ts @@ -226,23 +226,28 @@ export const UpdateEventHandlerMutation = mutationField('updateEventHandler', { if (input.actions == null || input.actions.length === 0) { await conductorAPI.updateEventHandler(config.conductorApiURL, { ...oldEventHandler, - ...makeFromGraphQLToApiEventHandler({ - ...input, - actions: [], - name, - event, - }), - actions: oldEventHandler.actions, + ...makeFromGraphQLToApiEventHandler( + { + ...input, + actions: [], + name, + event, + }, + oldEventHandler, + ), }); } else { await conductorAPI.updateEventHandler(config.conductorApiURL, { ...oldEventHandler, - ...makeFromGraphQLToApiEventHandler({ - ...input, - actions: input.actions, - name, - event, - }), + ...makeFromGraphQLToApiEventHandler( + { + ...input, + actions: input.actions, + name, + event, + }, + oldEventHandler, + ), }); } From 4610995b4174118ebb04bd22e21b3b13d81938b6 Mon Sep 17 00:00:00 2001 From: plehocky <117287338+plehocky@users.noreply.github.com> Date: Mon, 14 Aug 2023 14:45:46 +0200 Subject: [PATCH 48/69] added sorting to event handlers (#338) * added sorting * making workflows sorting optional * formatting * lint fix * removed filtering possibility by actions * formatting fix * typo fix * made ordering optional * convert graphql to api sortKey helper function added * use ternary operator; switch can be introduced later if needed --------- Co-authored-by: PeterL Co-authored-by: Martin Sottnik --- src/helpers/event-handler.helpers.ts | 15 +++++++++++++++ src/schema/api.graphql | 15 ++++++++++++++- src/schema/event-handler.ts | 24 +++++++++++++++++++++--- src/schema/nexus-typegen.ts | 9 ++++++++- src/schema/workflow.ts | 11 +++++------ 5 files changed, 63 insertions(+), 11 deletions(-) diff --git a/src/helpers/event-handler.helpers.ts b/src/helpers/event-handler.helpers.ts index 6dbf88cc..7fdfe1cc 100644 --- a/src/helpers/event-handler.helpers.ts +++ b/src/helpers/event-handler.helpers.ts @@ -1,5 +1,7 @@ +import { orderBy } from 'lodash'; import { ApiEventHandler, ApiEventHandlerAction } from '../external-api/conductor-network-types'; import { toGraphId } from './id-helper'; +import { NexusGenEnums } from '../schema/nexus-typegen'; type StartWorkflowGraphQL = { name?: string | null; @@ -241,3 +243,16 @@ export function filterEventHandlers( return true; }); } + +function convertGraphqlSortKeyToApiSortKey(sortKey: NexusGenEnums['SortEventHandlersBy']): keyof ApiEventHandler { + return sortKey === 'isActive' ? 'active' : sortKey; +} + +export function getOrderedEventHandlers( + eventHandlers: ApiEventHandler[], + sortKey: NexusGenEnums['SortEventHandlersBy'], + direction: string, +) { + const apiSortKey = convertGraphqlSortKeyToApiSortKey(sortKey); + return orderBy(eventHandlers, apiSortKey, [direction === 'ASC' ? 'asc' : 'desc']); +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 3300907e..b884feb9 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -446,6 +446,11 @@ type EventHandlerEdge { node: EventHandler! } +input EventHandlersOrderByInput { + direction: SortDirection! + sortKey: SortEventHandlersBy! +} + input ExecuteNewWorkflowInput { correlationId: String externalInputPayloadStoragePath: String @@ -890,6 +895,7 @@ type Query { filter: FilterEventHandlerInput first: Int last: Int + orderBy: EventHandlersOrderByInput ): EventHandlerConnection eventHandlersByEvent( activeOnly: Boolean @@ -947,7 +953,7 @@ type Query { filter: FilterWorkflowsInput first: Int last: Int - orderBy: WorkflowsOrderByInput! + orderBy: WorkflowsOrderByInput ): WorkflowConnection! zones(after: String, before: String, first: Int, last: Int): ZonesConnection! } @@ -1056,6 +1062,13 @@ enum SortDirection { DESC } +enum SortEventHandlersBy { + evaluatorType + event + isActive + name +} + enum SortExecutedWorkflowsBy { endTime startTime diff --git a/src/schema/event-handler.ts b/src/schema/event-handler.ts index a070a1e3..7b9cd338 100644 --- a/src/schema/event-handler.ts +++ b/src/schema/event-handler.ts @@ -10,10 +10,11 @@ import { stringArg, } from 'nexus'; import { v4 as uuid } from 'uuid'; -import { IsOkResponse, Node, PaginationConnectionArgs } from './global-types'; +import { IsOkResponse, Node, PaginationConnectionArgs, SortDirection } from './global-types'; import config from '../config'; import { filterEventHandlers, + getOrderedEventHandlers, makeFromApiToGraphQLEventHandler, makeFromGraphQLToApiEventHandler, } from '../helpers/event-handler.helpers'; @@ -107,18 +108,35 @@ export const FilterEventHandlerInput = inputObjectType({ }, }); +export const SortEventHandlersBy = enumType({ + name: 'SortEventHandlersBy', + members: ['isActive', 'name', 'evaluatorType', 'event'], +}); + +export const EventHandlersOrderByInput = inputObjectType({ + name: 'EventHandlersOrderByInput', + definition: (t) => { + t.nonNull.field('sortKey', { type: SortEventHandlersBy }); + t.nonNull.field('direction', { type: SortDirection }); + }, +}); + export const EventHandlerQuery = queryField('eventHandlers', { type: EventHandlerConnection, args: { filter: arg({ type: FilterEventHandlerInput }), ...PaginationConnectionArgs, + orderBy: EventHandlersOrderByInput, }, resolve: async (_, args, { conductorAPI }) => { - const { filter, ...paginationArgs } = args; + const { filter, orderBy: orderingArgs, ...paginationArgs } = args; const eventHandlers = await conductorAPI.getEventHandlers(config.conductorApiURL); const filteredEventHandlers = filterEventHandlers(eventHandlers, filter); - const mappedEventHandlersWithId = filteredEventHandlers.map((eventHandler) => ({ + const orderedEventHandlers = orderingArgs + ? getOrderedEventHandlers(filteredEventHandlers, orderingArgs.sortKey, orderingArgs.direction) + : filteredEventHandlers; + const mappedEventHandlersWithId = orderedEventHandlers.map((eventHandler) => ({ ...makeFromApiToGraphQLEventHandler(eventHandler), })); diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index c5502a6d..64cbb238 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -210,6 +210,11 @@ export interface NexusGenInputs { failTask?: NexusGenInputs['ActionFailTaskInput'] | null; // ActionFailTaskInput startWorkflow?: NexusGenInputs['ActionStartWorkflowInput'] | null; // ActionStartWorkflowInput }; + EventHandlersOrderByInput: { + // input type + direction: NexusGenEnums['SortDirection']; // SortDirection! + sortKey: NexusGenEnums['SortEventHandlersBy']; // SortEventHandlersBy! + }; ExecuteNewWorkflowInput: { // input type correlationId?: string | null; // String @@ -461,6 +466,7 @@ export interface NexusGenEnums { ScheduleStatus: 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; SortDeviceBy: 'CREATED_AT' | 'NAME'; SortDirection: 'ASC' | 'DESC'; + SortEventHandlersBy: 'evaluatorType' | 'event' | 'isActive' | 'name'; SortExecutedWorkflowsBy: 'endTime' | 'startTime' | 'status' | 'workflowId' | 'workflowName'; SortExecutedWorkflowsDirection: 'asc' | 'desc'; SortPollsBy: 'lastPollTime' | 'queueName' | 'workerId'; @@ -2842,6 +2848,7 @@ export interface NexusGenArgTypes { filter?: NexusGenInputs['FilterEventHandlerInput'] | null; // FilterEventHandlerInput first?: number | null; // Int last?: number | null; // Int + orderBy?: NexusGenInputs['EventHandlersOrderByInput'] | null; // EventHandlersOrderByInput }; eventHandlersByEvent: { // args @@ -2940,7 +2947,7 @@ export interface NexusGenArgTypes { filter?: NexusGenInputs['FilterWorkflowsInput'] | null; // FilterWorkflowsInput first?: number | null; // Int last?: number | null; // Int - orderBy: NexusGenInputs['WorkflowsOrderByInput']; // WorkflowsOrderByInput! + orderBy?: NexusGenInputs['WorkflowsOrderByInput'] | null; // WorkflowsOrderByInput }; zones: { // args diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 66e426ff..4327716e 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -167,7 +167,7 @@ export const WorkflowsQuery = extendType({ args: { ...PaginationConnectionArgs, filter: FilterWorkflowsInput, - orderBy: nonNull(WorkflowsOrderByInput), + orderBy: WorkflowsOrderByInput, }, resolve: async (_, args, { conductorAPI }) => { const { filter, orderBy: orderingArgs, ...paginationArgs } = args; @@ -176,11 +176,10 @@ export const WorkflowsQuery = extendType({ const filteredWorkflows = filter?.labels || filter?.keyword ? getFilteredWorkflows(workflows, filter) : workflows; - const orderedData = orderBy( - filteredWorkflows, - [orderingArgs.sortKey], - [orderingArgs.direction === 'ASC' ? 'asc' : 'desc'], - ); + const orderedData = + (orderingArgs && + orderBy(filteredWorkflows, [orderingArgs.sortKey], [orderingArgs.direction === 'ASC' ? 'asc' : 'desc'])) ?? + filteredWorkflows; const workflowsWithId = orderedData.map((w) => ({ ...w, From fd31ef32882144c363fb46300fe6296cd6253688 Mon Sep 17 00:00:00 2001 From: plehocky <117287338+plehocky@users.noreply.github.com> Date: Tue, 22 Aug 2023 12:52:30 +0200 Subject: [PATCH 49/69] added sorting to taskDefinitions query (#342) Co-authored-by: PeterL --- src/schema/api.graphql | 15 +++++++++++++++ src/schema/nexus-typegen.ts | 7 +++++++ src/schema/task-definitons.ts | 23 +++++++++++++++++++---- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/schema/api.graphql b/src/schema/api.graphql index b884feb9..f2bf3b3a 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -938,6 +938,7 @@ type Query { filter: FilterTaskDefinitionsInput first: Int last: Int + orderBy: TasksOrderByInput ): TaskDefinitionConnection! topology(filter: FilterTopologyInput): Topology topologyCommonNodes(nodes: [String!]!): TopologyCommonNodes @@ -1093,6 +1094,15 @@ enum SortPollsDirection { desc } +enum SortTasksBy { + name + responseTimeoutSeconds + retryCount + retryLogic + timeoutPolicy + timeoutSeconds +} + enum SortWorkflowsBy { name } @@ -1180,6 +1190,11 @@ enum TaskTimeoutPolicy { TIME_OUT_WF } +input TasksOrderByInput { + direction: SortDirection! + sortKey: SortTasksBy! +} + input TerminateWorkflowInput { reason: String } diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 64cbb238..5827b406 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -361,6 +361,11 @@ export interface NexusGenInputs { type?: string | null; // String workflowTaskType?: Array | null; // [WorkflowTaskType] }; + TasksOrderByInput: { + // input type + direction: NexusGenEnums['SortDirection']; // SortDirection! + sortKey: NexusGenEnums['SortTasksBy']; // SortTasksBy! + }; TerminateWorkflowInput: { // input type reason?: string | null; // String @@ -471,6 +476,7 @@ export interface NexusGenEnums { SortExecutedWorkflowsDirection: 'asc' | 'desc'; SortPollsBy: 'lastPollTime' | 'queueName' | 'workerId'; SortPollsDirection: 'asc' | 'desc'; + SortTasksBy: 'name' | 'responseTimeoutSeconds' | 'retryCount' | 'retryLogic' | 'timeoutPolicy' | 'timeoutSeconds'; SortWorkflowsBy: 'name'; TaskTimeoutPolicy: 'ALERT_ONLY' | 'RETRY' | 'TIME_OUT_WF'; TimeoutPolicy: 'ALERT_ONLY' | 'TIME_OUT_WF'; @@ -2922,6 +2928,7 @@ export interface NexusGenArgTypes { filter?: NexusGenInputs['FilterTaskDefinitionsInput'] | null; // FilterTaskDefinitionsInput first?: number | null; // Int last?: number | null; // Int + orderBy?: NexusGenInputs['TasksOrderByInput'] | null; // TasksOrderByInput }; topology: { // args diff --git a/src/schema/task-definitons.ts b/src/schema/task-definitons.ts index c0fb7bf6..eecf17c8 100644 --- a/src/schema/task-definitons.ts +++ b/src/schema/task-definitons.ts @@ -14,7 +14,7 @@ import config from '../config'; import { filterPollData, makeFromApiToGraphQLPollData } from '../helpers/task.helpers'; import { toGraphId } from '../helpers/id-helper'; import { getTaskDefinitionInput, getFilteredTaskDefinitions } from '../helpers/task-definition.helpers'; -import { IsOkResponse, Node, PageInfo, PaginationConnectionArgs } from './global-types'; +import { IsOkResponse, Node, PageInfo, PaginationConnectionArgs, SortDirection } from './global-types'; import { connectionFromArray } from '../helpers/connection.helpers'; const TaskTimeoutPolicy = enumType({ @@ -98,7 +98,17 @@ export const FilterTaskDefinitionsInput = inputObjectType({ t.string('keyword'); }, }); - +export const SortTasksBy = enumType({ + name: 'SortTasksBy', + members: ['name', 'timeoutPolicy', 'timeoutSeconds', 'responseTimeoutSeconds', 'retryCount', 'retryLogic'], +}); +export const TasksOrderByInput = inputObjectType({ + name: 'TasksOrderByInput', + definition: (t) => { + t.nonNull.field('sortKey', { type: SortTasksBy }); + t.nonNull.field('direction', { type: SortDirection }); + }, +}); export const TaskDefinitionsQuery = extendType({ type: 'Query', definition: (t) => { @@ -107,15 +117,20 @@ export const TaskDefinitionsQuery = extendType({ args: { ...PaginationConnectionArgs, filter: arg({ type: FilterTaskDefinitionsInput }), + orderBy: TasksOrderByInput, }, resolve: async (_, args, { conductorAPI }) => { - const { filter, ...paginationArgs } = args; + const { filter, orderBy: orderingArgs, ...paginationArgs } = args; const taskDefinitions = await conductorAPI.getTaskDefinitions(config.conductorApiURL); + const filteredTaskDefs = filter?.keyword ? getFilteredTaskDefinitions(taskDefinitions, filter.keyword) : taskDefinitions; + const orderedTaskDefs = orderingArgs?.sortKey + ? orderBy(filteredTaskDefs, orderingArgs?.sortKey, orderingArgs?.direction === 'ASC' ? 'asc' : 'desc') + : filteredTaskDefs; - const tasksWithId = filteredTaskDefs.map((task) => ({ + const tasksWithId = orderedTaskDefs.map((task) => ({ ...task, id: toGraphId('TaskDefinition', task.name), })); From af37af9b841b7e94fa863680e982529e290e9d3a Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 24 Aug 2023 10:50:58 +0200 Subject: [PATCH 50/69] FD-540 shortest path weights (#340) * topology query graphql * add helper functions * add weights to shortest path and net topology query * prisma upgraded 4.2.1 -> 5.1.1 * fix device.spec.ts test * use device name as nodeId (topology edges fix) * make changes according to latest changes in topolgoy-discovery (master) --------- Co-authored-by: Paulooze --- package.json | 4 +- .../topology-discovery.graphql.ts | 76 +++++--- src/external-api/conductor-network-types.ts | 2 +- .../topology-discovery-graphql.ts | 125 ++++++++++++- src/helpers/topology.helpers.ts | 164 +++++++++++++++++- src/schema/api.graphql | 14 +- src/schema/nexus-typegen.ts | 40 +++-- src/schema/topology.ts | 131 ++++---------- src/test/helpers.ts | 10 -- yarn.lock | 36 ++-- 10 files changed, 433 insertions(+), 169 deletions(-) diff --git a/package.json b/package.json index 0ad51c9b..2be25f66 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "dependencies": { "@devoxa/prisma-relay-cursor-connection": "2.2.2", "@graphql-tools/schema": "^9.0.9", - "@prisma/client": "4.2.1", + "@prisma/client": "5.1.1", "@types/express": "4.17.13", "@types/graphql-upload": "15.0.2", "@types/json-templates": "3.0.0", @@ -90,7 +90,7 @@ "node-ssh": "^13.0.0", "pino": "8.11.0", "pino-pretty": "9.4.0", - "prisma": "4.2.1", + "prisma": "5.1.1", "ssh2": "^1.11.0", "url-join": "4.0.1", "uuid": "^9.0.0", diff --git a/src/__generated__/topology-discovery.graphql.ts b/src/__generated__/topology-discovery.graphql.ts index 78eb839c..ae96a38f 100644 --- a/src/__generated__/topology-discovery.graphql.ts +++ b/src/__generated__/topology-discovery.graphql.ts @@ -12,17 +12,33 @@ export type Scalars = { Float: number; }; -export type AlternativePaths = { - __typename?: 'AlternativePaths'; - edges: Maybe>>>; -}; - export type Coordinates = { __typename?: 'Coordinates'; x: Scalars['Float']; y: Scalars['Float']; }; +export type CreateBackupResponse = { + __typename?: 'CreateBackupResponse'; + db_name: Scalars['String']; +}; + +export type DeleteBackupsResponse = { + __typename?: 'DeleteBackupsResponse'; + deleted_backups: Array; +}; + +export type Mutation = { + __typename?: 'Mutation'; + createBackup: CreateBackupResponse; + deleteBackups: DeleteBackupsResponse; +}; + + +export type MutationDeleteBackupsArgs = { + delete_age?: InputMaybe; +}; + export type NetDevice = Node & { __typename?: 'NetDevice'; id: Scalars['ID']; @@ -36,15 +52,15 @@ export type NetDevice = Node & { export type NetDeviceNetInterfacesArgs = { cursor?: InputMaybe; - filter?: InputMaybe; - first: Scalars['Int']; + filters?: InputMaybe; + first?: InputMaybe; }; export type NetDeviceNetNetworksArgs = { cursor?: InputMaybe; - filter?: InputMaybe; - first: Scalars['Int']; + filters?: InputMaybe; + first?: InputMaybe; }; export type NetDeviceConnection = { @@ -67,6 +83,7 @@ export type NetDeviceFilter = { export type NetInterface = Node & { __typename?: 'NetInterface'; id: Scalars['ID']; + igp_metric: Maybe; ipAddress: Scalars['String']; netDevice: Maybe; netLink: Maybe; @@ -115,8 +132,7 @@ export type NetNetworkFilter = { export type NetRoutingPathConnection = { __typename?: 'NetRoutingPathConnection'; - alternativePaths: Maybe; - shortestPath: Maybe; + edges: Maybe>; }; export type NetRoutingPathOutputCollections = @@ -127,6 +143,12 @@ export type Node = { id: Scalars['ID']; }; +export type NodeInfo = { + __typename?: 'NodeInfo'; + node: Scalars['ID']; + weight: Maybe; +}; + export type NodeStatus = | 'ok' | 'unknown'; @@ -153,8 +175,8 @@ export type PhyDevice = Node & { export type PhyDevicePhyInterfacesArgs = { cursor?: InputMaybe; - filter?: InputMaybe; - first: Scalars['Int']; + filters?: InputMaybe; + first?: InputMaybe; }; export type PhyDeviceConnection = { @@ -208,6 +230,7 @@ export type PhyInterfaceFilter = { export type Query = { __typename?: 'Query'; + backups: Array; netDevices: NetDeviceConnection; netRoutingPaths: Maybe; node: Maybe; @@ -217,8 +240,8 @@ export type Query = { export type QueryNetDevicesArgs = { cursor?: InputMaybe; - filter?: InputMaybe; - first: Scalars['Int']; + filters?: InputMaybe; + first?: InputMaybe; }; @@ -236,13 +259,14 @@ export type QueryNodeArgs = { export type QueryPhyDevicesArgs = { cursor?: InputMaybe; - filter?: InputMaybe; - first: Scalars['Int']; + filters?: InputMaybe; + first?: InputMaybe; }; -export type ShortestPath = { - __typename?: 'ShortestPath'; - edges: Maybe>; +export type RoutingPath = { + __typename?: 'RoutingPath'; + nodes: Array; + weight: Scalars['Int']; }; export type GetShortestPathQueryVariables = Exact<{ @@ -252,4 +276,14 @@ export type GetShortestPathQueryVariables = Exact<{ }>; -export type GetShortestPathQuery = { __typename?: 'Query', netRoutingPaths: { __typename?: 'NetRoutingPathConnection', shortestPath: { __typename?: 'ShortestPath', edges: Array | null } | null, alternativePaths: { __typename?: 'AlternativePaths', edges: Array | null> | null } | null } | null }; +export type GetShortestPathQuery = { __typename?: 'Query', netRoutingPaths: { __typename?: 'NetRoutingPathConnection', edges: Array<{ __typename?: 'RoutingPath', weight: number, nodes: Array<{ __typename?: 'NodeInfo', node: string, weight: number | null }> }> | null } | null }; + +export type TopologyDevicesQueryVariables = Exact<{ [key: string]: never; }>; + + +export type TopologyDevicesQuery = { __typename?: 'Query', phyDevices: { __typename?: 'PhyDeviceConnection', edges: Array<{ __typename?: 'PhyDeviceEdge', node: { __typename?: 'PhyDevice', id: string, name: string, coordinates: { __typename?: 'Coordinates', x: number, y: number }, details: { __typename?: 'PhyDeviceDetails', sw_version: string, device_type: string }, phyInterfaces: { __typename?: 'PhyInterfaceConnection', edges: Array<{ __typename?: 'PhyInterfaceEdge', node: { __typename?: 'PhyInterface', id: string, name: string, status: string, phyLink: { __typename?: 'PhyInterface', id: string, name: string, phyDevice: { __typename?: 'PhyDevice', id: string, name: string } | null } | null } | null } | null> | null } } | null } | null> | null } }; + +export type NetTopologyQueryVariables = Exact<{ [key: string]: never; }>; + + +export type NetTopologyQuery = { __typename?: 'Query', netDevices: { __typename?: 'NetDeviceConnection', edges: Array<{ __typename?: 'NetDeviceEdge', node: { __typename?: 'NetDevice', id: string, routerId: string, phyDevice: { __typename?: 'PhyDevice', id: string, routerId: string | null, coordinates: { __typename?: 'Coordinates', x: number, y: number } } | null, netInterfaces: { __typename?: 'NetInterfaceConnection', edges: Array<{ __typename?: 'NetInterfaceEdge', cursor: string, node: { __typename?: 'NetInterface', id: string, ipAddress: string, netDevice: { __typename?: 'NetDevice', id: string, routerId: string } | null, netLink: { __typename?: 'NetInterface', id: string, igp_metric: number | null, netDevice: { __typename?: 'NetDevice', id: string, routerId: string } | null } | null } | null } | null> | null }, netNetworks: { __typename?: 'NetNetworkConnection', edges: Array<{ __typename?: 'NetNetworkEdge', node: { __typename?: 'NetNetwork', id: string, subnet: string, coordinates: { __typename?: 'Coordinates', x: number, y: number } } | null } | null> | null } } | null } | null> | null } }; diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index 22884afc..91ae5c13 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -81,7 +81,7 @@ const WorkflowMetadataOptional = t.partial({ ownerEmail: optional(t.string), timeoutPolicy: optional(t.union([t.literal('TIME_OUT_WF'), t.literal('ALERT_ONLY')])), variables: optional(t.UnknownRecord), - inputTemplate: optional(t.record(t.string, t.UnknownRecord)), + inputTemplate: optional(t.UnknownRecord), }); const WorkflowMetadata = t.intersection([WorkflowMetadataRequired, WorkflowMetadataOptional]); diff --git a/src/external-api/topology-discovery-graphql.ts b/src/external-api/topology-discovery-graphql.ts index a17748b3..f82046aa 100644 --- a/src/external-api/topology-discovery-graphql.ts +++ b/src/external-api/topology-discovery-graphql.ts @@ -1,15 +1,115 @@ import { GraphQLClient, gql } from 'graphql-request'; import config from '../config'; -import { GetShortestPathQuery, GetShortestPathQueryVariables } from '../__generated__/topology-discovery.graphql'; +import { + GetShortestPathQuery, + GetShortestPathQueryVariables, + NetTopologyQuery, + NetTopologyQueryVariables, + TopologyDevicesQuery, + TopologyDevicesQueryVariables, +} from '../__generated__/topology-discovery.graphql'; const GET_SHORTEST_PATH = gql` query GetShortestPath($deviceFrom: ID!, $deviceTo: ID!, $collection: NetRoutingPathOutputCollections) { netRoutingPaths(deviceFrom: $deviceFrom, deviceTo: $deviceTo, outputCollection: $collection) { - shortestPath { - edges + edges { + weight + nodes { + node + weight + } } - alternativePaths { - edges + } + } +`; + +const GET_TOPOLOGY_DEVICES = gql` + query topologyDevices { + phyDevices { + edges { + node { + id + name + coordinates { + x + y + } + details { + sw_version + device_type + } + phyInterfaces { + edges { + node { + id + name + status + phyLink { + id + name + phyDevice { + id + name + } + } + } + } + } + } + } + } + } +`; + +const GET_NET_TOPOLOGY_DEVICES = gql` + query NetTopology { + netDevices { + edges { + node { + id + routerId + phyDevice { + id + routerId + coordinates { + x + y + } + } + netInterfaces { + edges { + cursor + node { + id + ipAddress + netDevice { + id + routerId + } + netLink { + id + igp_metric + netDevice { + id + routerId + } + } + } + } + } + netNetworks { + edges { + node { + id + subnet + coordinates { + x + y + } + } + } + } + } } } } @@ -26,12 +126,27 @@ function getTopologyDiscoveryApi() { const response = await client.request(GET_SHORTEST_PATH, { deviceFrom: from, deviceTo: to, + collection: 'NetInterface', }); return response; } + async function getTopologyDevices() { + const response = await client.request(GET_TOPOLOGY_DEVICES); + + return response; + } + + async function getNetTopologyDevices() { + const response = await client.request(GET_NET_TOPOLOGY_DEVICES); + + return response; + } + return { + getTopologyDevices, + getNetTopologyDevices, getShortestPath, }; } diff --git a/src/helpers/topology.helpers.ts b/src/helpers/topology.helpers.ts index 669aab97..0df7fe83 100644 --- a/src/helpers/topology.helpers.ts +++ b/src/helpers/topology.helpers.ts @@ -1,3 +1,5 @@ +import { device as PrismaDevice } from '@prisma/client'; +import { NetTopologyQuery, TopologyDevicesQuery } from '../__generated__/topology-discovery.graphql'; import { ArangoDevice, ArangoEdge, @@ -6,7 +8,8 @@ import { Status, TopologyDiffOutput, } from '../external-api/topology-network-types'; -import { unwrap } from './utils.helpers'; +import { omitNullValue, unwrap } from './utils.helpers'; +import { toGraphId } from './id-helper'; type FilterInput = { labelIds?: string[] | null; @@ -151,3 +154,162 @@ export function makeNodesMap( {} as Record, ); } + +function getStatus(status: string | undefined): 'ok' | 'unknown' { + return status === 'ok' ? 'ok' : 'unknown'; +} + +export function makeTopologyNodes(dbDevices: PrismaDevice[], topologyDevices?: TopologyDevicesQuery) { + if (!topologyDevices) { + return []; + } + const nodes = dbDevices + .map((device) => { + const node = topologyDevices?.phyDevices.edges?.find((e) => e?.node?.name === device.name)?.node; + if (node != null) { + return { + id: toGraphId('GraphNode', node.id), + deviceType: node.details.device_type ?? null, + softwareVersion: node.details.sw_version ?? null, + device, + interfaces: + node.phyInterfaces.edges?.map((e) => ({ + id: unwrap(e?.node?.id), + status: getStatus(e?.node?.status), + name: unwrap(e?.node?.name), + })) ?? [], + coordinates: node.coordinates, + }; + } + return null; + }) + .filter(omitNullValue); + return nodes; +} + +function getTopologyInterfaces(topologyDevices: TopologyDevicesQuery) { + return ( + topologyDevices.phyDevices.edges?.flatMap((e) => { + const node = e?.node; + if (!node) { + return []; + } + const nodeInterfaces = node.phyInterfaces.edges + ?.map((ie) => { + const inode = ie?.node; + if (!inode || !inode.phyLink) { + return null; + } + return { + ...inode, + nodeId: node.name, + }; + }) + .filter(omitNullValue); + return nodeInterfaces || []; + }) ?? [] + ); +} + +export function makeTopologyEdges(topologyDevices?: TopologyDevicesQuery) { + if (!topologyDevices) { + return []; + } + + return getTopologyInterfaces(topologyDevices).map((i) => ({ + id: `${i.id}-${i.phyLink?.id}`, + source: { + interface: i.id, + nodeId: i.nodeId, + }, + target: { + interface: unwrap(i.phyLink?.id), + nodeId: unwrap(i.phyLink?.phyDevice?.name), + }, + })); +} + +export function makeNetTopologyNodes(netTopologyDevices?: NetTopologyQuery) { + return ( + netTopologyDevices?.netDevices.edges + ?.map((e) => { + const node = e?.node; + if (!node) { + return null; + } + return { + id: toGraphId('GraphNode', node.id), + nodeId: node.id, + name: node.routerId, + interfaces: + node.netInterfaces.edges + ?.map((i) => { + const interfaceNode = i?.node; + if (!interfaceNode) { + return null; + } + return { + id: interfaceNode.id, + name: interfaceNode.ipAddress, + }; + }) + .filter(omitNullValue) ?? [], + coordinates: node.phyDevice?.coordinates ?? { x: 0, y: 0 }, + networks: + node.netNetworks.edges + ?.map((n) => { + const networkNode = n?.node; + if (!networkNode) { + return null; + } + return { + id: networkNode.id, + subnet: networkNode.subnet, + coordinates: networkNode.coordinates, + }; + }) + .filter(omitNullValue) ?? [], + }; + }) + .filter(omitNullValue) ?? [] + ); +} + +function getEdgesFromTopologyDevices(topologyDevices: NetTopologyQuery['netDevices']['edges']) { + return ( + topologyDevices + ?.flatMap((e) => { + const device = e?.node ?? null; + if (!device) { + return []; + } + + return device.netInterfaces.edges + ?.map((i) => { + const deviceInterface = i?.node; + if (!deviceInterface || !deviceInterface.netDevice || !deviceInterface.netLink?.netDevice) { + return null; + } + + return { + id: `${deviceInterface.id}-${deviceInterface.netLink.id}`, + weight: deviceInterface?.netLink?.igp_metric ?? null, + source: { + interface: deviceInterface.id, + nodeId: deviceInterface.netDevice.routerId, + }, + target: { + interface: deviceInterface.netLink.id, + nodeId: deviceInterface.netLink.netDevice.routerId, + }, + }; + }) + .filter(omitNullValue); + }) + .filter(omitNullValue) ?? [] + ); +} + +export function makeNetTopologyEdges(netTopologyDevices?: NetTopologyQuery) { + return netTopologyDevices ? getEdgesFromTopologyDevices(netTopologyDevices.netDevices.edges) : []; +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index f2bf3b3a..2dff9edb 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -625,6 +625,7 @@ type GraphEdge { id: ID! source: EdgeSourceTarget! target: EdgeSourceTarget! + weight: Int } enum GraphEdgeStatus { @@ -790,9 +791,14 @@ type NetNode { nodeId: String! } -type NetRoutingPaths { - alternativePaths: [[String!]!]! - shortestPath: [String!]! +type NetRoutingPathNode { + nodes: [NetRoutingPathNodeInfo!]! + weight: Int +} + +type NetRoutingPathNodeInfo { + name: String + weight: Int } type NetTopology { @@ -931,7 +937,7 @@ type Query { resourceTypeId: String ): PoolConnection! schedules(after: String, before: String, filter: ScheduleFilterInput, first: Int, last: Int): ScheduleConnection! - shortestPath(from: String!, to: String!): NetRoutingPaths + shortestPath(from: String!, to: String!): [NetRoutingPathNode!]! taskDefinitions( after: String before: String diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 5827b406..fc4a0ce5 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -727,6 +727,7 @@ export interface NexusGenObjects { id: string; // ID! source: NexusGenRootTypes['EdgeSourceTarget']; // EdgeSourceTarget! target: NexusGenRootTypes['EdgeSourceTarget']; // EdgeSourceTarget! + weight?: number | null; // Int }; GraphNode: { // root type @@ -816,10 +817,15 @@ export interface NexusGenObjects { networks: NexusGenRootTypes['NetNetwork'][]; // [NetNetwork!]! nodeId: string; // String! }; - NetRoutingPaths: { + NetRoutingPathNode: { // root type - alternativePaths: string[][]; // [[String!]!]! - shortestPath: string[]; // [String!]! + nodes: NexusGenRootTypes['NetRoutingPathNodeInfo'][]; // [NetRoutingPathNodeInfo!]! + weight?: number | null; // Int + }; + NetRoutingPathNodeInfo: { + // root type + name?: string | null; // String + weight?: number | null; // Int }; NetTopology: { // root type @@ -1348,6 +1354,7 @@ export interface NexusGenFieldTypes { id: string; // ID! source: NexusGenRootTypes['EdgeSourceTarget']; // EdgeSourceTarget! target: NexusGenRootTypes['EdgeSourceTarget']; // EdgeSourceTarget! + weight: number | null; // Int }; GraphNode: { // field return type @@ -1501,10 +1508,15 @@ export interface NexusGenFieldTypes { networks: NexusGenRootTypes['NetNetwork'][]; // [NetNetwork!]! nodeId: string; // String! }; - NetRoutingPaths: { + NetRoutingPathNode: { // field return type - alternativePaths: string[][]; // [[String!]!]! - shortestPath: string[]; // [String!]! + nodes: NexusGenRootTypes['NetRoutingPathNodeInfo'][]; // [NetRoutingPathNodeInfo!]! + weight: number | null; // Int + }; + NetRoutingPathNodeInfo: { + // field return type + name: string | null; // String + weight: number | null; // Int }; NetTopology: { // field return type @@ -1579,7 +1591,7 @@ export interface NexusGenFieldTypes { pollData: NexusGenRootTypes['PollDataConnection'] | null; // PollDataConnection pools: NexusGenRootTypes['PoolConnection']; // PoolConnection! schedules: NexusGenRootTypes['ScheduleConnection']; // ScheduleConnection! - shortestPath: NexusGenRootTypes['NetRoutingPaths'] | null; // NetRoutingPaths + shortestPath: NexusGenRootTypes['NetRoutingPathNode'][]; // [NetRoutingPathNode!]! taskDefinitions: NexusGenRootTypes['TaskDefinitionConnection']; // TaskDefinitionConnection! topology: NexusGenRootTypes['Topology'] | null; // Topology topologyCommonNodes: NexusGenRootTypes['TopologyCommonNodes'] | null; // TopologyCommonNodes @@ -2114,6 +2126,7 @@ export interface NexusGenFieldTypeNames { id: 'ID'; source: 'EdgeSourceTarget'; target: 'EdgeSourceTarget'; + weight: 'Int'; }; GraphNode: { // field return type name @@ -2267,10 +2280,15 @@ export interface NexusGenFieldTypeNames { networks: 'NetNetwork'; nodeId: 'String'; }; - NetRoutingPaths: { + NetRoutingPathNode: { + // field return type name + nodes: 'NetRoutingPathNodeInfo'; + weight: 'Int'; + }; + NetRoutingPathNodeInfo: { // field return type name - alternativePaths: 'String'; - shortestPath: 'String'; + name: 'String'; + weight: 'Int'; }; NetTopology: { // field return type name @@ -2345,7 +2363,7 @@ export interface NexusGenFieldTypeNames { pollData: 'PollDataConnection'; pools: 'PoolConnection'; schedules: 'ScheduleConnection'; - shortestPath: 'NetRoutingPaths'; + shortestPath: 'NetRoutingPathNode'; taskDefinitions: 'TaskDefinitionConnection'; topology: 'Topology'; topologyCommonNodes: 'TopologyCommonNodes'; diff --git a/src/schema/topology.ts b/src/schema/topology.ts index e0bfb66a..3ade7e62 100644 --- a/src/schema/topology.ts +++ b/src/schema/topology.ts @@ -9,11 +9,13 @@ import { makeInterfaceDeviceMap, makeInterfaceMap, makeInterfaceNameMap, - makeNetInterfaceMap, + makeNetTopologyEdges, + makeNetTopologyNodes, makeNodesMap, + makeTopologyEdges, + makeTopologyNodes, } from '../helpers/topology.helpers'; import { unwrap, omitNullValue } from '../helpers/utils.helpers'; -import { NetNetwork as NetNetworkType } from '../external-api/topology-network-types'; export const FilterTopologyInput = inputObjectType({ name: 'FilterTopologyInput', @@ -75,6 +77,7 @@ export const GraphEdge = objectType({ name: 'GraphEdge', definition: (t) => { t.nonNull.id('id'); + t.int('weight'); t.nonNull.field('source', { type: EdgeSourceTarget }); t.nonNull.field('target', { type: EdgeSourceTarget }); }, @@ -130,54 +133,22 @@ export const TopologyQuery = extendType({ args: { filter: FilterTopologyInput, }, - resolve: async (root, args, { prisma, tenantId, topologyDiscoveryAPI }) => { + resolve: async (_, args, { prisma, tenantId, topologyDiscoveryGraphQLAPI }) => { if (!config.topologyEnabled) { return null; } const { filter } = args; - const { has: interfaceEdges, interfaces } = await topologyDiscoveryAPI.getHasAndInterfaces( - unwrap(config.topologyDiscoveryURL), - ); - const interfaceDeviceMap = makeInterfaceDeviceMap(interfaceEdges); - const interfaceNameMap = makeInterfaceNameMap(interfaces, (i) => i.name); - const interfaceMap = makeInterfaceMap(interfaceEdges, interfaceNameMap); + const topologyDevices = await topologyDiscoveryGraphQLAPI?.getTopologyDevices(); const labels = filter?.labels ?? []; const dbLabels = await prisma.label.findMany({ where: { name: { in: labels } } }); const labelIds = dbLabels.map((l) => l.id); const filterQuery = getFilterQuery({ labelIds }); const dbDevices = await prisma.device.findMany({ where: { tenantId, ...filterQuery } }); - const linksAndDevices = await topologyDiscoveryAPI.getLinksAndDevices(unwrap(config.topologyDiscoveryURL)); - const { nodes, edges } = linksAndDevices; - const nodesMap = makeNodesMap(nodes, (n) => n.name); + return { - nodes: dbDevices - .map((device) => { - const node = nodes.find((n) => n.name === device.name); - if (node != null) { - return { - id: toGraphId('GraphNode', node._key), - deviceType: node.details.device_type ?? null, - softwareVersion: node.details.sw_version ?? null, - device, - interfaces: interfaceMap[node._id] ?? [], - coordinates: node.coordinates, - }; - } - return null; - }) - .filter(omitNullValue), - edges: edges.map((e) => ({ - id: e._id, - source: { - interface: e._from, - nodeId: nodesMap[interfaceDeviceMap[e._from]], - }, - target: { - interface: e._to, - nodeId: nodesMap[interfaceDeviceMap[e._to]], - }, - })), + nodes: makeTopologyNodes(dbDevices, topologyDevices), + edges: makeTopologyEdges(topologyDevices), }; }, }); @@ -375,68 +346,35 @@ export const NetTopologyQuery = extendType({ definition: (t) => { t.field('netTopology', { type: NetTopology, - resolve: async (root, _, { topologyDiscoveryAPI }) => { + resolve: async (root, _, { topologyDiscoveryGraphQLAPI }) => { if (!config.topologyEnabled) { return null; } - const topologyDiscoveryURL = unwrap(config.topologyDiscoveryURL); - const { has: interfaceEdges, interfaces } = await topologyDiscoveryAPI.getNetHasAndInterfaces( - topologyDiscoveryURL, - ); - const interfaceDeviceMap = makeInterfaceDeviceMap(interfaceEdges); - const interfaceNameMap = makeInterfaceNameMap(interfaces, (i) => i.ip_address); - const interfaceMap = makeNetInterfaceMap(interfaceEdges, interfaceNameMap); - const linksAndDevices = await topologyDiscoveryAPI.getNetLinksAndDevices(topologyDiscoveryURL); - const { nodes, edges } = linksAndDevices; - const nodesMap = makeNodesMap(nodes, (n) => n.router_id); - const { advertises, networks } = await topologyDiscoveryAPI.getNetAdvertisesAndNetworks(topologyDiscoveryURL); - - const networkMap: Record = advertises.reduce((acc, curr) => { - const network = unwrap(networks.find((n) => n._id === curr._to)); - return { - ...acc, - [curr._from]: acc[curr._from]?.length ? [...acc[curr._from], network] : [network], - }; - }, {} as Record); + const netDevices = await topologyDiscoveryGraphQLAPI?.getNetTopologyDevices(); return { - nodes: nodes.map((n) => ({ - id: toGraphId('GraphNode', n._id), - nodeId: n._id, - name: n.router_id, - interfaces: interfaceMap[n._id] ?? [], - coordinates: n.coordinates, - networks: (networkMap[n._id] ?? []).map((ntw) => { - const { _id, ...rest } = ntw; - return { - id: _id, - ...rest, - }; - }), - })), - edges: edges.map((e) => ({ - id: e._id, - source: { - interface: e._from, - nodeId: nodesMap[interfaceDeviceMap[e._from]], - }, - target: { - interface: e._to, - nodeId: nodesMap[interfaceDeviceMap[e._to]], - }, - })), + nodes: makeNetTopologyNodes(netDevices), + edges: makeNetTopologyEdges(netDevices), }; }, }); }, }); -export const NetRoutingsPaths = objectType({ - name: 'NetRoutingPaths', +export const NetRoutingPathNodeInfo = objectType({ + name: 'NetRoutingPathNodeInfo', + definition: (t) => { + t.int('weight'); + t.string('name'); + }, +}); + +export const NetRoutingPathNode = objectType({ + name: 'NetRoutingPathNode', definition: (t) => { - t.nonNull.field('shortestPath', { type: nonNull(list(nonNull('String'))) }); - t.nonNull.field('alternativePaths', { type: nonNull(list(nonNull(list(nonNull('String'))))) }); + t.int('weight'); + t.field('nodes', { type: nonNull(list(nonNull(NetRoutingPathNodeInfo))) }); }, }); @@ -444,7 +382,7 @@ export const ShortestPathQuery = extendType({ type: 'Query', definition: (t) => { t.field('shortestPath', { - type: NetRoutingsPaths, + type: nonNull(list(nonNull(NetRoutingPathNode))), args: { from: nonNull(stringArg()), to: nonNull(stringArg()), @@ -455,14 +393,15 @@ export const ShortestPathQuery = extendType({ const toNodeNativeId = fromGraphId('GraphNode', to); const shortestPathResult = await topologyDiscoveryGraphQLAPI?.getShortestPath(fromNodeNativeId, toNodeNativeId); - const shortestPath = shortestPathResult?.netRoutingPaths?.shortestPath?.edges ?? []; - const alternativePaths = - shortestPathResult?.netRoutingPaths?.alternativePaths?.edges?.filter(omitNullValue) ?? []; + const shortestPathNodes = shortestPathResult?.netRoutingPaths?.edges?.filter(omitNullValue) ?? []; - return { - shortestPath, - alternativePaths, - }; + return shortestPathNodes.map((n) => ({ + weight: n.weight, + nodes: n.nodes.map((nodes) => ({ + weight: nodes.weight, + name: nodes.node, + })), + })); }, }); }, diff --git a/src/test/helpers.ts b/src/test/helpers.ts index 3f0ef374..cd54aded 100644 --- a/src/test/helpers.ts +++ b/src/test/helpers.ts @@ -14,15 +14,6 @@ type TestContext = { db: PrismaClient; }; -function truncate(prisma: PrismaClient) { - // eslint-disable-next-line - // @ts-ignore - const models = Reflect.ownKeys(prisma).filter((key) => key[0] !== '_'); - // eslint-disable-next-line - // @ts-ignore - return Promise.all(models.map((modelKey) => prisma[modelKey].deleteMany())); -} - function graphqlTestContext() { let serverInstance: Server | null = null; return { @@ -53,7 +44,6 @@ function prismaTestContext() { // Run the migrations to ensure our schema has the required structure execSync(`${prismaBinary} db push`); // Construct a new Prisma Client connected to the generated schema - await truncate(prismaClient); return prismaClient; }, async after() { diff --git a/yarn.lock b/yarn.lock index 1c239d0f..697fccc6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1974,22 +1974,22 @@ tiny-glob "^0.2.9" tslib "^2.4.0" -"@prisma/client@4.2.1": - version "4.2.1" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-4.2.1.tgz#b384587f6066070381ea4c90228a14697a0c271b" - integrity sha512-PZBkY60+k5oix+e6IUfl3ub8TbRLNsPLdfWrdy2eh80WcHTaT+/UfvXf/B7gXedH7FRtbPFHZXk1hZenJiJZFQ== +"@prisma/client@5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.1.1.tgz#ea2b0c8599bdb3f86d92e8df46fba795a744db01" + integrity sha512-fxcCeK5pMQGcgCqCrWsi+I2rpIbk0rAhdrN+ke7f34tIrgPwA68ensrpin+9+fZvuV2OtzHmuipwduSY6HswdA== dependencies: - "@prisma/engines-version" "4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826" + "@prisma/engines-version" "5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e" -"@prisma/engines-version@4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826": - version "4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-4.2.0-33.2920a97877e12e055c1333079b8d19cee7f33826.tgz#63917e579b9f15460f102eaf08a4411a7e0666e7" - integrity sha512-tktkqdiwqE4QhmE088boPt+FwPj1Jub/zk+5F6sEfcRHzO5yz9jyMD5HFVtiwxZPLx/8Xg9ElnuTi8E5lWVQFQ== +"@prisma/engines-version@5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e": + version "5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e" + resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e.tgz#2e8a1f098ec09452dbe00923b24f582f95d1747c" + integrity sha512-owZqbY/wucbr65bXJ/ljrHPgQU5xXTSkmcE/JcbqE1kusuAXV/TLN3/exmz21SZ5rJ7WDkyk70J2G/n68iogbQ== -"@prisma/engines@4.2.1": - version "4.2.1" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-4.2.1.tgz#60c7d0acc1c0c5b70ece712e2cbe13f46a345d6e" - integrity sha512-0KqBwREUOjBiHwITsQzw2DWfLHjntvbqzGRawj4sBMnIiL5CXwyDUKeHOwXzKMtNr1rEjxEsypM14g0CzLRK3g== +"@prisma/engines@5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.1.1.tgz#9c26d209f93a563e048eab63b1976f222f1707d0" + integrity sha512-NV/4nVNWFZSJCCIA3HIFJbbDKO/NARc9ej0tX5S9k2EVbkrFJC4Xt9b0u4rNZWL4V+F5LAjvta8vzEUw0rw+HA== "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" @@ -6774,12 +6774,12 @@ pretty-format@^28.0.0, pretty-format@^28.1.3: ansi-styles "^5.0.0" react-is "^18.0.0" -prisma@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-4.2.1.tgz#3558359f15021aa4767de8c6d0ca1f285cf33d65" - integrity sha512-HuYqnTDgH8atjPGtYmY0Ql9XrrJnfW7daG1PtAJRW0E6gJxc50lY3vrIDn0yjMR3TvRlypjTcspQX8DT+xD4Sg== +prisma@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.1.1.tgz#8f5c0f9467a828746cb94f846d694dc7b7481a9e" + integrity sha512-WJFG/U7sMmcc6TjJTTifTfpI6Wjoh55xl4AzopVwAdyK68L9/ogNo8QQ2cxuUjJf/Wa82z/uhyh3wMzvRIBphg== dependencies: - "@prisma/engines" "4.2.1" + "@prisma/engines" "5.1.1" process-warning@^1.0.0: version "1.0.0" From 530f4dbfb03c92a095b2618b29f4fefaabcde7f2 Mon Sep 17 00:00:00 2001 From: plehocky <117287338+plehocky@users.noreply.github.com> Date: Thu, 24 Aug 2023 13:55:01 +0200 Subject: [PATCH 51/69] updated device sorting (#343) * updated device sorting * formatting * formatting --------- Co-authored-by: PeterL --- src/helpers/device-helpers.ts | 4 ++-- src/schema/api.graphql | 5 +++-- src/schema/device.ts | 2 +- src/schema/nexus-typegen.ts | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/helpers/device-helpers.ts b/src/helpers/device-helpers.ts index 90fa62ef..0e3c5a89 100644 --- a/src/helpers/device-helpers.ts +++ b/src/helpers/device-helpers.ts @@ -8,7 +8,7 @@ type FilterQuery = { name?: Record; }; type OrderingInput = { - sortKey: 'NAME' | 'CREATED_AT'; + sortKey: 'name' | 'createdAt' | 'serviceState'; direction: 'ASC' | 'DESC'; }; @@ -31,7 +31,7 @@ export function getFilterQuery(filter?: FilterInput | null): FilterQuery | undef export function getOrderingQuery(ordering?: OrderingInput | null): Record | undefined { return ordering ? { - orderBy: [{ [ordering.sortKey === 'NAME' ? 'name' : 'createdAt']: ordering.direction.toLowerCase() }], + orderBy: [{ [ordering.sortKey]: ordering.direction.toLowerCase() }], } : undefined; } diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 2dff9edb..bf7e0454 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -1060,8 +1060,9 @@ type Snapshot { } enum SortDeviceBy { - CREATED_AT - NAME + createdAt + name + serviceState } enum SortDirection { diff --git a/src/schema/device.ts b/src/schema/device.ts index 525ef660..19b707f6 100644 --- a/src/schema/device.ts +++ b/src/schema/device.ts @@ -175,7 +175,7 @@ export const FilterDevicesInput = inputObjectType({ }); export const SortDeviceBy = enumType({ name: 'SortDeviceBy', - members: ['NAME', 'CREATED_AT'], + members: ['name', 'createdAt', 'serviceState'], }); export const DeviceOrderByInput = inputObjectType({ name: 'DeviceOrderByInput', diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index fc4a0ce5..664b18e9 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -469,7 +469,7 @@ export interface NexusGenEnums { PoolType: 'allocating' | 'set' | 'singleton'; RetryLogic: 'EXPONENTIAL_BACKOFF' | 'FIXED' | 'LINEAR_BACKOFF'; ScheduleStatus: 'COMPLETED' | 'FAILED' | 'PAUSED' | 'RUNNING' | 'TERMINATED' | 'TIMED_OUT' | 'UNKNOWN'; - SortDeviceBy: 'CREATED_AT' | 'NAME'; + SortDeviceBy: 'createdAt' | 'name' | 'serviceState'; SortDirection: 'ASC' | 'DESC'; SortEventHandlersBy: 'evaluatorType' | 'event' | 'isActive' | 'name'; SortExecutedWorkflowsBy: 'endTime' | 'startTime' | 'status' | 'workflowId' | 'workflowName'; From d3b5b43a8b3058252ea85ab829b6b000ff52dec8 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 24 Aug 2023 14:50:55 +0200 Subject: [PATCH 52/69] new workflow properties added (#344) --- src/schema/api.graphql | 3 +++ src/schema/nexus-typegen.ts | 6 ++++++ src/schema/workflow.ts | 5 +++++ 3 files changed, 14 insertions(+) diff --git a/src/schema/api.graphql b/src/schema/api.graphql index bf7e0454..cfe8a234 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -1321,12 +1321,15 @@ type Workflow implements Node { inputParameters: [String!] name: String! outputParameters: [OutputParameter!] + ownerEmail: String restartable: Boolean + schemaVersion: Int tasks: String timeoutPolicy: TimeoutPolicy timeoutSeconds: Int! updatedAt: String updatedBy: String + variables: String version: Int } diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 664b18e9..f034bdf1 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -1771,12 +1771,15 @@ export interface NexusGenFieldTypes { inputParameters: string[] | null; // [String!] name: string; // String! outputParameters: NexusGenRootTypes['OutputParameter'][] | null; // [OutputParameter!] + ownerEmail: string | null; // String restartable: boolean | null; // Boolean + schemaVersion: number | null; // Int tasks: string | null; // String timeoutPolicy: NexusGenEnums['TimeoutPolicy'] | null; // TimeoutPolicy timeoutSeconds: number; // Int! updatedAt: string | null; // String updatedBy: string | null; // String + variables: string | null; // String version: number | null; // Int }; WorkflowConnection: { @@ -2543,12 +2546,15 @@ export interface NexusGenFieldTypeNames { inputParameters: 'String'; name: 'String'; outputParameters: 'OutputParameter'; + ownerEmail: 'String'; restartable: 'Boolean'; + schemaVersion: 'Int'; tasks: 'String'; timeoutPolicy: 'TimeoutPolicy'; timeoutSeconds: 'Int'; updatedAt: 'String'; updatedBy: 'String'; + variables: 'String'; version: 'Int'; }; WorkflowConnection: { diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 4327716e..d2179020 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -112,6 +112,11 @@ export const Workflow = objectType({ }); t.boolean('restartable'); t.field('timeoutPolicy', { type: TimeoutPolicy }); + t.string('ownerEmail'); + t.int('schemaVersion'); + t.string('variables', { + resolve: (w) => (w.variables ? JSON.stringify(w.variables) : null), + }); }, }); From ff16089be150bdc401127279aaf6289136c367dc Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Fri, 25 Aug 2023 14:07:26 +0200 Subject: [PATCH 53/69] external storage endpoint added (#345) --- src/external-api/network-types.ts | 8 ++++++++ src/external-api/uniconfig.ts | 9 +++++++++ src/schema/api.graphql | 5 +++++ src/schema/nexus-typegen.ts | 18 ++++++++++++++++++ src/schema/workflow.ts | 21 +++++++++++++++++++++ 5 files changed, 61 insertions(+) diff --git a/src/external-api/network-types.ts b/src/external-api/network-types.ts index e288f716..b4331798 100644 --- a/src/external-api/network-types.ts +++ b/src/external-api/network-types.ts @@ -445,3 +445,11 @@ export type UniconfigRevertChangesOutput = t.TypeOf; + +export function decodeUniconfigExternalStorageOutput(value: unknown): UniconfigExternalStorageOutput { + return extractResult(UniconfigExternalStorageOutputValidator.decode(value)); +} diff --git a/src/external-api/uniconfig.ts b/src/external-api/uniconfig.ts index 59d6c726..b51757d9 100644 --- a/src/external-api/uniconfig.ts +++ b/src/external-api/uniconfig.ts @@ -12,6 +12,7 @@ import { decodeUniconfigDeleteSnapshotOutput, decodeUniconfigDiffOuptut, decodeUniconfigDryRunCommitOutput, + decodeUniconfigExternalStorageOutput, decodeUniconfigInstallOutput, decodeUniconfigReplaceOutput, decodeUniconfigRevertChangesOutput, @@ -276,6 +277,13 @@ async function revertChanges(baseURL: string, params: RevertChangesInput): Promi return data; } +async function getExternalStorage(baseURL: string, path: string): Promise> { + const json = await sendGetRequest([baseURL, `/external/postgres/${path}`]); + const data = decodeUniconfigExternalStorageOutput(json); + + return data; +} + const uniconfigAPI = { getInstalledDevices, installDevice, @@ -295,6 +303,7 @@ const uniconfigAPI = { closeTransaction, getTransactionLog, revertChanges, + getExternalStorage, }; export type UniConfigAPI = typeof uniconfigAPI; diff --git a/src/schema/api.graphql b/src/schema/api.graphql index cfe8a234..79bf7075 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -579,6 +579,10 @@ input ExecutedWorkflowsOrderByInput { sortKey: SortExecutedWorkflowsBy! } +type ExternaStorage { + data: String! +} + input FilterDevicesInput { deviceName: String labels: [String!] @@ -916,6 +920,7 @@ type Query { pagination: PaginationArgs searchQuery: ExecutedWorkflowSearchInput ): ExecutedWorkflowConnection + externalStorage(path: String!): ExternaStorage labels(after: String, before: String, first: Int, last: Int): LabelConnection! locations(after: String, before: String, first: Int, last: Int): LocationConnection! netTopology: NetTopology diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index f034bdf1..04e85b6f 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -722,6 +722,10 @@ export interface NexusGenObjects { node: NexusGenRootTypes['ExecutedWorkflow']; // ExecutedWorkflow! }; ExecutedWorkflowTask: SourceTypes.ExecutedWorkflowTask; + ExternaStorage: { + // root type + data: string; // String! + }; GraphEdge: { // root type id: string; // ID! @@ -1349,6 +1353,10 @@ export interface NexusGenFieldTypes { updateTime: string | null; // String workflowType: string | null; // String }; + ExternaStorage: { + // field return type + data: string; // String! + }; GraphEdge: { // field return type id: string; // ID! @@ -1584,6 +1592,7 @@ export interface NexusGenFieldTypes { eventHandlers: NexusGenRootTypes['EventHandlerConnection'] | null; // EventHandlerConnection eventHandlersByEvent: NexusGenRootTypes['EventHandlerConnection'] | null; // EventHandlerConnection executedWorkflows: NexusGenRootTypes['ExecutedWorkflowConnection'] | null; // ExecutedWorkflowConnection + externalStorage: NexusGenRootTypes['ExternaStorage'] | null; // ExternaStorage labels: NexusGenRootTypes['LabelConnection']; // LabelConnection! locations: NexusGenRootTypes['LocationConnection']; // LocationConnection! netTopology: NexusGenRootTypes['NetTopology'] | null; // NetTopology @@ -2124,6 +2133,10 @@ export interface NexusGenFieldTypeNames { updateTime: 'String'; workflowType: 'String'; }; + ExternaStorage: { + // field return type name + data: 'String'; + }; GraphEdge: { // field return type name id: 'ID'; @@ -2359,6 +2372,7 @@ export interface NexusGenFieldTypeNames { eventHandlers: 'EventHandlerConnection'; eventHandlersByEvent: 'EventHandlerConnection'; executedWorkflows: 'ExecutedWorkflowConnection'; + externalStorage: 'ExternaStorage'; labels: 'LabelConnection'; locations: 'LocationConnection'; netTopology: 'NetTopology'; @@ -2895,6 +2909,10 @@ export interface NexusGenArgTypes { pagination?: NexusGenInputs['PaginationArgs'] | null; // PaginationArgs searchQuery?: NexusGenInputs['ExecutedWorkflowSearchInput'] | null; // ExecutedWorkflowSearchInput }; + externalStorage: { + // args + path: string; // String! + }; labels: { // args after?: string | null; // String diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index d2179020..b0e12983 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -1148,3 +1148,24 @@ export const ExecutedWorkflowSubscription = subscriptionField('controlExecutedWo }; }, }); + +export const ExternalStorage = objectType({ + name: 'ExternaStorage', + definition: (t) => { + t.nonNull.string('data'); + }, +}); + +export const WorkflowExternalStorage = queryField('externalStorage', { + type: ExternalStorage, + args: { + path: nonNull(stringArg()), + }, + resolve: async (_, { path }, { uniconfigAPI }) => { + const result = await uniconfigAPI.getExternalStorage(config.conductorApiURL, path); + + return { + data: JSON.stringify(result), + }; + }, +}); From 16bef8f694db92fd262bb80da2cd6362d266266a Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Fri, 25 Aug 2023 15:22:40 +0200 Subject: [PATCH 54/69] FD-540 backups query (#341) * topology query graphql * add helper functions * graphql backups query --- src/__generated__/resource-manager.graphql.ts | 112 +++++++++--------- .../topology-discovery.graphql.ts | 5 + .../topology-discovery-graphql.ts | 19 ++- src/schema/topology.ts | 6 +- 4 files changed, 77 insertions(+), 65 deletions(-) diff --git a/src/__generated__/resource-manager.graphql.ts b/src/__generated__/resource-manager.graphql.ts index 021d65fd..1f793f5c 100644 --- a/src/__generated__/resource-manager.graphql.ts +++ b/src/__generated__/resource-manager.graphql.ts @@ -25,7 +25,9 @@ export type AllocationStrategy = Node & { }; /** Supported languages for allocation strategy scripts */ -export type AllocationStrategyLang = 'js' | 'py'; +export type AllocationStrategyLang = + | 'js' + | 'py'; /** Input parameters for creating an allocation pool */ export type CreateAllocatingPoolInput = { @@ -239,12 +241,14 @@ export type Mutation = { UpdateTag: UpdateTagPayload; }; + export type MutationClaimResourceArgs = { description?: InputMaybe; poolId: Scalars['ID']; userInput: Scalars['Map']; }; + export type MutationClaimResourceWithAltIdArgs = { alternativeId: Scalars['Map']; description?: InputMaybe; @@ -252,67 +256,83 @@ export type MutationClaimResourceWithAltIdArgs = { userInput: Scalars['Map']; }; + export type MutationCreateAllocatingPoolArgs = { input?: InputMaybe; }; + export type MutationCreateAllocationStrategyArgs = { input?: InputMaybe; }; + export type MutationCreateNestedAllocatingPoolArgs = { input: CreateNestedAllocatingPoolInput; }; + export type MutationCreateNestedSetPoolArgs = { input: CreateNestedSetPoolInput; }; + export type MutationCreateNestedSingletonPoolArgs = { input: CreateNestedSingletonPoolInput; }; + export type MutationCreateResourceTypeArgs = { input: CreateResourceTypeInput; }; + export type MutationCreateSetPoolArgs = { input: CreateSetPoolInput; }; + export type MutationCreateSingletonPoolArgs = { input?: InputMaybe; }; + export type MutationCreateTagArgs = { input: CreateTagInput; }; + export type MutationDeleteAllocationStrategyArgs = { input?: InputMaybe; }; + export type MutationDeleteResourcePoolArgs = { input: DeleteResourcePoolInput; }; + export type MutationDeleteResourceTypeArgs = { input: DeleteResourceTypeInput; }; + export type MutationDeleteTagArgs = { input: DeleteTagInput; }; + export type MutationFreeResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; + export type MutationTagPoolArgs = { input: TagPoolInput; }; + export type MutationTestAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; currentResources: Array; @@ -320,20 +340,24 @@ export type MutationTestAllocationStrategyArgs = { userInput: Scalars['Map']; }; + export type MutationUntagPoolArgs = { input: UntagPoolInput; }; + export type MutationUpdateResourceAltIdArgs = { alternativeId: Scalars['Map']; input: Scalars['Map']; poolId: Scalars['ID']; }; + export type MutationUpdateResourceTypeNameArgs = { input: UpdateResourceTypeNameInput; }; + export type MutationUpdateTagArgs = { input: UpdateTagInput; }; @@ -367,7 +391,10 @@ export type PoolCapacityPayload = { }; /** Defines the type of pool */ -export type PoolType = 'allocating' | 'set' | 'singleton'; +export type PoolType = + | 'allocating' + | 'set' + | 'singleton'; /** Defines the type of the property */ export type PropertyType = Node & { @@ -404,14 +431,17 @@ export type Query = { node: Maybe; }; + export type QueryQueryAllocationStrategiesArgs = { byName?: InputMaybe; }; + export type QueryQueryAllocationStrategyArgs = { allocationStrategyId: Scalars['ID']; }; + export type QueryQueryEmptyResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -420,6 +450,7 @@ export type QueryQueryEmptyResourcePoolsArgs = { resourceTypeId?: InputMaybe; }; + export type QueryQueryLeafResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -430,10 +461,12 @@ export type QueryQueryLeafResourcePoolsArgs = { tags?: InputMaybe; }; + export type QueryQueryPoolCapacityArgs = { poolId: Scalars['ID']; }; + export type QueryQueryRecentlyActiveResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -443,23 +476,28 @@ export type QueryQueryRecentlyActiveResourcesArgs = { toDatetime?: InputMaybe; }; + export type QueryQueryRequiredPoolPropertiesArgs = { allocationStrategyName: Scalars['String']; }; + export type QueryQueryResourceArgs = { input: Scalars['Map']; poolId: Scalars['ID']; }; + export type QueryQueryResourcePoolArgs = { poolId: Scalars['ID']; }; + export type QueryQueryResourcePoolHierarchyPathArgs = { poolId: Scalars['ID']; }; + export type QueryQueryResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -470,10 +508,12 @@ export type QueryQueryResourcePoolsArgs = { tags?: InputMaybe; }; + export type QueryQueryResourceTypesArgs = { byName?: InputMaybe; }; + export type QueryQueryResourcesArgs = { after?: InputMaybe; before?: InputMaybe; @@ -482,6 +522,7 @@ export type QueryQueryResourcesArgs = { poolId: Scalars['ID']; }; + export type QueryQueryResourcesByAltIdArgs = { after?: InputMaybe; before?: InputMaybe; @@ -491,6 +532,7 @@ export type QueryQueryResourcesByAltIdArgs = { poolId?: InputMaybe; }; + export type QueryQueryRootResourcePoolsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -501,6 +543,7 @@ export type QueryQueryRootResourcePoolsArgs = { tags?: InputMaybe; }; + export type QuerySearchPoolsByTagsArgs = { after?: InputMaybe; before?: InputMaybe; @@ -509,6 +552,7 @@ export type QuerySearchPoolsByTagsArgs = { tags?: InputMaybe; }; + export type QueryNodeArgs = { id: Scalars['ID']; }; @@ -562,6 +606,7 @@ export type ResourcePool = Node & { id: Scalars['ID']; }; + /** A pool is an entity that contains allocated and free resources */ export type ResourcePoolAllocatedResourcesArgs = { after?: InputMaybe; @@ -665,39 +710,14 @@ export type UpdateTagPayload = { tag: Maybe; }; -export type PoolFragmentFragment = { - __typename: 'ResourcePool'; - id: string; - Name: string; - PoolType: PoolType; - PoolProperties: any; - Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; - ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; -}; +export type PoolFragmentFragment = { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }; export type GetPoolQueryVariables = Exact<{ nodeId: Scalars['ID']; }>; -export type GetPoolQuery = { - __typename?: 'Query'; - node: - | { __typename?: 'AllocationStrategy' } - | { __typename?: 'PropertyType' } - | { __typename?: 'Resource' } - | { - __typename: 'ResourcePool'; - id: string; - Name: string; - PoolType: PoolType; - PoolProperties: any; - Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; - ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; - } - | { __typename?: 'ResourceType' } - | { __typename?: 'Tag' } - | null; -}; + +export type GetPoolQuery = { __typename?: 'Query', node: { __typename?: 'AllocationStrategy' } | { __typename?: 'PropertyType' } | { __typename?: 'Resource' } | { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } } | { __typename?: 'ResourceType' } | { __typename?: 'Tag' } | null }; export type GetPoolsQueryVariables = Exact<{ resourceTypeId?: InputMaybe; @@ -708,37 +728,13 @@ export type GetPoolsQueryVariables = Exact<{ filterByResources?: InputMaybe; }>; -export type GetPoolsQuery = { - __typename?: 'Query'; - QueryRootResourcePools: { - __typename?: 'ResourcePoolConnection'; - totalCount: number; - edges: Array<{ - __typename?: 'ResourcePoolEdge'; - node: { - __typename: 'ResourcePool'; - id: string; - Name: string; - PoolType: PoolType; - PoolProperties: any; - Tags: Array<{ __typename?: 'Tag'; id: string; Tag: string }>; - ResourceType: { __typename?: 'ResourceType'; id: string; Name: string }; - }; - cursor: { __typename?: 'OutputCursor'; ID: string }; - } | null>; - pageInfo: { - __typename?: 'PageInfo'; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: { __typename?: 'OutputCursor'; ID: string } | null; - endCursor: { __typename?: 'OutputCursor'; ID: string } | null; - }; - }; -}; + +export type GetPoolsQuery = { __typename?: 'Query', QueryRootResourcePools: { __typename?: 'ResourcePoolConnection', totalCount: number, edges: Array<{ __typename?: 'ResourcePoolEdge', node: { __typename: 'ResourcePool', id: string, Name: string, PoolType: PoolType, PoolProperties: any, Tags: Array<{ __typename?: 'Tag', id: string, Tag: string }>, ResourceType: { __typename?: 'ResourceType', id: string, Name: string } }, cursor: { __typename?: 'OutputCursor', ID: string } } | null>, pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, hasPreviousPage: boolean, startCursor: { __typename?: 'OutputCursor', ID: string } | null, endCursor: { __typename?: 'OutputCursor', ID: string } | null } } }; export type FreeResourceMutationVariables = Exact<{ poolId: Scalars['ID']; input: Scalars['Map']; }>; -export type FreeResourceMutation = { __typename?: 'Mutation'; FreeResource: string }; + +export type FreeResourceMutation = { __typename?: 'Mutation', FreeResource: string }; diff --git a/src/__generated__/topology-discovery.graphql.ts b/src/__generated__/topology-discovery.graphql.ts index ae96a38f..64db863f 100644 --- a/src/__generated__/topology-discovery.graphql.ts +++ b/src/__generated__/topology-discovery.graphql.ts @@ -287,3 +287,8 @@ export type NetTopologyQueryVariables = Exact<{ [key: string]: never; }>; export type NetTopologyQuery = { __typename?: 'Query', netDevices: { __typename?: 'NetDeviceConnection', edges: Array<{ __typename?: 'NetDeviceEdge', node: { __typename?: 'NetDevice', id: string, routerId: string, phyDevice: { __typename?: 'PhyDevice', id: string, routerId: string | null, coordinates: { __typename?: 'Coordinates', x: number, y: number } } | null, netInterfaces: { __typename?: 'NetInterfaceConnection', edges: Array<{ __typename?: 'NetInterfaceEdge', cursor: string, node: { __typename?: 'NetInterface', id: string, ipAddress: string, netDevice: { __typename?: 'NetDevice', id: string, routerId: string } | null, netLink: { __typename?: 'NetInterface', id: string, igp_metric: number | null, netDevice: { __typename?: 'NetDevice', id: string, routerId: string } | null } | null } | null } | null> | null }, netNetworks: { __typename?: 'NetNetworkConnection', edges: Array<{ __typename?: 'NetNetworkEdge', node: { __typename?: 'NetNetwork', id: string, subnet: string, coordinates: { __typename?: 'Coordinates', x: number, y: number } } | null } | null> | null } } | null } | null> | null } }; + +export type GetBackupsQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetBackupsQuery = { __typename?: 'Query', backups: Array }; diff --git a/src/external-api/topology-discovery-graphql.ts b/src/external-api/topology-discovery-graphql.ts index f82046aa..6bfddd24 100644 --- a/src/external-api/topology-discovery-graphql.ts +++ b/src/external-api/topology-discovery-graphql.ts @@ -1,12 +1,11 @@ import { GraphQLClient, gql } from 'graphql-request'; import config from '../config'; import { + GetBackupsQuery, GetShortestPathQuery, GetShortestPathQueryVariables, NetTopologyQuery, - NetTopologyQueryVariables, TopologyDevicesQuery, - TopologyDevicesQueryVariables, } from '../__generated__/topology-discovery.graphql'; const GET_SHORTEST_PATH = gql` @@ -115,6 +114,12 @@ const GET_NET_TOPOLOGY_DEVICES = gql` } `; +const GET_BACKUPS = gql` + query GetBackups { + backups + } +`; + function getTopologyDiscoveryApi() { if (!config.topologyEnabled) { return undefined; @@ -133,14 +138,19 @@ function getTopologyDiscoveryApi() { } async function getTopologyDevices() { - const response = await client.request(GET_TOPOLOGY_DEVICES); + const response = await client.request(GET_TOPOLOGY_DEVICES); return response; } async function getNetTopologyDevices() { - const response = await client.request(GET_NET_TOPOLOGY_DEVICES); + const response = await client.request(GET_NET_TOPOLOGY_DEVICES); + + return response; + } + async function getBackups() { + const response = await client.request(GET_BACKUPS); return response; } @@ -148,6 +158,7 @@ function getTopologyDiscoveryApi() { getTopologyDevices, getNetTopologyDevices, getShortestPath, + getBackups, }; } diff --git a/src/schema/topology.ts b/src/schema/topology.ts index 3ade7e62..0cc3dfe1 100644 --- a/src/schema/topology.ts +++ b/src/schema/topology.ts @@ -160,12 +160,12 @@ export const TopologyVersionsQuery = extendType({ definition: (t) => { t.field('topologyVersions', { type: list(nonNull('String')), - resolve: async (_, _args, { topologyDiscoveryAPI }) => { + resolve: async (_, _args, { topologyDiscoveryGraphQLAPI }) => { if (!config.topologyEnabled) { return null; } - const { backups: versions } = await topologyDiscoveryAPI.getVersions(unwrap(config.topologyDiscoveryURL)); - return versions; + const data = await topologyDiscoveryGraphQLAPI?.getBackups(); + return data?.backups ?? []; }, }); }, From 7d5e387c596b3d02792ed1b3723fda288b186032 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 31 Aug 2023 11:17:15 +0200 Subject: [PATCH 55/69] regenarate seed script to conform new folder structure (#348) --- prisma/seed.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/prisma/seed.js b/prisma/seed.js index b18d9a47..0cb23ddf 100644 --- a/prisma/seed.js +++ b/prisma/seed.js @@ -9,8 +9,8 @@ const client_1 = require('@prisma/client'); const csv_parse_1 = require('csv-parse'); const fs_1 = require('fs'); const json_templates_1 = __importDefault(require('json-templates')); -const import_csv_helpers_1 = require('../helpers/import-csv.helpers'); -const unwrap_1 = __importDefault(require('../helpers/unwrap')); +const import_csv_helpers_1 = require('../src/helpers/import-csv.helpers'); +const utils_helpers_1 = require('../src/helpers/utils.helpers'); const DEFAULT_UNICONFIG_ZONE = 'localhost'; const { X_TENANT_ID } = process.env; if (!X_TENANT_ID) { @@ -70,7 +70,7 @@ async function getCreateDevicesArgs() { return { name: node_id, tenantId, - uniconfigZoneId: (0, unwrap_1.default)(uniconfigZoneId).id, + uniconfigZoneId: (0, utils_helpers_1.unwrap)(uniconfigZoneId).id, managementIp: ip_address, port: port_number, software: device_type, From b19713d8f712fe0edd637c892fc9edfd3afb45d2 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Mon, 4 Sep 2023 12:43:12 +0200 Subject: [PATCH 56/69] fix import paths (#349) --- prisma/seed.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prisma/seed.js b/prisma/seed.js index 0cb23ddf..e0a08879 100644 --- a/prisma/seed.js +++ b/prisma/seed.js @@ -9,8 +9,8 @@ const client_1 = require('@prisma/client'); const csv_parse_1 = require('csv-parse'); const fs_1 = require('fs'); const json_templates_1 = __importDefault(require('json-templates')); -const import_csv_helpers_1 = require('../src/helpers/import-csv.helpers'); -const utils_helpers_1 = require('../src/helpers/utils.helpers'); +const import_csv_helpers_1 = require('../helpers/import-csv.helpers'); +const utils_helpers_1 = require('../helpers/utils.helpers'); const DEFAULT_UNICONFIG_ZONE = 'localhost'; const { X_TENANT_ID } = process.env; if (!X_TENANT_ID) { From 99388d0979f64dc9baf0d40a067aedb9e0be6a28 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Tue, 5 Sep 2023 13:55:28 +0200 Subject: [PATCH 57/69] FD-540 diff and update positions (#350) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix incorrect blueprintId sent to database - change it to native db id (#314) * bump version 1.9.3 (#330) * Add labels into Dockerfile (#333) * Add source label for renovatebot * Update Dockerfile * Update docker-publish.yml * made filtering by device name case insensitive (#335) Co-authored-by: PeterL * diff queries, common nodes query and update positions mutation * revert status validator * remove logs * lint fixes * add type annotations to helpers functions * topology diff fixes * remove logs --------- Co-authored-by: Pavol Porubský Co-authored-by: Šimon Mišenčík Co-authored-by: plehocky <117287338+plehocky@users.noreply.github.com> Co-authored-by: PeterL --- .github/workflows/docker-publish.yml | 2 +- Dockerfile | 4 + package.json | 2 +- .../topology-discovery.graphql.ts | 100 +++++++++++++- .../topology-discovery-graphql.ts | 130 +++++++++++++++++- src/helpers/device-helpers.ts | 6 +- src/helpers/topology.helpers.ts | 2 +- src/schema/topology.ts | 34 ++--- 8 files changed, 253 insertions(+), 27 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index bc92995f..3a2903a8 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -27,7 +27,7 @@ jobs: fetch-depth: 0 - name: Build image - run: docker build . --file Dockerfile --tag $IMAGE_NAME + run: docker build --build-arg git_commit=$(git rev-parse HEAD) . --file Dockerfile --tag $IMAGE_NAME - name: Log into docker hub run: echo "${{ secrets.DOCKER_HUB_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} --password-stdin diff --git a/Dockerfile b/Dockerfile index 361a8374..f4a912b3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,10 @@ RUN yarn run build FROM node:18-slim +ARG git_commit=unspecified +LABEL git_commit="${git_commit}" +LABEL org.opencontainers.image.source="https://github.com/FRINXio/frinx-inventory-server" + RUN apt-get update RUN apt-get install -y openssl wget diff --git a/package.json b/package.json index 2be25f66..da5c67f5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@frinx/inventory-server", - "version": "1.9.2", + "version": "1.9.3", "engines": { "node": "18" }, diff --git a/src/__generated__/topology-discovery.graphql.ts b/src/__generated__/topology-discovery.graphql.ts index 64db863f..0c5b538c 100644 --- a/src/__generated__/topology-discovery.graphql.ts +++ b/src/__generated__/topology-discovery.graphql.ts @@ -10,6 +10,12 @@ export type Scalars = { Boolean: boolean; Int: number; Float: number; + JSON: any; +}; + +export type CommonNodesResponse = { + __typename?: 'CommonNodesResponse'; + common_nodes: Array; }; export type Coordinates = { @@ -18,6 +24,23 @@ export type Coordinates = { y: Scalars['Float']; }; +export type CoordinatesInput = { + node_name: Scalars['String']; + node_type: CoordinatesNodeType; + x: Scalars['Float']; + y: Scalars['Float']; +}; + +export type CoordinatesNodeType = + | 'device' + | 'network'; + +export type CoordinatesResponse = { + __typename?: 'CoordinatesResponse'; + not_updated: Array; + updated: Array; +}; + export type CreateBackupResponse = { __typename?: 'CreateBackupResponse'; db_name: Scalars['String']; @@ -32,6 +55,7 @@ export type Mutation = { __typename?: 'Mutation'; createBackup: CreateBackupResponse; deleteBackups: DeleteBackupsResponse; + updateCoordinates: CoordinatesResponse; }; @@ -39,6 +63,11 @@ export type MutationDeleteBackupsArgs = { delete_age?: InputMaybe; }; + +export type MutationUpdateCoordinatesArgs = { + coordinates_list: Array; +}; + export type NetDevice = Node & { __typename?: 'NetDevice'; id: Scalars['ID']; @@ -202,9 +231,15 @@ export type PhyDeviceFilter = { name?: InputMaybe; }; +export type PhyHasAndInterfacesResponse = { + __typename?: 'PhyHasAndInterfacesResponse'; + phy_has_and_interfaces_data: Scalars['JSON']; +}; + export type PhyInterface = Node & { __typename?: 'PhyInterface'; id: Scalars['ID']; + idLink: Maybe; name: Scalars['String']; phyDevice: Maybe; phyLink: Maybe; @@ -228,13 +263,28 @@ export type PhyInterfaceFilter = { status?: InputMaybe; }; +export type PhyLinksAndDevicesResponse = { + __typename?: 'PhyLinksAndDevicesResponse'; + phy_links_and_devices_data: Scalars['JSON']; +}; + export type Query = { __typename?: 'Query'; backups: Array; + commonNodes: CommonNodesResponse; netDevices: NetDeviceConnection; netRoutingPaths: Maybe; node: Maybe; phyDevices: PhyDeviceConnection; + phyHasAndInterfaces: PhyHasAndInterfacesResponse; + phyLinksAndDevices: PhyLinksAndDevicesResponse; + topologyDiff: TopologyResponse; +}; + + +export type QueryCommonNodesArgs = { + db_name?: InputMaybe; + selected_nodes: Array; }; @@ -263,12 +313,28 @@ export type QueryPhyDevicesArgs = { first?: InputMaybe; }; + +export type QueryTopologyDiffArgs = { + collection_type: TopologyDiffCollectionTypes; + new_db?: InputMaybe; + old_db?: InputMaybe; +}; + export type RoutingPath = { __typename?: 'RoutingPath'; nodes: Array; weight: Scalars['Int']; }; +export type TopologyDiffCollectionTypes = + | 'net' + | 'phy'; + +export type TopologyResponse = { + __typename?: 'TopologyResponse'; + diff_data: Maybe; +}; + export type GetShortestPathQueryVariables = Exact<{ deviceFrom: Scalars['ID']; deviceTo: Scalars['ID']; @@ -281,7 +347,7 @@ export type GetShortestPathQuery = { __typename?: 'Query', netRoutingPaths: { __ export type TopologyDevicesQueryVariables = Exact<{ [key: string]: never; }>; -export type TopologyDevicesQuery = { __typename?: 'Query', phyDevices: { __typename?: 'PhyDeviceConnection', edges: Array<{ __typename?: 'PhyDeviceEdge', node: { __typename?: 'PhyDevice', id: string, name: string, coordinates: { __typename?: 'Coordinates', x: number, y: number }, details: { __typename?: 'PhyDeviceDetails', sw_version: string, device_type: string }, phyInterfaces: { __typename?: 'PhyInterfaceConnection', edges: Array<{ __typename?: 'PhyInterfaceEdge', node: { __typename?: 'PhyInterface', id: string, name: string, status: string, phyLink: { __typename?: 'PhyInterface', id: string, name: string, phyDevice: { __typename?: 'PhyDevice', id: string, name: string } | null } | null } | null } | null> | null } } | null } | null> | null } }; +export type TopologyDevicesQuery = { __typename?: 'Query', phyDevices: { __typename?: 'PhyDeviceConnection', edges: Array<{ __typename?: 'PhyDeviceEdge', node: { __typename?: 'PhyDevice', id: string, name: string, coordinates: { __typename?: 'Coordinates', x: number, y: number }, details: { __typename?: 'PhyDeviceDetails', sw_version: string, device_type: string }, phyInterfaces: { __typename?: 'PhyInterfaceConnection', edges: Array<{ __typename?: 'PhyInterfaceEdge', node: { __typename?: 'PhyInterface', id: string, name: string, status: string, phyLink: { __typename?: 'PhyInterface', id: string, idLink: string | null, name: string, phyDevice: { __typename?: 'PhyDevice', id: string, name: string } | null } | null } | null } | null> | null } } | null } | null> | null } }; export type NetTopologyQueryVariables = Exact<{ [key: string]: never; }>; @@ -292,3 +358,35 @@ export type GetBackupsQueryVariables = Exact<{ [key: string]: never; }>; export type GetBackupsQuery = { __typename?: 'Query', backups: Array }; + +export type TopologyDiffQueryVariables = Exact<{ + new_db: Scalars['String']; + old_db: Scalars['String']; +}>; + + +export type TopologyDiffQuery = { __typename?: 'Query', topologyDiff: { __typename?: 'TopologyResponse', diff_data: any | null } }; + +export type GetLinksAndDevicesQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetLinksAndDevicesQuery = { __typename?: 'Query', phyLinksAndDevices: { __typename?: 'PhyLinksAndDevicesResponse', phy_links_and_devices_data: any } }; + +export type GetHasAndInterfacesQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetHasAndInterfacesQuery = { __typename?: 'Query', phyHasAndInterfaces: { __typename?: 'PhyHasAndInterfacesResponse', phy_has_and_interfaces_data: any } }; + +export type GetCommonNodesQueryVariables = Exact<{ + selectedNodes: Array | Scalars['String']; +}>; + + +export type GetCommonNodesQuery = { __typename?: 'Query', commonNodes: { __typename?: 'CommonNodesResponse', common_nodes: Array } }; + +export type UpdateCoordinatesMutationVariables = Exact<{ + coordinates: Array | CoordinatesInput; +}>; + + +export type UpdateCoordinatesMutation = { __typename?: 'Mutation', updateCoordinates: { __typename?: 'CoordinatesResponse', updated: Array } }; diff --git a/src/external-api/topology-discovery-graphql.ts b/src/external-api/topology-discovery-graphql.ts index 6bfddd24..d241aac9 100644 --- a/src/external-api/topology-discovery-graphql.ts +++ b/src/external-api/topology-discovery-graphql.ts @@ -1,12 +1,35 @@ import { GraphQLClient, gql } from 'graphql-request'; import config from '../config'; import { + CoordinatesInput, GetBackupsQuery, + GetCommonNodesQuery, + GetCommonNodesQueryVariables, + GetHasAndInterfacesQuery, + GetLinksAndDevicesQuery, GetShortestPathQuery, GetShortestPathQueryVariables, NetTopologyQuery, TopologyDevicesQuery, + TopologyDiffQuery, + TopologyDiffQueryVariables, + UpdateCoordinatesMutation, + UpdateCoordinatesMutationVariables, } from '../__generated__/topology-discovery.graphql'; +import { + HasAndInterfacesOutput, + LinksAndDevicesOutput, + TopologyDiffOutput, + decodeHasAndInterfacesOutput, + decodeLinksAndDevicesOutput, + decodeTopologyDiffOutput, +} from './topology-network-types'; + +type CoordinatesParam = { + device: string; + x: number; + y: number; +}; const GET_SHORTEST_PATH = gql` query GetShortestPath($deviceFrom: ID!, $deviceTo: ID!, $collection: NetRoutingPathOutputCollections) { @@ -45,6 +68,7 @@ const GET_TOPOLOGY_DEVICES = gql` status phyLink { id + idLink name phyDevice { id @@ -120,6 +144,46 @@ const GET_BACKUPS = gql` } `; +const GET_TOPOLOGY_DIFF = gql` + query topologyDiff($new_db: String!, $old_db: String!) { + topologyDiff(new_db: $new_db, old_db: $old_db, collection_type: phy) { + diff_data + } + } +`; + +const GET_LINKS_AND_DEVICES = gql` + query getLinksAndDevices { + phyLinksAndDevices { + phy_links_and_devices_data + } + } +`; + +const GET_HAS_AND_INTERFACES = gql` + query getHasAndInterfaces { + phyHasAndInterfaces { + phy_has_and_interfaces_data + } + } +`; + +const GET_COMMON_NODES = gql` + query getCommonNodes($selectedNodes: [String!]!) { + commonNodes(selected_nodes: $selectedNodes) { + common_nodes + } + } +`; + +const UPDATE_COORDINATES = gql` + mutation UpdateCoordinates($coordinates: [CoordinatesInput!]!) { + updateCoordinates(coordinates_list: $coordinates) { + updated + } + } +`; + function getTopologyDiscoveryApi() { if (!config.topologyEnabled) { return undefined; @@ -137,28 +201,88 @@ function getTopologyDiscoveryApi() { return response; } - async function getTopologyDevices() { + async function getTopologyDevices(): Promise { const response = await client.request(GET_TOPOLOGY_DEVICES); return response; } - async function getNetTopologyDevices() { + async function getNetTopologyDevices(): Promise { const response = await client.request(GET_NET_TOPOLOGY_DEVICES); return response; } - async function getBackups() { + async function getBackups(): Promise { const response = await client.request(GET_BACKUPS); return response; } + async function getTopologyDiff(version: string): Promise { + const response = await client.request(GET_TOPOLOGY_DIFF, { + // eslint-disable-next-line @typescript-eslint/naming-convention + new_db: 'current', + // eslint-disable-next-line @typescript-eslint/naming-convention + old_db: version, + }); + const json = decodeTopologyDiffOutput(response.topologyDiff.diff_data); + + return json; + } + + async function getHasAndInterfaces(): Promise { + const response = await client.request(GET_HAS_AND_INTERFACES); + const { phyHasAndInterfaces } = response; + const json = decodeHasAndInterfacesOutput(phyHasAndInterfaces.phy_has_and_interfaces_data); + + return json; + } + + async function getLinksAndDevices(): Promise { + const response = await client.request(GET_LINKS_AND_DEVICES); + const { phyLinksAndDevices } = response; + const json = decodeLinksAndDevicesOutput(phyLinksAndDevices.phy_links_and_devices_data); + + return json; + } + + async function getCommonNodes(selectedNodes: string[]): Promise { + const response = await client.request(GET_COMMON_NODES, { + selectedNodes, + }); + + return response.commonNodes.common_nodes; + } + + async function updateCoordinates(coordinates: CoordinatesParam[]): Promise { + const coordinatesInput: CoordinatesInput[] = coordinates.map((c) => ({ + // eslint-disable-next-line @typescript-eslint/naming-convention + node_name: c.device, + // eslint-disable-next-line @typescript-eslint/naming-convention + node_type: 'device', + x: c.x, + y: c.y, + })); + const response = await client.request( + UPDATE_COORDINATES, + { + coordinates: coordinatesInput, + }, + ); + + return response.updateCoordinates.updated; + } + return { getTopologyDevices, getNetTopologyDevices, getShortestPath, getBackups, + getTopologyDiff, + getHasAndInterfaces, + getLinksAndDevices, + getCommonNodes, + updateCoordinates, }; } diff --git a/src/helpers/device-helpers.ts b/src/helpers/device-helpers.ts index 0e3c5a89..df7ad054 100644 --- a/src/helpers/device-helpers.ts +++ b/src/helpers/device-helpers.ts @@ -7,6 +7,7 @@ type FilterQuery = { label?: Record; name?: Record; }; + type OrderingInput = { sortKey: 'name' | 'createdAt' | 'serviceState'; direction: 'ASC' | 'DESC'; @@ -15,9 +16,11 @@ type OrderingInput = { function getLabelsQuery(labelIds: string[]): Record | undefined { return labelIds.length ? { some: { labelId: { in: labelIds } } } : undefined; } + function getDeviceNameQuery(deviceName?: string | null): Record | undefined { - return deviceName ? { contains: deviceName } : undefined; + return deviceName ? { contains: deviceName, mode: 'insensitive' } : undefined; } + export function getFilterQuery(filter?: FilterInput | null): FilterQuery | undefined { if (!filter) { return undefined; @@ -28,6 +31,7 @@ export function getFilterQuery(filter?: FilterInput | null): FilterQuery | undef name: getDeviceNameQuery(deviceName), }; } + export function getOrderingQuery(ordering?: OrderingInput | null): Record | undefined { return ordering ? { diff --git a/src/helpers/topology.helpers.ts b/src/helpers/topology.helpers.ts index 0df7fe83..44d8dbdc 100644 --- a/src/helpers/topology.helpers.ts +++ b/src/helpers/topology.helpers.ts @@ -217,7 +217,7 @@ export function makeTopologyEdges(topologyDevices?: TopologyDevicesQuery) { } return getTopologyInterfaces(topologyDevices).map((i) => ({ - id: `${i.id}-${i.phyLink?.id}`, + id: i.phyLink?.idLink ?? '', source: { interface: i.id, nodeId: i.nodeId, diff --git a/src/schema/topology.ts b/src/schema/topology.ts index 0cc3dfe1..207e047b 100644 --- a/src/schema/topology.ts +++ b/src/schema/topology.ts @@ -15,7 +15,7 @@ import { makeTopologyEdges, makeTopologyNodes, } from '../helpers/topology.helpers'; -import { unwrap, omitNullValue } from '../helpers/utils.helpers'; +import { omitNullValue } from '../helpers/utils.helpers'; export const FilterTopologyInput = inputObjectType({ name: 'FilterTopologyInput', @@ -140,6 +140,7 @@ export const TopologyQuery = extendType({ const { filter } = args; const topologyDevices = await topologyDiscoveryGraphQLAPI?.getTopologyDevices(); + // console.log(JSON.stringify(topologyDevices, null, 2)); const labels = filter?.labels ?? []; const dbLabels = await prisma.label.findMany({ where: { name: { in: labels } } }); const labelIds = dbLabels.map((l) => l.id); @@ -179,15 +180,12 @@ export const TopologyCommonNodesQuery = extendType({ args: { nodes: nonNull(list(nonNull(stringArg()))), }, - resolve: async (_, args, { topologyDiscoveryAPI }) => { - if (!config.topologyEnabled) { + resolve: async (_, args, { topologyDiscoveryGraphQLAPI }) => { + if (!config.topologyEnabled || !topologyDiscoveryGraphQLAPI) { return null; } const { nodes } = args; - const { 'common-nodes': commonNodes } = await topologyDiscoveryAPI.getCommonNodes( - unwrap(config.topologyDiscoveryURL), - nodes, - ); + const commonNodes = await topologyDiscoveryGraphQLAPI.getCommonNodes(nodes); return { commonNodes, }; @@ -204,24 +202,22 @@ export const TopologyVersionDataQuery = extendType({ args: { version: nonNull(stringArg()), }, - resolve: async (_, args, { topologyDiscoveryAPI }) => { - if (!config.topologyEnabled) { + resolve: async (_, args, { topologyDiscoveryGraphQLAPI }) => { + if (!config.topologyEnabled || !topologyDiscoveryGraphQLAPI) { return { nodes: [], edges: [], }; } - const { nodes, edges } = await topologyDiscoveryAPI.getLinksAndDevices(unwrap(config.topologyDiscoveryURL)); + const { nodes, edges } = await topologyDiscoveryGraphQLAPI.getLinksAndDevices(); const { version } = args; - const result = await topologyDiscoveryAPI.getTopologyDiff(unwrap(config.topologyDiscoveryURL), version); + const result = await topologyDiscoveryGraphQLAPI.getTopologyDiff(version); const oldDevices = getOldTopologyDevices(nodes, result); // get interface edges for old version - const { has: interfaceEdges, interfaces } = await topologyDiscoveryAPI.getHasAndInterfaces( - unwrap(config.topologyDiscoveryURL), - ); + const { has: interfaceEdges, interfaces } = await topologyDiscoveryGraphQLAPI.getHasAndInterfaces(); const oldInterfaceEdges = getOldTopologyInterfaceEdges(interfaceEdges, result); const interfaceDeviceMap = makeInterfaceDeviceMap(oldInterfaceEdges); const interfaceNameMap = makeInterfaceNameMap( @@ -253,7 +249,7 @@ export const TopologyVersionDataQuery = extendType({ return { nodes: oldDevices.map((device) => ({ - id: toGraphId('GraphNode', device._key), + id: toGraphId('GraphNode', device._id), name: device.name, interfaces: interfaceMap[device._id] ?? [], coordinates: device.coordinates, @@ -291,14 +287,14 @@ export const UpdateGraphNodeCoordinatesMutation = extendType({ args: { input: nonNull(arg({ type: list(nonNull(GraphNodeCoordinatesInput)) })), }, - resolve: async (_, args, { topologyDiscoveryAPI }) => { - if (!config.topologyEnabled) { + resolve: async (_, args, { topologyDiscoveryGraphQLAPI }) => { + if (!config.topologyEnabled || !topologyDiscoveryGraphQLAPI) { return { deviceNames: [] }; } const { input } = args; const apiParams = input.map((i) => ({ device: i.deviceName, x: i.x, y: i.y })); - const response = await topologyDiscoveryAPI.updateCoordinates(unwrap(config.topologyDiscoveryURL), apiParams); - return { deviceNames: response.updated }; + const response = await topologyDiscoveryGraphQLAPI.updateCoordinates(apiParams); + return { deviceNames: response }; }, }); }, From 60e50805b41687baf550c8639ff5b705a1862244 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Thu, 7 Sep 2023 11:13:34 +0200 Subject: [PATCH 58/69] add missing workflow definition properties to make updating more customizable (#365) * add missing workflow definition properties to make updating more customizable * remove createTime and updateTime --- src/external-api/conductor-network-types.ts | 8 +++-- src/schema/api.graphql | 19 ++++++++++- src/schema/nexus-typegen.ts | 26 +++++++++++++-- src/schema/workflow.ts | 35 +++++++++++++++++++-- 4 files changed, 79 insertions(+), 9 deletions(-) diff --git a/src/external-api/conductor-network-types.ts b/src/external-api/conductor-network-types.ts index 91ae5c13..4b599a1e 100644 --- a/src/external-api/conductor-network-types.ts +++ b/src/external-api/conductor-network-types.ts @@ -80,8 +80,10 @@ const WorkflowMetadataOptional = t.partial({ workflowStatusListenerEnabled: optional(t.boolean), ownerEmail: optional(t.string), timeoutPolicy: optional(t.union([t.literal('TIME_OUT_WF'), t.literal('ALERT_ONLY')])), - variables: optional(t.UnknownRecord), - inputTemplate: optional(t.UnknownRecord), + variables: optional(t.record(t.string, t.unknown)), + inputTemplate: optional(t.record(t.string, t.unknown)), + ownerApp: optional(t.string), + accessPolicy: optional(t.record(t.string, t.string)), }); const WorkflowMetadata = t.intersection([WorkflowMetadataRequired, WorkflowMetadataOptional]); @@ -180,7 +182,7 @@ const ExecutedWorkflow = t.type({ externalInputPayloadStoragePath: optional(t.string), externalOutputPayloadStoragePath: optional(t.string), priority: optional(t.number), - variables: optional(t.record(t.string, t.UnknownRecord)), + variables: optional(t.record(t.string, t.unknown)), lastRetriedTime: optional(t.number), failedTaskNames: optional(t.array(t.string)), startTime: optional(t.number), diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 79bf7075..21a913e7 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -1318,14 +1318,18 @@ The `Upload` scalar type represents a file upload. scalar Upload type Workflow implements Node { + accessPolicy: Record createdAt: String createdBy: String description: String + failureWorkflow: String hasSchedule: Boolean id: ID! inputParameters: [String!] + inputTemplate: String name: String! outputParameters: [OutputParameter!] + ownerApp: String ownerEmail: String restartable: Boolean schemaVersion: Int @@ -1334,8 +1338,9 @@ type Workflow implements Node { timeoutSeconds: Int! updatedAt: String updatedBy: String - variables: String + variables: Record version: Int + workflowStatusListenerEnabled: Boolean } type WorkflowConnection { @@ -1373,15 +1378,27 @@ type WorkflowEdge { } input WorkflowInput { + accessPolicy: Record createdAt: String + createdBy: String description: String + failureWorkflow: String + inputParameters: [String!] + inputTemplate: String name: String! outputParameters: [OutputParameterInput!] + ownerApp: String + ownerEmail: String restartable: Boolean + schemaVersion: Int tasks: String! + timeoutPolicy: TimeoutPolicy timeoutSeconds: Int! updatedAt: String + updatedBy: String + variables: Record version: Int + workflowStatusListenerEnabled: Boolean } type WorkflowInstanceDetail { diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 04e85b6f..1b51caa6 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -432,15 +432,27 @@ export interface NexusGenInputs { }; WorkflowInput: { // input type + accessPolicy?: NexusGenScalars['Record'] | null; // Record createdAt?: string | null; // String + createdBy?: string | null; // String description?: string | null; // String + failureWorkflow?: string | null; // String + inputParameters?: string[] | null; // [String!] + inputTemplate?: string | null; // String name: string; // String! outputParameters?: NexusGenInputs['OutputParameterInput'][] | null; // [OutputParameterInput!] + ownerApp?: string | null; // String + ownerEmail?: string | null; // String restartable?: boolean | null; // Boolean + schemaVersion?: number | null; // Int tasks: string; // String! + timeoutPolicy?: NexusGenEnums['TimeoutPolicy'] | null; // TimeoutPolicy timeoutSeconds: number; // Int! updatedAt?: string | null; // String + updatedBy?: string | null; // String + variables?: NexusGenScalars['Record'] | null; // Record version?: number | null; // Int + workflowStatusListenerEnabled?: boolean | null; // Boolean }; WorkflowsOrderByInput: { // input type @@ -1772,14 +1784,18 @@ export interface NexusGenFieldTypes { }; Workflow: { // field return type + accessPolicy: NexusGenScalars['Record'] | null; // Record createdAt: string | null; // String createdBy: string | null; // String description: string | null; // String + failureWorkflow: string | null; // String hasSchedule: boolean | null; // Boolean id: string; // ID! inputParameters: string[] | null; // [String!] + inputTemplate: string | null; // String name: string; // String! outputParameters: NexusGenRootTypes['OutputParameter'][] | null; // [OutputParameter!] + ownerApp: string | null; // String ownerEmail: string | null; // String restartable: boolean | null; // Boolean schemaVersion: number | null; // Int @@ -1788,8 +1804,9 @@ export interface NexusGenFieldTypes { timeoutSeconds: number; // Int! updatedAt: string | null; // String updatedBy: string | null; // String - variables: string | null; // String + variables: NexusGenScalars['Record'] | null; // Record version: number | null; // Int + workflowStatusListenerEnabled: boolean | null; // Boolean }; WorkflowConnection: { // field return type @@ -2552,14 +2569,18 @@ export interface NexusGenFieldTypeNames { }; Workflow: { // field return type name + accessPolicy: 'Record'; createdAt: 'String'; createdBy: 'String'; description: 'String'; + failureWorkflow: 'String'; hasSchedule: 'Boolean'; id: 'ID'; inputParameters: 'String'; + inputTemplate: 'String'; name: 'String'; outputParameters: 'OutputParameter'; + ownerApp: 'String'; ownerEmail: 'String'; restartable: 'Boolean'; schemaVersion: 'Int'; @@ -2568,8 +2589,9 @@ export interface NexusGenFieldTypeNames { timeoutSeconds: 'Int'; updatedAt: 'String'; updatedBy: 'String'; - variables: 'String'; + variables: 'Record'; version: 'Int'; + workflowStatusListenerEnabled: 'Boolean'; }; WorkflowConnection: { // field return type name diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index b0e12983..1179b100 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -114,9 +114,12 @@ export const Workflow = objectType({ t.field('timeoutPolicy', { type: TimeoutPolicy }); t.string('ownerEmail'); t.int('schemaVersion'); - t.string('variables', { - resolve: (w) => (w.variables ? JSON.stringify(w.variables) : null), - }); + t.record('variables'); + t.string('ownerApp'); + t.string('inputTemplate'); + t.record('accessPolicy'); + t.string('failureWorkflow'); + t.boolean('workflowStatusListenerEnabled'); }, }); @@ -499,9 +502,23 @@ const WorkflowInput = inputObjectType({ t.string('description'); t.int('version'); t.boolean('restartable'); + t.list.nonNull.string('inputParameters'); t.list.nonNull.field({ name: 'outputParameters', type: OutputParameterInput }); + t.int('schemaVersion'); + t.string('ownerApp'); + t.string('ownerEmail'); + t.record('variables'); + t.string('inputTemplate'); + t.field('timeoutPolicy', { + type: TimeoutPolicy, + }); + t.string('createdBy'); + t.string('updatedBy'); t.string('createdAt'); t.string('updatedAt'); + t.record('accessPolicy'); + t.string('failureWorkflow'); + t.boolean('workflowStatusListenerEnabled'); }, }); @@ -630,6 +647,18 @@ export const UpdateWorkflowMutation = extendType({ outputParameters: outputParameters || undefined, createTime: workflow.createdAt ? Date.parse(workflow.createdAt) : undefined, updateTime: workflow.updatedAt ? Date.parse(workflow.updatedAt) : undefined, + createdBy: workflow.createdBy || undefined, + updatedBy: workflow.updatedBy || undefined, + schemaVersion: workflow.schemaVersion || undefined, + ownerApp: workflow.ownerApp || undefined, + ownerEmail: workflow.ownerEmail || undefined, + variables: workflow.variables || undefined, + inputTemplate: workflow.inputTemplate ? JSON.parse(workflow.inputTemplate) : undefined, + timeoutPolicy: workflow.timeoutPolicy || undefined, + accessPolicy: workflow.accessPolicy || undefined, + failureWorkflow: workflow.failureWorkflow || undefined, + workflowStatusListenerEnabled: workflow.workflowStatusListenerEnabled || undefined, + inputParameters: workflow.inputParameters || undefined, }; const result = await conductorAPI.editWorkflow(config.conductorApiURL, apiWorkflow); From 50e15222c466fedbf4c5cee6cdda12dffd0d3326 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 7 Sep 2023 16:15:19 +0200 Subject: [PATCH 59/69] bump version 2.0.1 (#367) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index da5c67f5..ba450751 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@frinx/inventory-server", - "version": "1.9.3", + "version": "2.0.1", "engines": { "node": "18" }, From b05f45d501faec0af061bec4436fc5a7864d7e51 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Mon, 11 Sep 2023 11:22:39 +0200 Subject: [PATCH 60/69] remove possibility to change values of createdAt or updatedAt values (#366) * remove possibility to change values of createdAt or updatedAt values for workflow definition from third parties * remove dates from inputs of workflow definition --- src/schema/api.graphql | 6 ------ src/schema/nexus-typegen.ts | 6 ------ src/schema/workflow.ts | 11 +++-------- 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 21a913e7..3d2a2446 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -1350,8 +1350,6 @@ type WorkflowConnection { } input WorkflowDefinitionInput { - createTime: Int - createdAt: Int createdBy: String description: String inputParameters: [String] @@ -1365,8 +1363,6 @@ input WorkflowDefinitionInput { tasks: [TaskInput!]! timeoutPolicy: TimeoutPolicy timeoutSeconds: Int! - updateTime: Int - updatedAt: Int updatedBy: String variables: String version: Int @@ -1379,7 +1375,6 @@ type WorkflowEdge { input WorkflowInput { accessPolicy: Record - createdAt: String createdBy: String description: String failureWorkflow: String @@ -1394,7 +1389,6 @@ input WorkflowInput { tasks: String! timeoutPolicy: TimeoutPolicy timeoutSeconds: Int! - updatedAt: String updatedBy: String variables: Record version: Int diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 1b51caa6..8707b909 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -409,8 +409,6 @@ export interface NexusGenInputs { }; WorkflowDefinitionInput: { // input type - createTime?: number | null; // Int - createdAt?: number | null; // Int createdBy?: string | null; // String description?: string | null; // String inputParameters?: Array | null; // [String] @@ -424,8 +422,6 @@ export interface NexusGenInputs { tasks: NexusGenInputs['TaskInput'][]; // [TaskInput!]! timeoutPolicy?: NexusGenEnums['TimeoutPolicy'] | null; // TimeoutPolicy timeoutSeconds: number; // Int! - updateTime?: number | null; // Int - updatedAt?: number | null; // Int updatedBy?: string | null; // String variables?: string | null; // String version?: number | null; // Int @@ -433,7 +429,6 @@ export interface NexusGenInputs { WorkflowInput: { // input type accessPolicy?: NexusGenScalars['Record'] | null; // Record - createdAt?: string | null; // String createdBy?: string | null; // String description?: string | null; // String failureWorkflow?: string | null; // String @@ -448,7 +443,6 @@ export interface NexusGenInputs { tasks: string; // String! timeoutPolicy?: NexusGenEnums['TimeoutPolicy'] | null; // TimeoutPolicy timeoutSeconds: number; // Int! - updatedAt?: string | null; // String updatedBy?: string | null; // String variables?: NexusGenScalars['Record'] | null; // Record version?: number | null; // Int diff --git a/src/schema/workflow.ts b/src/schema/workflow.ts index 1179b100..3894a312 100644 --- a/src/schema/workflow.ts +++ b/src/schema/workflow.ts @@ -223,10 +223,6 @@ export const WorkflowDefinitionInput = inputObjectType({ t.field('timeoutPolicy', { type: TimeoutPolicy, }); - t.int('createdAt'); - t.int('updatedAt'); - t.int('createTime'); - t.int('updateTime'); t.string('createdBy'); t.string('updatedBy'); }, @@ -514,8 +510,6 @@ const WorkflowInput = inputObjectType({ }); t.string('createdBy'); t.string('updatedBy'); - t.string('createdAt'); - t.string('updatedAt'); t.record('accessPolicy'); t.string('failureWorkflow'); t.boolean('workflowStatusListenerEnabled'); @@ -591,6 +585,8 @@ export const CreateWorkflowMutation = extendType({ tasks: parsedTasks, version: workflow.version || undefined, description: workflow.description || undefined, + createTime: Date.now(), + updateTime: Date.now(), }; await conductorAPI.createWorkflow(config.conductorApiURL, apiWorkflow); @@ -645,8 +641,7 @@ export const UpdateWorkflowMutation = extendType({ description: workflow.description || undefined, restartable: workflow.restartable || undefined, outputParameters: outputParameters || undefined, - createTime: workflow.createdAt ? Date.parse(workflow.createdAt) : undefined, - updateTime: workflow.updatedAt ? Date.parse(workflow.updatedAt) : undefined, + updateTime: Date.now(), createdBy: workflow.createdBy || undefined, updatedBy: workflow.updatedBy || undefined, schemaVersion: workflow.schemaVersion || undefined, From dc4aa1d3c563aa2a02c56b3307c4f6e1a64e5643 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Thu, 14 Sep 2023 13:22:00 +0200 Subject: [PATCH 61/69] add pool properties to resource pool (#369) --- src/helpers/resource-manager.helpers.ts | 1 + src/schema/api.graphql | 1 + src/schema/nexus-typegen.ts | 3 +++ src/schema/pool.ts | 1 + 4 files changed, 6 insertions(+) diff --git a/src/helpers/resource-manager.helpers.ts b/src/helpers/resource-manager.helpers.ts index 5718be84..1b1bc680 100644 --- a/src/helpers/resource-manager.helpers.ts +++ b/src/helpers/resource-manager.helpers.ts @@ -17,6 +17,7 @@ export function apiPoolEdgeToGraphqlPoolEdge(apiPool: PoolFragmentFragment) { id: apiPool.id, name: apiPool.Name, }, + poolProperties: apiPool.PoolProperties, }; } diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 3d2a2446..1eb5a815 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -863,6 +863,7 @@ input PollsOrderByInput { type Pool implements Node { id: ID! name: String! + poolProperties: Record! poolType: PoolType! resourceType: ResourceType! tags: [Tag!]! diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 8707b909..3e293287 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -877,6 +877,7 @@ export interface NexusGenObjects { // root type id: string; // ID! name: string; // String! + poolProperties: NexusGenScalars['Record']; // Record! poolType: NexusGenEnums['PoolType']; // PoolType! resourceType: NexusGenRootTypes['ResourceType']; // ResourceType! tags: NexusGenRootTypes['Tag'][]; // [Tag!]! @@ -1572,6 +1573,7 @@ export interface NexusGenFieldTypes { // field return type id: string; // ID! name: string; // String! + poolProperties: NexusGenScalars['Record']; // Record! poolType: NexusGenEnums['PoolType']; // PoolType! resourceType: NexusGenRootTypes['ResourceType']; // ResourceType! tags: NexusGenRootTypes['Tag'][]; // [Tag!]! @@ -2357,6 +2359,7 @@ export interface NexusGenFieldTypeNames { // field return type name id: 'ID'; name: 'String'; + poolProperties: 'Record'; poolType: 'PoolType'; resourceType: 'ResourceType'; tags: 'Tag'; diff --git a/src/schema/pool.ts b/src/schema/pool.ts index c01b6fdd..d1a04029 100644 --- a/src/schema/pool.ts +++ b/src/schema/pool.ts @@ -50,6 +50,7 @@ export const Pool = objectType({ t.nonNull.field('poolType', { type: PoolType }); t.nonNull.list.nonNull.field('tags', { type: Tag }); t.nonNull.field('resourceType', { type: ResourceType }); + t.nonNull.record('poolProperties'); }, }); From 4afea0517e0895cc0193913892c9c3900abb580a Mon Sep 17 00:00:00 2001 From: plehocky <117287338+plehocky@users.noreply.github.com> Date: Mon, 18 Sep 2023 11:01:31 +0200 Subject: [PATCH 62/69] added filtering by name to zones and labels (#368) * added filtering by name to zones and labels * lint error fix * lint error fix * lint error fix --------- Co-authored-by: PeterL --- src/schema/api.graphql | 12 ++++++++++-- src/schema/label.ts | 12 ++++++++++-- src/schema/nexus-typegen.ts | 10 ++++++++++ src/schema/zone.ts | 13 +++++++++++-- 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 1eb5a815..9a3e82e7 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -595,6 +595,10 @@ input FilterEventHandlerInput { name: String } +input FilterLabelsInput { + name: String! +} + input FilterPollDataInput { afterDate: String beforeDate: String @@ -620,6 +624,10 @@ input FilterWorkflowsInput { labels: [String!] } +input FilterZonesInput { + name: String! +} + input FreeResourceInput { poolId: String! resource: Record! @@ -922,7 +930,7 @@ type Query { searchQuery: ExecutedWorkflowSearchInput ): ExecutedWorkflowConnection externalStorage(path: String!): ExternaStorage - labels(after: String, before: String, first: Int, last: Int): LabelConnection! + labels(after: String, before: String, filter: FilterLabelsInput, first: Int, last: Int): LabelConnection! locations(after: String, before: String, first: Int, last: Int): LocationConnection! netTopology: NetTopology node(id: ID!, version: Int): Node @@ -968,7 +976,7 @@ type Query { last: Int orderBy: WorkflowsOrderByInput ): WorkflowConnection! - zones(after: String, before: String, first: Int, last: Int): ZonesConnection! + zones(after: String, before: String, filter: FilterZonesInput, first: Int, last: Int): ZonesConnection! } """ diff --git a/src/schema/label.ts b/src/schema/label.ts index 3ba15f54..bf6029d8 100644 --- a/src/schema/label.ts +++ b/src/schema/label.ts @@ -38,14 +38,22 @@ export const LabelConnection = objectType({ }, }); +export const FilterLabelsInput = inputObjectType({ + name: 'FilterLabelsInput', + definition: (t) => { + t.nonNull.string('name'); + }, +}); + export const LabelsQuery = extendType({ type: 'Query', definition: (t) => { t.nonNull.field('labels', { type: LabelConnection, - args: PaginationConnectionArgs, + args: { ...PaginationConnectionArgs, filter: FilterLabelsInput }, resolve: async (_, args, { prisma, tenantId }) => { - const baseArgs = { where: { tenantId } }; + const { filter } = args; + const baseArgs = { where: { tenantId, ...(filter?.name ? filter : {}) } }; const result = await findManyCursorConnection( (paginationArgs) => prisma.label.findMany({ ...baseArgs, ...paginationArgs }), () => prisma.label.count(baseArgs), diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 3e293287..97534962 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -267,6 +267,10 @@ export interface NexusGenInputs { isActive?: boolean | null; // Boolean name?: string | null; // String }; + FilterLabelsInput: { + // input type + name: string; // String! + }; FilterPollDataInput: { // input type afterDate?: string | null; // String @@ -292,6 +296,10 @@ export interface NexusGenInputs { keyword?: string | null; // String labels?: string[] | null; // [String!] }; + FilterZonesInput: { + // input type + name: string; // String! + }; FreeResourceInput: { // input type poolId: string; // String! @@ -2936,6 +2944,7 @@ export interface NexusGenArgTypes { // args after?: string | null; // String before?: string | null; // String + filter?: NexusGenInputs['FilterLabelsInput'] | null; // FilterLabelsInput first?: number | null; // Int last?: number | null; // Int }; @@ -3021,6 +3030,7 @@ export interface NexusGenArgTypes { // args after?: string | null; // String before?: string | null; // String + filter?: NexusGenInputs['FilterZonesInput'] | null; // FilterZonesInput first?: number | null; // Int last?: number | null; // Int }; diff --git a/src/schema/zone.ts b/src/schema/zone.ts index 29157c1c..876982fe 100644 --- a/src/schema/zone.ts +++ b/src/schema/zone.ts @@ -40,14 +40,23 @@ export const ZonesConnection = objectType({ t.nonNull.int('totalCount'); }, }); + +export const FilterZonesInput = inputObjectType({ + name: 'FilterZonesInput', + definition: (t) => { + t.nonNull.string('name'); + }, +}); + export const ZonesQuery = extendType({ type: 'Query', definition: (t) => { t.nonNull.field('zones', { type: ZonesConnection, - args: PaginationConnectionArgs, + args: { ...PaginationConnectionArgs, filter: FilterZonesInput }, resolve: async (_, args, { prisma, tenantId }) => { - const baseArgs = { where: { tenantId } }; + const { filter } = args; + const baseArgs = { where: { tenantId, ...(filter?.name ? filter : {}) } }; const result = await findManyCursorConnection( (paginationArgs) => prisma.uniconfigZone.findMany({ ...baseArgs, ...paginationArgs }), () => prisma.uniconfigZone.count(baseArgs), From e28698a12c38ac86b20a5fe5eed708b0670048c8 Mon Sep 17 00:00:00 2001 From: Marco <51787428+MarcoMruz@users.noreply.github.com> Date: Wed, 4 Oct 2023 18:24:22 +0200 Subject: [PATCH 63/69] Add bulk install (#373) * add support for bulk install of devices * remove logs and handle prisma JSONValue parsing * fix naming of input object type * fix parsing of mount params when one device installed * refactor code and move helper logic to helpers and add bulk uninstall mutation * refactor logic for bulk installation of devices * code improvements to make it easier to read * add nativeIds convertion and also fix parsing of prisma json's * add comments --- src/external-api/network-types.ts | 27 +++++++ src/external-api/uniconfig-cache.ts | 55 +++++++++++++- src/external-api/uniconfig.ts | 20 +++++ src/helpers/converters.ts | 18 ++++- src/helpers/device-helpers.ts | 26 +++++++ src/schema/api.graphql | 18 +++++ src/schema/device.ts | 112 +++++++++++++++++++++++++++- src/schema/nexus-typegen.ts | 44 +++++++++++ 8 files changed, 315 insertions(+), 5 deletions(-) diff --git a/src/external-api/network-types.ts b/src/external-api/network-types.ts index b4331798..85b999d0 100644 --- a/src/external-api/network-types.ts +++ b/src/external-api/network-types.ts @@ -35,6 +35,15 @@ export type UninstallDeviceInput = { }; }; +export type UninstallMultipleDevicesInput = { + input: { + nodes: { + 'node-id': string; + 'connection-type': 'netconf' | 'cli'; + }[]; + }; +}; + const UniconfigZonesOutputValidator = t.type({ instances: t.array(t.string), }); @@ -453,3 +462,21 @@ export type UniconfigExternalStorageOutput = t.TypeOf; + +export function decodeUniconfigMultipleNodesOutput(value: unknown): UniconfigMultipleNodesOutput { + return extractResult(UniconfigMultipleNodesOutputValidator.decode(value)); +} diff --git a/src/external-api/uniconfig-cache.ts b/src/external-api/uniconfig-cache.ts index 94182da0..f17c45f4 100644 --- a/src/external-api/uniconfig-cache.ts +++ b/src/external-api/uniconfig-cache.ts @@ -1,6 +1,13 @@ import urlJoin from 'url-join'; -import { UninstallDeviceInput } from './network-types'; -import { getCheckInstalledDevices, installDevice, uninstallDevice } from './uniconfig'; +import { Prisma } from '@prisma/client'; +import { UninstallDeviceInput, UninstallMultipleDevicesInput } from './network-types'; +import { + getCheckInstalledDevices, + installDevice, + installMultipleDevices, + uninstallDevice, + uninstallMultipleDevices, +} from './uniconfig'; export class UniconfigCache { private static instance: UniconfigCache; @@ -93,3 +100,47 @@ export async function uninstallDeviceCache({ await uninstallDevice(uniconfigURL, params); uniconfigCache.delete(uniconfigURL, deviceName); } + +export async function installMultipleDevicesCache({ + uniconfigURL, + devicesToInstall, + deviceNames, +}: { + uniconfigURL: Promise; + devicesToInstall: Prisma.JsonValue; + deviceNames: string[]; +}): Promise { + const uniconfigCache = UniconfigCache.getInstance(); + const url = await uniconfigURL; + const response = await installMultipleDevices(url, devicesToInstall); + + response.output['node-results']?.forEach((nodeResult) => { + if (nodeResult.status === 'fail') { + throw new Error(nodeResult['error-message'] ?? 'could not install device'); + } + }); + + deviceNames.forEach((deviceName) => uniconfigCache.delete(url, deviceName)); +} + +export async function uninstallMultipleDevicesCache({ + uniconfigURL, + deviceNames, + devicesToUninstall, +}: { + uniconfigURL: Promise; + devicesToUninstall: UninstallMultipleDevicesInput; + deviceNames: string[]; +}): Promise { + const uniconfigCache = UniconfigCache.getInstance(); + const url = await uniconfigURL; + const response = await uninstallMultipleDevices(url, devicesToUninstall); + + response.output['node-results']?.forEach((nodeResult) => { + if (nodeResult.status === 'fail') { + throw new Error(nodeResult['error-message'] ?? 'could not install device'); + } + }); + + deviceNames.forEach((deviceName) => uniconfigCache.delete(url, deviceName)); +} diff --git a/src/external-api/uniconfig.ts b/src/external-api/uniconfig.ts index b51757d9..7ca1f190 100644 --- a/src/external-api/uniconfig.ts +++ b/src/external-api/uniconfig.ts @@ -14,6 +14,7 @@ import { decodeUniconfigDryRunCommitOutput, decodeUniconfigExternalStorageOutput, decodeUniconfigInstallOutput, + decodeUniconfigMultipleNodesOutput, decodeUniconfigReplaceOutput, decodeUniconfigRevertChangesOutput, decodeUniconfigSnapshotOutput, @@ -34,6 +35,7 @@ import { UniconfigDiffOutput, UniconfigDryRunCommitOutput, UniconfigInstallOutput, + UniconfigMultipleNodesOutput, UniconfigReplaceInput, UniconfigReplaceOutput, UniconfigRevertChangesOutput, @@ -44,6 +46,7 @@ import { UniconfigSyncOutput, UniconfigTransactionLogOutput, UninstallDeviceInput, + UninstallMultipleDevicesInput, } from './network-types'; export async function getInstalledDevices(baseURL: string): Promise { @@ -74,6 +77,23 @@ export async function getCheckInstalledDevices( return data; } +export async function installMultipleDevices(baseURL: string, input: unknown): Promise { + const json = await sendPostRequest([baseURL, '/operations/connection-manager:install-multiple-nodes'], input); + const data = decodeUniconfigMultipleNodesOutput(json); + + return data; +} + +export async function uninstallMultipleDevices( + baseURL: string, + input: UninstallMultipleDevicesInput, +): Promise { + const json = await sendPostRequest([baseURL, '/operations/connection-manager:uninstall-multiple-nodes'], input); + const data = decodeUniconfigMultipleNodesOutput(json); + + return data; +} + /* TRANSACTION AWARE API CALLS: */ diff --git a/src/helpers/converters.ts b/src/helpers/converters.ts index 015ffbb8..83d8d574 100644 --- a/src/helpers/converters.ts +++ b/src/helpers/converters.ts @@ -23,7 +23,23 @@ export function prepareInstallParameters(deviceName: string, mountParameters: Pr input: { // eslint-disable-next-line @typescript-eslint/naming-convention 'node-id': deviceName, - ...(mountParameters as Record), + // we use typecast here because Prisma JSON is already a string and TS is not aware of it + ...JSON.parse(mountParameters as string), + }, + }; +} + +export function prepareMultipleInstallParameters( + inputs: { deviceName: string; params: Prisma.JsonValue }[], +): Prisma.JsonValue { + return { + input: { + nodes: inputs.map(({ deviceName, params }) => ({ + // eslint-disable-next-line @typescript-eslint/naming-convention + 'node-id': deviceName, + // we use typecast here because Prisma JSON is already a string and TS is not aware of it + ...JSON.parse(params as string), + })), }, }; } diff --git a/src/helpers/device-helpers.ts b/src/helpers/device-helpers.ts index df7ad054..8c8bb9ca 100644 --- a/src/helpers/device-helpers.ts +++ b/src/helpers/device-helpers.ts @@ -1,3 +1,6 @@ +import { Prisma } from '@prisma/client'; +import { Device } from '../schema/source-types'; + type FilterInput = { labelIds?: string[] | null; deviceName?: string | null; @@ -39,3 +42,26 @@ export function getOrderingQuery(ordering?: OrderingInput | null): Record(); + + devices.forEach((device) => { + const devicesInZone = zonesWithDevices.get(device.uniconfigZoneId) ?? []; + + const deviceToInstall = { + deviceName: device.name, + params: device.mountParameters, + }; + + zonesWithDevices.set(device.uniconfigZoneId, [...devicesInZone, deviceToInstall]); + }); + + return zonesWithDevices; +} diff --git a/src/schema/api.graphql b/src/schema/api.graphql index 9a3e82e7..a61166b4 100644 --- a/src/schema/api.graphql +++ b/src/schema/api.graphql @@ -139,6 +139,14 @@ type BlueprintEdge { node: Blueprint! } +type BulkInstallDevicePayload { + installedDevices: [Device!]! +} + +input BulkInstallDevicesInput { + deviceIds: [String!]! +} + input BulkOperationInput { executedWorkflowIds: [String!]! } @@ -148,6 +156,14 @@ type BulkOperationResponse { bulkSuccessfulResults: [String!] } +type BulkUninstallDevicePayload { + uninstalledDevices: [Device!]! +} + +input BulkUninstallDevicesInput { + deviceIds: [String!]! +} + type CSVImport { isOk: Boolean } @@ -738,11 +754,13 @@ type Mutation { addSnapshot(input: AddSnapshotInput!, transactionId: String!): AddSnapshotPayload addZone(input: AddZoneInput!): AddZonePayload! applySnapshot(input: ApplySnapshotInput!, transactionId: String!): ApplySnapshotPayload! + bulkInstallDevices(input: BulkInstallDevicesInput!): BulkInstallDevicePayload! bulkPauseWorkflow(input: BulkOperationInput!): BulkOperationResponse bulkRestartWorkflow(input: BulkOperationInput!): BulkOperationResponse bulkResumeWorkflow(input: BulkOperationInput!): BulkOperationResponse bulkRetryWorkflow(input: BulkOperationInput!): BulkOperationResponse bulkTerminateWorkflow(input: BulkOperationInput!): BulkOperationResponse + bulkUninstallDevices(input: BulkUninstallDevicesInput!): BulkUninstallDevicePayload! closeTransaction(deviceId: String!, transactionId: String!): CloseTransactionPayload! commitConfig(input: CommitConfigInput!, transactionId: String!): CommitConfigPayload! createEventHandler(input: CreateEventHandlerInput!): EventHandler diff --git a/src/schema/device.ts b/src/schema/device.ts index 19b707f6..6f0e8b65 100644 --- a/src/schema/device.ts +++ b/src/schema/device.ts @@ -20,10 +20,17 @@ import { v4 as uuid } from 'uuid'; import { getCachedDeviceInstallStatus, installDeviceCache, + installMultipleDevicesCache, uninstallDeviceCache, + uninstallMultipleDevicesCache, } from '../external-api/uniconfig-cache'; -import { decodeMountParams, getConnectionType, prepareInstallParameters } from '../helpers/converters'; -import { getFilterQuery, getOrderingQuery } from '../helpers/device-helpers'; +import { + decodeMountParams, + getConnectionType, + prepareInstallParameters, + prepareMultipleInstallParameters, +} from '../helpers/converters'; +import { getFilterQuery, getOrderingQuery, makeZonesWithDevicesFromDevices } from '../helpers/device-helpers'; import { decodeMetadataOutput } from '../helpers/device-types'; import { fromGraphId, toGraphId } from '../helpers/id-helper'; import { CSVParserToPromise, CSVValuesToJSON, isHeaderValid } from '../helpers/import-csv.helpers'; @@ -605,3 +612,104 @@ export const UniconfigShellSession = extendType({ }); }, }); + +export const BulkInstallDevicePayload = objectType({ + name: 'BulkInstallDevicePayload', + definition: (t) => { + t.nonNull.list.nonNull.field('installedDevices', { type: Device }); + }, +}); + +export const BulkInstallDevicesInput = inputObjectType({ + name: 'BulkInstallDevicesInput', + definition: (t) => { + t.nonNull.list.nonNull.string('deviceIds'); + }, +}); + +export const BulkInstallDevicesMutation = extendType({ + type: 'Mutation', + definition: (t) => { + t.nonNull.field('bulkInstallDevices', { + type: BulkInstallDevicePayload, + args: { + input: nonNull(arg({ type: BulkInstallDevicesInput })), + }, + resolve: async (_, args, { prisma, tenantId }) => { + const { deviceIds } = args.input; + const nativeIds = deviceIds.map((id) => fromGraphId('Device', id)); + const devices = await prisma.device.findMany({ where: { id: { in: nativeIds }, tenantId } }); + const zonesWithDevices = makeZonesWithDevicesFromDevices(devices); + + const devicesToInstallWithParams = [...zonesWithDevices.entries()].map( + ([uniconfigZoneId, devicesToInstall]) => ({ + uniconfigURL: getUniconfigURL(prisma, uniconfigZoneId), + devicesToInstall: prepareMultipleInstallParameters(devicesToInstall), + deviceNames: devicesToInstall.map((device) => device.deviceName), + }), + ); + + await Promise.all( + devicesToInstallWithParams.map((devicesToInstall) => installMultipleDevicesCache(devicesToInstall)), + ); + + return { installedDevices: devices }; + }, + }); + }, +}); + +export const BulkUninstallDevicePayload = objectType({ + name: 'BulkUninstallDevicePayload', + definition: (t) => { + t.nonNull.list.nonNull.field('uninstalledDevices', { type: Device }); + }, +}); + +export const BulkUninstallDevicesInput = inputObjectType({ + name: 'BulkUninstallDevicesInput', + definition: (t) => { + t.nonNull.list.nonNull.string('deviceIds'); + }, +}); + +export const BulkUninstallDevicesMutation = extendType({ + type: 'Mutation', + definition: (t) => { + t.nonNull.field('bulkUninstallDevices', { + type: BulkUninstallDevicePayload, + args: { + input: nonNull(arg({ type: BulkUninstallDevicesInput })), + }, + resolve: async (_, args, { prisma, tenantId }) => { + const { deviceIds } = args.input; + const nativeIds = deviceIds.map((id) => fromGraphId('Device', id)); + const devices = await prisma.device.findMany({ where: { id: { in: nativeIds }, tenantId } }); + const zonesWithDevices = makeZonesWithDevicesFromDevices(devices); + + const devicesToUninstallWithParams = [...zonesWithDevices.entries()].map( + ([uniconfigZoneId, devicesToUninstall]) => ({ + uniconfigURL: getUniconfigURL(prisma, uniconfigZoneId), + devicesToUninstall: { + input: { + nodes: devicesToUninstall.map(({ deviceName, params }) => ({ + // eslint-disable-next-line @typescript-eslint/naming-convention + 'node-id': deviceName, + // eslint-disable-next-line @typescript-eslint/naming-convention + 'connection-type': getConnectionType(decodeMountParams(params)), + })), + }, + }, + deviceNames: devicesToUninstall.map((device) => device.deviceName), + }), + ); + + await Promise.all( + devicesToUninstallWithParams.map((devicesToUninstall) => uninstallMultipleDevicesCache(devicesToUninstall)), + ); + + return { uninstalledDevices: devices }; + }, + }); + }, +}); diff --git a/src/schema/nexus-typegen.ts b/src/schema/nexus-typegen.ts index 97534962..5c6d655a 100644 --- a/src/schema/nexus-typegen.ts +++ b/src/schema/nexus-typegen.ts @@ -106,10 +106,18 @@ export interface NexusGenInputs { deviceId: string; // String! name: string; // String! }; + BulkInstallDevicesInput: { + // input type + deviceIds: string[]; // [String!]! + }; BulkOperationInput: { // input type executedWorkflowIds: string[]; // [String!]! }; + BulkUninstallDevicesInput: { + // input type + deviceIds: string[]; // [String!]! + }; CSVImportInput: { // input type file: NexusGenScalars['Upload']; // Upload! @@ -589,11 +597,19 @@ export interface NexusGenObjects { cursor: string; // String! node: NexusGenRootTypes['Blueprint']; // Blueprint! }; + BulkInstallDevicePayload: { + // root type + installedDevices: NexusGenRootTypes['Device'][]; // [Device!]! + }; BulkOperationResponse: { // root type bulkErrorResults?: string | null; // String bulkSuccessfulResults?: string[] | null; // [String!] }; + BulkUninstallDevicePayload: { + // root type + uninstalledDevices: NexusGenRootTypes['Device'][]; // [Device!]! + }; CSVImport: { // root type isOk?: boolean | null; // Boolean @@ -1142,11 +1158,19 @@ export interface NexusGenFieldTypes { cursor: string; // String! node: NexusGenRootTypes['Blueprint']; // Blueprint! }; + BulkInstallDevicePayload: { + // field return type + installedDevices: NexusGenRootTypes['Device'][]; // [Device!]! + }; BulkOperationResponse: { // field return type bulkErrorResults: string | null; // String bulkSuccessfulResults: string[] | null; // [String!] }; + BulkUninstallDevicePayload: { + // field return type + uninstalledDevices: NexusGenRootTypes['Device'][]; // [Device!]! + }; CSVImport: { // field return type isOk: boolean | null; // Boolean @@ -1467,11 +1491,13 @@ export interface NexusGenFieldTypes { addSnapshot: NexusGenRootTypes['AddSnapshotPayload'] | null; // AddSnapshotPayload addZone: NexusGenRootTypes['AddZonePayload']; // AddZonePayload! applySnapshot: NexusGenRootTypes['ApplySnapshotPayload']; // ApplySnapshotPayload! + bulkInstallDevices: NexusGenRootTypes['BulkInstallDevicePayload']; // BulkInstallDevicePayload! bulkPauseWorkflow: NexusGenRootTypes['BulkOperationResponse'] | null; // BulkOperationResponse bulkRestartWorkflow: NexusGenRootTypes['BulkOperationResponse'] | null; // BulkOperationResponse bulkResumeWorkflow: NexusGenRootTypes['BulkOperationResponse'] | null; // BulkOperationResponse bulkRetryWorkflow: NexusGenRootTypes['BulkOperationResponse'] | null; // BulkOperationResponse bulkTerminateWorkflow: NexusGenRootTypes['BulkOperationResponse'] | null; // BulkOperationResponse + bulkUninstallDevices: NexusGenRootTypes['BulkUninstallDevicePayload']; // BulkUninstallDevicePayload! closeTransaction: NexusGenRootTypes['CloseTransactionPayload']; // CloseTransactionPayload! commitConfig: NexusGenRootTypes['CommitConfigPayload']; // CommitConfigPayload! createEventHandler: NexusGenRootTypes['EventHandler'] | null; // EventHandler @@ -1928,11 +1954,19 @@ export interface NexusGenFieldTypeNames { cursor: 'String'; node: 'Blueprint'; }; + BulkInstallDevicePayload: { + // field return type name + installedDevices: 'Device'; + }; BulkOperationResponse: { // field return type name bulkErrorResults: 'String'; bulkSuccessfulResults: 'String'; }; + BulkUninstallDevicePayload: { + // field return type name + uninstalledDevices: 'Device'; + }; CSVImport: { // field return type name isOk: 'Boolean'; @@ -2253,11 +2287,13 @@ export interface NexusGenFieldTypeNames { addSnapshot: 'AddSnapshotPayload'; addZone: 'AddZonePayload'; applySnapshot: 'ApplySnapshotPayload'; + bulkInstallDevices: 'BulkInstallDevicePayload'; bulkPauseWorkflow: 'BulkOperationResponse'; bulkRestartWorkflow: 'BulkOperationResponse'; bulkResumeWorkflow: 'BulkOperationResponse'; bulkRetryWorkflow: 'BulkOperationResponse'; bulkTerminateWorkflow: 'BulkOperationResponse'; + bulkUninstallDevices: 'BulkUninstallDevicePayload'; closeTransaction: 'CloseTransactionPayload'; commitConfig: 'CommitConfigPayload'; createEventHandler: 'EventHandler'; @@ -2684,6 +2720,10 @@ export interface NexusGenArgTypes { input: NexusGenInputs['ApplySnapshotInput']; // ApplySnapshotInput! transactionId: string; // String! }; + bulkInstallDevices: { + // args + input: NexusGenInputs['BulkInstallDevicesInput']; // BulkInstallDevicesInput! + }; bulkPauseWorkflow: { // args input: NexusGenInputs['BulkOperationInput']; // BulkOperationInput! @@ -2704,6 +2744,10 @@ export interface NexusGenArgTypes { // args input: NexusGenInputs['BulkOperationInput']; // BulkOperationInput! }; + bulkUninstallDevices: { + // args + input: NexusGenInputs['BulkUninstallDevicesInput']; // BulkUninstallDevicesInput! + }; closeTransaction: { // args deviceId: string; // String! From b29124b6873410ce02883046c6874c922994e748 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 5 Oct 2023 14:45:34 +0200 Subject: [PATCH 64/69] bump version 2.0.2 (#375) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ba450751..2371f232 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@frinx/inventory-server", - "version": "2.0.1", + "version": "2.0.2", "engines": { "node": "18" }, From 1fe622c071b0a68d90098942c8bcff2da5fd25dd Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Mon, 9 Oct 2023 11:10:21 +0200 Subject: [PATCH 65/69] resource type fix (#374) --- src/helpers/resource-manager.helpers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helpers/resource-manager.helpers.ts b/src/helpers/resource-manager.helpers.ts index 1b1bc680..635b8d3c 100644 --- a/src/helpers/resource-manager.helpers.ts +++ b/src/helpers/resource-manager.helpers.ts @@ -14,8 +14,8 @@ export function apiPoolEdgeToGraphqlPoolEdge(apiPool: PoolFragmentFragment) { tag: t.Tag, })), resourceType: { - id: apiPool.id, - name: apiPool.Name, + id: apiPool.ResourceType.id, + name: apiPool.ResourceType.Name, }, poolProperties: apiPool.PoolProperties, }; From de1a97bb89a1116dc57e96fa46f04923edcc3205 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Fri, 20 Oct 2023 13:06:36 +0200 Subject: [PATCH 66/69] bump version 2.0.3 (#381) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2371f232..2606564b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@frinx/inventory-server", - "version": "2.0.2", + "version": "2.0.3", "engines": { "node": "18" }, From 71d2467327e8742b952154cbf3c2d2214fcf9512 Mon Sep 17 00:00:00 2001 From: plehocky <117287338+plehocky@users.noreply.github.com> Date: Tue, 5 Dec 2023 23:12:03 +0100 Subject: [PATCH 67/69] deleted topology discovery rest APIcode (#384) * deleted topology discovery rest APIcode * removed topology URL from .env.example and config.ts * formatting --------- Co-authored-by: PeterL --- .env.example | 1 - src/config.ts | 9 +- src/context.ts | 3 - src/external-api/topology-discovery.ts | 110 ------------------------- 4 files changed, 2 insertions(+), 121 deletions(-) delete mode 100644 src/external-api/topology-discovery.ts diff --git a/.env.example b/.env.example index 74df2e81..e3956b95 100644 --- a/.env.example +++ b/.env.example @@ -14,5 +14,4 @@ TOPOLOGY_ENABLED=true # these fields are optional, they are used for topology functionality # if TOPOLOGY_ENABLED=false they are ignored # either define all of them or do not define them at all -TOPOLOGY_DISCOVERY_API_URL=http://10.19.0.5:8080/api/topology/data TOPOLOGY_DISCOVERY_GRAPHQL_API_URL=http://localhost:5000/api/graphql diff --git a/src/config.ts b/src/config.ts index a9d9771e..5cdc0acb 100644 --- a/src/config.ts +++ b/src/config.ts @@ -31,7 +31,6 @@ function optionalEnvString(key: string): string | null { type TopologyConfigEnabled = { topologyEnabled: true; - topologyDiscoveryURL: string; topologyDiscoveryGraphqlURL: string; }; @@ -44,7 +43,6 @@ type TopologyConfig = TopologyConfigDisabled | TopologyConfigEnabled; // all arango params must be present or none function getTopologyConfig(): TopologyConfig { const topologyEnabled = stringToBoolean(envString('TOPOLOGY_ENABLED')); - const topologyDiscoveryURL = optionalEnvString('TOPOLOGY_DISCOVERY_API_URL'); const topologyDiscoveryGraphqlURL = optionalEnvString('TOPOLOGY_DISCOVERY_GRAPHQL_API_URL'); if (!topologyEnabled) { return { @@ -52,15 +50,12 @@ function getTopologyConfig(): TopologyConfig { }; } - if (!topologyDiscoveryURL || !topologyDiscoveryGraphqlURL) { - throw new Error( - 'Not all mandatory topology discovery url (TOPOLOGY_DISCOVERY_API_URL, TOPOLOGY_DISCOVERY_GRAPHQL_API_URL) were found.', - ); + if (!topologyDiscoveryGraphqlURL) { + throw new Error('Not all mandatory topology discovery url (TOPOLOGY_DISCOVERY_GRAPHQL_API_URL) were found.'); } return { topologyEnabled: true, - topologyDiscoveryURL, topologyDiscoveryGraphqlURL, }; } diff --git a/src/context.ts b/src/context.ts index bc8e14d0..44fb1a77 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,6 +1,5 @@ import { PrismaClient } from '@prisma/client'; import { ExpressContext } from 'apollo-server-express'; -import topologyDiscoveryAPI, { TopologyDiscoveryAPI } from './external-api/topology-discovery'; import getTopologyDiscoveryApi, { TopologyDiscoveryGraphQLAPI } from './external-api/topology-discovery-graphql'; import conductorAPI, { ConductorAPI } from './external-api/conductor'; import uniconfigAPI, { UniConfigAPI } from './external-api/uniconfig'; @@ -12,7 +11,6 @@ export type Context = { prisma: PrismaClient; tenantId: string; uniconfigAPI: UniConfigAPI; - topologyDiscoveryAPI: TopologyDiscoveryAPI; topologyDiscoveryGraphQLAPI?: TopologyDiscoveryGraphQLAPI; conductorAPI: ConductorAPI; schedulerAPI: SchedulerAPI; @@ -34,7 +32,6 @@ export default function createContext(context: ExpressContext): Context { prisma: prismaClient, tenantId, uniconfigAPI, - topologyDiscoveryAPI, topologyDiscoveryGraphQLAPI: getTopologyDiscoveryApi(), conductorAPI, schedulerAPI, diff --git a/src/external-api/topology-discovery.ts b/src/external-api/topology-discovery.ts deleted file mode 100644 index 1c11ed0b..00000000 --- a/src/external-api/topology-discovery.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { sendGetRequest, sendPatchRequest, sendPostRequest } from './helpers'; -import { - decodeHasAndInterfacesOutput, - decodeLinksAndDevicesOutput, - decodeNetAdvertisesAndNetworks, - decodeNetHasAndInterfacesOutput, - decodeNetLinksAndDevicesOutput, - decodeTopologyCommonNodesOutput, - decodeTopologyDiffOutput, - decodeUpdateCoordinatesOutput, - decodeVersionsOutput, - HasAndInterfacesOutput, - LinksAndDevicesOutput, - NetAdvertisesAndNetworksOutput, - NetHasAndInterfacesOutput, - NetLinksAndDevicesOutput, - TopologyCommonNodesOutput, - TopologyDiffOutput, - UpdateCoordinatesOutput, - VersionsOutput, -} from './topology-network-types'; - -async function getVersions(baseURL: string): Promise { - const json = await sendGetRequest([baseURL, '/backup']); - const data = decodeVersionsOutput(json); - return data; -} - -async function getTopologyDiff(baseURL: string, version: string): Promise { - const body = { - // eslint-disable-next-line @typescript-eslint/naming-convention - new_db: 'current', - // eslint-disable-next-line @typescript-eslint/naming-convention - old_db: version, - }; - const json = await sendPostRequest([baseURL, '/diff'], body); - const data = decodeTopologyDiffOutput(json); - return data; -} - -async function getCommonNodes(baseURL: string, nodes: string[]): Promise { - const body = { - // eslint-disable-next-line @typescript-eslint/naming-convention - 'selected-nodes': nodes, - }; - const json = await sendPostRequest([baseURL, '/common-nodes'], body); - const data = decodeTopologyCommonNodesOutput(json); - return data; -} - -async function getLinksAndDevices(baseURL: string): Promise { - const json = await sendGetRequest([baseURL, '/links-and-devices']); - const data = decodeLinksAndDevicesOutput(json); - return data; -} - -async function getHasAndInterfaces(baseURL: string): Promise { - const json = await sendGetRequest([baseURL, '/has-and-interfaces']); - const data = decodeHasAndInterfacesOutput(json); - return data; -} - -type NodeCoordinatesBody = { - device: string; - x: number; - y: number; -}; - -async function updateCoordinates( - baseURL: string, - nodeCoordinates: NodeCoordinatesBody[], -): Promise { - const json = await sendPatchRequest([baseURL, '/coordinates'], nodeCoordinates); - const data = decodeUpdateCoordinatesOutput(json); - return data; -} - -async function getNetHasAndInterfaces(baseURL: string): Promise { - const json = await sendGetRequest([baseURL, '/net-has-and-interfaces']); - const data = decodeNetHasAndInterfacesOutput(json); - return data; -} - -async function getNetLinksAndDevices(baseURL: string): Promise { - const json = await sendGetRequest([baseURL, '/net-links-and-devices']); - const data = decodeNetLinksAndDevicesOutput(json); - return data; -} - -async function getNetAdvertisesAndNetworks(baseURL: string): Promise { - const json = await sendGetRequest([baseURL, '/net-advertises-and-networks']); - const data = decodeNetAdvertisesAndNetworks(json); - return data; -} - -const topologyDiscoveryAPI = { - getVersions, - getTopologyDiff, - getCommonNodes, - getLinksAndDevices, - getHasAndInterfaces, - updateCoordinates, - getNetHasAndInterfaces, - getNetLinksAndDevices, - getNetAdvertisesAndNetworks, -}; - -export type TopologyDiscoveryAPI = typeof topologyDiscoveryAPI; - -export default topologyDiscoveryAPI; From 370a2aad15d17b390096fbc1dd8a580e9be57c75 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Wed, 20 Dec 2023 13:37:18 +0100 Subject: [PATCH 68/69] install device fix (#386) * dont parse json object params * fix lint * seed moun params fix * revert change --- prisma/seed.js | 2 +- prisma/seed.ts | 2 +- src/helpers/converters.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/prisma/seed.js b/prisma/seed.js index e0a08879..d55cb48b 100644 --- a/prisma/seed.js +++ b/prisma/seed.js @@ -75,7 +75,7 @@ async function getCreateDevicesArgs() { port: port_number, software: device_type, softwareVersion: version, - mountParameters: JSON.stringify(JSON.parse(parsedTemplate(device))), + mountParameters: JSON.parse(parsedTemplate(device)), source: 'IMPORTED', }; }); diff --git a/prisma/seed.ts b/prisma/seed.ts index 4175c2aa..523682b3 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -79,7 +79,7 @@ async function getCreateDevicesArgs(): Promise { port: port_number, software: device_type, softwareVersion: version, - mountParameters: JSON.stringify(JSON.parse(parsedTemplate(device))), + mountParameters: JSON.parse(parsedTemplate(device)), source: 'IMPORTED' as const, }; }); diff --git a/src/helpers/converters.ts b/src/helpers/converters.ts index 83d8d574..6e8926c3 100644 --- a/src/helpers/converters.ts +++ b/src/helpers/converters.ts @@ -24,7 +24,7 @@ export function prepareInstallParameters(deviceName: string, mountParameters: Pr // eslint-disable-next-line @typescript-eslint/naming-convention 'node-id': deviceName, // we use typecast here because Prisma JSON is already a string and TS is not aware of it - ...JSON.parse(mountParameters as string), + ...(mountParameters as JSONObject), }, }; } From 806de4579e2bf13573015545a7e2c0bc613a01e6 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Wed, 20 Dec 2023 13:44:40 +0100 Subject: [PATCH 69/69] bump version 2.0.4 (#387) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2606564b..acd8e90f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@frinx/inventory-server", - "version": "2.0.3", + "version": "2.0.4", "engines": { "node": "18" },