chore(server): apollo server v3 -> v4 (#2880)
* main changes seem to be done? * lint fix * minor cleanup * dataloader clear
This commit is contained in:
committed by
GitHub
parent
939504fd8d
commit
c92938eff3
@@ -78,7 +78,6 @@
|
||||
"core-js-compat/semver": "^7.5.4",
|
||||
"eslint": "^9.4.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"graphql": "^15.3.0",
|
||||
"levelup/bl": ">=1.2.3",
|
||||
"levelup/semver": ">=5.7.2",
|
||||
"mocha/serialize-javascript": ">=6.0.2",
|
||||
|
||||
@@ -491,7 +491,7 @@ export const resolveGenericStatusCode = (errors: GraphQLErrors) => {
|
||||
if (
|
||||
errors.some((e) =>
|
||||
['UNAUTHENTICATED', 'UNAUTHORIZED_ACCESS_ERROR'].includes(
|
||||
e.extensions?.code || ''
|
||||
(e.extensions?.code || '') as string
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -499,7 +499,7 @@ export const resolveGenericStatusCode = (errors: GraphQLErrors) => {
|
||||
if (
|
||||
errors.some((e) =>
|
||||
['NOT_FOUND_ERROR', 'STREAM_NOT_FOUND', 'AUTOMATION_NOT_FOUND'].includes(
|
||||
e.extensions?.code || ''
|
||||
(e.extensions?.code || '') as string
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
+37
-47
@@ -21,17 +21,11 @@ import {
|
||||
import { errorLoggingMiddleware } from '@/logging/errorLogging'
|
||||
import prometheusClient from 'prom-client'
|
||||
|
||||
import {
|
||||
ApolloServer,
|
||||
ForbiddenError,
|
||||
ApolloServerExpressConfig,
|
||||
ApolloError
|
||||
} from 'apollo-server-express'
|
||||
import {
|
||||
ApolloServerPluginLandingPageLocalDefault,
|
||||
ApolloServerPluginUsageReportingDisabled,
|
||||
ApolloServerPluginUsageReporting
|
||||
} from 'apollo-server-core'
|
||||
import { ApolloServer } from '@apollo/server'
|
||||
import { expressMiddleware } from '@apollo/server/express4'
|
||||
import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default'
|
||||
import { ApolloServerPluginUsageReporting } from '@apollo/server/plugin/usageReporting'
|
||||
import { ApolloServerPluginUsageReportingDisabled } from '@apollo/server/plugin/disabled'
|
||||
|
||||
import { ExecutionParams, SubscriptionServer } from 'subscriptions-transport-ws'
|
||||
import { execute, subscribe } from 'graphql'
|
||||
@@ -65,8 +59,13 @@ import { buildMocksConfig } from '@/modules/mocks'
|
||||
import { defaultErrorHandler } from '@/modules/core/rest/defaultErrorHandler'
|
||||
import { migrateDbToLatest } from '@/db/migrations'
|
||||
import { statusCodePlugin } from '@/modules/core/graph/plugins/statusCode'
|
||||
import { ForbiddenError } from '@/modules/shared/errors'
|
||||
import { loggingPlugin } from '@/modules/core/graph/plugins/logging'
|
||||
import { isUserGraphqlError } from '@/modules/shared/helpers/graphqlHelper'
|
||||
|
||||
let graphqlServer: ApolloServer
|
||||
const GRAPHQL_PATH = '/graphql'
|
||||
|
||||
let graphqlServer: ApolloServer<GraphQLContext>
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type SubscriptionResponse = { errors?: GraphQLError[]; data?: any }
|
||||
@@ -93,10 +92,7 @@ function logSubscriptionOperation(params: {
|
||||
const errors = response?.errors || (error ? [error] : [])
|
||||
if (errors.length) {
|
||||
for (const error of errors) {
|
||||
if (
|
||||
(error instanceof GraphQLError && error.extensions?.code === 'FORBIDDEN') ||
|
||||
error instanceof ApolloError
|
||||
) {
|
||||
if (error instanceof GraphQLError && isUserGraphqlError(error)) {
|
||||
logger.info(error, errMsg)
|
||||
} else {
|
||||
logger.error(error, errMsg)
|
||||
@@ -112,10 +108,7 @@ function logSubscriptionOperation(params: {
|
||||
* is that graphql-ws uses an entirely different protocol, so the client-side has to change as well, and so old clients
|
||||
* will be unable to use any WebSocket/subscriptions functionality with the updated server
|
||||
*/
|
||||
function buildApolloSubscriptionServer(
|
||||
apolloServer: ApolloServer,
|
||||
server: http.Server
|
||||
): SubscriptionServer {
|
||||
function buildApolloSubscriptionServer(server: http.Server): SubscriptionServer {
|
||||
const schema = ModulesSetup.graphSchema()
|
||||
|
||||
// Init metrics
|
||||
@@ -153,7 +146,6 @@ function buildApolloSubscriptionServer(
|
||||
schema,
|
||||
execute,
|
||||
subscribe,
|
||||
validationRules: apolloServer.requestOptions.validationRules,
|
||||
onConnect: async (connectionParams: Record<string, unknown>) => {
|
||||
metricConnectCounter.inc()
|
||||
metricConnectedClients.inc()
|
||||
@@ -235,41 +227,37 @@ function buildApolloSubscriptionServer(
|
||||
},
|
||||
{
|
||||
server,
|
||||
path: apolloServer.graphqlPath
|
||||
path: GRAPHQL_PATH
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Apollo Server instance
|
||||
* @param optionOverrides Optionally override ctor options
|
||||
* @param subscriptionServerResolver If you expect to use subscriptions on this instance,
|
||||
* pass in a callable that resolves the subscription server
|
||||
*/
|
||||
export async function buildApolloServer(
|
||||
optionOverrides?: Partial<ApolloServerExpressConfig>,
|
||||
subscriptionServerResolver?: () => SubscriptionServer
|
||||
): Promise<ApolloServer> {
|
||||
const debug = optionOverrides?.debug || isDevEnv() || isTestEnv()
|
||||
export async function buildApolloServer(options?: {
|
||||
subscriptionServer?: SubscriptionServer
|
||||
}): Promise<ApolloServer<GraphQLContext>> {
|
||||
const includeStacktraceInErrorResponses = isDevEnv() || isTestEnv()
|
||||
const subscriptionServer = options?.subscriptionServer
|
||||
const schema = ModulesSetup.graphSchema(await buildMocksConfig())
|
||||
|
||||
const server = new ApolloServer({
|
||||
schema,
|
||||
context: buildContext,
|
||||
plugins: [
|
||||
statusCodePlugin,
|
||||
require('@/logging/apolloPlugin'),
|
||||
loggingPlugin,
|
||||
ApolloServerPluginLandingPageLocalDefault({
|
||||
embed: true,
|
||||
includeCookies: true
|
||||
}),
|
||||
...(subscriptionServerResolver
|
||||
...(subscriptionServer
|
||||
? [
|
||||
{
|
||||
async serverWillStart() {
|
||||
return {
|
||||
async drainServer() {
|
||||
subscriptionServerResolver().close()
|
||||
subscriptionServer?.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -289,9 +277,8 @@ export async function buildApolloServer(
|
||||
cache: 'bounded',
|
||||
persistedQueries: false,
|
||||
csrfPrevention: true,
|
||||
formatError: buildErrorFormatter(debug),
|
||||
debug,
|
||||
...optionOverrides
|
||||
formatError: buildErrorFormatter({ includeStacktraceInErrorResponses }),
|
||||
includeStacktraceInErrorResponses
|
||||
})
|
||||
await server.start()
|
||||
|
||||
@@ -350,13 +337,20 @@ export async function init() {
|
||||
// Initialize default modules, including rest api handlers
|
||||
await ModulesSetup.init(app)
|
||||
|
||||
// Init HTTP server & subscription server
|
||||
const server = http.createServer(app)
|
||||
const subscriptionServer = buildApolloSubscriptionServer(server)
|
||||
|
||||
// Initialize graphql server
|
||||
// (Apollo Server v3 has an ugly API here - the ApolloServer ctor needs SubscriptionServer,
|
||||
// and the SubscriptionServer ctor needs ApolloServer...hence the callback passed into buildApolloServer)
|
||||
// eslint-disable-next-line prefer-const
|
||||
let subscriptionServer: SubscriptionServer
|
||||
graphqlServer = await buildApolloServer(undefined, () => subscriptionServer)
|
||||
graphqlServer.applyMiddleware({ app })
|
||||
graphqlServer = await buildApolloServer({
|
||||
subscriptionServer
|
||||
})
|
||||
app.use(
|
||||
GRAPHQL_PATH,
|
||||
expressMiddleware(graphqlServer, {
|
||||
context: buildContext
|
||||
})
|
||||
)
|
||||
|
||||
// Expose prometheus metrics
|
||||
app.get('/metrics', async (req, res) => {
|
||||
@@ -368,10 +362,6 @@ export async function init() {
|
||||
}
|
||||
})
|
||||
|
||||
// Init HTTP server & subscription server
|
||||
const server = http.createServer(app)
|
||||
subscriptionServer = buildApolloSubscriptionServer(graphqlServer, server)
|
||||
|
||||
// At the very end adding default error handler middleware
|
||||
app.use(defaultErrorHandler)
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { buildApolloServer } from '@/app'
|
||||
import {
|
||||
deleteRequestById,
|
||||
getPendingAccessRequest
|
||||
@@ -28,16 +29,15 @@ import {
|
||||
useStreamAccessRequest
|
||||
} from '@/test/graphql/accessRequests'
|
||||
import { StreamRole } from '@/test/graphql/generated/graphql'
|
||||
import { createAuthedTestContext, ServerAndContext } from '@/test/graphqlHelper'
|
||||
import { truncateTables } from '@/test/hooks'
|
||||
import { EmailSendingServiceMock } from '@/test/mocks/global'
|
||||
import {
|
||||
buildNotificationsStateTracker,
|
||||
NotificationsStateManager
|
||||
} from '@/test/notificationsHelper'
|
||||
import { buildAuthenticatedApolloServer } from '@/test/serverHelper'
|
||||
import { getStreamActivities } from '@/test/speckle-helpers/activityStreamHelper'
|
||||
import { BasicTestStream, createTestStreams } from '@/test/speckle-helpers/streamHelper'
|
||||
import { ApolloServer } from 'apollo-server-express'
|
||||
import { expect } from 'chai'
|
||||
import { noop } from 'lodash'
|
||||
|
||||
@@ -55,7 +55,7 @@ const cleanup = async () => {
|
||||
}
|
||||
|
||||
describe('Stream access requests', () => {
|
||||
let apollo: ApolloServer
|
||||
let apollo: ServerAndContext
|
||||
let notificationsStateManager: NotificationsStateManager
|
||||
|
||||
const me: BasicTestUser = {
|
||||
@@ -105,7 +105,10 @@ describe('Stream access requests', () => {
|
||||
[otherGuysPublicStream, otherGuy],
|
||||
[myPrivateStream, me]
|
||||
])
|
||||
apollo = await buildAuthenticatedApolloServer(me.id)
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(me.id)
|
||||
}
|
||||
notificationsStateManager = buildNotificationsStateTracker()
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
'use strict'
|
||||
const { ForbiddenError } = require('apollo-server-express')
|
||||
|
||||
const { ForbiddenError } = require('@/modules/shared/errors')
|
||||
const {
|
||||
getApp,
|
||||
getAllPublicApps,
|
||||
|
||||
@@ -10,8 +10,8 @@ const { validateToken, revokeTokenById } = require(`@/modules/core/services/toke
|
||||
const { revokeRefreshToken } = require(`@/modules/auth/services/apps`)
|
||||
const { validateScopes } = require(`@/modules/shared`)
|
||||
const { InvalidAccessCodeRequestError } = require('@/modules/auth/errors')
|
||||
const { ForbiddenError } = require('apollo-server-errors')
|
||||
const { Scopes } = require('@speckle/shared')
|
||||
const { ForbiddenError } = require('@/modules/shared/errors')
|
||||
|
||||
// TODO: Secure these endpoints!
|
||||
module.exports = (app) => {
|
||||
|
||||
@@ -13,9 +13,12 @@ import {
|
||||
StreamBlobsArgs
|
||||
} from '@/modules/core/graph/generated/graphql'
|
||||
import { StreamGraphQLReturn } from '@/modules/core/helpers/graphTypes'
|
||||
import { NotFoundError, ResourceMismatch } from '@/modules/shared/errors'
|
||||
import {
|
||||
BadRequestError,
|
||||
NotFoundError,
|
||||
ResourceMismatch
|
||||
} from '@/modules/shared/errors'
|
||||
import { Nullable } from '@speckle/shared'
|
||||
import { UserInputError } from 'apollo-server-errors'
|
||||
|
||||
const streamBlobResolvers = {
|
||||
async blobs(parent: StreamGraphQLReturn, args: StreamBlobsArgs | ProjectBlobsArgs) {
|
||||
@@ -47,7 +50,7 @@ const streamBlobResolvers = {
|
||||
})) as Nullable<BlobStorageRecord>
|
||||
} catch (err: unknown) {
|
||||
if (err instanceof NotFoundError) return null
|
||||
if (err instanceof ResourceMismatch) throw new UserInputError(err.message)
|
||||
if (err instanceof ResourceMismatch) throw new BadRequestError(err.message)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
const { buildApolloServer } = require('@/app')
|
||||
const { addLoadersToCtx } = require('@/modules/shared/middleware')
|
||||
const { truncateTables } = require('@/test/hooks')
|
||||
const { Roles, AllScopes } = require('@/modules/core/helpers/mainConstants')
|
||||
const { createStream } = require('@/modules/core/services/streams')
|
||||
const { createUser } = require('@/modules/core/services/users')
|
||||
const crs = require('crypto-random-string')
|
||||
const { gql } = require('apollo-server-express')
|
||||
const { gql } = require('graphql-tag')
|
||||
const { createBlobs } = require('@/modules/blobstorage/tests/helpers')
|
||||
const { expect } = require('chai')
|
||||
const { Users, Streams } = require('@/modules/core/dbSchema')
|
||||
const { createAuthedTestContext, executeOperation } = require('@/test/graphqlHelper')
|
||||
|
||||
describe('Blobs graphql @blobstorage', () => {
|
||||
/** @type {import('apollo-server-express').ApolloServer} */
|
||||
let apollo
|
||||
/** @type {import('@/test/graphqlHelper').ServerAndContext} */
|
||||
let graphqlServer
|
||||
|
||||
const user = {
|
||||
name: 'Baron Von Blubba',
|
||||
email: 'zebarron@bubble.bobble',
|
||||
@@ -21,16 +20,10 @@ describe('Blobs graphql @blobstorage', () => {
|
||||
before(async () => {
|
||||
await truncateTables(['blob_storage', Users.name, Streams.name])
|
||||
user.id = await createUser(user)
|
||||
apollo = await buildApolloServer({
|
||||
context: () =>
|
||||
addLoadersToCtx({
|
||||
auth: true,
|
||||
userId: crs({ length: 10 }),
|
||||
role: Roles.Server.User,
|
||||
token: 'asd',
|
||||
scopes: AllScopes
|
||||
})
|
||||
})
|
||||
graphqlServer = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(user.id)
|
||||
}
|
||||
})
|
||||
|
||||
it('Stream has blob metadata for a single blob', async () => {
|
||||
@@ -50,13 +43,12 @@ describe('Blobs graphql @blobstorage', () => {
|
||||
`
|
||||
const streamId = await createStream({ ownerId: user.id })
|
||||
const [blob] = await createBlobs({ streamId, number: 1 })
|
||||
const result = await apollo.executeOperation({
|
||||
query,
|
||||
variables: {
|
||||
streamId,
|
||||
blobId: blob.id
|
||||
}
|
||||
|
||||
const result = await executeOperation(graphqlServer, query, {
|
||||
streamId,
|
||||
blobId: blob.id
|
||||
})
|
||||
|
||||
const blobMetadata = result.data.stream.blob
|
||||
expect(blobMetadata.id).to.equal(blob.id)
|
||||
expect(blobMetadata.fileSize).to.equal(blob.fileSize)
|
||||
@@ -79,7 +71,7 @@ describe('Blobs graphql @blobstorage', () => {
|
||||
const number = 10
|
||||
const fileSize = 123
|
||||
await createBlobs({ streamId, number, fileSize })
|
||||
const result = await apollo.executeOperation({ query, variables: { streamId } })
|
||||
const result = await executeOperation(graphqlServer, query, { streamId })
|
||||
expect(result.data.stream.blobs.totalCount).to.equal(number)
|
||||
expect(result.data.stream.blobs.totalSize).to.equal(number * fileSize)
|
||||
})
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { pubsub } from '@/modules/shared/utils/subscriptions'
|
||||
import { ForbiddenError as ApolloForbiddenError } from 'apollo-server-express'
|
||||
import { ForbiddenError } from '@/modules/shared/errors'
|
||||
import { getStream } from '@/modules/core/services/streams'
|
||||
import { Roles } from '@/modules/core/helpers/mainConstants'
|
||||
@@ -77,7 +76,7 @@ const getStreamComment = async (
|
||||
|
||||
const comment = await getComment({ id: commentId, userId: ctx.userId })
|
||||
if (comment?.streamId !== streamId)
|
||||
throw new ApolloForbiddenError('You do not have access to this comment.')
|
||||
throw new ForbiddenError('You do not have access to this comment.')
|
||||
|
||||
return comment
|
||||
}
|
||||
@@ -285,21 +284,21 @@ export = {
|
||||
Stream: {
|
||||
async commentCount(parent, _args, context) {
|
||||
if (context.role === Roles.Server.ArchivedUser)
|
||||
throw new ApolloForbiddenError('You are not authorized.')
|
||||
throw new ForbiddenError('You are not authorized.')
|
||||
return await context.loaders.streams.getCommentThreadCount.load(parent.id)
|
||||
}
|
||||
},
|
||||
Commit: {
|
||||
async commentCount(parent, args, context) {
|
||||
if (context.role === Roles.Server.ArchivedUser)
|
||||
throw new ApolloForbiddenError('You are not authorized.')
|
||||
throw new ForbiddenError('You are not authorized.')
|
||||
return await getResourceCommentCount({ resourceId: parent.id })
|
||||
}
|
||||
},
|
||||
Object: {
|
||||
async commentCount(parent, args, context) {
|
||||
if (context.role === Roles.Server.ArchivedUser)
|
||||
throw new ApolloForbiddenError('You are not authorized.')
|
||||
throw new ForbiddenError('You are not authorized.')
|
||||
return await getResourceCommentCount({ resourceId: parent.id })
|
||||
}
|
||||
},
|
||||
@@ -368,17 +367,7 @@ export = {
|
||||
projectId: args.streamId,
|
||||
authCtx: context
|
||||
})
|
||||
// const stream = await getStream({
|
||||
// streamId: args.streamId,
|
||||
// userId: context.userId
|
||||
// })
|
||||
// if (!stream) {
|
||||
// throw new ApolloError('Stream not found')
|
||||
// }
|
||||
|
||||
// if (!stream.isPublic && !context.auth) {
|
||||
// return false
|
||||
// }
|
||||
await pubsub.publish(CommentSubscriptions.ViewerActivity, {
|
||||
userViewerActivity: args.data,
|
||||
streamId: args.streamId,
|
||||
@@ -396,7 +385,7 @@ export = {
|
||||
})
|
||||
|
||||
if (!stream?.allowPublicComments && !stream?.role)
|
||||
throw new ApolloForbiddenError('You are not authorized.')
|
||||
throw new ForbiddenError('You are not authorized.')
|
||||
|
||||
await pubsub.publish(CommentSubscriptions.CommentThreadActivity, {
|
||||
commentThreadActivity: { type: 'reply-typing-status', data: args.data },
|
||||
@@ -408,7 +397,7 @@ export = {
|
||||
|
||||
async commentCreate(parent, args, context) {
|
||||
if (!context.userId)
|
||||
throw new ApolloForbiddenError('Only registered users can comment.')
|
||||
throw new ForbiddenError('Only registered users can comment.')
|
||||
|
||||
const stream = await getStream({
|
||||
streamId: args.input.streamId,
|
||||
@@ -416,7 +405,7 @@ export = {
|
||||
})
|
||||
|
||||
if (!stream?.allowPublicComments && !stream?.role)
|
||||
throw new ApolloForbiddenError('You are not authorized.')
|
||||
throw new ForbiddenError('You are not authorized.')
|
||||
|
||||
const comment = await createComment({
|
||||
userId: context.userId,
|
||||
@@ -441,13 +430,8 @@ export = {
|
||||
requireProjectRole: true
|
||||
})
|
||||
const matchUser = !stream.role
|
||||
try {
|
||||
await editComment({ userId: context.userId!, input: args.input, matchUser })
|
||||
return true
|
||||
} catch (err) {
|
||||
if (err instanceof ForbiddenError) throw new ApolloForbiddenError(err.message)
|
||||
throw err
|
||||
}
|
||||
await editComment({ userId: context.userId!, input: args.input, matchUser })
|
||||
return true
|
||||
},
|
||||
|
||||
// used for flagging a comment as viewed
|
||||
@@ -467,13 +451,7 @@ export = {
|
||||
requireProjectRole: true
|
||||
})
|
||||
|
||||
let updatedComment
|
||||
try {
|
||||
updatedComment = await archiveComment({ ...args, userId: context.userId! }) // NOTE: permissions check inside service
|
||||
} catch (err) {
|
||||
if (err instanceof ForbiddenError) throw new ApolloForbiddenError(err.message)
|
||||
throw err
|
||||
}
|
||||
const updatedComment = await archiveComment({ ...args, userId: context.userId! }) // NOTE: permissions check inside service
|
||||
|
||||
await addCommentArchivedActivity({
|
||||
streamId: args.streamId,
|
||||
@@ -488,7 +466,7 @@ export = {
|
||||
|
||||
async commentReply(parent, args, context) {
|
||||
if (!context.userId)
|
||||
throw new ApolloForbiddenError('Only registered users can comment.')
|
||||
throw new ForbiddenError('Only registered users can comment.')
|
||||
|
||||
const stream = await getStream({
|
||||
streamId: args.input.streamId,
|
||||
@@ -496,7 +474,7 @@ export = {
|
||||
})
|
||||
|
||||
if (!stream?.allowPublicComments && !stream?.role)
|
||||
throw new ApolloForbiddenError('You are not authorized.')
|
||||
throw new ForbiddenError('You are not authorized.')
|
||||
|
||||
const reply = await createCommentReply({
|
||||
authorId: context.userId,
|
||||
@@ -528,7 +506,7 @@ export = {
|
||||
})
|
||||
|
||||
if (!stream?.allowPublicComments && !stream?.role)
|
||||
throw new ApolloForbiddenError('You are not authorized.')
|
||||
throw new ForbiddenError('You are not authorized.')
|
||||
|
||||
// dont report users activity to himself
|
||||
if (context.userId && context.userId === payload.authorId) {
|
||||
@@ -552,7 +530,7 @@ export = {
|
||||
})
|
||||
|
||||
if (!stream?.allowPublicComments && !stream?.role)
|
||||
throw new ApolloForbiddenError('You are not authorized.')
|
||||
throw new ForbiddenError('You are not authorized.')
|
||||
|
||||
// if we're listening for a stream's root comments events
|
||||
if (!variables.resourceIds) {
|
||||
@@ -601,7 +579,7 @@ export = {
|
||||
})
|
||||
|
||||
if (!stream?.allowPublicComments && !stream?.role)
|
||||
throw new ApolloForbiddenError('You are not authorized.')
|
||||
throw new ForbiddenError('You are not authorized.')
|
||||
|
||||
return (
|
||||
payload.streamId === variables.streamId &&
|
||||
@@ -630,7 +608,7 @@ export = {
|
||||
])
|
||||
|
||||
if (!stream?.isPublic && !stream?.role)
|
||||
throw new ApolloForbiddenError('You are not authorized.')
|
||||
throw new ForbiddenError('You are not authorized.')
|
||||
|
||||
// dont report users activity to himself
|
||||
if (
|
||||
@@ -665,7 +643,7 @@ export = {
|
||||
])
|
||||
|
||||
if (!(stream?.isDiscoverable || stream?.isPublic) && !stream?.role)
|
||||
throw new ApolloForbiddenError('You are not authorized.')
|
||||
throw new ForbiddenError('You are not authorized.')
|
||||
|
||||
if (!target.resourceIdString) {
|
||||
return true
|
||||
|
||||
@@ -2,15 +2,14 @@ const expect = require('chai').expect
|
||||
|
||||
const crs = require('crypto-random-string')
|
||||
const { buildApolloServer } = require('@/app')
|
||||
const { addLoadersToCtx } = require('@/modules/shared/middleware')
|
||||
const { beforeEachContext } = require('@/test/hooks')
|
||||
const { Roles, AllScopes } = require('@/modules/core/helpers/mainConstants')
|
||||
const { Roles } = require('@/modules/core/helpers/mainConstants')
|
||||
const {
|
||||
grantPermissionsStream,
|
||||
updateStream
|
||||
} = require('@/modules/core/services/streams')
|
||||
const { createUser } = require('@/modules/core/services/users')
|
||||
const { gql } = require('apollo-server-express')
|
||||
const { gql } = require('graphql-tag')
|
||||
const { createStream } = require('@/modules/core/services/streams')
|
||||
const { createObject } = require('@/modules/core/services/objects')
|
||||
const { createComment } = require('@/modules/comments/services')
|
||||
@@ -18,6 +17,11 @@ const { createCommitByBranchName } = require('@/modules/core/services/commits')
|
||||
const {
|
||||
convertBasicStringToDocument
|
||||
} = require('@/modules/core/services/richTextEditorService')
|
||||
const {
|
||||
createTestContext,
|
||||
createAuthedTestContext,
|
||||
executeOperation
|
||||
} = require('@/test/graphqlHelper')
|
||||
|
||||
function buildCommentInputFromString(textString) {
|
||||
return convertBasicStringToDocument(textString)
|
||||
@@ -27,7 +31,7 @@ const testForbiddenResponse = (result) => {
|
||||
expect(result.errors, 'This should have failed').to.exist
|
||||
expect(result.errors.length).to.be.above(0)
|
||||
expect(result.errors[0].extensions.code).to.match(
|
||||
/(STREAM_INVALID_ACCESS_ERROR|FORBIDDEN)/
|
||||
/(STREAM_INVALID_ACCESS_ERROR|FORBIDDEN|UNAUTHORIZED_ACCESS_ERROR)/
|
||||
)
|
||||
}
|
||||
|
||||
@@ -40,14 +44,32 @@ const testResult = (shouldSucceed, result, successTests) => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* apollo: import('@/test/graphqlHelper').ServerAndContext,
|
||||
* resources: {
|
||||
* streamId: string,
|
||||
* objectId: string,
|
||||
* commentId: string,
|
||||
* testActorId: string
|
||||
* },
|
||||
* shouldSucceed: boolean,
|
||||
* streamId: string
|
||||
* }} TestContext
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const writeComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
mutation ($input: CommentCreateInput!) {
|
||||
commentCreate(input: $input)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
{
|
||||
input: {
|
||||
streamId: resources.streamId,
|
||||
text: buildCommentInputFromString('foo'),
|
||||
@@ -56,16 +78,20 @@ const writeComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
resources: [{ resourceId: resources.streamId, resourceType: 'stream' }]
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.commentCreate).to.be.string
|
||||
expect(res.data.commentCreate.length).to.equal(10)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const broadcastViewerActivity = async ({ apollo, resources, shouldSucceed }) => {
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
mutation ($streamId: String!, $resourceId: String!, $data: JSONObject) {
|
||||
userViewerActivityBroadcast(
|
||||
streamId: $streamId
|
||||
@@ -74,20 +100,24 @@ const broadcastViewerActivity = async ({ apollo, resources, shouldSucceed }) =>
|
||||
)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
{
|
||||
streamId: resources.streamId,
|
||||
data: {},
|
||||
resourceId: resources.objectId
|
||||
}
|
||||
})
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.userViewerActivityBroadcast).to.be.true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const broadcastCommentActivity = async ({ apollo, resources, shouldSucceed }) => {
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
mutation ($streamId: String!, $commentId: String!, $data: JSONObject) {
|
||||
userCommentThreadActivityBroadcast(
|
||||
streamId: $streamId
|
||||
@@ -96,36 +126,43 @@ const broadcastCommentActivity = async ({ apollo, resources, shouldSucceed }) =>
|
||||
)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
{
|
||||
streamId: resources.streamId,
|
||||
data: {},
|
||||
commentId: resources.commentId
|
||||
}
|
||||
})
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.userCommentThreadActivityBroadcast).to.be.true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const viewAComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
mutation ($streamId: String!, $commentId: String!) {
|
||||
commentView(streamId: $streamId, commentId: $commentId)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
{
|
||||
streamId: resources.streamId,
|
||||
commentId: resources.commentId
|
||||
}
|
||||
})
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.commentView).to.be.true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const archiveMyComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
const context = await apollo.context()
|
||||
const context = apollo.context
|
||||
const { id: commentId } = await createComment({
|
||||
userId: context.userId,
|
||||
input: {
|
||||
@@ -139,40 +176,47 @@ const archiveMyComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
]
|
||||
}
|
||||
})
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
mutation ($streamId: String!, $commentId: String!) {
|
||||
commentArchive(streamId: $streamId, commentId: $commentId)
|
||||
}
|
||||
`,
|
||||
variables: { streamId: resources.streamId, commentId }
|
||||
})
|
||||
{ streamId: resources.streamId, commentId }
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.commentArchive).to.be.true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const archiveOthersComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
mutation ($streamId: String!, $commentId: String!) {
|
||||
commentArchive(streamId: $streamId, commentId: $commentId)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
{
|
||||
streamId: resources.streamId,
|
||||
commentId: resources.commentId
|
||||
}
|
||||
})
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.commentArchive).to.be.true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const editMyComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
const context = await apollo.context()
|
||||
const { id: commentId } = await createComment({
|
||||
userId: context.userId,
|
||||
userId: apollo.context.userId,
|
||||
input: {
|
||||
streamId: resources.streamId,
|
||||
text: buildCommentInputFromString('i wrote this myself'),
|
||||
@@ -184,13 +228,14 @@ const editMyComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
]
|
||||
}
|
||||
})
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
mutation ($input: CommentEditInput!) {
|
||||
commentEdit(input: $input)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
{
|
||||
input: {
|
||||
streamId: resources.streamId,
|
||||
id: commentId,
|
||||
@@ -198,20 +243,24 @@ const editMyComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
blobIds: []
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.commentEdit).to.be.true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const editOthersComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
mutation ($input: CommentEditInput!) {
|
||||
commentEdit(input: $input)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
{
|
||||
input: {
|
||||
streamId: resources.streamId,
|
||||
id: resources.commentId,
|
||||
@@ -221,20 +270,24 @@ const editOthersComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
blobIds: []
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.commentEdit).to.be.true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const replyToAComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
mutation ($input: ReplyCreateInput!) {
|
||||
commentReply(input: $input)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
{
|
||||
input: {
|
||||
streamId: resources.streamId,
|
||||
parentComment: resources.commentId,
|
||||
@@ -245,16 +298,20 @@ const replyToAComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
data: {}
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.commentReply).to.be.string
|
||||
expect(res.data.commentReply.length).to.equal(10)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const queryComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
query ($id: String!, $streamId: String!) {
|
||||
comment(id: $id, streamId: $streamId) {
|
||||
id
|
||||
@@ -270,16 +327,20 @@ const queryComment = async ({ apollo, resources, shouldSucceed }) => {
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
{
|
||||
id: resources.commentId,
|
||||
streamId: resources.streamId
|
||||
}
|
||||
})
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.comment.id).to.exist
|
||||
expect(res.data.comment.id).to.equal(resources.commentId)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const queryComments = async ({ apollo, resources, shouldSucceed }) => {
|
||||
const object = {
|
||||
foo: 123,
|
||||
@@ -304,8 +365,9 @@ const queryComments = async ({ apollo, resources, shouldSucceed }) => {
|
||||
)
|
||||
)
|
||||
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
query ($streamId: String!, $resources: [ResourceIdentifierInput]) {
|
||||
comments(streamId: $streamId, resources: $resources) {
|
||||
totalCount
|
||||
@@ -318,20 +380,23 @@ const queryComments = async ({ apollo, resources, shouldSucceed }) => {
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
{
|
||||
streamId: resources.streamId,
|
||||
resources: [
|
||||
// i expected this to work as intersection, but it works as union
|
||||
{ resourceId: objectId, resourceType: 'object' }
|
||||
]
|
||||
}
|
||||
})
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.comments.totalCount).to.be.equal(numberOfComments)
|
||||
expect(res.data.comments.items.map((i) => i.id)).to.be.equalInAnyOrder(commentIds)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const queryStreamCommentCount = async ({ apollo, resources, shouldSucceed }) => {
|
||||
await createComment({
|
||||
userId: resources.testActorId,
|
||||
@@ -344,8 +409,9 @@ const queryStreamCommentCount = async ({ apollo, resources, shouldSucceed }) =>
|
||||
}
|
||||
})
|
||||
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
query ($id: String!) {
|
||||
stream(id: $id) {
|
||||
id
|
||||
@@ -353,13 +419,16 @@ const queryStreamCommentCount = async ({ apollo, resources, shouldSucceed }) =>
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: { id: resources.streamId }
|
||||
})
|
||||
{ id: resources.streamId }
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.stream.commentCount).to.be.greaterThanOrEqual(1)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const queryObjectCommentCount = async ({ apollo, resources, shouldSucceed }) => {
|
||||
const objectId = await createObject({
|
||||
streamId: resources.streamId,
|
||||
@@ -379,8 +448,9 @@ const queryObjectCommentCount = async ({ apollo, resources, shouldSucceed }) =>
|
||||
}
|
||||
})
|
||||
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
query ($id: String!, $objectId: String!) {
|
||||
stream(id: $id) {
|
||||
object(id: $objectId) {
|
||||
@@ -389,13 +459,16 @@ const queryObjectCommentCount = async ({ apollo, resources, shouldSucceed }) =>
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: { id: resources.streamId, objectId }
|
||||
})
|
||||
{ id: resources.streamId, objectId }
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.stream.object.commentCount).to.equal(1)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const queryCommitCommentCount = async ({ apollo, resources, shouldSucceed }) => {
|
||||
const objectId = await createObject({
|
||||
streamId: resources.streamId,
|
||||
@@ -422,8 +495,9 @@ const queryCommitCommentCount = async ({ apollo, resources, shouldSucceed }) =>
|
||||
}
|
||||
})
|
||||
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
query ($id: String!, $commitId: String!) {
|
||||
stream(id: $id) {
|
||||
commit(id: $commitId) {
|
||||
@@ -432,13 +506,16 @@ const queryCommitCommentCount = async ({ apollo, resources, shouldSucceed }) =>
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: { id: resources.streamId, commitId }
|
||||
})
|
||||
{ id: resources.streamId, commitId }
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
expect(res.data.stream.commit.commentCount).to.equal(1)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TestContext} param0
|
||||
*/
|
||||
const queryCommitCollectionCommentCount = async ({
|
||||
apollo,
|
||||
resources,
|
||||
@@ -469,8 +546,9 @@ const queryCommitCollectionCommentCount = async ({
|
||||
}
|
||||
})
|
||||
|
||||
const res = await apollo.executeOperation({
|
||||
query: gql`
|
||||
const res = await executeOperation(
|
||||
apollo,
|
||||
gql`
|
||||
query ($id: String!) {
|
||||
otherUser(id: $id) {
|
||||
commits {
|
||||
@@ -481,8 +559,8 @@ const queryCommitCollectionCommentCount = async ({
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: { id: resources.testActorId }
|
||||
})
|
||||
{ id: resources.testActorId }
|
||||
)
|
||||
testResult(shouldSucceed, res, (res) => {
|
||||
res.data.otherUser.commits.items
|
||||
.map((i) => i.commentCount)
|
||||
@@ -830,19 +908,20 @@ describe('Graphql @comments', () => {
|
||||
userContext.streamData.forEach((streamContext) => {
|
||||
const stream = streamContext.stream
|
||||
let resources
|
||||
/**
|
||||
* @type {import('@/test/graphqlHelper').ServerAndContext}
|
||||
*/
|
||||
let apollo
|
||||
|
||||
before(async () => {
|
||||
apollo = await buildApolloServer({
|
||||
context: () =>
|
||||
addLoadersToCtx({
|
||||
auth: true,
|
||||
userId: user?.id,
|
||||
role: user?.role,
|
||||
token: 'asd',
|
||||
scopes: AllScopes
|
||||
})
|
||||
})
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: user
|
||||
? createAuthedTestContext(user.id, {
|
||||
...(user.role ? { role: user.role } : {})
|
||||
})
|
||||
: createTestContext()
|
||||
}
|
||||
|
||||
if (user && stream.role) {
|
||||
await grantPermissionsStream({
|
||||
|
||||
@@ -35,8 +35,7 @@ const {
|
||||
} = require('@/modules/comments/services/commentTextService')
|
||||
const { range } = require('lodash')
|
||||
const { buildApolloServer } = require('@/app')
|
||||
const { addLoadersToCtx } = require('@/modules/shared/middleware')
|
||||
const { Roles, AllScopes } = require('@/modules/core/helpers/mainConstants')
|
||||
const { AllScopes } = require('@/modules/core/helpers/mainConstants')
|
||||
const { createAuthTokenForUser } = require('@/test/authHelper')
|
||||
const { uploadBlob } = require('@/test/blobHelper')
|
||||
const { Comments } = require('@/modules/core/dbSchema')
|
||||
@@ -47,6 +46,7 @@ const {
|
||||
} = require('@/test/notificationsHelper')
|
||||
const { NotificationType } = require('@/modules/notifications/helpers/types')
|
||||
const { EmailSendingServiceMock } = require('@/test/mocks/global')
|
||||
const { createAuthedTestContext } = require('@/test/graphqlHelper')
|
||||
|
||||
function buildCommentInputFromString(textString) {
|
||||
return convertBasicStringToDocument(textString)
|
||||
@@ -999,7 +999,7 @@ describe('Comments @comments', () => {
|
||||
})
|
||||
|
||||
describe('when authenticated', () => {
|
||||
/** @type {import('apollo-server-express').ApolloServer} */
|
||||
/** @type {import('@/test/graphqlHelper').ServerAndContext} */
|
||||
let apollo
|
||||
let userToken
|
||||
let blob1
|
||||
@@ -1008,16 +1008,10 @@ describe('Comments @comments', () => {
|
||||
const scopes = AllScopes
|
||||
|
||||
// Init apollo instance w/ authenticated context
|
||||
apollo = await buildApolloServer({
|
||||
context: () =>
|
||||
addLoadersToCtx({
|
||||
auth: true,
|
||||
userId: user.id,
|
||||
role: Roles.Server.User,
|
||||
token: 'asd',
|
||||
scopes
|
||||
})
|
||||
})
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(user.id)
|
||||
}
|
||||
|
||||
// Init token for authenticating w/ REST API
|
||||
userToken = await createAuthTokenForUser(user.id, scopes)
|
||||
|
||||
+57
-26
@@ -1,10 +1,29 @@
|
||||
/* eslint-disable camelcase */
|
||||
/* istanbul ignore file */
|
||||
const { ApolloError } = require('apollo-server-express')
|
||||
const prometheusClient = require('prom-client')
|
||||
const { graphqlLogger } = require('@/logging/logging')
|
||||
const { redactSensitiveVariables } = require('@/logging/loggingHelper')
|
||||
const { GraphQLError } = require('graphql')
|
||||
import prometheusClient from 'prom-client'
|
||||
import { graphqlLogger } from '@/logging/logging'
|
||||
import { redactSensitiveVariables } from '@/logging/loggingHelper'
|
||||
import { FieldNode, GraphQLError, SelectionNode } from 'graphql'
|
||||
import { ApolloServerPlugin } from '@apollo/server'
|
||||
import { GraphQLContext } from '@/modules/shared/helpers/typeHelper'
|
||||
import { isUserGraphqlError } from '@/modules/shared/helpers/graphqlHelper'
|
||||
|
||||
type ApolloLoggingPluginTransaction = {
|
||||
start: number
|
||||
op: string
|
||||
name: string
|
||||
finish: () => void
|
||||
}
|
||||
|
||||
declare module '@apollo/server' {
|
||||
interface GraphQLRequest {
|
||||
/**
|
||||
* Set and used in our apollo logging plugin
|
||||
*/
|
||||
transaction?: ApolloLoggingPluginTransaction
|
||||
}
|
||||
}
|
||||
|
||||
const isFieldNode = (node: SelectionNode): node is FieldNode => node.kind === 'Field'
|
||||
|
||||
const metricCallCount = new prometheusClient.Counter({
|
||||
name: 'speckle_server_apollo_calls',
|
||||
@@ -12,19 +31,33 @@ const metricCallCount = new prometheusClient.Counter({
|
||||
labelNames: ['actionName']
|
||||
})
|
||||
|
||||
/** @type {import('apollo-server-core').PluginDefinition} */
|
||||
module.exports = {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
requestDidStart(ctx) {
|
||||
export const loggingPlugin: ApolloServerPlugin<GraphQLContext> = {
|
||||
requestDidStart: async () => {
|
||||
const apolloRequestStart = Date.now()
|
||||
return {
|
||||
didResolveOperation(ctx) {
|
||||
let logger = ctx.context.log || graphqlLogger
|
||||
const auth = ctx.context
|
||||
didResolveOperation: async (ctx) => {
|
||||
let logger = ctx.contextValue.log || graphqlLogger
|
||||
|
||||
if (!ctx.operation) {
|
||||
logger.debug('Attempted to log a GQL operation without an operation')
|
||||
return
|
||||
}
|
||||
|
||||
const firstSelectedField =
|
||||
ctx.operation.selectionSet.selections.find(isFieldNode)
|
||||
if (!firstSelectedField) {
|
||||
logger.debug(
|
||||
'Attempted to log a GQL operation without a top-level field selection'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const auth = ctx.contextValue
|
||||
const userId = auth?.userId
|
||||
|
||||
const op = `GQL ${ctx.operation.operation} ${ctx.operation.selectionSet.selections[0].name.value}`
|
||||
const name = `GQL ${ctx.operation.selectionSet.selections[0].name.value}`
|
||||
const actionName = `${ctx.operation.operation} ${firstSelectedField.name.value}`
|
||||
const op = `GQL ${actionName}`
|
||||
const name = `GQL ${firstSelectedField.name.value}`
|
||||
const kind = ctx.operation.operation
|
||||
const query = ctx.request.query
|
||||
const variables = ctx.request.variables
|
||||
@@ -43,23 +76,23 @@ module.exports = {
|
||||
op,
|
||||
name,
|
||||
finish: () => {
|
||||
//TODO add tracing with opentelemetry
|
||||
// TODO: add tracing with opentelemetry
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const actionName = `${ctx.operation.operation} ${ctx.operation.selectionSet.selections[0].name.value}`
|
||||
logger = logger.child({ actionName })
|
||||
metricCallCount.labels(actionName).inc()
|
||||
} catch (e) {
|
||||
logger.error({ err: e, transaction }, 'Error while defining action name')
|
||||
}
|
||||
|
||||
ctx.request.http
|
||||
ctx.request.transaction = transaction
|
||||
ctx.context.log = logger
|
||||
ctx.contextValue.log = logger
|
||||
},
|
||||
didEncounterErrors(ctx) {
|
||||
let logger = ctx.context.log || graphqlLogger
|
||||
didEncounterErrors: async (ctx) => {
|
||||
let logger = ctx.contextValue.log || graphqlLogger
|
||||
logger = logger.child({
|
||||
apollo_query_duration_ms: Date.now() - apolloRequestStart
|
||||
})
|
||||
@@ -77,10 +110,7 @@ module.exports = {
|
||||
graphql_variables: variables
|
||||
})
|
||||
}
|
||||
if (
|
||||
(err instanceof GraphQLError && err.extensions?.code === 'FORBIDDEN') ||
|
||||
err instanceof ApolloError
|
||||
) {
|
||||
if (err instanceof GraphQLError && isUserGraphqlError(err)) {
|
||||
logger.info(
|
||||
{ err },
|
||||
'{graphql_operation_value} failed after {apollo_query_duration_ms} ms'
|
||||
@@ -93,12 +123,13 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
},
|
||||
willSendResponse(ctx) {
|
||||
const logger = ctx.context.log || graphqlLogger
|
||||
willSendResponse: async (ctx) => {
|
||||
const logger = ctx.contextValue.log || graphqlLogger
|
||||
|
||||
if (ctx.request.transaction) {
|
||||
ctx.request.transaction.finish()
|
||||
}
|
||||
|
||||
logger.info(
|
||||
{
|
||||
apollo_query_duration_ms: Date.now() - apolloRequestStart
|
||||
@@ -1,8 +1,9 @@
|
||||
import { RateLimitError } from '@/modules/core/errors/ratelimit'
|
||||
import { BaseError } from '@/modules/shared/errors'
|
||||
import { Nullable } from '@speckle/shared'
|
||||
import type { ApolloServerPlugin } from 'apollo-server-plugin-base'
|
||||
import type { ApolloServerPlugin } from '@apollo/server'
|
||||
import type { GraphQLError } from 'graphql'
|
||||
import { GraphQLContext } from '@/modules/shared/helpers/typeHelper'
|
||||
|
||||
const getErrorCode = (e: GraphQLError): Nullable<string> => {
|
||||
const extensionsCode = e.extensions?.code as string
|
||||
@@ -15,7 +16,7 @@ const getErrorCode = (e: GraphQLError): Nullable<string> => {
|
||||
return infoCode
|
||||
}
|
||||
|
||||
export const statusCodePlugin: ApolloServerPlugin = {
|
||||
export const statusCodePlugin: ApolloServerPlugin<GraphQLContext> = {
|
||||
requestDidStart: async () => {
|
||||
return {
|
||||
willSendResponse: async (reqCtx) => {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
'use strict'
|
||||
|
||||
const { ForbiddenError } = require('apollo-server-express')
|
||||
const { ForbiddenError } = require('@/modules/shared/errors')
|
||||
const {
|
||||
createPersonalAccessToken,
|
||||
revokeToken,
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
'use strict'
|
||||
|
||||
const { CommitNotFoundError } = require('@/modules/core/errors/commit')
|
||||
const { UserInputError } = require('apollo-server-express')
|
||||
const { withFilter } = require('graphql-subscriptions')
|
||||
const {
|
||||
pubsub,
|
||||
@@ -41,6 +38,7 @@ const {
|
||||
const { StreamInvalidAccessError } = require('@/modules/core/errors/stream')
|
||||
const { Roles } = require('@speckle/shared')
|
||||
const { toProjectIdWhitelist } = require('@/modules/core/helpers/token')
|
||||
const { BadRequestError } = require('@/modules/shared/errors')
|
||||
|
||||
// subscription events
|
||||
const COMMIT_CREATED = CommitPubsubEvents.CommitCreated
|
||||
@@ -61,7 +59,7 @@ const getUserCommits = async (publicOnly, userId, args, streamIdWhitelist) => {
|
||||
streamIdWhitelist
|
||||
})
|
||||
if (args.limit && args.limit > 100)
|
||||
throw new UserInputError(
|
||||
throw new BadRequestError(
|
||||
'Cannot return more than 100 items, please use pagination.'
|
||||
)
|
||||
const { commits: items, cursor } = await getCommitsByUserId({
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { UserInputError } from 'apollo-server-express'
|
||||
import {
|
||||
getStream,
|
||||
getStreams,
|
||||
@@ -49,6 +48,7 @@ import { queryAllResourceInvitesFactory } from '@/modules/serverinvites/reposito
|
||||
import db from '@/db/knex'
|
||||
import { getInvitationTargetUsersFactory } from '@/modules/serverinvites/services/retrieval'
|
||||
import { getUsers } from '@/modules/core/repositories/users'
|
||||
import { BadRequestError } from '@/modules/shared/errors'
|
||||
|
||||
const getUserStreamsCore = async (
|
||||
forOtherUser: boolean,
|
||||
@@ -125,7 +125,7 @@ export = {
|
||||
|
||||
async adminStreams(parent, args, ctx) {
|
||||
if (args.limit && args.limit > 50)
|
||||
throw new UserInputError('Cannot return more than 50 items at a time.')
|
||||
throw new BadRequestError('Cannot return more than 50 items at a time.')
|
||||
|
||||
const { streams, totalCount } = await getStreams({
|
||||
offset: args.offset,
|
||||
@@ -200,7 +200,7 @@ export = {
|
||||
const { limit, cursor } = args
|
||||
|
||||
if (userId !== requestedUserId)
|
||||
throw new UserInputError("Cannot view another user's favorite streams")
|
||||
throw new BadRequestError("Cannot view another user's favorite streams")
|
||||
|
||||
return await getFavoriteStreamsCollection({
|
||||
userId,
|
||||
@@ -305,12 +305,14 @@ export = {
|
||||
const { streamId, favorited } = args
|
||||
const { userId, resourceAccessRules } = ctx
|
||||
|
||||
return await favoriteStream({
|
||||
const stream = await favoriteStream({
|
||||
userId: userId!,
|
||||
streamId,
|
||||
favorited,
|
||||
userResourceAccessRules: resourceAccessRules
|
||||
})
|
||||
|
||||
return stream
|
||||
},
|
||||
|
||||
async streamLeave(_parent, args, ctx) {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
'use strict'
|
||||
const { UserInputError } = require('apollo-server-express')
|
||||
const {
|
||||
getUser,
|
||||
getUserByEmail,
|
||||
@@ -28,6 +26,7 @@ const {
|
||||
findServerInvitesFactory
|
||||
} = require('@/modules/serverinvites/repositories/serverInvites')
|
||||
const db = require('@/db/knex')
|
||||
const { BadRequestError } = require('@/modules/shared/errors')
|
||||
|
||||
/** @type {import('@/modules/core/graph/generated/graphql').Resolvers} */
|
||||
module.exports = {
|
||||
@@ -60,7 +59,7 @@ module.exports = {
|
||||
else await validateScopes(context.scopes, Scopes.Users.Read)
|
||||
|
||||
if (!args.id && !context.userId) {
|
||||
throw new UserInputError('You must provide an user id.')
|
||||
throw new BadRequestError('You must provide an user id.')
|
||||
}
|
||||
|
||||
return await getUser(args.id || context.userId)
|
||||
@@ -81,10 +80,10 @@ module.exports = {
|
||||
await validateScopes(context.scopes, Scopes.Users.Read)
|
||||
|
||||
if (args.query.length < 3)
|
||||
throw new UserInputError('Search query must be at least 3 carachters.')
|
||||
throw new BadRequestError('Search query must be at least 3 carachters.')
|
||||
|
||||
if (args.limit && args.limit > 100)
|
||||
throw new UserInputError(
|
||||
throw new BadRequestError(
|
||||
'Cannot return more than 100 items, please use pagination.'
|
||||
)
|
||||
|
||||
@@ -173,7 +172,7 @@ module.exports = {
|
||||
const user = await getUser(context.userId)
|
||||
|
||||
if (args.userConfirmation.email !== user.email) {
|
||||
throw new UserInputError('Malformed input: emails do not match.')
|
||||
throw new BadRequestError('Malformed input: emails do not match.')
|
||||
}
|
||||
|
||||
// The below are not really needed anymore as we've added the hasRole and hasScope
|
||||
|
||||
+24
-22
@@ -1,7 +1,9 @@
|
||||
const _ = require('lodash')
|
||||
const VError = require('verror')
|
||||
const { ZodError } = require('zod')
|
||||
const { fromZodError } = require('zod-validation-error')
|
||||
import { ApolloServerOptions, BaseContext } from '@apollo/server'
|
||||
import { GraphQLError } from 'graphql'
|
||||
import _ from 'lodash'
|
||||
import { VError } from 'verror'
|
||||
import { ZodError } from 'zod'
|
||||
import { fromZodError } from 'zod-validation-error'
|
||||
|
||||
/**
|
||||
* Some VError implementation details that we want to remove from object representations
|
||||
@@ -11,32 +13,36 @@ const VERROR_TRASH_PROPS = ['jse_shortmsg', 'jse_cause', 'jse_info']
|
||||
|
||||
/**
|
||||
* Builds apollo server error formatter
|
||||
* @param {boolean} debug
|
||||
* @returns {(e: import('graphql').GraphQLError) => import('graphql').GraphQLFormattedError}
|
||||
*/
|
||||
function buildErrorFormatter(debug) {
|
||||
export function buildErrorFormatter(params: {
|
||||
includeStacktraceInErrorResponses: boolean
|
||||
}): ApolloServerOptions<BaseContext>['formatError'] {
|
||||
const { includeStacktraceInErrorResponses } = params
|
||||
|
||||
// TODO: Add support for client-aware errors and obfuscate everything else
|
||||
return function (error) {
|
||||
const debugMode = debug
|
||||
const realError = error.originalError ? error.originalError : error
|
||||
return function (formattedError, error) {
|
||||
let realError = error || formattedError
|
||||
if (realError instanceof GraphQLError && realError.originalError) {
|
||||
realError = realError.originalError
|
||||
}
|
||||
|
||||
// If error is a ZodError, convert its message to something more readable
|
||||
if (realError instanceof ZodError) {
|
||||
return {
|
||||
...error,
|
||||
...formattedError,
|
||||
message: fromZodError(realError).message,
|
||||
extensions: { ...error.extensions, code: 'BAD_REQUEST' }
|
||||
extensions: { ...formattedError.extensions, code: 'BAD_REQUEST' }
|
||||
}
|
||||
}
|
||||
|
||||
// If error isn't a VError child, don't do anything extra
|
||||
if (!(realError instanceof VError)) {
|
||||
return error
|
||||
return formattedError
|
||||
}
|
||||
|
||||
// Converting VError based error to Apollo's format
|
||||
const extensions = {
|
||||
...(error.extensions || {}),
|
||||
...(formattedError.extensions || {}),
|
||||
...(VError.info(realError) || {})
|
||||
}
|
||||
|
||||
@@ -47,7 +53,7 @@ function buildErrorFormatter(debug) {
|
||||
if (extensions.exception) {
|
||||
extensions.exception = _.omit(extensions.exception, VERROR_TRASH_PROPS)
|
||||
|
||||
if (debugMode) {
|
||||
if (includeStacktraceInErrorResponses) {
|
||||
extensions.exception.stacktrace = VError.fullStack(realError)
|
||||
} else {
|
||||
delete extensions.exception.stacktrace
|
||||
@@ -55,14 +61,10 @@ function buildErrorFormatter(debug) {
|
||||
}
|
||||
|
||||
return {
|
||||
message: error.message,
|
||||
locations: error.locations,
|
||||
path: error.path,
|
||||
message: formattedError.message,
|
||||
locations: formattedError.locations,
|
||||
path: formattedError.path,
|
||||
extensions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
buildErrorFormatter
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
ProjectModelsTreeArgs,
|
||||
StreamBranchesArgs
|
||||
} from '@/modules/core/graph/generated/graphql'
|
||||
import { UserInputError } from 'apollo-server-core'
|
||||
import { getBranchesByStreamId } from '@/modules/core/services/branches'
|
||||
import {
|
||||
getStructuredProjectModels,
|
||||
@@ -19,6 +18,7 @@ import { last } from 'lodash'
|
||||
import { Merge } from 'type-fest'
|
||||
import { ModelsTreeItemGraphQLReturn } from '@/modules/core/helpers/graphTypes'
|
||||
import { getMaximumProjectModelsPerPage } from '@/modules/shared/helpers/envHelper'
|
||||
import { BadRequestError } from '@/modules/shared/errors'
|
||||
|
||||
export async function getStructuredStreamModels(streamId: string) {
|
||||
return getStructuredProjectModels(streamId)
|
||||
@@ -30,7 +30,7 @@ export async function getPaginatedStreamBranches(
|
||||
) {
|
||||
const maxProjectModelsPerPage = getMaximumProjectModelsPerPage()
|
||||
if (params.limit && params.limit > maxProjectModelsPerPage)
|
||||
throw new UserInputError(
|
||||
throw new BadRequestError(
|
||||
`Cannot return more than ${maxProjectModelsPerPage} items, please use pagination.`
|
||||
)
|
||||
const { items, cursor, totalCount } = await getBranchesByStreamId({
|
||||
|
||||
@@ -13,14 +13,14 @@ import {
|
||||
getCommitsByStreamId,
|
||||
getCommitsTotalCountByStreamId
|
||||
} from '@/modules/core/services/commits'
|
||||
import { UserInputError } from 'apollo-server-core'
|
||||
import { BadRequestError } from '@/modules/shared/errors'
|
||||
|
||||
export async function getPaginatedStreamCommits(
|
||||
streamId: string,
|
||||
params: StreamCommitsArgs
|
||||
) {
|
||||
if (params.limit && params.limit > 100)
|
||||
throw new UserInputError(
|
||||
throw new BadRequestError(
|
||||
'Cannot return more than 100 items, please use pagination.'
|
||||
)
|
||||
const { commits: items, cursor } = await getCommitsByStreamId({
|
||||
@@ -41,7 +41,7 @@ export async function getPaginatedBranchCommits(
|
||||
params: PaginatedBranchCommitsParams & { filter?: Nullable<ModelVersionsFilter> }
|
||||
) {
|
||||
if (params.limit && params.limit > 100)
|
||||
throw new UserInputError(
|
||||
throw new BadRequestError(
|
||||
'Cannot return more than 100 items, please use pagination.'
|
||||
)
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
const { authorizeResolver } = require(`@/modules/shared`)
|
||||
|
||||
const { Roles } = require('@/modules/core/helpers/mainConstants')
|
||||
const { LogicError } = require('@/modules/shared/errors')
|
||||
const { ForbiddenError, UserInputError } = require('apollo-server-express')
|
||||
const {
|
||||
LogicError,
|
||||
ForbiddenError,
|
||||
BadRequestError
|
||||
} = require('@/modules/shared/errors')
|
||||
const {
|
||||
StreamInvalidAccessError,
|
||||
StreamAccessUpdateError
|
||||
@@ -170,7 +173,7 @@ async function addOrUpdateStreamCollaborator(
|
||||
if (role === Roles.Stream.Owner) {
|
||||
const userServerRole = await ServerAcl.knex().where({ userId }).first()
|
||||
if (userServerRole.role === Roles.Server.Guest)
|
||||
throw new UserInputError('Server guests cannot own streams')
|
||||
throw new BadRequestError('Server guests cannot own streams')
|
||||
}
|
||||
|
||||
const stream = await grantStreamPermissions({
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { buildApolloServer } from '@/app'
|
||||
import { Commits, Streams, Users } from '@/modules/core/dbSchema'
|
||||
import { Roles } from '@/modules/core/helpers/mainConstants'
|
||||
import { getCommits } from '@/modules/core/repositories/commits'
|
||||
@@ -5,14 +6,14 @@ import { createBranch } from '@/modules/core/services/branches'
|
||||
import { addOrUpdateStreamCollaborator } from '@/modules/core/services/streams/streamAccessService'
|
||||
import { BasicTestUser, createTestUsers } from '@/test/authHelper'
|
||||
import { deleteCommits, moveCommits } from '@/test/graphql/commits'
|
||||
import { truncateTables } from '@/test/hooks'
|
||||
import {
|
||||
buildAuthenticatedApolloServer,
|
||||
buildUnauthenticatedApolloServer
|
||||
} from '@/test/serverHelper'
|
||||
createAuthedTestContext,
|
||||
createTestContext,
|
||||
ServerAndContext
|
||||
} from '@/test/graphqlHelper'
|
||||
import { truncateTables } from '@/test/hooks'
|
||||
import { BasicTestCommit, createTestCommits } from '@/test/speckle-helpers/commitHelper'
|
||||
import { BasicTestStream, createTestStreams } from '@/test/speckle-helpers/streamHelper'
|
||||
import { ApolloServer } from 'apollo-server-express'
|
||||
import { expect } from 'chai'
|
||||
import { times } from 'lodash'
|
||||
import { describe } from 'mocha'
|
||||
@@ -120,7 +121,7 @@ describe('Batch commits', () => {
|
||||
]
|
||||
|
||||
const buildBatchActionInvoker =
|
||||
(apollo: ApolloServer) => (type: BatchActionType, commitIds: string[]) => {
|
||||
(apollo: ServerAndContext) => (type: BatchActionType, commitIds: string[]) => {
|
||||
if (type === BatchActionType.Delete) {
|
||||
return deleteCommits(apollo, { input: { commitIds } })
|
||||
} else if (type === BatchActionType.Move) {
|
||||
@@ -135,11 +136,14 @@ describe('Batch commits', () => {
|
||||
type BatchActionInvoker = ReturnType<typeof buildBatchActionInvoker>
|
||||
|
||||
describe('when authenticated', () => {
|
||||
let apollo: ApolloServer
|
||||
let apollo: ServerAndContext
|
||||
let invokeBatchAction: BatchActionInvoker
|
||||
|
||||
before(async () => {
|
||||
apollo = await buildAuthenticatedApolloServer(me.id)
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(me.id)
|
||||
}
|
||||
invokeBatchAction = buildBatchActionInvoker(apollo)
|
||||
})
|
||||
|
||||
@@ -268,11 +272,14 @@ describe('Batch commits', () => {
|
||||
})
|
||||
|
||||
describe('when not authenticated', () => {
|
||||
let apollo: ApolloServer
|
||||
let apollo: ServerAndContext
|
||||
let invokeBatchAction: BatchActionInvoker
|
||||
|
||||
before(async () => {
|
||||
apollo = await buildUnauthenticatedApolloServer()
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createTestContext()
|
||||
}
|
||||
invokeBatchAction = buildBatchActionInvoker(apollo)
|
||||
})
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { buildApolloServer } from '@/app'
|
||||
import { Commits, Streams, Users } from '@/modules/core/dbSchema'
|
||||
import { Roles } from '@/modules/core/helpers/mainConstants'
|
||||
import { addOrUpdateStreamCollaborator } from '@/modules/core/services/streams/streamAccessService'
|
||||
import { Nullable } from '@/modules/shared/helpers/typeHelper'
|
||||
import { BasicTestUser, createTestUsers } from '@/test/authHelper'
|
||||
import { readOtherUsersCommits, readOwnCommits } from '@/test/graphql/commits'
|
||||
import { createAuthedTestContext, ServerAndContext } from '@/test/graphqlHelper'
|
||||
import { truncateTables } from '@/test/hooks'
|
||||
import { buildAuthenticatedApolloServer } from '@/test/serverHelper'
|
||||
import { createTestCommit } from '@/test/speckle-helpers/commitHelper'
|
||||
import { BasicTestStream, createTestStreams } from '@/test/speckle-helpers/streamHelper'
|
||||
import { ApolloServer } from 'apollo-server-express'
|
||||
import { expect } from 'chai'
|
||||
|
||||
describe('Commits (GraphQL)', () => {
|
||||
@@ -94,10 +94,13 @@ describe('Commits (GraphQL)', () => {
|
||||
})
|
||||
|
||||
describe('when user authenticated', async () => {
|
||||
let apollo: ApolloServer
|
||||
let apollo: ServerAndContext
|
||||
|
||||
before(async () => {
|
||||
apollo = await buildAuthenticatedApolloServer(me.id)
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(me.id)
|
||||
}
|
||||
})
|
||||
|
||||
describe('and reading user commits', async () => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { buildApolloServer } from '@/app'
|
||||
import { Streams, Users } from '@/modules/core/dbSchema'
|
||||
import { getStream, setStreamFavorited } from '@/modules/core/repositories/streams'
|
||||
import { Nullable, Optional } from '@/modules/shared/helpers/typeHelper'
|
||||
@@ -11,14 +12,14 @@ import {
|
||||
readDiscoverableStreams,
|
||||
updateStream
|
||||
} from '@/test/graphql/streams'
|
||||
import { truncateTables } from '@/test/hooks'
|
||||
import {
|
||||
buildAuthenticatedApolloServer,
|
||||
buildUnauthenticatedApolloServer
|
||||
} from '@/test/serverHelper'
|
||||
createAuthedTestContext,
|
||||
createTestContext,
|
||||
ServerAndContext
|
||||
} from '@/test/graphqlHelper'
|
||||
import { truncateTables } from '@/test/hooks'
|
||||
import { BasicTestStream, createTestStream } from '@/test/speckle-helpers/streamHelper'
|
||||
import { wait } from '@speckle/shared'
|
||||
import { ApolloServer } from 'apollo-server-express'
|
||||
import { expect } from 'chai'
|
||||
import dayjs from 'dayjs'
|
||||
import { shuffle } from 'lodash'
|
||||
@@ -28,7 +29,7 @@ const READABLE_DISCOVERABLE_STREAM_COUNT = 15
|
||||
const cleanup = async () => await truncateTables([Streams.name, Users.name])
|
||||
|
||||
describe('Discoverable streams', () => {
|
||||
let apollo: ApolloServer
|
||||
let apollo: ServerAndContext
|
||||
|
||||
const me: BasicTestUser = {
|
||||
name: 'itsaa meeee',
|
||||
@@ -111,7 +112,10 @@ describe('Discoverable streams', () => {
|
||||
}
|
||||
}
|
||||
|
||||
apollo = await buildUnauthenticatedApolloServer()
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createTestContext()
|
||||
}
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
@@ -234,10 +238,13 @@ describe('Discoverable streams', () => {
|
||||
})
|
||||
|
||||
describe('when authenticated', () => {
|
||||
let apollo: ApolloServer
|
||||
let apollo: ServerAndContext
|
||||
|
||||
before(async () => {
|
||||
apollo = await buildAuthenticatedApolloServer(me.id)
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(me.id)
|
||||
}
|
||||
})
|
||||
|
||||
it('can be retrieved with role properly filled out', async () => {
|
||||
|
||||
@@ -3,13 +3,16 @@ const expect = require('chai').expect
|
||||
|
||||
const { buildApolloServer } = require('@/app')
|
||||
const { StreamFavorites, Streams, Users } = require('@/modules/core/dbSchema')
|
||||
const { Roles, AllScopes } = require('@/modules/core/helpers/mainConstants')
|
||||
const { createStream } = require('@/modules/core/services/streams')
|
||||
const { createUser } = require('@/modules/core/services/users')
|
||||
const { addLoadersToCtx } = require('@/modules/shared/middleware')
|
||||
const { truncateTables } = require('@/test/hooks')
|
||||
const { gql } = require('apollo-server-express')
|
||||
const { gql } = require('graphql-tag')
|
||||
const { sleep } = require('@/test/helpers')
|
||||
const {
|
||||
createAuthedTestContext,
|
||||
createTestContext,
|
||||
executeOperation
|
||||
} = require('@/test/graphqlHelper')
|
||||
|
||||
/**
|
||||
* Cleaning up relevant tables
|
||||
@@ -140,26 +143,17 @@ describe('Favorite streams', () => {
|
||||
})
|
||||
|
||||
describe('when authenticated', () => {
|
||||
/** @type {import('apollo-server-express').ApolloServer} */
|
||||
/** @type {import('@/test/graphqlHelper').ServerAndContext} */
|
||||
let apollo
|
||||
|
||||
const favoriteStream = async (sid, favorited) =>
|
||||
await apollo.executeOperation({
|
||||
query: favoriteMutationGql,
|
||||
variables: { sid, favorited }
|
||||
})
|
||||
await executeOperation(apollo, favoriteMutationGql, { sid, favorited })
|
||||
|
||||
before(async () => {
|
||||
apollo = await buildApolloServer({
|
||||
context: () =>
|
||||
addLoadersToCtx({
|
||||
auth: true,
|
||||
userId: me.id,
|
||||
role: Roles.Server.User,
|
||||
token: 'asd',
|
||||
scopes: AllScopes
|
||||
})
|
||||
})
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(me.id)
|
||||
}
|
||||
|
||||
// Drop all favorites to ensure we don't favorite already favorited streams
|
||||
await StreamFavorites.knex().truncate()
|
||||
@@ -242,10 +236,7 @@ describe('Favorite streams', () => {
|
||||
]
|
||||
|
||||
const getFavorites = async (cursor, limit = 10) =>
|
||||
await apollo.executeOperation({
|
||||
query: favoriteStreamsQueryGql,
|
||||
variables: { cursor, limit }
|
||||
})
|
||||
await executeOperation(apollo, favoriteStreamsQueryGql, { cursor, limit })
|
||||
|
||||
const favoritedStreamIds = () => favoritableStreams.map((s) => s.id)
|
||||
|
||||
@@ -267,10 +258,11 @@ describe('Favorite streams', () => {
|
||||
})
|
||||
|
||||
it("throw error if trying to get another user's favorite stream collection", async () => {
|
||||
const { data, errors } = await apollo.executeOperation({
|
||||
query: anotherUserFavoriteStreamsQueryGql,
|
||||
variables: { limit: 10, uid: otherGuy.id }
|
||||
})
|
||||
const { data, errors } = await executeOperation(
|
||||
apollo,
|
||||
anotherUserFavoriteStreamsQueryGql,
|
||||
{ limit: 10, uid: otherGuy.id }
|
||||
)
|
||||
|
||||
expect(data).to.be.ok
|
||||
expect(data.otherUser?.favoriteStreams).to.not.be.ok
|
||||
@@ -327,23 +319,16 @@ describe('Favorite streams', () => {
|
||||
oldNewQueryDataset.forEach(({ display, isNew }) => {
|
||||
it(`return total favorites count for user (${display} query)`, async () => {
|
||||
// "Log in" with other user
|
||||
const apollo = await buildApolloServer({
|
||||
context: () =>
|
||||
addLoadersToCtx({
|
||||
auth: true,
|
||||
userId: otherGuy.id,
|
||||
role: Roles.Server.User,
|
||||
token: 'asd',
|
||||
scopes: AllScopes
|
||||
})
|
||||
})
|
||||
const apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(otherGuy.id)
|
||||
}
|
||||
|
||||
const { data, errors } = await apollo.executeOperation({
|
||||
query: isNew
|
||||
? totalOwnedStreamsFavoritesNew
|
||||
: totalOwnedStreamsFavoritesOld,
|
||||
variables: { uid: me.id }
|
||||
})
|
||||
const { data, errors } = await executeOperation(
|
||||
apollo,
|
||||
isNew ? totalOwnedStreamsFavoritesNew : totalOwnedStreamsFavoritesOld,
|
||||
{ uid: me.id }
|
||||
)
|
||||
|
||||
expect(errors).to.not.be.ok
|
||||
|
||||
@@ -356,19 +341,20 @@ describe('Favorite streams', () => {
|
||||
})
|
||||
|
||||
describe('when not authenticated', () => {
|
||||
/** @type {import('apollo-server-express').ApolloServer} */
|
||||
/** @type {import('@/test/graphqlHelper').ServerAndContext} */
|
||||
let apollo
|
||||
|
||||
before(async () => {
|
||||
apollo = await buildApolloServer({
|
||||
context: () => ({})
|
||||
})
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createTestContext()
|
||||
}
|
||||
})
|
||||
|
||||
it("can't be favorited", async () => {
|
||||
const result = await apollo.executeOperation({
|
||||
query: favoriteMutationGql,
|
||||
variables: { sid: myPubStream.id, favorited: true }
|
||||
const result = await executeOperation(apollo, favoriteMutationGql, {
|
||||
sid: myPubStream.id,
|
||||
favorited: true
|
||||
})
|
||||
|
||||
expect(result.data.streamFavorite).to.not.be.ok
|
||||
@@ -377,9 +363,7 @@ describe('Favorite streams', () => {
|
||||
})
|
||||
|
||||
it("can't be retrieved", async () => {
|
||||
const result = await apollo.executeOperation({
|
||||
query: favoriteStreamsQueryGql
|
||||
})
|
||||
const result = await executeOperation(apollo, favoriteStreamsQueryGql)
|
||||
|
||||
expect(result.data.activeUser).to.be.null
|
||||
expect(result.errors).to.not.be.ok
|
||||
|
||||
@@ -15,9 +15,9 @@ const { createUser } = require('@/modules/core/services/users')
|
||||
|
||||
const { validateScopes, authorizeResolver } = require('@/modules/shared')
|
||||
const { buildContext } = require('@/modules/shared/middleware')
|
||||
const { ForbiddenError } = require('apollo-server-express')
|
||||
const { Roles, Scopes } = require('@speckle/shared')
|
||||
const { throwForNotHavingServerRole } = require('@/modules/shared/authz')
|
||||
const { ForbiddenError } = require('@/modules/shared/errors')
|
||||
|
||||
describe('Generic AuthN & AuthZ controller tests', () => {
|
||||
before(async () => {
|
||||
|
||||
@@ -303,7 +303,7 @@ describe('GraphQL API Core @core-api', () => {
|
||||
})
|
||||
expect(goodTokenScopesBadEmail.body.errors).to.exist
|
||||
expect(goodTokenScopesBadEmail.body.errors[0].extensions?.code).to.equal(
|
||||
'BAD_USER_INPUT'
|
||||
'BAD_REQUEST_ERROR'
|
||||
)
|
||||
const goodTokenScopesGoodEmail = await sendRequest(userDelete.token, {
|
||||
query:
|
||||
@@ -626,7 +626,9 @@ describe('GraphQL API Core @core-api', () => {
|
||||
query: '{ adminStreams(limit: 200) { totalCount items { id name } } }'
|
||||
})
|
||||
expect(streamResults.body.errors).to.exist
|
||||
expect(streamResults.body.errors[0].extensions.code).to.equal('BAD_USER_INPUT')
|
||||
expect(streamResults.body.errors[0].extensions.code).to.equal(
|
||||
'BAD_REQUEST_ERROR'
|
||||
)
|
||||
|
||||
streamResults = await sendRequest(userA.token, {
|
||||
query: '{ adminStreams(limit: 2) { totalCount items { id name } } }'
|
||||
@@ -1269,14 +1271,14 @@ describe('GraphQL API Core @core-api', () => {
|
||||
let res = await sendRequest(userB.token, { query: queryLim })
|
||||
expect(res).to.be.json
|
||||
expect(res.body.errors).to.exist
|
||||
expect(res.body.errors[0].extensions.code).to.equal('BAD_USER_INPUT')
|
||||
expect(res.body.errors[0].extensions.code).to.equal('BAD_REQUEST_ERROR')
|
||||
|
||||
const queryPagination =
|
||||
'query { userSearch( query: "matteo", limit: 200 ) { cursor items { id name } } } '
|
||||
res = await sendRequest(userB.token, { query: queryPagination })
|
||||
expect(res).to.be.json
|
||||
expect(res.body.errors).to.exist
|
||||
expect(res.body.errors[0].extensions.code).to.equal('BAD_USER_INPUT')
|
||||
expect(res.body.errors[0].extensions.code).to.equal('BAD_REQUEST_ERROR')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const expect = require('chai').expect
|
||||
const request = require('supertest')
|
||||
const { gql } = require('apollo-server-express')
|
||||
const { gql } = require('graphql-tag')
|
||||
const { WebSocketLink } = require('@apollo/client/link/ws')
|
||||
const { execute } = require('@apollo/client/core')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { gql } from 'apollo-server-express'
|
||||
import { gql } from 'graphql-tag'
|
||||
|
||||
export const createObjectMutation = gql`
|
||||
mutation CreateObject($input: ObjectCreateInput!) {
|
||||
|
||||
@@ -22,10 +22,6 @@ import {
|
||||
isStreamCollaborator
|
||||
} from '@/modules/core/services/streams/streamAccessService'
|
||||
import { Roles } from '@/modules/core/helpers/mainConstants'
|
||||
import {
|
||||
buildAuthenticatedApolloServer,
|
||||
buildUnauthenticatedApolloServer
|
||||
} from '@/test/serverHelper'
|
||||
import {
|
||||
getLimitedUserStreams,
|
||||
getUserStreams,
|
||||
@@ -43,7 +39,6 @@ import {
|
||||
} from '@/modules/core/repositories/streams'
|
||||
import { has, times } from 'lodash'
|
||||
import { Streams } from '@/modules/core/dbSchema'
|
||||
import { ApolloServer } from 'apollo-server-express'
|
||||
import { Nullable } from '@/modules/shared/helpers/typeHelper'
|
||||
import { sleep } from '@/test/helpers'
|
||||
import dayjs, { Dayjs } from 'dayjs'
|
||||
@@ -53,6 +48,12 @@ import {
|
||||
} from '@/test/graphql/generated/graphql'
|
||||
import { Get } from 'type-fest'
|
||||
import { changeUserRole } from '@/modules/core/services/users'
|
||||
import {
|
||||
createAuthedTestContext,
|
||||
createTestContext,
|
||||
ServerAndContext
|
||||
} from '@/test/graphqlHelper'
|
||||
import { buildApolloServer } from '@/app'
|
||||
|
||||
describe('Streams @core-streams', () => {
|
||||
const userOne: BasicTestUser = {
|
||||
@@ -210,7 +211,10 @@ describe('Streams @core-streams', () => {
|
||||
userOne.id
|
||||
)
|
||||
|
||||
const apollo = await buildAuthenticatedApolloServer(userTwo.id)
|
||||
const apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(userTwo.id)
|
||||
}
|
||||
const { data, errors } = await leaveStream(apollo, { streamId })
|
||||
|
||||
expect(errors).to.be.not.ok
|
||||
@@ -445,7 +449,7 @@ describe('Streams @core-streams', () => {
|
||||
* Base test for testing paginated & unpaginated User.streams query in various circumstances
|
||||
*/
|
||||
const testPaginatedUserStreams = async (
|
||||
apollo: ApolloServer,
|
||||
apollo: ServerAndContext,
|
||||
pagination: boolean,
|
||||
userId: string,
|
||||
isOtherUser: boolean,
|
||||
@@ -534,12 +538,15 @@ describe('Streams @core-streams', () => {
|
||||
}
|
||||
|
||||
describe('and user is authenticated', () => {
|
||||
let apollo: ApolloServer
|
||||
let apollo: ServerAndContext
|
||||
let activeUserId: string
|
||||
|
||||
before(async () => {
|
||||
activeUserId = userOne.id
|
||||
apollo = await buildAuthenticatedApolloServer(activeUserId)
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(activeUserId)
|
||||
}
|
||||
})
|
||||
|
||||
paginationDataset.forEach(({ display, pagination }) => {
|
||||
@@ -562,10 +569,13 @@ describe('Streams @core-streams', () => {
|
||||
})
|
||||
|
||||
describe('and user is not authenticated', () => {
|
||||
let apollo: ApolloServer
|
||||
let apollo: ServerAndContext
|
||||
|
||||
before(async () => {
|
||||
apollo = await buildUnauthenticatedApolloServer()
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createTestContext()
|
||||
}
|
||||
})
|
||||
|
||||
userLimitedUserDataSet.forEach(({ display, limitedUser }) => {
|
||||
@@ -573,8 +583,17 @@ describe('Streams @core-streams', () => {
|
||||
const results = limitedUser
|
||||
? await getLimitedUserStreams(apollo, { userId: userOne.id })
|
||||
: await getUserStreams(apollo, { userId: userOne.id })
|
||||
|
||||
const user = results.data
|
||||
? 'otherUser' in results.data
|
||||
? results.data.otherUser
|
||||
: 'user' in results.data
|
||||
? results.data.user
|
||||
: null
|
||||
: null
|
||||
|
||||
expect(results).to.haveGraphQLErrors()
|
||||
expect(results.data?.otherUser || results.data?.user).to.be.not.ok
|
||||
expect(user).to.be.not.ok
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -6,12 +6,11 @@ import { times, clamp } from 'lodash'
|
||||
import { createStreamInviteDirectly } from '@/test/speckle-helpers/inviteHelper'
|
||||
import { getAdminUsersList } from '@/test/graphql/users'
|
||||
import { buildApolloServer } from '@/app'
|
||||
import { addLoadersToCtx } from '@/modules/shared/middleware'
|
||||
import { Roles, AllScopes } from '@/modules/core/helpers/mainConstants'
|
||||
import { Roles } from '@/modules/core/helpers/mainConstants'
|
||||
import { expect } from 'chai'
|
||||
import { ApolloServer } from 'apollo-server-express'
|
||||
import { Optional } from '@/modules/shared/helpers/typeHelper'
|
||||
import { wait } from '@speckle/shared'
|
||||
import { createAuthedTestContext, ServerAndContext } from '@/test/graphqlHelper'
|
||||
|
||||
// To ensure that the invites are created in the correct order, we need to wait a bit between each creation
|
||||
const WAIT_TIMEOUT = 5
|
||||
@@ -59,7 +58,7 @@ describe('[Admin users list]', () => {
|
||||
const totalCount = USER_COUNT + SERVER_INVITE_COUNT + STREAM_INVITE_COUNT
|
||||
const totalInviteCount = SERVER_INVITE_COUNT + STREAM_INVITE_COUNT
|
||||
|
||||
let apollo: ApolloServer
|
||||
let apollo: ServerAndContext
|
||||
let orderedUserIds: string[] = []
|
||||
let orderedInviteIds: string[] = []
|
||||
|
||||
@@ -176,16 +175,10 @@ describe('[Admin users list]', () => {
|
||||
orderedInviteIds = await getOrderedInviteIds()
|
||||
orderedUserIds = await getOrderedUserIds()
|
||||
|
||||
apollo = await buildApolloServer({
|
||||
context: () =>
|
||||
addLoadersToCtx({
|
||||
auth: true,
|
||||
userId: me.id,
|
||||
role: Roles.Server.Admin,
|
||||
token: 'asd',
|
||||
scopes: AllScopes
|
||||
})
|
||||
})
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(me.id!, { role: Roles.Server.Admin })
|
||||
}
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
|
||||
@@ -2,11 +2,6 @@ import { Users } from '@/modules/core/dbSchema'
|
||||
import { BasicTestUser, createTestUsers } from '@/test/authHelper'
|
||||
import { getActiveUser, getOtherUser } from '@/test/graphql/users'
|
||||
import { beforeEachContext, truncateTables } from '@/test/hooks'
|
||||
import {
|
||||
buildAuthenticatedApolloServer,
|
||||
buildUnauthenticatedApolloServer
|
||||
} from '@/test/serverHelper'
|
||||
import { ApolloServer } from 'apollo-server-express'
|
||||
import { expect } from 'chai'
|
||||
import { createUser } from '@/modules/core/services/users'
|
||||
import {
|
||||
@@ -20,7 +15,12 @@ import {
|
||||
} from '@/modules/core/repositories/userEmails'
|
||||
import { db } from '@/db/knex'
|
||||
import { before } from 'mocha'
|
||||
import { testApolloServer } from '@/test/graphqlHelper'
|
||||
import {
|
||||
createAuthedTestContext,
|
||||
createTestContext,
|
||||
ServerAndContext,
|
||||
testApolloServer
|
||||
} from '@/test/graphqlHelper'
|
||||
import { GetActiveUserEmailsDocument } from '@/test/graphql/generated/graphql'
|
||||
import { validateAndCreateUserEmailFactory } from '@/modules/core/services/userEmails'
|
||||
import { finalizeInvitedServerRegistrationFactory } from '@/modules/serverinvites/services/processing'
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
updateAllInviteTargetsFactory
|
||||
} from '@/modules/serverinvites/repositories/serverInvites'
|
||||
import { requestNewEmailVerification } from '@/modules/emails/services/verification/request'
|
||||
import { buildApolloServer } from '@/app'
|
||||
|
||||
const createUserEmail = validateAndCreateUserEmailFactory({
|
||||
createUserEmail: createUserEmailFactory({ db }),
|
||||
@@ -64,10 +65,13 @@ describe('Users (GraphQL)', () => {
|
||||
})
|
||||
|
||||
describe('when unauthenticated', () => {
|
||||
let apollo: ApolloServer
|
||||
let apollo: ServerAndContext
|
||||
|
||||
before(async () => {
|
||||
apollo = await buildUnauthenticatedApolloServer()
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createTestContext()
|
||||
}
|
||||
})
|
||||
|
||||
it('activeUser returns null', async () => {
|
||||
@@ -88,10 +92,13 @@ describe('Users (GraphQL)', () => {
|
||||
})
|
||||
|
||||
describe('when authenticated', () => {
|
||||
let apollo: ApolloServer
|
||||
let apollo: ServerAndContext
|
||||
|
||||
before(async () => {
|
||||
apollo = await buildAuthenticatedApolloServer(me.id)
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(me.id)
|
||||
}
|
||||
})
|
||||
|
||||
it('activeUser returns authenticated user info', async () => {
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import { EmailVerifications, UserEmails, Users } from '@/modules/core/dbSchema'
|
||||
import { BasicTestUser, createTestUser, createTestUsers } from '@/test/authHelper'
|
||||
import { buildApp, truncateTables } from '@/test/hooks'
|
||||
import {
|
||||
buildAuthenticatedApolloServer,
|
||||
buildUnauthenticatedApolloServer
|
||||
} from '@/test/serverHelper'
|
||||
import { ApolloServer } from 'apollo-server-express'
|
||||
import request from 'supertest'
|
||||
import { expect } from 'chai'
|
||||
import { deleteVerifications, getPendingToken } from '@/modules/emails/repositories'
|
||||
@@ -19,6 +14,12 @@ import { Express } from 'express'
|
||||
import { getUser } from '@/modules/core/repositories/users'
|
||||
import dayjs from 'dayjs'
|
||||
import { EmailSendingServiceMock } from '@/test/mocks/global'
|
||||
import {
|
||||
createAuthedTestContext,
|
||||
createTestContext,
|
||||
ServerAndContext
|
||||
} from '@/test/graphqlHelper'
|
||||
import { buildApolloServer } from '@/app'
|
||||
|
||||
const mailerMock = EmailSendingServiceMock
|
||||
|
||||
@@ -71,10 +72,13 @@ describe('Email verifications @emails', () => {
|
||||
})
|
||||
|
||||
describe('when authenticated', () => {
|
||||
let apollo: ApolloServer
|
||||
let apollo: ServerAndContext
|
||||
|
||||
before(async () => {
|
||||
apollo = await buildAuthenticatedApolloServer(userA.id)
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(userA.id)
|
||||
}
|
||||
})
|
||||
|
||||
it('pending verification is reported correctly', async () => {
|
||||
@@ -101,7 +105,10 @@ describe('Email verifications @emails', () => {
|
||||
|
||||
describe('and requesting verification', () => {
|
||||
const invokeRequestVerification = async (user: BasicTestUser) => {
|
||||
const apollo = await buildAuthenticatedApolloServer(user.id)
|
||||
const apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createAuthedTestContext(user.id)
|
||||
}
|
||||
return await requestVerification(apollo, {})
|
||||
}
|
||||
|
||||
@@ -147,10 +154,13 @@ describe('Email verifications @emails', () => {
|
||||
})
|
||||
|
||||
describe('when not authenticated', () => {
|
||||
let apollo: ApolloServer
|
||||
let apollo: ServerAndContext
|
||||
|
||||
before(async () => {
|
||||
apollo = await buildUnauthenticatedApolloServer()
|
||||
apollo = {
|
||||
apollo: await buildApolloServer(),
|
||||
context: createTestContext()
|
||||
}
|
||||
})
|
||||
|
||||
it('cant request an account verification', async () => {
|
||||
|
||||
@@ -57,7 +57,7 @@ describe('FileUploads @fileuploads', () => {
|
||||
|
||||
after(async () => {
|
||||
process.env['CANONICAL_URL'] = existingCanonicalUrl
|
||||
await server.close()
|
||||
await server?.close()
|
||||
})
|
||||
|
||||
describe('Uploads files', () => {
|
||||
|
||||
@@ -141,7 +141,7 @@ exports.graphDataloadersBuilders = () => {
|
||||
/**
|
||||
* GQL components will be loaded even from disabled modules to avoid schema complexity, so ensure
|
||||
* that resolvers return valid values even if the module is disabled
|
||||
* @returns {Pick<import('apollo-server-express').Config, 'resolvers' | 'typeDefs'> & { directiveBuilders: Record<string, import('@/modules/core/graph/helpers/directiveHelper').GraphqlDirectiveBuilder>}}
|
||||
* @returns {Pick<import('@apollo/server').ApolloServerOptions, 'resolvers' | 'typeDefs'> & { directiveBuilders: Record<string, import('@/modules/core/graph/helpers/directiveHelper').GraphqlDirectiveBuilder>}}
|
||||
*/
|
||||
const graphComponents = () => {
|
||||
// Base query and mutation to allow for type extension by modules.
|
||||
|
||||
@@ -83,7 +83,7 @@ const buildBaseConfig = async (): Promise<SpeckleModuleMocksConfig> => {
|
||||
|
||||
/**
|
||||
* Define mocking config in dev env
|
||||
* https://www.apollographql.com/docs/apollo-server/v3/testing/mocking
|
||||
* https://www.apollographql.com/docs/apollo-server/testing/mocking
|
||||
*/
|
||||
export async function buildMocksConfig(): Promise<{
|
||||
mocks: boolean | IMocks
|
||||
|
||||
@@ -227,7 +227,7 @@ describe('[Stream & Server Invites]', () => {
|
||||
streamId: otherGuyAlreadyInvitedStream.id
|
||||
})
|
||||
|
||||
expect(data?.serverInviteCreate).to.be.not.ok
|
||||
expect(data?.streamInviteCreate).to.be.not.ok
|
||||
expect(errors).to.be.ok
|
||||
expect(errors!.map((e) => e.message).join('|')).to.contain(
|
||||
'user is already a collaborator'
|
||||
|
||||
@@ -2,6 +2,15 @@ import { AuthContext } from '@/modules/shared/authz'
|
||||
import { base64Decode, base64Encode } from '@/modules/shared/helpers/cryptoHelper'
|
||||
import DataLoader from 'dataloader'
|
||||
import dayjs, { Dayjs } from 'dayjs'
|
||||
import { ApolloServerErrorCode } from '@apollo/server/errors'
|
||||
import { GraphQLError } from 'graphql'
|
||||
import {
|
||||
BadRequestError,
|
||||
ForbiddenError,
|
||||
InvalidArgumentError,
|
||||
NotFoundError,
|
||||
UnauthorizedError
|
||||
} from '@/modules/shared/errors'
|
||||
|
||||
/**
|
||||
* Encode cursor to turn it into an opaque & obfuscated value
|
||||
@@ -65,3 +74,25 @@ export const defineRequestDataloaders = <
|
||||
): RequestDataLoadersBuilder<T> => {
|
||||
return builder
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a lower significance error, caused by user error (and thus - not a bug in our code)
|
||||
*/
|
||||
export const isUserGraphqlError = (error: GraphQLError): boolean => {
|
||||
const userCodes = [
|
||||
ForbiddenError.code,
|
||||
UnauthorizedError.code,
|
||||
BadRequestError.code,
|
||||
NotFoundError.code,
|
||||
InvalidArgumentError.code,
|
||||
ApolloServerErrorCode.BAD_REQUEST,
|
||||
ApolloServerErrorCode.BAD_USER_INPUT,
|
||||
ApolloServerErrorCode.GRAPHQL_PARSE_FAILED,
|
||||
ApolloServerErrorCode.GRAPHQL_VALIDATION_FAILED,
|
||||
ApolloServerErrorCode.OPERATION_RESOLUTION_FAILURE,
|
||||
ApolloServerErrorCode.PERSISTED_QUERY_NOT_FOUND,
|
||||
ApolloServerErrorCode.PERSISTED_QUERY_NOT_SUPPORTED
|
||||
]
|
||||
const code = error.extensions?.code as string
|
||||
return userCodes.includes(code)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { AuthContext } from '@/modules/shared/authz'
|
||||
import { Express } from 'express'
|
||||
import { ConditionalKeys, SetRequired } from 'type-fest'
|
||||
import pino from 'pino'
|
||||
import { BaseContext } from '@apollo/server'
|
||||
|
||||
export type MarkNullableOptional<T> = SetRequired<
|
||||
Partial<T>,
|
||||
@@ -40,14 +41,15 @@ export type SpeckleModule<T extends Record<string, unknown> = Record<string, unk
|
||||
shutdown?: () => MaybeAsync<void>
|
||||
} & T
|
||||
|
||||
export type GraphQLContext = AuthContext & {
|
||||
/**
|
||||
* Request-scoped GraphQL dataloaders
|
||||
* @see https://github.com/graphql/dataloader
|
||||
*/
|
||||
loaders: RequestDataLoaders
|
||||
export type GraphQLContext = BaseContext &
|
||||
AuthContext & {
|
||||
/**
|
||||
* Request-scoped GraphQL dataloaders
|
||||
* @see https://github.com/graphql/dataloader
|
||||
*/
|
||||
loaders: RequestDataLoaders
|
||||
|
||||
log: pino.Logger
|
||||
}
|
||||
log: pino.Logger
|
||||
}
|
||||
|
||||
export { Nullable, Optional, MaybeNullOrUndefined, MaybeAsync, MaybeFalsy }
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
'use strict'
|
||||
const knex = require(`@/db/knex`)
|
||||
const { ForbiddenError } = require('apollo-server-express')
|
||||
const {
|
||||
pubsub,
|
||||
StreamSubscriptions,
|
||||
@@ -17,6 +15,7 @@ const {
|
||||
isResourceAllowed
|
||||
} = require('@/modules/core/helpers/token')
|
||||
const db = require('@/db/knex')
|
||||
const { ForbiddenError } = require('@/modules/shared/errors')
|
||||
const ServerAcl = () => ServerAclSchema.knex()
|
||||
|
||||
/**
|
||||
|
||||
@@ -156,7 +156,7 @@ export async function buildContext({
|
||||
cleanLoadersEarly
|
||||
}: {
|
||||
req: MaybeNullOrUndefined<Request>
|
||||
token: Nullable<string>
|
||||
token?: Nullable<string>
|
||||
cleanLoadersEarly?: boolean
|
||||
}): Promise<GraphQLContext> {
|
||||
const ctx =
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
const { ForbiddenError } = require('apollo-server-express')
|
||||
|
||||
const { authorizeResolver } = require('@/modules/shared')
|
||||
const {
|
||||
deleteWebhook,
|
||||
@@ -10,6 +8,7 @@ const {
|
||||
const { Roles } = require('@speckle/shared')
|
||||
const { getWebhookByIdFactory } = require('../../repositories/webhooks')
|
||||
const { db } = require('@/db/knex')
|
||||
const { ForbiddenError } = require('@/modules/shared/errors')
|
||||
|
||||
const streamWebhooksResolver = async (parent, args, context) => {
|
||||
await authorizeResolver(
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
import { GraphqlDirectiveBuilder } from '@/modules/core/graph/helpers/directiveHelper'
|
||||
import { authorizeResolver } from '@/modules/shared'
|
||||
import { ForbiddenError } from '@/modules/shared/errors'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { gql } from 'apollo-server-express'
|
||||
import { gql } from 'graphql-tag'
|
||||
|
||||
export const basicWorkspaceFragment = gql`
|
||||
fragment BasicWorkspace on Workspace {
|
||||
|
||||
@@ -56,7 +56,6 @@ import {
|
||||
createTestStreams,
|
||||
leaveStream
|
||||
} from '@/test/speckle-helpers/streamHelper'
|
||||
import { ForbiddenError } from 'apollo-server-express'
|
||||
import { Workspaces } from '@/modules/workspaces/helpers/db'
|
||||
import {
|
||||
generateRegistrationParams,
|
||||
@@ -78,6 +77,7 @@ import { markUserEmailAsVerifiedFactory } from '@/modules/core/services/users/em
|
||||
import { createRandomPassword } from '@/modules/core/helpers/testHelpers'
|
||||
import { addOrUpdateStreamCollaborator } from '@/modules/core/services/streams/streamAccessService'
|
||||
import { WorkspaceProtectedError } from '@/modules/workspaces/errors/workspace'
|
||||
import { ForbiddenError } from '@/modules/shared/errors'
|
||||
|
||||
enum InviteByTarget {
|
||||
Email = 'email',
|
||||
|
||||
@@ -38,15 +38,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.7.0",
|
||||
"@apollo/server": "^4.11.0",
|
||||
"@aws-sdk/client-s3": "^3.276.0",
|
||||
"@aws-sdk/lib-storage": "^3.100.0",
|
||||
"@godaddy/terminus": "^4.9.0",
|
||||
"@graphql-tools/schema": "^10.0.4",
|
||||
"@graphql-tools/mock": "^9.0.4",
|
||||
"@graphql-tools/schema": "^10.0.6",
|
||||
"@mailchimp/mailchimp_marketing": "^3.0.80",
|
||||
"@speckle/objectloader": "workspace:^",
|
||||
"@speckle/shared": "workspace:^",
|
||||
"ajv": "^8.12.0",
|
||||
"apollo-server-express": "^3.10.2",
|
||||
"bcrypt": "^5.0.0",
|
||||
"bull": "^4.8.5",
|
||||
"busboy": "^1.4.0",
|
||||
@@ -65,10 +66,10 @@
|
||||
"express-async-errors": "^3.1.1",
|
||||
"express-prom-bundle": "^6.6.0",
|
||||
"express-session": "^1.17.1",
|
||||
"graphql": "^15",
|
||||
"graphql-redis-subscriptions": "^2.2.2",
|
||||
"graphql-scalars": "^1.18.0",
|
||||
"graphql-subscriptions": "^2.0.0",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"ioredis": "^5.2.2",
|
||||
"jose": "^5.6.3",
|
||||
"knex": "^2.4.1",
|
||||
@@ -129,6 +130,7 @@
|
||||
"@types/compression": "^1.7.2",
|
||||
"@types/connect-redis": "^0.0.23",
|
||||
"@types/cookie-parser": "^1.4.7",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/debug": "^4.1.7",
|
||||
"@types/deep-equal-in-any-order": "^1.0.1",
|
||||
"@types/ejs": "^3.1.1",
|
||||
@@ -159,7 +161,6 @@
|
||||
"@types/zxcvbn": "^4.4.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.39.0",
|
||||
"@typescript-eslint/parser": "^5.39.0",
|
||||
"apollo-server-plugin-base": "^3.7.2",
|
||||
"axios": "^1.7.4",
|
||||
"chai": "^4.2.0",
|
||||
"chai-as-promised": "^7.1.2",
|
||||
@@ -170,6 +171,7 @@
|
||||
"enforce-unique": "^1.3.0",
|
||||
"eslint": "^8.11.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"graphql": "^16.6.0",
|
||||
"http-proxy-middleware": "v3.0.0-beta.0",
|
||||
"ioredis-mock": "^8.9.0",
|
||||
"mocha": "^10.1.0",
|
||||
|
||||
@@ -10,8 +10,8 @@ import {
|
||||
UseStreamAccessRequestMutation,
|
||||
UseStreamAccessRequestMutationVariables
|
||||
} from '@/test/graphql/generated/graphql'
|
||||
import { executeOperation } from '@/test/graphqlHelper'
|
||||
import { ApolloServer, gql } from 'apollo-server-express'
|
||||
import { executeOperation, ExecuteOperationServer } from '@/test/graphqlHelper'
|
||||
import { gql } from 'graphql-tag'
|
||||
|
||||
const basicStreamAccessRequestFragment = gql`
|
||||
fragment BasicStreamAccessRequestFields on StreamAccessRequest {
|
||||
@@ -89,7 +89,7 @@ const useStreamAccessRequestMutation = gql`
|
||||
`
|
||||
|
||||
export const createStreamAccessRequest = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: CreateStreamAccessRequestMutationVariables
|
||||
) =>
|
||||
executeOperation<
|
||||
@@ -98,7 +98,7 @@ export const createStreamAccessRequest = (
|
||||
>(apollo, createStreamAccessRequestMutation, variables)
|
||||
|
||||
export const getStreamAccessRequest = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: GetStreamAccessRequestQueryVariables
|
||||
) =>
|
||||
executeOperation<GetStreamAccessRequestQuery, GetStreamAccessRequestQueryVariables>(
|
||||
@@ -108,7 +108,7 @@ export const getStreamAccessRequest = (
|
||||
)
|
||||
|
||||
export const getFullStreamAccessRequest = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: GetFullStreamAccessRequestQueryVariables
|
||||
) =>
|
||||
executeOperation<
|
||||
@@ -117,7 +117,7 @@ export const getFullStreamAccessRequest = (
|
||||
>(apollo, getFullStreamAccessRequestQuery, variables)
|
||||
|
||||
export const getPendingStreamAccessRequests = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: GetPendingStreamAccessRequestsQueryVariables
|
||||
) =>
|
||||
executeOperation<
|
||||
@@ -126,7 +126,7 @@ export const getPendingStreamAccessRequests = (
|
||||
>(apollo, getPendingStreamAccessRequestsQuery, variables)
|
||||
|
||||
export const useStreamAccessRequest = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: UseStreamAccessRequestMutationVariables
|
||||
) =>
|
||||
executeOperation<
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { gql } from 'apollo-server-express'
|
||||
import { gql } from 'graphql-tag'
|
||||
|
||||
export const createTokenMutation = gql`
|
||||
mutation CreateToken($token: ApiTokenCreateInput!) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { gql } from 'apollo-server-express'
|
||||
import { gql } from 'graphql-tag'
|
||||
|
||||
export const automateFunctionFragment = gql`
|
||||
fragment TestAutomateFunction on AutomateFunction {
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
GetCommentsQuery,
|
||||
GetCommentsQueryVariables
|
||||
} from '@/test/graphql/generated/graphql'
|
||||
import { executeOperation } from '@/test/graphqlHelper'
|
||||
import { ApolloServer, gql } from 'apollo-server-express'
|
||||
import { executeOperation, ExecuteOperationServer } from '@/test/graphqlHelper'
|
||||
import { gql } from 'graphql-tag'
|
||||
|
||||
const commentWithRepliesFragment = gql`
|
||||
fragment CommentWithReplies on Comment {
|
||||
@@ -76,7 +76,7 @@ const getCommentsQuery = gql`
|
||||
`
|
||||
|
||||
export const createComment = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: CreateCommentMutationVariables
|
||||
) =>
|
||||
executeOperation<CreateCommentMutation, CreateCommentMutationVariables>(
|
||||
@@ -86,7 +86,7 @@ export const createComment = (
|
||||
)
|
||||
|
||||
export const createReply = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: CreateReplyMutationVariables
|
||||
) =>
|
||||
executeOperation<CreateReplyMutation, CreateReplyMutationVariables>(
|
||||
@@ -95,7 +95,10 @@ export const createReply = (
|
||||
variables
|
||||
)
|
||||
|
||||
export const getComment = (apollo: ApolloServer, variables: GetCommentQueryVariables) =>
|
||||
export const getComment = (
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: GetCommentQueryVariables
|
||||
) =>
|
||||
executeOperation<GetCommentQuery, GetCommentQueryVariables>(
|
||||
apollo,
|
||||
getCommentQuery,
|
||||
@@ -103,7 +106,7 @@ export const getComment = (apollo: ApolloServer, variables: GetCommentQueryVaria
|
||||
)
|
||||
|
||||
export const getComments = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: GetCommentsQueryVariables
|
||||
) =>
|
||||
executeOperation<GetCommentsQuery, GetCommentsQueryVariables>(
|
||||
|
||||
@@ -10,8 +10,8 @@ import {
|
||||
ReadStreamBranchCommitsQuery,
|
||||
ReadStreamBranchCommitsQueryVariables
|
||||
} from '@/test/graphql/generated/graphql'
|
||||
import { executeOperation } from '@/test/graphqlHelper'
|
||||
import { ApolloServer, gql } from 'apollo-server-express'
|
||||
import { executeOperation, ExecuteOperationServer } from '@/test/graphqlHelper'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
const baseCommitFieldsFragment = gql`
|
||||
fragment BaseCommitFields on Commit {
|
||||
@@ -108,7 +108,7 @@ const deleteCommitsMutation = gql`
|
||||
`
|
||||
|
||||
export const readOwnCommits = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: ReadOwnCommitsQueryVariables
|
||||
) =>
|
||||
executeOperation<ReadOwnCommitsQuery, ReadOwnCommitsQueryVariables>(
|
||||
@@ -118,7 +118,7 @@ export const readOwnCommits = (
|
||||
)
|
||||
|
||||
export const readOtherUsersCommits = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: ReadOtherUsersCommitsQueryVariables
|
||||
) =>
|
||||
executeOperation<ReadOtherUsersCommitsQuery, ReadOtherUsersCommitsQueryVariables>(
|
||||
@@ -128,7 +128,7 @@ export const readOtherUsersCommits = (
|
||||
)
|
||||
|
||||
export const readStreamBranchCommits = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: ReadStreamBranchCommitsQueryVariables
|
||||
) =>
|
||||
executeOperation<ReadStreamBranchCommitsQuery, ReadStreamBranchCommitsQueryVariables>(
|
||||
@@ -138,7 +138,7 @@ export const readStreamBranchCommits = (
|
||||
)
|
||||
|
||||
export const moveCommits = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: MoveCommitsMutationVariables
|
||||
) =>
|
||||
executeOperation<MoveCommitsMutation, MoveCommitsMutationVariables>(
|
||||
@@ -148,7 +148,7 @@ export const moveCommits = (
|
||||
)
|
||||
|
||||
export const deleteCommits = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: DeleteCommitsMutationVariables
|
||||
) =>
|
||||
executeOperation<DeleteCommitsMutation, DeleteCommitsMutationVariables>(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { gql } from 'apollo-server-express'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const createProjectModelQuery = gql`
|
||||
mutation CreateProjectModel($input: CreateModelInput!) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { gql } from 'apollo-server-express'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
const basicProjectAccessRequestFragment = gql`
|
||||
fragment BasicProjectAccessRequestFields on ProjectAccessRequest {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { gql } from 'apollo-server-express'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const createProjectCommentMutation = gql`
|
||||
mutation CreateProjectComment($input: CreateCommentInput!) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { gql } from 'apollo-server-express'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const basicProjectFieldsFragment = gql`
|
||||
fragment BasicProjectFields on Project {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { gql } from 'apollo-server-express'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const createServerInviteMutation = gql`
|
||||
mutation CreateServerInvite($input: ServerInviteCreateInput!) {
|
||||
|
||||
@@ -14,8 +14,8 @@ import {
|
||||
GetLimitedUserStreamsQuery,
|
||||
GetLimitedUserStreamsQueryVariables
|
||||
} from '@/test/graphql/generated/graphql'
|
||||
import { executeOperation } from '@/test/graphqlHelper'
|
||||
import { ApolloServer, gql } from 'apollo-server-express'
|
||||
import { executeOperation, ExecuteOperationServer } from '@/test/graphqlHelper'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const basicStreamFieldsFragment = gql`
|
||||
fragment BasicStreamFields on Stream {
|
||||
@@ -129,7 +129,7 @@ const getLimitedUserStreamsQuery = gql`
|
||||
`
|
||||
|
||||
export const leaveStream = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: LeaveStreamMutationVariables
|
||||
) =>
|
||||
executeOperation<LeaveStreamMutation, LeaveStreamMutationVariables>(
|
||||
@@ -139,7 +139,7 @@ export const leaveStream = (
|
||||
)
|
||||
|
||||
export const createStream = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: CreateStreamMutationVariables
|
||||
) =>
|
||||
executeOperation<CreateStreamMutation, CreateStreamMutationVariables>(
|
||||
@@ -149,7 +149,7 @@ export const createStream = (
|
||||
)
|
||||
|
||||
export const updateStream = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: UpdateStreamMutationVariables
|
||||
) =>
|
||||
executeOperation<UpdateStreamMutation, UpdateStreamMutationVariables>(
|
||||
@@ -158,7 +158,10 @@ export const updateStream = (
|
||||
variables
|
||||
)
|
||||
|
||||
export const readStream = (apollo: ApolloServer, variables: ReadStreamQueryVariables) =>
|
||||
export const readStream = (
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: ReadStreamQueryVariables
|
||||
) =>
|
||||
executeOperation<ReadStreamQuery, ReadStreamQueryVariables>(
|
||||
apollo,
|
||||
readStreamQuery,
|
||||
@@ -166,7 +169,7 @@ export const readStream = (apollo: ApolloServer, variables: ReadStreamQueryVaria
|
||||
)
|
||||
|
||||
export const readDiscoverableStreams = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: ReadDiscoverableStreamsQueryVariables
|
||||
) =>
|
||||
executeOperation<ReadDiscoverableStreamsQuery, ReadDiscoverableStreamsQueryVariables>(
|
||||
@@ -176,7 +179,7 @@ export const readDiscoverableStreams = (
|
||||
)
|
||||
|
||||
export const getUserStreams = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: GetUserStreamsQueryVariables
|
||||
) =>
|
||||
executeOperation<GetUserStreamsQuery, GetUserStreamsQueryVariables>(
|
||||
@@ -186,7 +189,7 @@ export const getUserStreams = (
|
||||
)
|
||||
|
||||
export const getLimitedUserStreams = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: GetLimitedUserStreamsQueryVariables
|
||||
) =>
|
||||
executeOperation<GetLimitedUserStreamsQuery, GetLimitedUserStreamsQueryVariables>(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { gql } from 'apollo-server-express'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const userWithEmailsFragment = gql`
|
||||
fragment UserWithEmails on User {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { ApolloServer, gql } from 'apollo-server-express'
|
||||
import {
|
||||
GetActiveUserQuery,
|
||||
GetActiveUserQueryVariables,
|
||||
@@ -11,7 +10,8 @@ import {
|
||||
RequestVerificationMutation,
|
||||
RequestVerificationMutationVariables
|
||||
} from '@/test/graphql/generated/graphql'
|
||||
import { executeOperation } from '@/test/graphqlHelper'
|
||||
import { executeOperation, ExecuteOperationServer } from '@/test/graphqlHelper'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
const baseUserFieldsFragment = gql`
|
||||
fragment BaseUserFields on User {
|
||||
@@ -99,14 +99,14 @@ const requestVerificationMutation = gql`
|
||||
}
|
||||
`
|
||||
|
||||
export const getActiveUser = (apollo: ApolloServer) =>
|
||||
export const getActiveUser = (apollo: ExecuteOperationServer) =>
|
||||
executeOperation<GetActiveUserQuery, GetActiveUserQueryVariables>(
|
||||
apollo,
|
||||
getActiveUserQuery
|
||||
)
|
||||
|
||||
export const getOtherUser = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: GetOtherUserQueryVariables
|
||||
) =>
|
||||
executeOperation<GetOtherUserQuery, GetOtherUserQueryVariables>(
|
||||
@@ -116,7 +116,7 @@ export const getOtherUser = (
|
||||
)
|
||||
|
||||
export async function getAdminUsersList(
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: GetAdminUsersQueryVariables
|
||||
) {
|
||||
return await executeOperation<GetAdminUsersQuery, GetAdminUsersQueryVariables>(
|
||||
@@ -127,7 +127,7 @@ export async function getAdminUsersList(
|
||||
}
|
||||
|
||||
export const getPendingEmailVerificationStatus = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables: GetPendingEmailVerificationStatusQueryVariables
|
||||
) =>
|
||||
executeOperation<
|
||||
@@ -136,7 +136,7 @@ export const getPendingEmailVerificationStatus = (
|
||||
>(apollo, getPendingEmailVerificationStatusQuery, variables)
|
||||
|
||||
export const requestVerification = (
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
variables?: RequestVerificationMutationVariables
|
||||
) =>
|
||||
executeOperation<RequestVerificationMutation, RequestVerificationMutationVariables>(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { gql } from 'apollo-server-express'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const createProjectVersionMutation = gql`
|
||||
mutation CreateProjectVersion($input: CreateVersionInput!) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { gql } from 'apollo-server-express'
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export const workspaceFragment = gql`
|
||||
fragment TestWorkspace on Workspace {
|
||||
|
||||
@@ -1,36 +1,77 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { ApolloServer } from 'apollo-server-express'
|
||||
import { GraphQLResponse } from 'apollo-server-types'
|
||||
import { DocumentNode } from 'graphql'
|
||||
import { GraphQLContext, Nullable } from '@/modules/shared/helpers/typeHelper'
|
||||
import { GraphQLContext } from '@/modules/shared/helpers/typeHelper'
|
||||
import { TypedDocumentNode } from '@graphql-typed-document-node/core'
|
||||
import { buildApolloServer } from '@/app'
|
||||
import { addLoadersToCtx } from '@/modules/shared/middleware'
|
||||
import { buildUnauthenticatedApolloServer } from '@/test/serverHelper'
|
||||
import { Roles } from '@/modules/core/helpers/mainConstants'
|
||||
import { AllScopes } from '@speckle/shared'
|
||||
import { AllScopes, MaybeNullOrUndefined } from '@speckle/shared'
|
||||
import { expect } from 'chai'
|
||||
import { ApolloServer, GraphQLResponse } from '@apollo/server'
|
||||
|
||||
type TypedGraphqlResponse<R = Record<string, any>> = GraphQLResponse & {
|
||||
data: Nullable<R>
|
||||
type TypedGraphqlResponse<R = Record<string, any>> = GraphQLResponse<R>
|
||||
|
||||
export const getResponseResults = <TData = Record<string, unknown>>(
|
||||
res: GraphQLResponse<TData>
|
||||
) => {
|
||||
const body = res.body
|
||||
if (body.kind === 'incremental') {
|
||||
return {
|
||||
data: body.initialResult.data as MaybeNullOrUndefined<TData>,
|
||||
errors: body.initialResult.errors
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
data: body.singleResult.data as MaybeNullOrUndefined<TData>,
|
||||
errors: body.singleResult.errors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type ExecuteOperationResponse<R extends Record<string, any>> = {
|
||||
res: TypedGraphqlResponse<R>
|
||||
} & ReturnType<typeof getResponseResults<R>>
|
||||
|
||||
export type ServerAndContext = {
|
||||
apollo: ApolloServer<GraphQLContext>
|
||||
context?: MaybeNullOrUndefined<GraphQLContext>
|
||||
}
|
||||
export type ExecuteOperationServer = ServerAndContext
|
||||
|
||||
/**
|
||||
* Use this to execute GQL operations from tests against an Apollo instance and get
|
||||
* a properly typed response
|
||||
* @deprecated Use `testApolloServer` instead
|
||||
*/
|
||||
export async function executeOperation<
|
||||
R extends Record<string, any> = Record<string, any>,
|
||||
V extends Record<string, any> = Record<string, any>
|
||||
>(
|
||||
apollo: ApolloServer,
|
||||
apollo: ExecuteOperationServer,
|
||||
query: DocumentNode,
|
||||
variables?: V
|
||||
): Promise<TypedGraphqlResponse<R>> {
|
||||
return (await apollo.executeOperation({
|
||||
query,
|
||||
variables
|
||||
})) as TypedGraphqlResponse<R>
|
||||
variables?: V,
|
||||
context?: GraphQLContext
|
||||
): Promise<ExecuteOperationResponse<R>> {
|
||||
const server: ApolloServer<GraphQLContext> = apollo.apollo
|
||||
const contextValue = context || apollo.context || createTestContext()
|
||||
|
||||
const res = (await server.executeOperation(
|
||||
{
|
||||
query,
|
||||
variables
|
||||
},
|
||||
{ contextValue }
|
||||
)) as TypedGraphqlResponse<R>
|
||||
|
||||
const results = getResponseResults(res)
|
||||
|
||||
// Replicate clearing dataloaders after each request
|
||||
contextValue.loaders.clearAll()
|
||||
|
||||
return {
|
||||
...results,
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,6 +92,19 @@ export const createTestContext = (
|
||||
...(ctx || {})
|
||||
})
|
||||
|
||||
export const createAuthedTestContext = (
|
||||
userId: string,
|
||||
ctxOverrides?: Partial<Parameters<typeof addLoadersToCtx>[0]>
|
||||
): GraphQLContext =>
|
||||
addLoadersToCtx({
|
||||
auth: true,
|
||||
userId,
|
||||
role: Roles.Server.User,
|
||||
token: 'asd',
|
||||
scopes: AllScopes,
|
||||
...(ctxOverrides || {})
|
||||
})
|
||||
|
||||
/**
|
||||
* Utilities that make it easier to test against an Apollo Server instance
|
||||
*/
|
||||
@@ -61,21 +115,16 @@ export const testApolloServer = async (params?: {
|
||||
*/
|
||||
authUserId?: string
|
||||
}) => {
|
||||
const initialCtx: GraphQLContext | undefined = params?.authUserId
|
||||
? createTestContext({
|
||||
auth: true,
|
||||
userId: params.authUserId,
|
||||
role: Roles.Server.User,
|
||||
token: 'asd',
|
||||
scopes: AllScopes
|
||||
})
|
||||
: params?.context
|
||||
let baseCtx: GraphQLContext
|
||||
if (params?.authUserId) {
|
||||
baseCtx = createAuthedTestContext(params.authUserId)
|
||||
} else if (params?.context) {
|
||||
baseCtx = params.context
|
||||
} else {
|
||||
baseCtx = createTestContext()
|
||||
}
|
||||
|
||||
const instance = initialCtx
|
||||
? await buildApolloServer({
|
||||
context: initialCtx
|
||||
})
|
||||
: await buildUnauthenticatedApolloServer()
|
||||
const instance = await buildApolloServer()
|
||||
|
||||
/**
|
||||
* Execute an operation against Apollo and get a properly typed response
|
||||
@@ -96,26 +145,31 @@ export const testApolloServer = async (params?: {
|
||||
*/
|
||||
assertNoErrors: boolean
|
||||
}>
|
||||
): Promise<TypedGraphqlResponse<R>> => {
|
||||
const realInstance = options?.context
|
||||
? await buildApolloServer({
|
||||
context: createTestContext({
|
||||
...(initialCtx || {}),
|
||||
...options.context
|
||||
})
|
||||
): Promise<ExecuteOperationResponse<R>> => {
|
||||
const ctx = options?.context
|
||||
? createTestContext({
|
||||
...(baseCtx || {}),
|
||||
...options.context
|
||||
})
|
||||
: instance
|
||||
: baseCtx
|
||||
|
||||
const res = (await realInstance.executeOperation({
|
||||
query,
|
||||
variables
|
||||
})) as TypedGraphqlResponse<R>
|
||||
const res = (await instance.executeOperation(
|
||||
{
|
||||
query,
|
||||
variables
|
||||
},
|
||||
{ contextValue: ctx }
|
||||
)) as TypedGraphqlResponse<R>
|
||||
|
||||
if (options?.assertNoErrors) {
|
||||
expect(res).to.not.haveGraphQLErrors()
|
||||
}
|
||||
|
||||
return res
|
||||
const results = getResponseResults(res)
|
||||
return {
|
||||
...results,
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
return { execute, server: instance }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Optional } from '@/modules/shared/helpers/typeHelper'
|
||||
import { GraphQLResponse } from 'apollo-server-core'
|
||||
import { ExecuteOperationResponse } from '@/test/graphqlHelper'
|
||||
import { AssertionError } from 'chai'
|
||||
import { isString } from 'lodash'
|
||||
|
||||
@@ -21,7 +21,8 @@ const graphqlChaiPlugin: Chai.ChaiPlugin = (_chai, utils) => {
|
||||
Assertion.prototype,
|
||||
'haveGraphQLErrors',
|
||||
function (
|
||||
this: ChaiPluginThis<GraphQLResponse>,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
this: ChaiPluginThis<ExecuteOperationResponse<any>>,
|
||||
messageOrOptions?: string | ({ message: string } | { code: string })
|
||||
) {
|
||||
const message = isString(messageOrOptions)
|
||||
|
||||
@@ -1,40 +1,5 @@
|
||||
import { buildApolloServer } from '@/app'
|
||||
import { Roles, AllScopes } from '@/modules/core/helpers/mainConstants'
|
||||
import { addLoadersToCtx } from '@/modules/shared/middleware'
|
||||
import net from 'net'
|
||||
|
||||
/**
|
||||
* Build an ApolloServer instance with an authenticated context
|
||||
*/
|
||||
export function buildAuthenticatedApolloServer(
|
||||
userId: string,
|
||||
role = Roles.Server.User,
|
||||
scopes = AllScopes
|
||||
) {
|
||||
return buildApolloServer({
|
||||
context: () =>
|
||||
addLoadersToCtx({
|
||||
auth: true,
|
||||
userId,
|
||||
role,
|
||||
token: 'asd',
|
||||
scopes
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an unauthenticated ApolloServer instance
|
||||
*/
|
||||
export function buildUnauthenticatedApolloServer() {
|
||||
return buildApolloServer({
|
||||
context: () =>
|
||||
addLoadersToCtx({
|
||||
auth: false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export async function getFreeServerPort() {
|
||||
return new Promise((res) => {
|
||||
const srv = net.createServer()
|
||||
|
||||
@@ -85,6 +85,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/cache-control-types@npm:^1.0.3":
|
||||
version: 1.0.3
|
||||
resolution: "@apollo/cache-control-types@npm:1.0.3"
|
||||
peerDependencies:
|
||||
graphql: 14.x || 15.x || 16.x
|
||||
checksum: 10/a588e52bfa51e37a1dcd667469c827cbd1145df131650478fa7c7e6f9b01eb71ce9147f94be60c5b3ee0d4f83fd3304da1a78a342ae254c12cfc18e6e3f1e615
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/client@npm:^3.6.6, @apollo/client@npm:^3.7.0, @apollo/client@npm:^3.7.14, @apollo/client@npm:^3.8.0, @apollo/client@npm:^3.9.6":
|
||||
version: 3.9.7
|
||||
resolution: "@apollo/client@npm:3.9.7"
|
||||
@@ -122,9 +131,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/protobufjs@npm:1.2.4":
|
||||
version: 1.2.4
|
||||
resolution: "@apollo/protobufjs@npm:1.2.4"
|
||||
"@apollo/protobufjs@npm:1.2.7":
|
||||
version: 1.2.7
|
||||
resolution: "@apollo/protobufjs@npm:1.2.7"
|
||||
dependencies:
|
||||
"@protobufjs/aspromise": "npm:^1.1.2"
|
||||
"@protobufjs/base64": "npm:^1.1.2"
|
||||
@@ -137,36 +146,11 @@ __metadata:
|
||||
"@protobufjs/pool": "npm:^1.1.0"
|
||||
"@protobufjs/utf8": "npm:^1.1.0"
|
||||
"@types/long": "npm:^4.0.0"
|
||||
"@types/node": "npm:^10.1.0"
|
||||
long: "npm:^4.0.0"
|
||||
bin:
|
||||
apollo-pbjs: bin/pbjs
|
||||
apollo-pbts: bin/pbts
|
||||
checksum: 10/9cd57a469f5dd4c7901060019cec2ff31e1c3e5bec9eb2f0eaa22af166a7aae605c7976204810818614fb1f7fba36dd0e3b0197b8187af7f427aacd4c30b00f5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/protobufjs@npm:1.2.6":
|
||||
version: 1.2.6
|
||||
resolution: "@apollo/protobufjs@npm:1.2.6"
|
||||
dependencies:
|
||||
"@protobufjs/aspromise": "npm:^1.1.2"
|
||||
"@protobufjs/base64": "npm:^1.1.2"
|
||||
"@protobufjs/codegen": "npm:^2.0.4"
|
||||
"@protobufjs/eventemitter": "npm:^1.1.0"
|
||||
"@protobufjs/fetch": "npm:^1.1.0"
|
||||
"@protobufjs/float": "npm:^1.0.2"
|
||||
"@protobufjs/inquire": "npm:^1.1.0"
|
||||
"@protobufjs/path": "npm:^1.1.2"
|
||||
"@protobufjs/pool": "npm:^1.1.0"
|
||||
"@protobufjs/utf8": "npm:^1.1.0"
|
||||
"@types/long": "npm:^4.0.0"
|
||||
"@types/node": "npm:^10.1.0"
|
||||
long: "npm:^4.0.0"
|
||||
bin:
|
||||
apollo-pbjs: bin/pbjs
|
||||
apollo-pbts: bin/pbts
|
||||
checksum: 10/a134200f943983edbb46cdf358a5e4364599870dc9be4dbce043dfa842903cb0ad4f16e1d99f06f49cf00fbfb6ad95dbac101c9187ce723c968eeb27e6c66822
|
||||
checksum: 10/9b2c2d5daa5221397bc9cf37f3fa8a45dc6f217783d0fe51eca12895f88f8a5d1b66efba2e288657a1c2da5b2e20fe0eb649a440ceeb30bfc5a3af75ccea832d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -185,101 +169,171 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.dropunuseddefinitions@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "@apollo/utils.dropunuseddefinitions@npm:1.1.0"
|
||||
peerDependencies:
|
||||
graphql: 14.x || 15.x || 16.x
|
||||
checksum: 10/b66e07086ea65bcb94d84cfd5e6d90d0406c4e7f602c9a5e793c2001273380a4f61c287f60ee1d81d47d49d3a62ef3f0afb8049243540d3021ff445869124094
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.keyvaluecache@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "@apollo/utils.keyvaluecache@npm:1.0.1"
|
||||
"@apollo/server-gateway-interface@npm:^1.1.1":
|
||||
version: 1.1.1
|
||||
resolution: "@apollo/server-gateway-interface@npm:1.1.1"
|
||||
dependencies:
|
||||
"@apollo/utils.logger": "npm:^1.0.0"
|
||||
"@apollo/usage-reporting-protobuf": "npm:^4.1.1"
|
||||
"@apollo/utils.fetcher": "npm:^2.0.0"
|
||||
"@apollo/utils.keyvaluecache": "npm:^2.1.0"
|
||||
"@apollo/utils.logger": "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
graphql: 14.x || 15.x || 16.x
|
||||
checksum: 10/af0e95399297aa403c32ffff08c6dfa91a70aae73d5954f36e357f045cdb7e89f3bb4c3e70816d244f8f18af21d257bc79e934dd8bbaa1214c5f6d42a6a825d0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/server@npm:^4.11.0":
|
||||
version: 4.11.0
|
||||
resolution: "@apollo/server@npm:4.11.0"
|
||||
dependencies:
|
||||
"@apollo/cache-control-types": "npm:^1.0.3"
|
||||
"@apollo/server-gateway-interface": "npm:^1.1.1"
|
||||
"@apollo/usage-reporting-protobuf": "npm:^4.1.1"
|
||||
"@apollo/utils.createhash": "npm:^2.0.0"
|
||||
"@apollo/utils.fetcher": "npm:^2.0.0"
|
||||
"@apollo/utils.isnodelike": "npm:^2.0.0"
|
||||
"@apollo/utils.keyvaluecache": "npm:^2.1.0"
|
||||
"@apollo/utils.logger": "npm:^2.0.0"
|
||||
"@apollo/utils.usagereporting": "npm:^2.1.0"
|
||||
"@apollo/utils.withrequired": "npm:^2.0.0"
|
||||
"@graphql-tools/schema": "npm:^9.0.0"
|
||||
"@types/express": "npm:^4.17.13"
|
||||
"@types/express-serve-static-core": "npm:^4.17.30"
|
||||
"@types/node-fetch": "npm:^2.6.1"
|
||||
async-retry: "npm:^1.2.1"
|
||||
cors: "npm:^2.8.5"
|
||||
express: "npm:^4.17.1"
|
||||
loglevel: "npm:^1.6.8"
|
||||
lru-cache: "npm:^7.10.1"
|
||||
checksum: 10/3a5ac26b3db86076cfa9154e535563993da5d541449a2403dfb5e2fca6fab03af3ad71ed375fe051b301b856d1bb2089f94e8aede4ff34d05828a38830c6c593
|
||||
negotiator: "npm:^0.6.3"
|
||||
node-abort-controller: "npm:^3.1.1"
|
||||
node-fetch: "npm:^2.6.7"
|
||||
uuid: "npm:^9.0.0"
|
||||
whatwg-mimetype: "npm:^3.0.0"
|
||||
peerDependencies:
|
||||
graphql: ^16.6.0
|
||||
checksum: 10/2f4d20dfcab2261d7c090d81bebccfd56ead1b9740e964fb2b7bd65058bff57b9bc175c4a3b2eb0c7d5fc8a7cc4ea2685ac6d0d2a147244964fa4c432db7c30f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.logger@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "@apollo/utils.logger@npm:1.0.0"
|
||||
checksum: 10/9be2b269d6d1cf2235c7b49a5edbb36c87589facf79516521df66d0c782709b7301a1365693b6e15d77f482d231bbb0fea4c2ae42faac7068cc4e014ce338c68
|
||||
"@apollo/usage-reporting-protobuf@npm:^4.1.0, @apollo/usage-reporting-protobuf@npm:^4.1.1":
|
||||
version: 4.1.1
|
||||
resolution: "@apollo/usage-reporting-protobuf@npm:4.1.1"
|
||||
dependencies:
|
||||
"@apollo/protobufjs": "npm:1.2.7"
|
||||
checksum: 10/07679e0058d0f67200bcbb05405697d4052dd6d921b8ed717878d75c60efe5af4dd1c387f9e72be17d050967b3c334ee3eab8954c4dc40aed0f1013eb30fb251
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.printwithreducedwhitespace@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "@apollo/utils.printwithreducedwhitespace@npm:1.1.0"
|
||||
"@apollo/utils.createhash@npm:^2.0.0":
|
||||
version: 2.0.1
|
||||
resolution: "@apollo/utils.createhash@npm:2.0.1"
|
||||
dependencies:
|
||||
"@apollo/utils.isnodelike": "npm:^2.0.1"
|
||||
sha.js: "npm:^2.4.11"
|
||||
checksum: 10/9e3ba58fd44f7900133a2219b0b66c0656a9c729f7a2ed1a459af8f4149925f0602d9766e57a0cc2acb8d24623f5c34ebad0faac0004cd59060fd6b1c91d5029
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.dropunuseddefinitions@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "@apollo/utils.dropunuseddefinitions@npm:2.0.1"
|
||||
peerDependencies:
|
||||
graphql: 14.x || 15.x || 16.x
|
||||
checksum: 10/86536751681c64f35a2d37b0c2f69a39d91ea0e4f0c3c993d9f76fa109f85e9d306e6994bd6e38eef1e4e5b83245125aaa125ecc94e185d90b3255f06a538503
|
||||
checksum: 10/c12166f2551fb44045a8210317b7776abc263136bd07bfe3c6eecdb050468590fc73e524efc437cad21cc4cfcd1efc3e110285025150c2073a4b303934898ac1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.removealiases@npm:1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "@apollo/utils.removealiases@npm:1.0.0"
|
||||
"@apollo/utils.fetcher@npm:^2.0.0":
|
||||
version: 2.0.1
|
||||
resolution: "@apollo/utils.fetcher@npm:2.0.1"
|
||||
checksum: 10/e173d215c3544dade7b4a08733234d5180973c79e8e738e9e2530f2067e8731a5faa7f15176f4ca91f3cc95a4c70166a686c7382a6c6100f56ad5befcd613f9f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.isnodelike@npm:^2.0.0, @apollo/utils.isnodelike@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "@apollo/utils.isnodelike@npm:2.0.1"
|
||||
checksum: 10/c2e858186a60cccb7e4fc53e8b97b2a4d5470cd4975ad9cccd29e57a23eff1aa3a0c03edceb13c423632224ce2c327c6f1bb8bd77dc3fb039316bba5750536ec
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.keyvaluecache@npm:^2.1.0":
|
||||
version: 2.1.1
|
||||
resolution: "@apollo/utils.keyvaluecache@npm:2.1.1"
|
||||
dependencies:
|
||||
"@apollo/utils.logger": "npm:^2.0.1"
|
||||
lru-cache: "npm:^7.14.1"
|
||||
checksum: 10/9a6bc7c4645415329a93e77861cb1a9874b2171b741a3a667c277c6339f2ba46fb40011982e7b0993b118af1cc02e59e58fcbe7033ca6216cefec01e7b8eeda6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.logger@npm:^2.0.0, @apollo/utils.logger@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "@apollo/utils.logger@npm:2.0.1"
|
||||
checksum: 10/f975c81fcc7e54669b975031349f292930dc4cc3dd6bdc58bc7fe2159e0398a7d18b28860ee324c23722b005848e258094a143d20f6989fde5837379240b0066
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.printwithreducedwhitespace@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "@apollo/utils.printwithreducedwhitespace@npm:2.0.1"
|
||||
peerDependencies:
|
||||
graphql: 14.x || 15.x || 16.x
|
||||
checksum: 10/fda30ad4ee1fbf012e4289b9963b8b75a102eadbdfa5e558dc923cfc68df42eff6e232dc20c34b7e7563e5aac7ae3781d17919cd8f5eccb90c4225a274b2af93
|
||||
checksum: 10/16cd191e66f3801b15deb581426cd1f55066bb824c32d63fe9de9c255bea2e2b6ee1ffc88873607830d2df0f3b4d9a14c707b709f205062e21a502f08f40d513
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.sortast@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "@apollo/utils.sortast@npm:1.1.0"
|
||||
"@apollo/utils.removealiases@npm:2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "@apollo/utils.removealiases@npm:2.0.1"
|
||||
peerDependencies:
|
||||
graphql: 14.x || 15.x || 16.x
|
||||
checksum: 10/2f3f925b239bce49fe9d80bb9fbb551992c8d9180af160e780faf1c88971a30ef16b842e82e1f27a0e1f8c649af0a442ef95f6838d4cde6148939ec73d9464f6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.sortast@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "@apollo/utils.sortast@npm:2.0.1"
|
||||
dependencies:
|
||||
lodash.sortby: "npm:^4.7.0"
|
||||
peerDependencies:
|
||||
graphql: 14.x || 15.x || 16.x
|
||||
checksum: 10/5ec695d8c91efd82ad75cb3e27662644c71e22be71793908135b38965be6fe1f229c24fd2f4fed1bc1829b84bec2a1f6470817a83c633d95292db7635a625471
|
||||
checksum: 10/b71245558ebd64bf93b98aec933d4b5f5758e0fecf7915728d94725ed4201fb2515e2af92fe01a595638147e5e0ef50a27ab5323d9b76eeb126769fb1e58f051
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.stripsensitiveliterals@npm:^1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "@apollo/utils.stripsensitiveliterals@npm:1.2.0"
|
||||
"@apollo/utils.stripsensitiveliterals@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "@apollo/utils.stripsensitiveliterals@npm:2.0.1"
|
||||
peerDependencies:
|
||||
graphql: 14.x || 15.x || 16.x
|
||||
checksum: 10/5910186a30be23fac59652d350e83a8a7a53adb9146ed545906f6893ad9c8d380752e679348ee210ae01fa39cc0487692b632e960003dcedc2282bd28de2aa01
|
||||
checksum: 10/a3f74af0626f89d61f7ed1d25194f6b77006a06653399eecaea0b246cf685a85465091f2dc70280b127871b5c1eda7ded799ce176271c2612946acdc9453d388
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollo/utils.usagereporting@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "@apollo/utils.usagereporting@npm:1.0.0"
|
||||
"@apollo/utils.usagereporting@npm:^2.1.0":
|
||||
version: 2.1.0
|
||||
resolution: "@apollo/utils.usagereporting@npm:2.1.0"
|
||||
dependencies:
|
||||
"@apollo/utils.dropunuseddefinitions": "npm:^1.1.0"
|
||||
"@apollo/utils.printwithreducedwhitespace": "npm:^1.1.0"
|
||||
"@apollo/utils.removealiases": "npm:1.0.0"
|
||||
"@apollo/utils.sortast": "npm:^1.1.0"
|
||||
"@apollo/utils.stripsensitiveliterals": "npm:^1.2.0"
|
||||
apollo-reporting-protobuf: "npm:^3.3.1"
|
||||
"@apollo/usage-reporting-protobuf": "npm:^4.1.0"
|
||||
"@apollo/utils.dropunuseddefinitions": "npm:^2.0.1"
|
||||
"@apollo/utils.printwithreducedwhitespace": "npm:^2.0.1"
|
||||
"@apollo/utils.removealiases": "npm:2.0.1"
|
||||
"@apollo/utils.sortast": "npm:^2.0.1"
|
||||
"@apollo/utils.stripsensitiveliterals": "npm:^2.0.1"
|
||||
peerDependencies:
|
||||
graphql: 14.x || 15.x || 16.x
|
||||
checksum: 10/e243fa4495e77bfbe5cfcf5bff1f3f7a26493eac1db9b98104263906c24f93dd64ed67fa4308f6868fef960d08d718c07508c15c6668ee8e78fa05565b438158
|
||||
checksum: 10/8af4b23000a4c35ba568e6a532e4120ab0e55b291c7b902f2d10a51aad877d0438b80c019296436870ee265edcc8881521fb9a0829796f23a3b2cb73449ac890
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollographql/apollo-tools@npm:^0.5.3":
|
||||
version: 0.5.4
|
||||
resolution: "@apollographql/apollo-tools@npm:0.5.4"
|
||||
peerDependencies:
|
||||
graphql: ^14.2.1 || ^15.0.0 || ^16.0.0
|
||||
checksum: 10/4f69566d23ffb77ffedd87c679dcab608400f297e4cd5423151977b917737c427015485a8e0436feeb5154574171742ab626fb1a8f5ae2739070757976fd49f2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@apollographql/graphql-playground-html@npm:1.6.29":
|
||||
version: 1.6.29
|
||||
resolution: "@apollographql/graphql-playground-html@npm:1.6.29"
|
||||
dependencies:
|
||||
xss: "npm:^1.0.8"
|
||||
checksum: 10/5e45cdc122dbc18c71f89fd9be8c19d1e35417ea27d3915206438d351f7775894957cd5b8bb378921bb96a8f6e6a9d182ce3d674abaddefd36a3a7e9cf6f1e68
|
||||
"@apollo/utils.withrequired@npm:^2.0.0":
|
||||
version: 2.0.1
|
||||
resolution: "@apollo/utils.withrequired@npm:2.0.1"
|
||||
checksum: 10/ddd3a72d0f13e6283128d1aae787b65f8ef0bf2f2cf351e143c479f0838679e72d82f42f653b6baadd33a092854fc9cb9dd8af4a45938ee25b718274cef408ee
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -10500,27 +10554,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/merge@npm:8.3.1":
|
||||
version: 8.3.1
|
||||
resolution: "@graphql-tools/merge@npm:8.3.1"
|
||||
"@graphql-tools/merge@npm:^8.4.1":
|
||||
version: 8.4.2
|
||||
resolution: "@graphql-tools/merge@npm:8.4.2"
|
||||
dependencies:
|
||||
"@graphql-tools/utils": "npm:8.9.0"
|
||||
"@graphql-tools/utils": "npm:^9.2.1"
|
||||
tslib: "npm:^2.4.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/9354a68aa1b851ee72d2d727a3a264279f1e5ed95100f6c6e7e0a2ad7449943d2ebe6fce43b4873a15e5c3e9df52ea9d23ff51ffc1f73c417c4ccf368f8486ab
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/merge@npm:8.3.6":
|
||||
version: 8.3.6
|
||||
resolution: "@graphql-tools/merge@npm:8.3.6"
|
||||
dependencies:
|
||||
"@graphql-tools/utils": "npm:8.12.0"
|
||||
tslib: "npm:^2.4.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/511136c82cd40bcaa4570068859db7537b67fed0dd91918eb6447c10fed633beb790f39d846b3a3b982556a8f5f2aba860c920f2477023db92a1faac91ad36ac
|
||||
checksum: 10/62a4e93812e11d083c17f7763f4333a29dbe99fddbff705ff5942a0bdbb9dcd14f668bd76bd3edda485534d5d1a7f09bac311b979196b6149df11d8968a83723
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -10536,17 +10578,29 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/mock@npm:^8.1.2":
|
||||
version: 8.7.6
|
||||
resolution: "@graphql-tools/mock@npm:8.7.6"
|
||||
"@graphql-tools/merge@npm:^9.0.6":
|
||||
version: 9.0.7
|
||||
resolution: "@graphql-tools/merge@npm:9.0.7"
|
||||
dependencies:
|
||||
"@graphql-tools/schema": "npm:9.0.4"
|
||||
"@graphql-tools/utils": "npm:8.12.0"
|
||||
"@graphql-tools/utils": "npm:^10.5.4"
|
||||
tslib: "npm:^2.4.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/afe9b11f2d1e43dd3fce8e510aa20846137acfb6cb6d9362e5cfe954f2daaa5c169b77c3013a21f3263c690dee2f3b3e235e305e49c3cc398bdb166ddf2d082b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/mock@npm:^9.0.4":
|
||||
version: 9.0.4
|
||||
resolution: "@graphql-tools/mock@npm:9.0.4"
|
||||
dependencies:
|
||||
"@graphql-tools/schema": "npm:^10.0.4"
|
||||
"@graphql-tools/utils": "npm:^10.2.1"
|
||||
fast-json-stable-stringify: "npm:^2.1.0"
|
||||
tslib: "npm:^2.4.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/8acad4f9491993b7fd517f8491529eac0df24df257e42351d6fdaa9a6cf41936ec7015b1fc8c9219c6629fa60e9aca346578d98d75bf41005ce18063464bdfb3
|
||||
checksum: 10/fca1716a70177da0361d68330676e5af37671b5dc16868202fe19f40cc4fc0df043d926923e7ad771ec2914ff360c83ef5624fc149637f3fbd10e82f2a7175f5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -10600,20 +10654,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/schema@npm:9.0.4":
|
||||
version: 9.0.4
|
||||
resolution: "@graphql-tools/schema@npm:9.0.4"
|
||||
dependencies:
|
||||
"@graphql-tools/merge": "npm:8.3.6"
|
||||
"@graphql-tools/utils": "npm:8.12.0"
|
||||
tslib: "npm:^2.4.0"
|
||||
value-or-promise: "npm:1.0.11"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/8478d77b9d585e7f411563494a6eff4fd4fad5d507284b2384f57e3cf5b98f5ac875034b633afc902fe4accbcf5da1a629f460a4c27ca41bd3ce7dc16eb96bfe
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/schema@npm:^10.0.0, @graphql-tools/schema@npm:^10.0.3, @graphql-tools/schema@npm:^10.0.4":
|
||||
version: 10.0.4
|
||||
resolution: "@graphql-tools/schema@npm:10.0.4"
|
||||
@@ -10628,17 +10668,31 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/schema@npm:^8.0.0":
|
||||
version: 8.5.1
|
||||
resolution: "@graphql-tools/schema@npm:8.5.1"
|
||||
"@graphql-tools/schema@npm:^10.0.6":
|
||||
version: 10.0.6
|
||||
resolution: "@graphql-tools/schema@npm:10.0.6"
|
||||
dependencies:
|
||||
"@graphql-tools/merge": "npm:8.3.1"
|
||||
"@graphql-tools/utils": "npm:8.9.0"
|
||||
"@graphql-tools/merge": "npm:^9.0.6"
|
||||
"@graphql-tools/utils": "npm:^10.5.4"
|
||||
tslib: "npm:^2.4.0"
|
||||
value-or-promise: "npm:1.0.11"
|
||||
value-or-promise: "npm:^1.0.12"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/98f57502cc67ee48157bcf6f26c334e27b0673ec6f5a35c1a5bc1901772063c8bfdca435f81664ab1a41f9274b43dc78aa12791feee83546640d0a034b38c836
|
||||
checksum: 10/f667ed6bf8c8419cee8929c19b1b31c55894526a25f36463d106baf31b19cee8b297281eef07de7e3d94173d03a8ade4570a6e338b1482a27f8eae09d9ade4a8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/schema@npm:^9.0.0":
|
||||
version: 9.0.19
|
||||
resolution: "@graphql-tools/schema@npm:9.0.19"
|
||||
dependencies:
|
||||
"@graphql-tools/merge": "npm:^8.4.1"
|
||||
"@graphql-tools/utils": "npm:^9.2.1"
|
||||
tslib: "npm:^2.4.0"
|
||||
value-or-promise: "npm:^1.0.12"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/762811fe08ec67000b190305783677ea086e6b300a1882f46b804bdf790e32de986bef7bbd574ddd4114393ca9b97422cc604390652537d4595eba7dde825259
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -10665,28 +10719,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/utils@npm:8.12.0":
|
||||
version: 8.12.0
|
||||
resolution: "@graphql-tools/utils@npm:8.12.0"
|
||||
dependencies:
|
||||
tslib: "npm:^2.4.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/9a3f377a7b8c069af4160ba76338a9ebfbe15c2c7290b3eb4bb11787a741abcda239e30af4e13be8cf899da38a64a5444ba993fa1dd2717165233dd66f4846d1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/utils@npm:8.9.0":
|
||||
version: 8.9.0
|
||||
resolution: "@graphql-tools/utils@npm:8.9.0"
|
||||
dependencies:
|
||||
tslib: "npm:^2.4.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/de5930b33664c53f0d22781bb16b4e029afaad165539faf80bd520adfad969c024891db672a2ff96195d8d1185bac66b284ebde67938e554d04c0798453da002
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/utils@npm:^10.0.0":
|
||||
version: 10.0.11
|
||||
resolution: "@graphql-tools/utils@npm:10.0.11"
|
||||
@@ -10715,6 +10747,32 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/utils@npm:^10.5.4":
|
||||
version: 10.5.4
|
||||
resolution: "@graphql-tools/utils@npm:10.5.4"
|
||||
dependencies:
|
||||
"@graphql-typed-document-node/core": "npm:^3.1.1"
|
||||
cross-inspect: "npm:1.0.1"
|
||||
dset: "npm:^3.1.2"
|
||||
tslib: "npm:^2.4.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/e6750800be215cbd8b4cc67019ba91b881c6093a4ac71258eeef9f1f3101b1e81e862435fd5b05cb40d94d40e396d0a3629ad6613226d7a4f75b8c5329a03aa7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/utils@npm:^9.2.1":
|
||||
version: 9.2.1
|
||||
resolution: "@graphql-tools/utils@npm:9.2.1"
|
||||
dependencies:
|
||||
"@graphql-typed-document-node/core": "npm:^3.1.1"
|
||||
tslib: "npm:^2.4.0"
|
||||
peerDependencies:
|
||||
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
|
||||
checksum: 10/b1665043c2180a74d1e071f9f495ce16b2f46eeed1b319a290ae58f699629fe0a47b619c4f9be89135ff20b1c34fe6cc27e86570cf1e2cff07d3ae204f3d170d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@graphql-tools/wrap@npm:^10.0.2":
|
||||
version: 10.0.5
|
||||
resolution: "@graphql-tools/wrap@npm:10.0.5"
|
||||
@@ -11171,13 +11229,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@josephg/resolvable@npm:^1.0.0":
|
||||
version: 1.0.1
|
||||
resolution: "@josephg/resolvable@npm:1.0.1"
|
||||
checksum: 10/64eb763b5138bdae4fb59c0c0e89ed261b690917ae6bd777b533257668f151b8868698fb73dfd7665746ad07c7c917fe89ccfdf2404048d39f373f57f1a14e34
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@jridgewell/gen-mapping@npm:^0.1.0":
|
||||
version: 0.1.1
|
||||
resolution: "@jridgewell/gen-mapping@npm:0.1.1"
|
||||
@@ -15350,6 +15401,7 @@ __metadata:
|
||||
dependencies:
|
||||
"@apollo/client": "npm:^3.7.0"
|
||||
"@apollo/rover": "npm:^0.23.0"
|
||||
"@apollo/server": "npm:^4.11.0"
|
||||
"@aws-sdk/client-s3": "npm:^3.276.0"
|
||||
"@aws-sdk/lib-storage": "npm:^3.100.0"
|
||||
"@bull-board/express": "npm:^4.2.2"
|
||||
@@ -15360,7 +15412,8 @@ __metadata:
|
||||
"@graphql-codegen/typescript": "npm:^4.0.7"
|
||||
"@graphql-codegen/typescript-operations": "npm:^4.2.1"
|
||||
"@graphql-codegen/typescript-resolvers": "npm:^4.1.0"
|
||||
"@graphql-tools/schema": "npm:^10.0.4"
|
||||
"@graphql-tools/mock": "npm:^9.0.4"
|
||||
"@graphql-tools/schema": "npm:^10.0.6"
|
||||
"@mailchimp/mailchimp_marketing": "npm:^3.0.80"
|
||||
"@parcel/watcher": "npm:^2.4.1"
|
||||
"@speckle/objectloader": "workspace:^"
|
||||
@@ -15374,6 +15427,7 @@ __metadata:
|
||||
"@types/compression": "npm:^1.7.2"
|
||||
"@types/connect-redis": "npm:^0.0.23"
|
||||
"@types/cookie-parser": "npm:^1.4.7"
|
||||
"@types/cors": "npm:^2.8.17"
|
||||
"@types/debug": "npm:^4.1.7"
|
||||
"@types/deep-equal-in-any-order": "npm:^1.0.1"
|
||||
"@types/ejs": "npm:^3.1.1"
|
||||
@@ -15405,8 +15459,6 @@ __metadata:
|
||||
"@typescript-eslint/eslint-plugin": "npm:^5.39.0"
|
||||
"@typescript-eslint/parser": "npm:^5.39.0"
|
||||
ajv: "npm:^8.12.0"
|
||||
apollo-server-express: "npm:^3.10.2"
|
||||
apollo-server-plugin-base: "npm:^3.7.2"
|
||||
axios: "npm:^1.7.4"
|
||||
bcrypt: "npm:^5.0.0"
|
||||
bull: "npm:^4.8.5"
|
||||
@@ -15435,10 +15487,11 @@ __metadata:
|
||||
express-async-errors: "npm:^3.1.1"
|
||||
express-prom-bundle: "npm:^6.6.0"
|
||||
express-session: "npm:^1.17.1"
|
||||
graphql: "npm:^15"
|
||||
graphql: "npm:^16.6.0"
|
||||
graphql-redis-subscriptions: "npm:^2.2.2"
|
||||
graphql-scalars: "npm:^1.18.0"
|
||||
graphql-subscriptions: "npm:^2.0.0"
|
||||
graphql-tag: "npm:^2.12.6"
|
||||
http-proxy-middleware: "npm:v3.0.0-beta.0"
|
||||
ioredis: "npm:^5.2.2"
|
||||
ioredis-mock: "npm:^8.9.0"
|
||||
@@ -17719,15 +17772,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/accepts@npm:^1.3.5":
|
||||
version: 1.3.5
|
||||
resolution: "@types/accepts@npm:1.3.5"
|
||||
dependencies:
|
||||
"@types/node": "npm:*"
|
||||
checksum: 10/3984edd631d9e308ef10286454a05e2388812a740d404abf93522a3bc3d10032ae6a60816e8cc4ae1bc96367db39e543d3ef862944cea53d1eea48be1f624fc2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/apollo-upload-client@npm:^17.0.1":
|
||||
version: 17.0.1
|
||||
resolution: "@types/apollo-upload-client@npm:17.0.1"
|
||||
@@ -17834,7 +17878,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/body-parser@npm:*, @types/body-parser@npm:1.19.2":
|
||||
"@types/body-parser@npm:*":
|
||||
version: 1.19.2
|
||||
resolution: "@types/body-parser@npm:1.19.2"
|
||||
dependencies:
|
||||
@@ -17971,10 +18015,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/cors@npm:2.8.12":
|
||||
version: 2.8.12
|
||||
resolution: "@types/cors@npm:2.8.12"
|
||||
checksum: 10/8c45f112c7d1d2d831b4b266f2e6ed33a1887a35dcbfe2a18b28370751fababb7cd045e745ef84a523c33a25932678097bf79afaa367c6cb3fa0daa7a6438257
|
||||
"@types/cors@npm:^2.8.17":
|
||||
version: 2.8.17
|
||||
resolution: "@types/cors@npm:2.8.17"
|
||||
dependencies:
|
||||
"@types/node": "npm:*"
|
||||
checksum: 10/469bd85e29a35977099a3745c78e489916011169a664e97c4c3d6538143b0a16e4cc72b05b407dc008df3892ed7bf595f9b7c0f1f4680e169565ee9d64966bde
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -18141,14 +18187,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/express-serve-static-core@npm:4.17.30":
|
||||
version: 4.17.30
|
||||
resolution: "@types/express-serve-static-core@npm:4.17.30"
|
||||
"@types/express-serve-static-core@npm:^4.17.30":
|
||||
version: 4.19.5
|
||||
resolution: "@types/express-serve-static-core@npm:4.19.5"
|
||||
dependencies:
|
||||
"@types/node": "npm:*"
|
||||
"@types/qs": "npm:*"
|
||||
"@types/range-parser": "npm:*"
|
||||
checksum: 10/1074c5769ae052fcb7ea0a2d4a807090a832ec6f8e1ca9105cd949f6dbc99a745a0d3e5b8c8fb64e7105b4a23d8283aa50fd3234d3b7f821899efbed3675b179
|
||||
"@types/send": "npm:*"
|
||||
checksum: 10/49350c6315eeb7d640e13e6138ba6005121b3b610b1e25746fccd5b86b559be810a4ba384b9bd7eee288975b5bd8cf67c1772c646254b812beaa488774eb5513
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -18161,7 +18208,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/express@npm:*, @types/express@npm:4.17.13, @types/express@npm:^4.17.13":
|
||||
"@types/express@npm:*, @types/express@npm:^4.17.13":
|
||||
version: 4.17.13
|
||||
resolution: "@types/express@npm:4.17.13"
|
||||
dependencies:
|
||||
@@ -18583,6 +18630,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node-fetch@npm:^2.6.1":
|
||||
version: 2.6.11
|
||||
resolution: "@types/node-fetch@npm:2.6.11"
|
||||
dependencies:
|
||||
"@types/node": "npm:*"
|
||||
form-data: "npm:^4.0.0"
|
||||
checksum: 10/c416df8f182ec3826278ea42557fda08f169a48a05e60722d9c8edd4e5b2076ae281c6b6601ad406035b7201f885b0257983b61c26b3f9eb0f41192a807b5de5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node-forge@npm:^1.3.0":
|
||||
version: 1.3.11
|
||||
resolution: "@types/node-forge@npm:1.3.11"
|
||||
@@ -18608,13 +18665,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:^10.1.0":
|
||||
version: 10.17.60
|
||||
resolution: "@types/node@npm:10.17.60"
|
||||
checksum: 10/f9161493b3284b1d41d5d594c2768625acdd9e33f992f71ccde47861916e662e2ae438d2cc5f1b285053391a31b52a7564ecedc22d485610d236bfad9c7e6a1c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:^13.7.0":
|
||||
version: 13.13.52
|
||||
resolution: "@types/node@npm:13.13.52"
|
||||
@@ -19016,6 +19066,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/send@npm:*":
|
||||
version: 0.17.4
|
||||
resolution: "@types/send@npm:0.17.4"
|
||||
dependencies:
|
||||
"@types/mime": "npm:^1"
|
||||
"@types/node": "npm:*"
|
||||
checksum: 10/28320a2aa1eb704f7d96a65272a07c0bf3ae7ed5509c2c96ea5e33238980f71deeed51d3631927a77d5250e4091b3e66bce53b42d770873282c6a20bb8b0280d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/serve-index@npm:^1.9.1":
|
||||
version: 1.9.1
|
||||
resolution: "@types/serve-index@npm:1.9.1"
|
||||
@@ -22638,146 +22698,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"apollo-datasource@npm:^3.3.2":
|
||||
version: 3.3.2
|
||||
resolution: "apollo-datasource@npm:3.3.2"
|
||||
dependencies:
|
||||
"@apollo/utils.keyvaluecache": "npm:^1.0.1"
|
||||
apollo-server-env: "npm:^4.2.1"
|
||||
checksum: 10/70244e792655b357213b92e9dd0e8ca553724857847c9bedb53a1dbf7a92fc0d8b05a60d77203d6c30331599b44c5d7cc5f4d94c934465fa05b146b681ed2293
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"apollo-reporting-protobuf@npm:^3.3.1, apollo-reporting-protobuf@npm:^3.3.2":
|
||||
version: 3.3.2
|
||||
resolution: "apollo-reporting-protobuf@npm:3.3.2"
|
||||
dependencies:
|
||||
"@apollo/protobufjs": "npm:1.2.4"
|
||||
checksum: 10/92b527b062a7ca65c6a19a01899a5d45e9271301fb5c5841e3e90e420d125cce5bf0e1575bc4bb1064720793a1ff270acb0387cf82d5decb3d6a08ecc767eb65
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"apollo-reporting-protobuf@npm:^3.4.0":
|
||||
version: 3.4.0
|
||||
resolution: "apollo-reporting-protobuf@npm:3.4.0"
|
||||
dependencies:
|
||||
"@apollo/protobufjs": "npm:1.2.6"
|
||||
checksum: 10/d6c731c1e07f952770166c71222a34ea97dd90f4b1d74f3261caa1542e1fb81a591c74586cd973c28c12e8bb9aa54ff0de411698f2311978f7144f98258c1a0b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"apollo-server-core@npm:^3.10.2":
|
||||
version: 3.12.1
|
||||
resolution: "apollo-server-core@npm:3.12.1"
|
||||
dependencies:
|
||||
"@apollo/utils.keyvaluecache": "npm:^1.0.1"
|
||||
"@apollo/utils.logger": "npm:^1.0.0"
|
||||
"@apollo/utils.usagereporting": "npm:^1.0.0"
|
||||
"@apollographql/apollo-tools": "npm:^0.5.3"
|
||||
"@apollographql/graphql-playground-html": "npm:1.6.29"
|
||||
"@graphql-tools/mock": "npm:^8.1.2"
|
||||
"@graphql-tools/schema": "npm:^8.0.0"
|
||||
"@josephg/resolvable": "npm:^1.0.0"
|
||||
apollo-datasource: "npm:^3.3.2"
|
||||
apollo-reporting-protobuf: "npm:^3.4.0"
|
||||
apollo-server-env: "npm:^4.2.1"
|
||||
apollo-server-errors: "npm:^3.3.1"
|
||||
apollo-server-plugin-base: "npm:^3.7.2"
|
||||
apollo-server-types: "npm:^3.8.0"
|
||||
async-retry: "npm:^1.2.1"
|
||||
fast-json-stable-stringify: "npm:^2.1.0"
|
||||
graphql-tag: "npm:^2.11.0"
|
||||
loglevel: "npm:^1.6.8"
|
||||
lru-cache: "npm:^6.0.0"
|
||||
node-abort-controller: "npm:^3.0.1"
|
||||
sha.js: "npm:^2.4.11"
|
||||
uuid: "npm:^9.0.0"
|
||||
whatwg-mimetype: "npm:^3.0.0"
|
||||
peerDependencies:
|
||||
graphql: ^15.3.0 || ^16.0.0
|
||||
checksum: 10/2e273d60a91ef7faf85687445bcb5f1affcfcd85a363968d570c82a57ce533076780be14e8d55c4d3ed7168fa19167960830bce5525436cc78a5e5e71752c473
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"apollo-server-env@npm:^4.2.1":
|
||||
version: 4.2.1
|
||||
resolution: "apollo-server-env@npm:4.2.1"
|
||||
dependencies:
|
||||
node-fetch: "npm:^2.6.7"
|
||||
checksum: 10/9172288c89c2ebb2a02d58542f807896de1ca0ba80c430f09242f2fa9ece40d7ecb8f9527357ba5e1d9997c64c364e7a9716e4f5485c5fb4938f69627bf1cea4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"apollo-server-errors@npm:^3.3.1":
|
||||
version: 3.3.1
|
||||
resolution: "apollo-server-errors@npm:3.3.1"
|
||||
peerDependencies:
|
||||
graphql: ^15.3.0 || ^16.0.0
|
||||
checksum: 10/5090af0280e40ce9b3b042fca6bd195d84c8507d8fe0b16b7fd52501b8f88cb2b5cca99882a9c5253f04c78b94ff2d350eb148867e20b0ddd6211071bb17f553
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"apollo-server-express@npm:^3.10.2":
|
||||
version: 3.10.2
|
||||
resolution: "apollo-server-express@npm:3.10.2"
|
||||
dependencies:
|
||||
"@types/accepts": "npm:^1.3.5"
|
||||
"@types/body-parser": "npm:1.19.2"
|
||||
"@types/cors": "npm:2.8.12"
|
||||
"@types/express": "npm:4.17.13"
|
||||
"@types/express-serve-static-core": "npm:4.17.30"
|
||||
accepts: "npm:^1.3.5"
|
||||
apollo-server-core: "npm:^3.10.2"
|
||||
apollo-server-types: "npm:^3.6.2"
|
||||
body-parser: "npm:^1.19.0"
|
||||
cors: "npm:^2.8.5"
|
||||
parseurl: "npm:^1.3.3"
|
||||
peerDependencies:
|
||||
express: ^4.17.1
|
||||
graphql: ^15.3.0 || ^16.0.0
|
||||
checksum: 10/a26a8fd794824c49ca4c866347fea3f3553a59e58a14dc1ed2af737173eeda7a62ce69b99aaaaf2d7e3ba20eeb222583c1e45db88f6539e80978d2a3e1e337b9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"apollo-server-plugin-base@npm:^3.7.2":
|
||||
version: 3.7.2
|
||||
resolution: "apollo-server-plugin-base@npm:3.7.2"
|
||||
dependencies:
|
||||
apollo-server-types: "npm:^3.8.0"
|
||||
peerDependencies:
|
||||
graphql: ^15.3.0 || ^16.0.0
|
||||
checksum: 10/b2599f51e66dce930208c1c6f6b4394e3bde6c635e971a80d677b33e7d3d6c2050453ede99bde66281e4d6d6675094b6fb50a5ec30d16e04bee13d7570ad2715
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"apollo-server-types@npm:^3.6.2":
|
||||
version: 3.6.2
|
||||
resolution: "apollo-server-types@npm:3.6.2"
|
||||
dependencies:
|
||||
"@apollo/utils.keyvaluecache": "npm:^1.0.1"
|
||||
"@apollo/utils.logger": "npm:^1.0.0"
|
||||
apollo-reporting-protobuf: "npm:^3.3.2"
|
||||
apollo-server-env: "npm:^4.2.1"
|
||||
peerDependencies:
|
||||
graphql: ^15.3.0 || ^16.0.0
|
||||
checksum: 10/c513b2890ee453beb859041540a6b35cb6db6c8a7060f30a572b7531d6b998b8fe99519966a9052b4fd7c962d6bd1a62ab61036b933db8eaa1981a54f92e2785
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"apollo-server-types@npm:^3.8.0":
|
||||
version: 3.8.0
|
||||
resolution: "apollo-server-types@npm:3.8.0"
|
||||
dependencies:
|
||||
"@apollo/utils.keyvaluecache": "npm:^1.0.1"
|
||||
"@apollo/utils.logger": "npm:^1.0.0"
|
||||
apollo-reporting-protobuf: "npm:^3.4.0"
|
||||
apollo-server-env: "npm:^4.2.1"
|
||||
peerDependencies:
|
||||
graphql: ^15.3.0 || ^16.0.0
|
||||
checksum: 10/c802fecba27ff5f0b45fc4a3d6c88e18c39c6e5ba5785db067588d4e0c7d56aba6f4dc69171b07ac6348e9e313b036c57c178af58b8b3414331517e0b280324e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"apollo-upload-client@npm:^17.0.0":
|
||||
version: 17.0.0
|
||||
resolution: "apollo-upload-client@npm:17.0.0"
|
||||
@@ -23978,26 +23898,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"body-parser@npm:^1.19.0":
|
||||
version: 1.20.0
|
||||
resolution: "body-parser@npm:1.20.0"
|
||||
dependencies:
|
||||
bytes: "npm:3.1.2"
|
||||
content-type: "npm:~1.0.4"
|
||||
debug: "npm:2.6.9"
|
||||
depd: "npm:2.0.0"
|
||||
destroy: "npm:1.2.0"
|
||||
http-errors: "npm:2.0.0"
|
||||
iconv-lite: "npm:0.4.24"
|
||||
on-finished: "npm:2.4.1"
|
||||
qs: "npm:6.10.3"
|
||||
raw-body: "npm:2.5.1"
|
||||
type-is: "npm:~1.6.18"
|
||||
unpipe: "npm:1.0.0"
|
||||
checksum: 10/63fe82c27fdacac51d26665c3d13d4c6e48d1c3e9efe1fbc0fd18801aa9a598ab1023b09298ae4b3d0a7598d55902d793f7fa1b5551da99c16eabfed9b022a51
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"bonjour-service@npm:^1.0.11":
|
||||
version: 1.0.12
|
||||
resolution: "bonjour-service@npm:1.0.12"
|
||||
@@ -25618,7 +25518,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"commander@npm:^2.19.0, commander@npm:^2.20.0, commander@npm:^2.20.3":
|
||||
"commander@npm:^2.19.0, commander@npm:^2.20.0":
|
||||
version: 2.20.3
|
||||
resolution: "commander@npm:2.20.3"
|
||||
checksum: 10/90c5b6898610cd075984c58c4f88418a4fb44af08c1b1415e9854c03171bec31b336b7f3e4cefe33de994b3f12b03c5e2d638da4316df83593b9e82554e7e95b
|
||||
@@ -26442,6 +26342,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cross-inspect@npm:1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "cross-inspect@npm:1.0.1"
|
||||
dependencies:
|
||||
tslib: "npm:^2.4.0"
|
||||
checksum: 10/7c1e02e0a9670b62416a3ea1df7ae880fdad3aa0a857de8932c4e5f8acd71298c7e3db9da8e9da603f5692cd1879938f5e72e34a9f5d1345987bef656d117fc1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cross-spawn@npm:7.0.3, cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.1, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3":
|
||||
version: 7.0.3
|
||||
resolution: "cross-spawn@npm:7.0.3"
|
||||
@@ -26646,13 +26555,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cssfilter@npm:0.0.10":
|
||||
version: 0.0.10
|
||||
resolution: "cssfilter@npm:0.0.10"
|
||||
checksum: 10/1e45182f42de848f092f50a313113c28a88e4ac98333bf1603ee1c3b200384a3bc83c12e35cd61135e3b0f218295f600d51120ca1f926b7958b2d3262d711214
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cssnano-preset-default@npm:^6.0.1":
|
||||
version: 6.0.1
|
||||
resolution: "cssnano-preset-default@npm:6.0.1"
|
||||
@@ -29923,7 +29825,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"express@npm:>=4.19.2, express@npm:^4.17.3, express@npm:^4.19.2":
|
||||
"express@npm:>=4.19.2, express@npm:^4.17.1, express@npm:^4.17.3, express@npm:^4.19.2":
|
||||
version: 4.19.2
|
||||
resolution: "express@npm:4.19.2"
|
||||
dependencies:
|
||||
@@ -31988,10 +31890,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"graphql@npm:^15.3.0":
|
||||
version: 15.8.0
|
||||
resolution: "graphql@npm:15.8.0"
|
||||
checksum: 10/f8d830287a9028d6779b59c437e0ade63a713b47521b02b60316df1761b805b1a7ce03be88053d224b7f78f5d1d1a786d287ab229cd158b42ebeea9e86daaba5
|
||||
"graphql@npm:14 - 16, graphql@npm:^16.6.0":
|
||||
version: 16.9.0
|
||||
resolution: "graphql@npm:16.9.0"
|
||||
checksum: 10/5833f82bb6c31bec120bbf9cd400eda873e1bb7ef5c17974fa262cd82dc68728fda5d4cb859dc8aaa4c4fe4f6fe1103a9c47efc01a12c02ae5cb581d8e4029e2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"graphql@npm:^15.0.0":
|
||||
version: 15.9.0
|
||||
resolution: "graphql@npm:15.9.0"
|
||||
checksum: 10/ce1f50672bcb369395d07a47048bcbb429ed1ce06dbcafb7a0999df791cb7aa7206be21497907973dbc8a01df3cd7f632f43c583f248538f186f5adfa1a0d1c5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -39064,10 +38973,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"node-abort-controller@npm:^3.0.1":
|
||||
version: 3.0.1
|
||||
resolution: "node-abort-controller@npm:3.0.1"
|
||||
checksum: 10/7437b015830a2f714692fd372c01ce5c8c66f332a205455f58ddc8b3228314e588a20abd34a2b037c9cc438ced74e75492c7fc04f4dc0cf7bf0c0ac4160175e3
|
||||
"node-abort-controller@npm:^3.1.1":
|
||||
version: 3.1.1
|
||||
resolution: "node-abort-controller@npm:3.1.1"
|
||||
checksum: 10/0a2cdb7ec0aeaf3cb31e1ca0e192f5add48f1c5c9c9ed822129f9dddbd9432f69b7425982f94ce803c56a2104884530aa67cd57696e5774b2e5b8ec2f58de042
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -43622,15 +43531,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"qs@npm:6.10.3, qs@npm:^6.4.0, qs@npm:^6.5.1":
|
||||
version: 6.10.3
|
||||
resolution: "qs@npm:6.10.3"
|
||||
dependencies:
|
||||
side-channel: "npm:^1.0.4"
|
||||
checksum: 10/73d07bfd77f07bec3750dca5e6d165cba0c87ce3e4688bb26e5e462e725ab1289ecdb69164b0b4a4d1b913e2a3ae6b22acbb8b2feb5c8f31bd76f2380f3dc23d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"qs@npm:6.11.0, qs@npm:^6.10.0":
|
||||
version: 6.11.0
|
||||
resolution: "qs@npm:6.11.0"
|
||||
@@ -43640,6 +43540,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"qs@npm:^6.4.0, qs@npm:^6.5.1":
|
||||
version: 6.10.3
|
||||
resolution: "qs@npm:6.10.3"
|
||||
dependencies:
|
||||
side-channel: "npm:^1.0.4"
|
||||
checksum: 10/73d07bfd77f07bec3750dca5e6d165cba0c87ce3e4688bb26e5e462e725ab1289ecdb69164b0b4a4d1b913e2a3ae6b22acbb8b2feb5c8f31bd76f2380f3dc23d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"qs@npm:~6.5.2":
|
||||
version: 6.5.3
|
||||
resolution: "qs@npm:6.5.3"
|
||||
@@ -43757,18 +43666,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"raw-body@npm:2.5.1":
|
||||
version: 2.5.1
|
||||
resolution: "raw-body@npm:2.5.1"
|
||||
dependencies:
|
||||
bytes: "npm:3.1.2"
|
||||
http-errors: "npm:2.0.0"
|
||||
iconv-lite: "npm:0.4.24"
|
||||
unpipe: "npm:1.0.0"
|
||||
checksum: 10/280bedc12db3490ecd06f740bdcf66093a07535374b51331242382c0e130bb273ebb611b7bc4cba1b4b4e016cc7b1f4b05a6df885a6af39c2bc3b94c02291c84
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"raw-body@npm:2.5.2":
|
||||
version: 2.5.2
|
||||
resolution: "raw-body@npm:2.5.2"
|
||||
@@ -50102,7 +49999,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"value-or-promise@npm:1.0.11, value-or-promise@npm:^1.0.11":
|
||||
"value-or-promise@npm:^1.0.11":
|
||||
version: 1.0.11
|
||||
resolution: "value-or-promise@npm:1.0.11"
|
||||
checksum: 10/9bd1cf82be5b59ec4a7ee9fa17ca7b3f16165c3ea33ebabe514f7a20e4f88dd11f912900f0279760618eb7fbd5e3bb2a4cf4b351b5fd8e8da69aa2719725e54a
|
||||
@@ -52130,18 +52027,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"xss@npm:^1.0.8":
|
||||
version: 1.0.11
|
||||
resolution: "xss@npm:1.0.11"
|
||||
dependencies:
|
||||
commander: "npm:^2.20.3"
|
||||
cssfilter: "npm:0.0.10"
|
||||
bin:
|
||||
xss: bin/xss
|
||||
checksum: 10/00f0e85d7b7e5e1b2908366866637f8aa0707c7f433837c553e45f94bd824897e89b4332a092fcf2bfe8f66f196e0c6570a0069ed60c24f0e26a566bbb5b51e2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"xtend@npm:^2.2.0":
|
||||
version: 2.2.0
|
||||
resolution: "xtend@npm:2.2.0"
|
||||
|
||||
Reference in New Issue
Block a user