From 0b2ca9a515cba10ad8765e27427ea5faab270225 Mon Sep 17 00:00:00 2001 From: Kristaps Fabians Geikins Date: Wed, 10 Jul 2024 12:33:53 +0300 Subject: [PATCH] feat: add missing FE1 fields to the FE2 GQL schema (#2471) * WIP version create * commitCreate migrated * minor cleanup * commitReceived migrated * added Project.object * Project.comment introduced * moving away old API usages in FE1 * ProjectMutations.batchDelete * project pending access requests * WIP project access req tests * project access req tests done * ModelByName test * version mutation tests * project.object tests * batch delete tests * minor improvements to redirect logging --- .pre-commit-config.yaml | 2 +- .../server-management/DeleteProjectDialog.vue | 4 +- .../components/viewer/dataviewer/Object.vue | 4 +- .../lib/common/generated/gql/gql.ts | 24 +- .../lib/common/generated/gql/graphql.ts | 159 +++++-- .../server-management/graphql/mutations.ts | 6 +- .../frontend-2/lib/viewer/graphql/queries.ts | 4 +- .../frontend-2/middleware/redirects.global.ts | 186 +++++--- packages/frontend-2/middleware/thread.ts | 9 +- .../typedefs/accessrequests.graphql | 64 ++- .../assets/comments/typedefs/comments.gql | 8 +- .../core/typedefs/branchesAndCommits.graphql | 6 +- .../core/typedefs/modelsAndVersions.graphql | 24 + .../assets/core/typedefs/objects.graphql | 14 +- .../assets/core/typedefs/projects.graphql | 5 + .../assets/core/typedefs/streams.graphql | 2 +- packages/server/codegen.yml | 3 + .../accessrequests/graph/resolvers/index.ts | 87 ++++ .../accessrequests/helpers/graphTypes.ts | 3 + .../modules/accessrequests/services/stream.ts | 60 ++- .../tests/projectAccessRequests.spec.ts | 417 ++++++++++++++++++ .../tests/streamAccessRequests.spec.ts | 2 +- .../comments/graph/resolvers/comments.js | 36 +- .../comments/tests/projectComments.spec.ts | 91 ++++ packages/server/modules/core/errors/commit.ts | 5 + .../modules/core/graph/generated/graphql.ts | 191 ++++++-- .../modules/core/graph/resolvers/commits.js | 22 +- .../modules/core/graph/resolvers/models.ts | 10 + .../resolvers/{objects.js => objects.ts} | 40 +- .../modules/core/graph/resolvers/projects.ts | 10 + .../modules/core/graph/resolvers/versions.ts | 52 ++- packages/server/modules/core/graph/scalars.js | 2 - .../server/modules/core/helpers/graphTypes.ts | 9 +- packages/server/modules/core/helpers/token.ts | 1 - .../core/services/commit/management.ts | 36 +- .../server/modules/core/services/objects.js | 18 +- .../services/streams/streamAccessService.js | 6 +- .../server/modules/core/tests/models.spec.ts | 89 ++++ .../modules/core/tests/projects.spec.ts | 132 ++++++ .../modules/core/tests/versions.spec.ts | 126 ++++++ .../graph/generated/graphql.ts | 129 +++++- packages/server/modules/shared/index.js | 2 +- .../server/test/graphql/generated/graphql.ts | 242 +++++++++- packages/server/test/graphql/models.ts | 25 ++ .../test/graphql/projectAccessRequests.ts | 90 ++++ .../server/test/graphql/projectComments.ts | 16 + packages/server/test/graphql/projects.ts | 41 +- packages/server/test/graphql/versions.ts | 25 ++ packages/server/test/graphqlHelper.ts | 26 +- .../test/speckle-helpers/branchHelper.ts | 44 ++ .../test/speckle-helpers/commitHelper.ts | 33 +- .../test/speckle-helpers/streamHelper.ts | 2 +- 52 files changed, 2359 insertions(+), 285 deletions(-) create mode 100644 packages/server/modules/accessrequests/tests/projectAccessRequests.spec.ts create mode 100644 packages/server/modules/comments/tests/projectComments.spec.ts rename packages/server/modules/core/graph/resolvers/{objects.js => objects.ts} (65%) create mode 100644 packages/server/modules/core/tests/models.spec.ts create mode 100644 packages/server/modules/core/tests/projects.spec.ts create mode 100644 packages/server/modules/core/tests/versions.spec.ts create mode 100644 packages/server/test/graphql/models.ts create mode 100644 packages/server/test/graphql/projectAccessRequests.ts create mode 100644 packages/server/test/graphql/projectComments.ts create mode 100644 packages/server/test/graphql/versions.ts create mode 100644 packages/server/test/speckle-helpers/branchHelper.ts diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 02b781c6c..26293854a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,7 +41,7 @@ repos: - id: helm-documentation name: Helm Json Schema language: system - files: utils/helm/speckle-server/values.yaml + files: utils\/helm\/speckle\-server\/values\.yaml entry: utils/helm/update-schema-json.sh description: If this fails it is because the values.yaml file was updated. Or has missing or incorrect documentation. diff --git a/packages/frontend-2/components/server-management/DeleteProjectDialog.vue b/packages/frontend-2/components/server-management/DeleteProjectDialog.vue index efc3970b5..59e0ee159 100644 --- a/packages/frontend-2/components/server-management/DeleteProjectDialog.vue +++ b/packages/frontend-2/components/server-management/DeleteProjectDialog.vue @@ -61,7 +61,7 @@ const deleteConfirmed = async () => { }, { update: (cache, { data }) => { - if (data?.streamsDelete) { + if (data?.projectMutations.batchDelete) { // Remove project from cache const cacheId = getCacheId('Project', projectId) cache.evict({ @@ -103,7 +103,7 @@ const deleteConfirmed = async () => { } ).catch(convertThrowIntoFetchResult) - if (result?.data?.streamsDelete) { + if (result?.data?.projectMutations.batchDelete) { triggerNotification({ type: ToastNotificationType.Success, title: 'Project deleted', diff --git a/packages/frontend-2/components/viewer/dataviewer/Object.vue b/packages/frontend-2/components/viewer/dataviewer/Object.vue index fc5431ba6..4ae248ad9 100644 --- a/packages/frontend-2/components/viewer/dataviewer/Object.vue +++ b/packages/frontend-2/components/viewer/dataviewer/Object.vue @@ -26,7 +26,7 @@ const props = defineProps<{ }>() const { result, loading, load } = useLazyQuery(viewerRawObjectQuery, () => ({ - streamId: projectId.value, + projectId: projectId.value, objectId: props.object['referencedId'] as string })) @@ -35,7 +35,7 @@ if (props.object['referencedId']) { } const kvps = computed(() => { - const obj = (result.value?.stream?.object?.data || props.object) as Record< + const obj = (result.value?.project?.object?.data || props.object) as Record< string, unknown > diff --git a/packages/frontend-2/lib/common/generated/gql/gql.ts b/packages/frontend-2/lib/common/generated/gql/gql.ts index ec8ec2ba4..7225af425 100644 --- a/packages/frontend-2/lib/common/generated/gql/gql.ts +++ b/packages/frontend-2/lib/common/generated/gql/gql.ts @@ -194,7 +194,7 @@ const documents = { "\n subscription OnProjectAutomationsUpdated($id: String!) {\n projectAutomationsUpdated(projectId: $id) {\n type\n automationId\n automation {\n id\n ...ProjectPageAutomationPage_Automation\n ...ProjectPageAutomationsRow_Automation\n }\n }\n }\n": types.OnProjectAutomationsUpdatedDocument, "\n mutation ServerInfoUpdate($info: ServerInfoUpdateInput!) {\n serverInfoUpdate(info: $info)\n }\n": types.ServerInfoUpdateDocument, "\n mutation AdminPanelDeleteUser($userConfirmation: UserDeleteInput!) {\n adminDeleteUser(userConfirmation: $userConfirmation)\n }\n": types.AdminPanelDeleteUserDocument, - "\n mutation AdminPanelDeleteProject($ids: [String!]) {\n streamsDelete(ids: $ids)\n }\n": types.AdminPanelDeleteProjectDocument, + "\n mutation AdminPanelDeleteProject($ids: [String!]!) {\n projectMutations {\n batchDelete(ids: $ids)\n }\n }\n": types.AdminPanelDeleteProjectDocument, "\n mutation AdminPanelResendInvite($inviteId: String!) {\n inviteResend(inviteId: $inviteId)\n }\n": types.AdminPanelResendInviteDocument, "\n mutation AdminPanelDeleteInvite($inviteId: String!) {\n inviteDelete(inviteId: $inviteId)\n }\n": types.AdminPanelDeleteInviteDocument, "\n mutation AdminChangeUseRole($userRoleInput: UserRoleInput!) {\n userRoleChange(userRoleInput: $userRoleInput)\n }\n": types.AdminChangeUseRoleDocument, @@ -224,14 +224,14 @@ const documents = { "\n query ViewerModelVersions(\n $projectId: String!\n $modelId: String!\n $versionsCursor: String\n ) {\n project(id: $projectId) {\n id\n role\n model(id: $modelId) {\n id\n versions(cursor: $versionsCursor, limit: 5) {\n totalCount\n cursor\n items {\n ...ViewerModelVersionCardItem\n }\n }\n }\n }\n }\n": types.ViewerModelVersionsDocument, "\n query ViewerDiffVersions(\n $projectId: String!\n $modelId: String!\n $versionAId: String!\n $versionBId: String!\n ) {\n project(id: $projectId) {\n id\n model(id: $modelId) {\n id\n versionA: version(id: $versionAId) {\n ...ViewerModelVersionCardItem\n }\n versionB: version(id: $versionBId) {\n ...ViewerModelVersionCardItem\n }\n }\n }\n }\n": types.ViewerDiffVersionsDocument, "\n query ViewerLoadedThreads(\n $projectId: String!\n $filter: ProjectCommentsFilter!\n $cursor: String\n $limit: Int = 25\n ) {\n project(id: $projectId) {\n id\n commentThreads(filter: $filter, cursor: $cursor, limit: $limit) {\n totalCount\n totalArchivedCount\n items {\n ...ViewerCommentThread\n ...LinkableComment\n }\n }\n }\n }\n": types.ViewerLoadedThreadsDocument, - "\n query Stream($streamId: String!, $objectId: String!) {\n stream(id: $streamId) {\n id\n object(id: $objectId) {\n id\n data\n }\n }\n }\n": types.StreamDocument, + "\n query ViewerRawProjectObject($projectId: String!, $objectId: String!) {\n project(id: $projectId) {\n id\n object(id: $objectId) {\n id\n data\n }\n }\n }\n": types.ViewerRawProjectObjectDocument, "\n subscription OnViewerUserActivityBroadcasted(\n $target: ViewerUpdateTrackingTarget!\n $sessionId: String!\n ) {\n viewerUserActivityBroadcasted(target: $target, sessionId: $sessionId) {\n userName\n userId\n user {\n ...LimitedUserAvatar\n }\n state\n status\n sessionId\n }\n }\n": types.OnViewerUserActivityBroadcastedDocument, "\n subscription OnViewerCommentsUpdated($target: ViewerUpdateTrackingTarget!) {\n projectCommentsUpdated(target: $target) {\n id\n type\n comment {\n id\n parent {\n id\n }\n ...ViewerCommentThread\n }\n }\n }\n": types.OnViewerCommentsUpdatedDocument, "\n fragment LinkableComment on Comment {\n id\n viewerResources {\n modelId\n versionId\n objectId\n }\n }\n": types.LinkableCommentFragmentDoc, - "\n query LegacyBranchRedirectMetadata($streamId: String!, $branchName: String!) {\n stream(id: $streamId) {\n branch(name: $branchName) {\n id\n }\n }\n }\n": types.LegacyBranchRedirectMetadataDocument, - "\n query LegacyViewerCommitRedirectMetadata($streamId: String!, $commitId: String!) {\n stream(id: $streamId) {\n commit(id: $commitId) {\n id\n branch {\n id\n }\n }\n }\n }\n": types.LegacyViewerCommitRedirectMetadataDocument, - "\n query LegacyViewerStreamRedirectMetadata($streamId: String!) {\n stream(id: $streamId) {\n id\n commits(limit: 1) {\n totalCount\n items {\n id\n branch {\n id\n }\n }\n }\n }\n }\n": types.LegacyViewerStreamRedirectMetadataDocument, - "\n query ResolveCommentLink($commentId: String!, $projectId: String!) {\n comment(id: $commentId, streamId: $projectId) {\n ...LinkableComment\n }\n }\n": types.ResolveCommentLinkDocument, + "\n query LegacyBranchRedirectMetadata($streamId: String!, $branchName: String!) {\n project(id: $streamId) {\n modelByName(name: $branchName) {\n id\n }\n }\n }\n": types.LegacyBranchRedirectMetadataDocument, + "\n query LegacyViewerCommitRedirectMetadata($streamId: String!, $commitId: String!) {\n project(id: $streamId) {\n version(id: $commitId) {\n id\n model {\n id\n }\n }\n }\n }\n": types.LegacyViewerCommitRedirectMetadataDocument, + "\n query LegacyViewerStreamRedirectMetadata($streamId: String!) {\n project(id: $streamId) {\n id\n versions(limit: 1) {\n totalCount\n items {\n id\n model {\n id\n }\n }\n }\n }\n }\n": types.LegacyViewerStreamRedirectMetadataDocument, + "\n query ResolveCommentLink($commentId: String!, $projectId: String!) {\n project(id: $projectId) {\n comment(id: $commentId) {\n id\n ...LinkableComment\n }\n }\n }\n": types.ResolveCommentLinkDocument, "\n fragment AutomateFunctionPage_AutomateFunction on AutomateFunction {\n id\n name\n description\n logo\n supportedSourceApps\n tags\n ...AutomateFunctionPageHeader_Function\n ...AutomateFunctionPageInfo_AutomateFunction\n ...AutomateAutomationCreateDialog_AutomateFunction\n creator {\n id\n }\n }\n": types.AutomateFunctionPage_AutomateFunctionFragmentDoc, "\n query AutomateFunctionPage($functionId: ID!) {\n automateFunction(id: $functionId) {\n ...AutomateFunctionPage_AutomateFunction\n }\n }\n": types.AutomateFunctionPageDocument, "\n query AutomateFunctionsPage($search: String, $cursor: String = null) {\n ...AutomateFunctionsPageItems_Query\n ...AutomateFunctionsPageHeader_Query\n }\n": types.AutomateFunctionsPageDocument, @@ -982,7 +982,7 @@ export function graphql(source: "\n mutation AdminPanelDeleteUser($userConfirma /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n mutation AdminPanelDeleteProject($ids: [String!]) {\n streamsDelete(ids: $ids)\n }\n"): (typeof documents)["\n mutation AdminPanelDeleteProject($ids: [String!]) {\n streamsDelete(ids: $ids)\n }\n"]; +export function graphql(source: "\n mutation AdminPanelDeleteProject($ids: [String!]!) {\n projectMutations {\n batchDelete(ids: $ids)\n }\n }\n"): (typeof documents)["\n mutation AdminPanelDeleteProject($ids: [String!]!) {\n projectMutations {\n batchDelete(ids: $ids)\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -1102,7 +1102,7 @@ export function graphql(source: "\n query ViewerLoadedThreads(\n $projectId: /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n query Stream($streamId: String!, $objectId: String!) {\n stream(id: $streamId) {\n id\n object(id: $objectId) {\n id\n data\n }\n }\n }\n"): (typeof documents)["\n query Stream($streamId: String!, $objectId: String!) {\n stream(id: $streamId) {\n id\n object(id: $objectId) {\n id\n data\n }\n }\n }\n"]; +export function graphql(source: "\n query ViewerRawProjectObject($projectId: String!, $objectId: String!) {\n project(id: $projectId) {\n id\n object(id: $objectId) {\n id\n data\n }\n }\n }\n"): (typeof documents)["\n query ViewerRawProjectObject($projectId: String!, $objectId: String!) {\n project(id: $projectId) {\n id\n object(id: $objectId) {\n id\n data\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -1118,19 +1118,19 @@ export function graphql(source: "\n fragment LinkableComment on Comment {\n /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n query LegacyBranchRedirectMetadata($streamId: String!, $branchName: String!) {\n stream(id: $streamId) {\n branch(name: $branchName) {\n id\n }\n }\n }\n"): (typeof documents)["\n query LegacyBranchRedirectMetadata($streamId: String!, $branchName: String!) {\n stream(id: $streamId) {\n branch(name: $branchName) {\n id\n }\n }\n }\n"]; +export function graphql(source: "\n query LegacyBranchRedirectMetadata($streamId: String!, $branchName: String!) {\n project(id: $streamId) {\n modelByName(name: $branchName) {\n id\n }\n }\n }\n"): (typeof documents)["\n query LegacyBranchRedirectMetadata($streamId: String!, $branchName: String!) {\n project(id: $streamId) {\n modelByName(name: $branchName) {\n id\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n query LegacyViewerCommitRedirectMetadata($streamId: String!, $commitId: String!) {\n stream(id: $streamId) {\n commit(id: $commitId) {\n id\n branch {\n id\n }\n }\n }\n }\n"): (typeof documents)["\n query LegacyViewerCommitRedirectMetadata($streamId: String!, $commitId: String!) {\n stream(id: $streamId) {\n commit(id: $commitId) {\n id\n branch {\n id\n }\n }\n }\n }\n"]; +export function graphql(source: "\n query LegacyViewerCommitRedirectMetadata($streamId: String!, $commitId: String!) {\n project(id: $streamId) {\n version(id: $commitId) {\n id\n model {\n id\n }\n }\n }\n }\n"): (typeof documents)["\n query LegacyViewerCommitRedirectMetadata($streamId: String!, $commitId: String!) {\n project(id: $streamId) {\n version(id: $commitId) {\n id\n model {\n id\n }\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n query LegacyViewerStreamRedirectMetadata($streamId: String!) {\n stream(id: $streamId) {\n id\n commits(limit: 1) {\n totalCount\n items {\n id\n branch {\n id\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query LegacyViewerStreamRedirectMetadata($streamId: String!) {\n stream(id: $streamId) {\n id\n commits(limit: 1) {\n totalCount\n items {\n id\n branch {\n id\n }\n }\n }\n }\n }\n"]; +export function graphql(source: "\n query LegacyViewerStreamRedirectMetadata($streamId: String!) {\n project(id: $streamId) {\n id\n versions(limit: 1) {\n totalCount\n items {\n id\n model {\n id\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query LegacyViewerStreamRedirectMetadata($streamId: String!) {\n project(id: $streamId) {\n id\n versions(limit: 1) {\n totalCount\n items {\n id\n model {\n id\n }\n }\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n query ResolveCommentLink($commentId: String!, $projectId: String!) {\n comment(id: $commentId, streamId: $projectId) {\n ...LinkableComment\n }\n }\n"): (typeof documents)["\n query ResolveCommentLink($commentId: String!, $projectId: String!) {\n comment(id: $commentId, streamId: $projectId) {\n ...LinkableComment\n }\n }\n"]; +export function graphql(source: "\n query ResolveCommentLink($commentId: String!, $projectId: String!) {\n project(id: $projectId) {\n comment(id: $commentId) {\n id\n ...LinkableComment\n }\n }\n }\n"): (typeof documents)["\n query ResolveCommentLink($commentId: String!, $projectId: String!) {\n project(id: $projectId) {\n comment(id: $commentId) {\n id\n ...LinkableComment\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/packages/frontend-2/lib/common/generated/gql/graphql.ts b/packages/frontend-2/lib/common/generated/gql/graphql.ts index 102873424..6a847cdde 100644 --- a/packages/frontend-2/lib/common/generated/gql/graphql.ts +++ b/packages/frontend-2/lib/common/generated/gql/graphql.ts @@ -18,7 +18,6 @@ export type Scalars = { BigInt: { input: any; output: any; } /** A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. */ DateTime: { input: string; output: string; } - EmailAddress: { input: any; output: any; } /** The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ JSONObject: { input: {}; output: {}; } }; @@ -798,6 +797,16 @@ export type CreateModelInput = { projectId: Scalars['ID']['input']; }; +export type CreateVersionInput = { + message?: InputMaybe; + modelId: Scalars['String']['input']; + objectId: Scalars['String']['input']; + parents?: InputMaybe>; + projectId: Scalars['String']['input']; + sourceApplication?: InputMaybe; + totalChildrenCount?: InputMaybe; +}; + export type DeleteModelInput = { id: Scalars['ID']['input']; projectId: Scalars['ID']['input']; @@ -988,6 +997,13 @@ export type LimitedUserTimelineArgs = { limit?: Scalars['Int']['input']; }; +export type MarkReceivedVersionInput = { + message?: InputMaybe; + projectId: Scalars['String']['input']; + sourceApplication: Scalars['String']['input']; + versionId: Scalars['String']['input']; +}; + export type Model = { __typename?: 'Model'; author: LimitedUser; @@ -1157,11 +1173,11 @@ export type Mutation = { * @deprecated Use commentMutations version */ commentView: Scalars['Boolean']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.create instead. */ commitCreate: Scalars['String']['output']; /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.delete instead. */ commitDelete: Scalars['Boolean']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.markReceived instead. */ commitReceive: Scalars['Boolean']['output']; /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.update/moveToModel instead. */ commitUpdate: Scalars['Boolean']['output']; @@ -1187,7 +1203,7 @@ export type Mutation = { inviteResend: Scalars['Boolean']['output']; modelMutations: ModelMutations; /** @deprecated Part of the old API surface and will be removed in the future. */ - objectCreate: Array>; + objectCreate: Array; projectMutations: ProjectMutations; /** (Re-)send the account verification e-mail */ requestVerification: Scalars['Boolean']['output']; @@ -1199,12 +1215,12 @@ export type Mutation = { serverInviteCreate: Scalars['Boolean']['output']; /** * Request access to a specific stream - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use ProjectAccessRequestMutations.create instead. */ streamAccessRequestCreate: StreamAccessRequest; /** * Accept or decline a stream access request. Must be a stream owner to invoke this. - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use ProjectAccessRequestMutations.use instead. */ streamAccessRequestUse: Scalars['Boolean']['output']; /** @@ -1261,7 +1277,7 @@ export type Mutation = { * @deprecated Part of the old API surface and will be removed in the future. Use ProjectMutations.updateRole instead. */ streamUpdatePermission?: Maybe; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use ProjectMutations.batchDelete instead. */ streamsDelete: Scalars['Boolean']['output']; /** * Used for broadcasting real time typing status in comment threads. Does not persist any info. @@ -1578,6 +1594,7 @@ export type MutationWebhookUpdateArgs = { export type Object = { __typename?: 'Object'; + /** @deprecated Not implemented. */ applicationId?: Maybe; /** * Get any objects that this object references. In the case of commits, this will give you a commit's constituent objects. @@ -1617,7 +1634,7 @@ export type ObjectChildrenArgs = { export type ObjectCollection = { __typename?: 'ObjectCollection'; cursor?: Maybe; - objects: Array>; + objects: Array; totalCount: Scalars['Int']['output']; }; @@ -1678,6 +1695,8 @@ export type Project = { blob?: Maybe; /** Get the metadata collection of blobs stored for this stream. */ blobs?: Maybe; + /** Get specific project comment/thread by ID */ + comment?: Maybe; /** All comment threads in this project */ commentThreads: ProjectCommentCollection; createdAt: Scalars['DateTime']['output']; @@ -1687,6 +1706,8 @@ export type Project = { invitedTeam?: Maybe>; /** Returns a specific model by its ID */ model: Model; + /** Retrieve a specific project model by its ID */ + modelByName: Model; /** Return a model tree of children for the specified model name */ modelChildrenTree: Array; /** Returns a flat list of all models */ @@ -1697,6 +1718,9 @@ export type Project = { */ modelsTree: ModelsTreeItemCollection; name: Scalars['String']['output']; + object?: Maybe; + /** Pending project access requests */ + pendingAccessRequests?: Maybe>; /** Returns a list models that are being created from a file import */ pendingImportedModels: Array; /** Active user's role for this project. `null` if request is not authenticated, or the project is not explicitly shared with you. */ @@ -1740,6 +1764,11 @@ export type ProjectBlobsArgs = { }; +export type ProjectCommentArgs = { + id: Scalars['String']['input']; +}; + + export type ProjectCommentThreadsArgs = { cursor?: InputMaybe; filter?: InputMaybe; @@ -1752,6 +1781,11 @@ export type ProjectModelArgs = { }; +export type ProjectModelByNameArgs = { + name: Scalars['String']['input']; +}; + + export type ProjectModelChildrenTreeArgs = { fullName: Scalars['String']['input']; }; @@ -1771,6 +1805,11 @@ export type ProjectModelsTreeArgs = { }; +export type ProjectObjectArgs = { + id: Scalars['String']['input']; +}; + + export type ProjectPendingImportedModelsArgs = { limit?: InputMaybe; }; @@ -1797,6 +1836,38 @@ export type ProjectWebhooksArgs = { id?: InputMaybe; }; +/** Created when a user requests to become a contributor on a project */ +export type ProjectAccessRequest = { + __typename?: 'ProjectAccessRequest'; + createdAt: Scalars['DateTime']['output']; + id: Scalars['ID']['output']; + /** Can only be selected if authed user has proper access */ + project: Project; + projectId: Scalars['String']['output']; + requester: LimitedUser; + requesterId: Scalars['String']['output']; +}; + +export type ProjectAccessRequestMutations = { + __typename?: 'ProjectAccessRequestMutations'; + /** Request access to a specific project */ + create: ProjectAccessRequest; + /** Accept or decline a project access request. Must be a project owner to invoke this. */ + use: Project; +}; + + +export type ProjectAccessRequestMutationsCreateArgs = { + projectId: Scalars['String']['input']; +}; + + +export type ProjectAccessRequestMutationsUseArgs = { + accept: Scalars['Boolean']['input']; + requestId: Scalars['String']['input']; + role?: StreamRole; +}; + export type ProjectAutomationCreateInput = { enabled: Scalars['Boolean']['input']; name: Scalars['String']['input']; @@ -2039,7 +2110,11 @@ export enum ProjectModelsUpdatedMessageType { export type ProjectMutations = { __typename?: 'ProjectMutations'; + /** Access request related mutations */ + accessRequestMutations: ProjectAccessRequestMutations; automationMutations: ProjectAutomationMutations; + /** Batch delete projects */ + batchDelete: Scalars['Boolean']['output']; /** Create new project */ create: Project; /** @@ -2065,6 +2140,11 @@ export type ProjectMutationsAutomationMutationsArgs = { }; +export type ProjectMutationsBatchDeleteArgs = { + ids: Array; +}; + + export type ProjectMutationsCreateArgs = { input?: InputMaybe; }; @@ -2228,7 +2308,7 @@ export type Query = { automateFunctions: AutomateFunctionCollection; /** Part of the automation/function creation handshake mechanism */ automateValidateAuthCode: Scalars['Boolean']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use Project.comment instead. */ comment?: Maybe; /** * This query can be used in the following ways: @@ -2267,7 +2347,7 @@ export type Query = { stream?: Maybe; /** * Get authed user's stream access request - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use User.projectAccessRequest instead. */ streamAccessRequest?: Maybe; /** @@ -2632,7 +2712,7 @@ export type Stream = { * @deprecated Part of the old API surface and will be removed in the future. Use Project.blobs instead. */ blobs?: Maybe; - /** @deprecated Part of the old API surface and will be removed in the future. Use Project.model instead. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use Project.model or Project.modelByName instead. */ branch?: Maybe; /** @deprecated Part of the old API surface and will be removed in the future. Use Project.models or Project.modelsTree instead. */ branches?: Maybe; @@ -2677,11 +2757,11 @@ export type Stream = { /** Whether the stream can be viewed by non-contributors */ isPublic: Scalars['Boolean']['output']; name: Scalars['String']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use Project.object instead. */ object?: Maybe; /** * Pending stream access requests - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use Project.pendingAccessRequests instead. */ pendingAccessRequests?: Maybe>; /** Collaborators who have been invited, but not yet accepted. */ @@ -3185,6 +3265,8 @@ export type User = { name: Scalars['String']['output']; notificationPreferences: Scalars['JSONObject']['output']; profiles?: Maybe; + /** Get pending project access request, that the user made */ + projectAccessRequest?: Maybe; /** Get all invitations to projects that the active user has */ projectInvites: Array; /** Get projects that the user participates in */ @@ -3250,6 +3332,15 @@ export type UserFavoriteStreamsArgs = { }; +/** + * Full user type, should only be used in the context of admin operations or + * when a user is reading/writing info about himself + */ +export type UserProjectAccessRequestArgs = { + projectId: Scalars['String']['input']; +}; + + /** * Full user type, should only be used in the context of admin operations or * when a user is reading/writing info about himself @@ -3394,18 +3485,30 @@ export type VersionCreatedTriggerDefinition = { export type VersionMutations = { __typename?: 'VersionMutations'; + create: Version; delete: Scalars['Boolean']['output']; + markReceived: Scalars['Boolean']['output']; moveToModel: Model; requestGendoAIRender: Scalars['Boolean']['output']; update: Version; }; +export type VersionMutationsCreateArgs = { + input: CreateVersionInput; +}; + + export type VersionMutationsDeleteArgs = { input: DeleteVersionsInput; }; +export type VersionMutationsMarkReceivedArgs = { + input: MarkReceivedVersionInput; +}; + + export type VersionMutationsMoveToModelArgs = { input: MoveVersionsInput; }; @@ -4407,11 +4510,11 @@ export type AdminPanelDeleteUserMutationVariables = Exact<{ export type AdminPanelDeleteUserMutation = { __typename?: 'Mutation', adminDeleteUser: boolean }; export type AdminPanelDeleteProjectMutationVariables = Exact<{ - ids?: InputMaybe | Scalars['String']['input']>; + ids: Array | Scalars['String']['input']; }>; -export type AdminPanelDeleteProjectMutation = { __typename?: 'Mutation', streamsDelete: boolean }; +export type AdminPanelDeleteProjectMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', batchDelete: boolean } }; export type AdminPanelResendInviteMutationVariables = Exact<{ inviteId: Scalars['String']['input']; @@ -4602,13 +4705,13 @@ export type ViewerLoadedThreadsQueryVariables = Exact<{ export type ViewerLoadedThreadsQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, commentThreads: { __typename?: 'ProjectCommentCollection', totalCount: number, totalArchivedCount: number, items: Array<{ __typename?: 'Comment', id: string, rawText: string, archived: boolean, createdAt: string, viewedAt?: string | null, viewerState?: {} | null, viewerResources: Array<{ __typename?: 'ViewerResourceItem', modelId?: string | null, versionId?: string | null, objectId: string }>, author: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null }, replies: { __typename?: 'CommentCollection', totalCount: number, cursor?: string | null, items: Array<{ __typename?: 'Comment', id: string, archived: boolean, rawText: string, createdAt: string, text: { __typename?: 'SmartTextEditorValue', doc?: {} | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, fileType: string, fileSize?: number | null }> | null }, author: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null } }> }, replyAuthors: { __typename?: 'CommentReplyAuthorCollection', totalCount: number, items: Array<{ __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null }> }, resources: Array<{ __typename?: 'ResourceIdentifier', resourceId: string, resourceType: ResourceType }>, text: { __typename?: 'SmartTextEditorValue', doc?: {} | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, fileType: string, fileSize?: number | null }> | null } }> } } }; -export type StreamQueryVariables = Exact<{ - streamId: Scalars['String']['input']; +export type ViewerRawProjectObjectQueryVariables = Exact<{ + projectId: Scalars['String']['input']; objectId: Scalars['String']['input']; }>; -export type StreamQuery = { __typename?: 'Query', stream?: { __typename?: 'Stream', id: string, object?: { __typename?: 'Object', id: string, data?: {} | null } | null } | null }; +export type ViewerRawProjectObjectQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, object?: { __typename?: 'Object', id: string, data?: {} | null } | null } }; export type OnViewerUserActivityBroadcastedSubscriptionVariables = Exact<{ target: ViewerUpdateTrackingTarget; @@ -4633,7 +4736,7 @@ export type LegacyBranchRedirectMetadataQueryVariables = Exact<{ }>; -export type LegacyBranchRedirectMetadataQuery = { __typename?: 'Query', stream?: { __typename?: 'Stream', branch?: { __typename?: 'Branch', id: string } | null } | null }; +export type LegacyBranchRedirectMetadataQuery = { __typename?: 'Query', project: { __typename?: 'Project', modelByName: { __typename?: 'Model', id: string } } }; export type LegacyViewerCommitRedirectMetadataQueryVariables = Exact<{ streamId: Scalars['String']['input']; @@ -4641,14 +4744,14 @@ export type LegacyViewerCommitRedirectMetadataQueryVariables = Exact<{ }>; -export type LegacyViewerCommitRedirectMetadataQuery = { __typename?: 'Query', stream?: { __typename?: 'Stream', commit?: { __typename?: 'Commit', id: string, branch?: { __typename?: 'Branch', id: string } | null } | null } | null }; +export type LegacyViewerCommitRedirectMetadataQuery = { __typename?: 'Query', project: { __typename?: 'Project', version?: { __typename?: 'Version', id: string, model: { __typename?: 'Model', id: string } } | null } }; export type LegacyViewerStreamRedirectMetadataQueryVariables = Exact<{ streamId: Scalars['String']['input']; }>; -export type LegacyViewerStreamRedirectMetadataQuery = { __typename?: 'Query', stream?: { __typename?: 'Stream', id: string, commits?: { __typename?: 'CommitCollection', totalCount: number, items?: Array<{ __typename?: 'Commit', id: string, branch?: { __typename?: 'Branch', id: string } | null }> | null } | null } | null }; +export type LegacyViewerStreamRedirectMetadataQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, versions: { __typename?: 'VersionCollection', totalCount: number, items: Array<{ __typename?: 'Version', id: string, model: { __typename?: 'Model', id: string } }> } } }; export type ResolveCommentLinkQueryVariables = Exact<{ commentId: Scalars['String']['input']; @@ -4656,7 +4759,7 @@ export type ResolveCommentLinkQueryVariables = Exact<{ }>; -export type ResolveCommentLinkQuery = { __typename?: 'Query', comment?: { __typename?: 'Comment', id: string, viewerResources: Array<{ __typename?: 'ViewerResourceItem', modelId?: string | null, versionId?: string | null, objectId: string }> } | null }; +export type ResolveCommentLinkQuery = { __typename?: 'Query', project: { __typename?: 'Project', comment?: { __typename?: 'Comment', id: string, viewerResources: Array<{ __typename?: 'ViewerResourceItem', modelId?: string | null, versionId?: string | null, objectId: string }> } | null } }; export type AutomateFunctionPage_AutomateFunctionFragment = { __typename?: 'AutomateFunction', id: string, name: string, description: string, logo?: string | null, supportedSourceApps: Array, tags: Array, automationCount: number, isFeatured: boolean, creator?: { __typename?: 'LimitedUser', id: string } | null, repo: { __typename?: 'BasicGitRepositoryMetadata', id: string, url: string, owner: string, name: string }, releases: { __typename?: 'AutomateFunctionReleaseCollection', totalCount: number, items: Array<{ __typename?: 'AutomateFunctionRelease', id: string, inputSchema?: {} | null, createdAt: string, commitId: string }> } }; @@ -4876,7 +4979,7 @@ export const OnProjectTriggeredAutomationsStatusUpdatedDocument = {"kind":"Docum export const OnProjectAutomationsUpdatedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"OnProjectAutomationsUpdated"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectAutomationsUpdated"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"projectId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"automationId"}},{"kind":"Field","name":{"kind":"Name","value":"automation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageAutomationPage_Automation"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageAutomationsRow_Automation"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"PendingFileUpload"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"FileUpload"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"projectId"}},{"kind":"Field","name":{"kind":"Name","value":"modelName"}},{"kind":"Field","name":{"kind":"Name","value":"convertedStatus"}},{"kind":"Field","name":{"kind":"Name","value":"convertedMessage"}},{"kind":"Field","name":{"kind":"Name","value":"uploadDate"}},{"kind":"Field","name":{"kind":"Name","value":"convertedLastUpdate"}},{"kind":"Field","name":{"kind":"Name","value":"fileType"}},{"kind":"Field","name":{"kind":"Name","value":"fileName"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsCardRenameDialog"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Model"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsCardDeleteDialog"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Model"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageModelsActions"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Model"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FunctionRunStatusForSummary"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunctionRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TriggeredAutomationsStatusSummary"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"TriggeredAutomationsStatus"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"automationRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"functionRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"FunctionRunStatusForSummary"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialogFunctionRun_AutomateFunctionRun"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunctionRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"results"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"statusMessage"}},{"kind":"Field","name":{"kind":"Name","value":"contextView"}},{"kind":"Field","name":{"kind":"Name","value":"function"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomationsStatusOrderedRuns_AutomationRun"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"automation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"functionRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialogRunsRows_AutomateRun"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"functionRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialogFunctionRun_AutomateFunctionRun"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomationsStatusOrderedRuns_AutomationRun"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatus"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"TriggeredAutomationsStatus"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"automationRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialogRunsRows_AutomateRun"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateRunsTriggerStatus_TriggeredAutomationsStatus"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"TriggeredAutomationsStatus"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"TriggeredAutomationsStatusSummary"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatus"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Model"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","alias":{"kind":"Name","value":"versionCount"},"name":{"kind":"Name","value":"versions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","alias":{"kind":"Name","value":"commentThreadCount"},"name":{"kind":"Name","value":"commentThreads"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"0"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"pendingImportedVersions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"PendingFileUpload"}}]}},{"kind":"Field","name":{"kind":"Name","value":"previewUrl"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageModelsCardRenameDialog"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageModelsCardDeleteDialog"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageModelsActions"}},{"kind":"Field","name":{"kind":"Name","value":"automationsStatus"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateRunsTriggerStatus_TriggeredAutomationsStatus"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationHeader_Automation"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Automation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"isTestAutomation"}},{"kind":"Field","name":{"kind":"Name","value":"currentRevision"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"triggerDefinitions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"VersionCreatedTriggerDefinition"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"model"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CommonModelSelectorModel"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Model"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationFunctionSettingsDialog_AutomationRevision"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomationRevision"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"triggerDefinitions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"VersionCreatedTriggerDefinition"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"CommonModelSelectorModel"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomationsFunctionsCard_AutomateFunction"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"isFeatured"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"repo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"owner"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationFunctionSettingsDialog_AutomationRevisionFunction"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomationRevisionFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"parameters"}},{"kind":"Field","name":{"kind":"Name","value":"release"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"inputSchema"}},{"kind":"Field","name":{"kind":"Name","value":"function"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationFunctions_Automation"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Automation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"currentRevision"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageAutomationFunctionSettingsDialog_AutomationRevision"}},{"kind":"Field","name":{"kind":"Name","value":"functions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"release"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"function"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomationsFunctionsCard_AutomateFunction"}},{"kind":"Field","name":{"kind":"Name","value":"releases"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageAutomationFunctionSettingsDialog_AutomationRevisionFunction"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomationRunDetails"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"functionRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FunctionRunStatusForSummary"}},{"kind":"Field","name":{"kind":"Name","value":"statusMessage"}}]}},{"kind":"Field","name":{"kind":"Name","value":"trigger"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"VersionCreatedTrigger"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"version"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"model"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationRuns_Automation"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Automation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"isTestAutomation"}},{"kind":"Field","name":{"kind":"Name","value":"runs"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"10"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomationRunDetails"}}]}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationPage_Automation"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Automation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageAutomationHeader_Automation"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageAutomationFunctions_Automation"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageAutomationRuns_Automation"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectPageAutomationsRow_Automation"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Automation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"isTestAutomation"}},{"kind":"Field","name":{"kind":"Name","value":"currentRevision"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"triggerDefinitions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"VersionCreatedTriggerDefinition"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"model"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"runs"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"10"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomationRunDetails"}}]}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}}]}}]}}]} as unknown as DocumentNode; export const ServerInfoUpdateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"ServerInfoUpdate"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"info"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ServerInfoUpdateInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serverInfoUpdate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"info"},"value":{"kind":"Variable","name":{"kind":"Name","value":"info"}}}]}]}}]} as unknown as DocumentNode; export const AdminPanelDeleteUserDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AdminPanelDeleteUser"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"userConfirmation"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UserDeleteInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"adminDeleteUser"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"userConfirmation"},"value":{"kind":"Variable","name":{"kind":"Name","value":"userConfirmation"}}}]}]}}]} as unknown as DocumentNode; -export const AdminPanelDeleteProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AdminPanelDeleteProject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"ids"}},"type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"streamsDelete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"ids"},"value":{"kind":"Variable","name":{"kind":"Name","value":"ids"}}}]}]}}]} as unknown as DocumentNode; +export const AdminPanelDeleteProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AdminPanelDeleteProject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"ids"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"batchDelete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"ids"},"value":{"kind":"Variable","name":{"kind":"Name","value":"ids"}}}]}]}}]}}]} as unknown as DocumentNode; export const AdminPanelResendInviteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AdminPanelResendInvite"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"inviteResend"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"inviteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}}}]}]}}]} as unknown as DocumentNode; export const AdminPanelDeleteInviteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AdminPanelDeleteInvite"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"inviteDelete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"inviteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}}}]}]}}]} as unknown as DocumentNode; export const AdminChangeUseRoleDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AdminChangeUseRole"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"userRoleInput"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UserRoleInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userRoleChange"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"userRoleInput"},"value":{"kind":"Variable","name":{"kind":"Name","value":"userRoleInput"}}}]}]}}]} as unknown as DocumentNode; @@ -4900,12 +5003,12 @@ export const ViewerLoadedResourcesDocument = {"kind":"Document","definitions":[{ export const ViewerModelVersionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ViewerModelVersions"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"versionsCursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"versions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"versionsCursor"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"5"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerModelVersionCardItem"}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"LimitedUserAvatar"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LimitedUser"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewerModelVersionCardItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Version"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"referencedObject"}},{"kind":"Field","name":{"kind":"Name","value":"sourceApplication"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"previewUrl"}},{"kind":"Field","name":{"kind":"Name","value":"authorUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}}]}}]} as unknown as DocumentNode; export const ViewerDiffVersionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ViewerDiffVersions"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"versionAId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"versionBId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","alias":{"kind":"Name","value":"versionA"},"name":{"kind":"Name","value":"version"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"versionAId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerModelVersionCardItem"}}]}},{"kind":"Field","alias":{"kind":"Name","value":"versionB"},"name":{"kind":"Name","value":"version"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"versionBId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerModelVersionCardItem"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"LimitedUserAvatar"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LimitedUser"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewerModelVersionCardItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Version"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"referencedObject"}},{"kind":"Field","name":{"kind":"Name","value":"sourceApplication"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"previewUrl"}},{"kind":"Field","name":{"kind":"Name","value":"authorUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}}]}}]} as unknown as DocumentNode; export const ViewerLoadedThreadsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ViewerLoadedThreads"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectCommentsFilter"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}},"defaultValue":{"kind":"IntValue","value":"25"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"commentThreads"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"totalArchivedCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerCommentThread"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"LinkableComment"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"LimitedUserAvatar"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LimitedUser"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ThreadCommentAttachment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"text"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attachments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fileName"}},{"kind":"Field","name":{"kind":"Name","value":"fileType"}},{"kind":"Field","name":{"kind":"Name","value":"fileSize"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewerCommentsReplyItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"archived"}},{"kind":"Field","name":{"kind":"Name","value":"rawText"}},{"kind":"Field","name":{"kind":"Name","value":"text"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"doc"}}]}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ThreadCommentAttachment"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FormUsersSelectItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LimitedUser"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewerCommentsListItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"rawText"}},{"kind":"Field","name":{"kind":"Name","value":"archived"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"viewedAt"}},{"kind":"Field","name":{"kind":"Name","value":"replies"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerCommentsReplyItem"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"replyAuthors"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"4"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FormUsersSelectItem"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"resources"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"resourceId"}},{"kind":"Field","name":{"kind":"Name","value":"resourceType"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewerCommentBubblesData"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"viewedAt"}},{"kind":"Field","name":{"kind":"Name","value":"viewerState"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewerCommentThread"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerCommentsListItem"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerCommentBubblesData"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerCommentsReplyItem"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"LinkableComment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"viewerResources"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelId"}},{"kind":"Field","name":{"kind":"Name","value":"versionId"}},{"kind":"Field","name":{"kind":"Name","value":"objectId"}}]}}]}}]} as unknown as DocumentNode; -export const StreamDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Stream"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"objectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stream"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"object"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"objectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"data"}}]}}]}}]}}]} as unknown as DocumentNode; +export const ViewerRawProjectObjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ViewerRawProjectObject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"objectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"object"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"objectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"data"}}]}}]}}]}}]} as unknown as DocumentNode; export const OnViewerUserActivityBroadcastedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"OnViewerUserActivityBroadcasted"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"target"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ViewerUpdateTrackingTarget"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"sessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"viewerUserActivityBroadcasted"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"target"},"value":{"kind":"Variable","name":{"kind":"Name","value":"target"}}},{"kind":"Argument","name":{"kind":"Name","value":"sessionId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"sessionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userName"}},{"kind":"Field","name":{"kind":"Name","value":"userId"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}},{"kind":"Field","name":{"kind":"Name","value":"state"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"sessionId"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"LimitedUserAvatar"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LimitedUser"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}}]} as unknown as DocumentNode; export const OnViewerCommentsUpdatedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"OnViewerCommentsUpdated"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"target"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ViewerUpdateTrackingTarget"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectCommentsUpdated"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"target"},"value":{"kind":"Variable","name":{"kind":"Name","value":"target"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"comment"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"parent"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerCommentThread"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"LimitedUserAvatar"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LimitedUser"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ThreadCommentAttachment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"text"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"attachments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fileName"}},{"kind":"Field","name":{"kind":"Name","value":"fileType"}},{"kind":"Field","name":{"kind":"Name","value":"fileSize"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewerCommentsReplyItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"archived"}},{"kind":"Field","name":{"kind":"Name","value":"rawText"}},{"kind":"Field","name":{"kind":"Name","value":"text"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"doc"}}]}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ThreadCommentAttachment"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"FormUsersSelectItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LimitedUser"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewerCommentsListItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"rawText"}},{"kind":"Field","name":{"kind":"Name","value":"archived"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LimitedUserAvatar"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"viewedAt"}},{"kind":"Field","name":{"kind":"Name","value":"replies"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerCommentsReplyItem"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"replyAuthors"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"4"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FormUsersSelectItem"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"resources"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"resourceId"}},{"kind":"Field","name":{"kind":"Name","value":"resourceType"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewerCommentBubblesData"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"viewedAt"}},{"kind":"Field","name":{"kind":"Name","value":"viewerState"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewerCommentThread"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerCommentsListItem"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerCommentBubblesData"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewerCommentsReplyItem"}}]}}]} as unknown as DocumentNode; -export const LegacyBranchRedirectMetadataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"LegacyBranchRedirectMetadata"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"branchName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stream"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"branch"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"branchName"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]} as unknown as DocumentNode; -export const LegacyViewerCommitRedirectMetadataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"LegacyViewerCommitRedirectMetadata"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"commitId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stream"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"commit"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"commitId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"branch"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]}}]} as unknown as DocumentNode; -export const LegacyViewerStreamRedirectMetadataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"LegacyViewerStreamRedirectMetadata"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stream"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"commits"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"branch"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; -export const ResolveCommentLinkDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ResolveCommentLink"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"commentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"comment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"commentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"streamId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"LinkableComment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"LinkableComment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"viewerResources"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelId"}},{"kind":"Field","name":{"kind":"Name","value":"versionId"}},{"kind":"Field","name":{"kind":"Name","value":"objectId"}}]}}]}}]} as unknown as DocumentNode; +export const LegacyBranchRedirectMetadataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"LegacyBranchRedirectMetadata"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"branchName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelByName"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"branchName"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]} as unknown as DocumentNode; +export const LegacyViewerCommitRedirectMetadataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"LegacyViewerCommitRedirectMetadata"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"commitId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"version"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"commitId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]}}]} as unknown as DocumentNode; +export const LegacyViewerStreamRedirectMetadataDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"LegacyViewerStreamRedirectMetadata"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"versions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; +export const ResolveCommentLinkDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ResolveCommentLink"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"commentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"comment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"commentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"LinkableComment"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"LinkableComment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"viewerResources"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelId"}},{"kind":"Field","name":{"kind":"Name","value":"versionId"}},{"kind":"Field","name":{"kind":"Name","value":"objectId"}}]}}]}}]} as unknown as DocumentNode; export const AutomateFunctionPageDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AutomateFunctionPage"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"functionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"automateFunction"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"functionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateFunctionPage_AutomateFunction"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateFunctionPageHeader_Function"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"repo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"owner"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"releases"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateFunctionPageParametersDialog_AutomateFunctionRelease"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunctionRelease"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"inputSchema"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateFunctionPageInfo_AutomateFunction"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"repo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"owner"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"automationCount"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"releases"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"inputSchema"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"commitId"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateFunctionPageParametersDialog_AutomateFunctionRelease"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomationsFunctionsCard_AutomateFunction"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"isFeatured"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"repo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"owner"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateAutomationCreateDialogFunctionParametersStep_AutomateFunction"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"releases"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"inputSchema"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateAutomationCreateDialog_AutomateFunction"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomationsFunctionsCard_AutomateFunction"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateAutomationCreateDialogFunctionParametersStep_AutomateFunction"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateFunctionPage_AutomateFunction"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"supportedSourceApps"}},{"kind":"Field","name":{"kind":"Name","value":"tags"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateFunctionPageHeader_Function"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateFunctionPageInfo_AutomateFunction"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateAutomationCreateDialog_AutomateFunction"}},{"kind":"Field","name":{"kind":"Name","value":"creator"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode; export const AutomateFunctionsPageDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AutomateFunctionsPage"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"search"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}},"defaultValue":{"kind":"NullValue"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateFunctionsPageItems_Query"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateFunctionsPageHeader_Query"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomationsFunctionsCard_AutomateFunction"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"isFeatured"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"repo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"owner"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateAutomationCreateDialogFunctionParametersStep_AutomateFunction"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"releases"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"inputSchema"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateAutomationCreateDialog_AutomateFunction"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomationsFunctionsCard_AutomateFunction"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateAutomationCreateDialogFunctionParametersStep_AutomateFunction"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateFunctionCreateDialogTemplateStep_AutomateFunctionTemplate"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunctionTemplate"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"url"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateFunctionsPageItems_Query"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"automateFunctions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"20"}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"search"},"value":{"kind":"Variable","name":{"kind":"Name","value":"search"}}}]}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomationsFunctionsCard_AutomateFunction"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateAutomationCreateDialog_AutomateFunction"}}]}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateFunctionsPageHeader_Query"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"automateInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasAutomateGithubApp"}},{"kind":"Field","name":{"kind":"Name","value":"availableGithubOrgs"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"serverInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"automate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"availableFunctionTemplates"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateFunctionCreateDialogTemplateStep_AutomateFunctionTemplate"}}]}}]}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file diff --git a/packages/frontend-2/lib/server-management/graphql/mutations.ts b/packages/frontend-2/lib/server-management/graphql/mutations.ts index 5ce4d5fc3..0545d3fda 100644 --- a/packages/frontend-2/lib/server-management/graphql/mutations.ts +++ b/packages/frontend-2/lib/server-management/graphql/mutations.ts @@ -13,8 +13,10 @@ export const adminDeleteUserMutation = graphql(` `) export const adminDeleteProjectMutation = graphql(` - mutation AdminPanelDeleteProject($ids: [String!]) { - streamsDelete(ids: $ids) + mutation AdminPanelDeleteProject($ids: [String!]!) { + projectMutations { + batchDelete(ids: $ids) + } } `) diff --git a/packages/frontend-2/lib/viewer/graphql/queries.ts b/packages/frontend-2/lib/viewer/graphql/queries.ts index 17c754ab4..1c711148b 100644 --- a/packages/frontend-2/lib/viewer/graphql/queries.ts +++ b/packages/frontend-2/lib/viewer/graphql/queries.ts @@ -136,8 +136,8 @@ export const viewerLoadedThreadsQuery = graphql(` `) export const viewerRawObjectQuery = graphql(` - query Stream($streamId: String!, $objectId: String!) { - stream(id: $streamId) { + query ViewerRawProjectObject($projectId: String!, $objectId: String!) { + project(id: $projectId) { id object(id: $objectId) { id diff --git a/packages/frontend-2/middleware/redirects.global.ts b/packages/frontend-2/middleware/redirects.global.ts index ff261c400..28280d5e5 100644 --- a/packages/frontend-2/middleware/redirects.global.ts +++ b/packages/frontend-2/middleware/redirects.global.ts @@ -14,8 +14,8 @@ import { ViewerHashStateKeys } from '~/lib/viewer/composables/setup/urlHashState const legacyBranchMetadataQuery = graphql(` query LegacyBranchRedirectMetadata($streamId: String!, $branchName: String!) { - stream(id: $streamId) { - branch(name: $branchName) { + project(id: $streamId) { + modelByName(name: $branchName) { id } } @@ -24,10 +24,10 @@ const legacyBranchMetadataQuery = graphql(` const legacyViewerCommitMetadataQuery = graphql(` query LegacyViewerCommitRedirectMetadata($streamId: String!, $commitId: String!) { - stream(id: $streamId) { - commit(id: $commitId) { + project(id: $streamId) { + version(id: $commitId) { id - branch { + model { id } } @@ -37,13 +37,13 @@ const legacyViewerCommitMetadataQuery = graphql(` const legacyViewerStreamMetadataQuery = graphql(` query LegacyViewerStreamRedirectMetadata($streamId: String!) { - stream(id: $streamId) { + project(id: $streamId) { id - commits(limit: 1) { + versions(limit: 1) { totalCount items { id - branch { + model { id } } @@ -68,6 +68,7 @@ const adminPageRgx = /^\/admin\/?/ */ export default defineNuxtRouteMiddleware(async (to) => { + const logger = useLogger() const path = to.path const apollo = useApolloClientFromNuxt() const resourceBuilder = () => SpeckleViewer.ViewerRoute.resourceBuilder() @@ -91,23 +92,33 @@ export default defineNuxtRouteMiddleware(async (to) => { const resourceIdString = resourceIdStringBuilder.addObject(viewerId).toString() return navigateTo(modelRoute(viewerStreamId, resourceIdString, hashState)) } else { - const { data } = await apollo + const { data, errors } = await apollo .query({ query: legacyViewerCommitMetadataQuery, variables: { streamId: viewerStreamId, commitId: viewerId } }) .catch(convertThrowIntoFetchResult) - const branchId = data?.stream?.commit?.branch?.id + const branchId = data?.project?.version?.model?.id - return navigateTo( - branchId - ? modelRoute( - viewerStreamId, - resourceIdStringBuilder.addModel(branchId, viewerId).toString(), - hashState - ) - : projectRoute(viewerStreamId) - ) + if (branchId) { + return navigateTo( + modelRoute( + viewerStreamId, + resourceIdStringBuilder.addModel(branchId, viewerId).toString(), + hashState + ) + ) + } else { + logger.warn( + { + errors, + streamId: viewerStreamId, + commitId: viewerId + }, + "Couldn't resolve legacy viewer redirect commit metadata" + ) + return navigateTo(projectRoute(viewerStreamId)) + } } } @@ -131,6 +142,7 @@ export default defineNuxtRouteMiddleware(async (to) => { const branchName = to.query['branch'] as Optional // get first branch commit if (!streamId?.length) { + logger.warn('No stream ID provided for embed viewer redirect') return navigateTo(homeRoute) } @@ -141,27 +153,37 @@ export default defineNuxtRouteMiddleware(async (to) => { }) ) } else if (commitId?.length) { - const { data } = await apollo + const { data, errors } = await apollo .query({ query: legacyViewerCommitMetadataQuery, variables: { streamId, commitId } }) .catch(convertThrowIntoFetchResult) - const branchId = data?.stream?.commit?.branch?.id + const branchId = data?.project?.version?.model?.id - return navigateTo( - branchId - ? modelRoute( - streamId, - resourceBuilder().addModel(branchId, commitId).toString(), - { - [ViewerHashStateKeys.EmbedOptions]: JSON.stringify(embedOptions) - } - ) - : projectRoute(viewerStreamId) - ) + if (branchId) { + return navigateTo( + modelRoute( + streamId, + resourceBuilder().addModel(branchId, commitId).toString(), + { + [ViewerHashStateKeys.EmbedOptions]: JSON.stringify(embedOptions) + } + ) + ) + } else { + logger.warn( + { + errors, + streamId, + commitId + }, + "Couldn't resolve legacy commit embed redirect metadata" + ) + return navigateTo(projectRoute(streamId)) + } } else if (branchName?.length) { - const { data } = await apollo + const { data, errors } = await apollo .query({ query: legacyBranchMetadataQuery, variables: { @@ -171,44 +193,63 @@ export default defineNuxtRouteMiddleware(async (to) => { }) .catch(convertThrowIntoFetchResult) - return navigateTo( - data?.stream?.branch?.id - ? modelRoute( - streamId, - resourceBuilder().addModel(data.stream.branch.id).toString(), - { - [ViewerHashStateKeys.EmbedOptions]: JSON.stringify(embedOptions) - } - ) - : projectRoute(streamId) - ) + const branchId = data?.project?.modelByName?.id + if (branchId) { + return navigateTo( + modelRoute(streamId, resourceBuilder().addModel(branchId).toString(), { + [ViewerHashStateKeys.EmbedOptions]: JSON.stringify(embedOptions) + }) + ) + } else { + logger.warn( + { + errors, + streamId, + branchName: decodeURIComponent(branchName) + }, + "Couldn't resolve legacy branch embed redirect metadata" + ) + return navigateTo(projectRoute(streamId)) + } } else { - const { data } = await apollo + const { data, errors } = await apollo .query({ query: legacyViewerStreamMetadataQuery, variables: { streamId } }) .catch(convertThrowIntoFetchResult) - return navigateTo( - data?.stream?.commits?.items?.length && data.stream.commits.items[0].branch - ? modelRoute( - data.stream.id, - SpeckleViewer.ViewerRoute.resourceBuilder() - .addModel( - data.stream.commits.items[0].branch.id, - data.stream.commits.items[0].id - ) - .toString(), - { - [ViewerHashStateKeys.EmbedOptions]: JSON.stringify(embedOptions) - } - ) - : projectRoute(streamId) - ) + if ( + data?.project?.versions?.items?.length && + data.project.versions.items[0].model + ) { + return navigateTo( + modelRoute( + data.project.id, + SpeckleViewer.ViewerRoute.resourceBuilder() + .addModel( + data.project.versions.items[0].model.id, + data.project.versions.items[0].id + ) + .toString(), + { + [ViewerHashStateKeys.EmbedOptions]: JSON.stringify(embedOptions) + } + ) + ) + } else { + logger.warn( + { + errors, + streamId + }, + "Couldn't resolve legacy stream embed redirect metadata" + ) + return navigateTo(projectRoute(streamId)) + } } } const [, branchStreamId, branchName] = path.match(streamBranchPageRgx) || [] if (branchStreamId && branchName) { - const { data } = await apollo + const { data, errors } = await apollo .query({ query: legacyBranchMetadataQuery, variables: { @@ -217,13 +258,22 @@ export default defineNuxtRouteMiddleware(async (to) => { } }) .catch(convertThrowIntoFetchResult) - const branchId = data?.stream?.branch?.id + const branchId = data?.project?.modelByName?.id - return navigateTo( - branchId - ? modelVersionsRoute(branchStreamId, branchId) - : projectRoute(branchStreamId) - ) + if (branchId) { + return navigateTo(modelVersionsRoute(branchStreamId, branchId)) + } else { + logger.warn( + { + errors, + streamId: branchStreamId, + branchName: decodeURIComponent(branchName) + }, + "Couldn't resolve legacy branch redirect metadata" + ) + + return navigateTo(projectRoute(branchStreamId)) + } } const [, streamId] = path.match(streamPageRgx) || [] diff --git a/packages/frontend-2/middleware/thread.ts b/packages/frontend-2/middleware/thread.ts index bf027c250..3b37eacf4 100644 --- a/packages/frontend-2/middleware/thread.ts +++ b/packages/frontend-2/middleware/thread.ts @@ -5,8 +5,11 @@ import { getLinkToThread } from '~/lib/viewer/helpers/comments' const resolveLinkQuery = graphql(` query ResolveCommentLink($commentId: String!, $projectId: String!) { - comment(id: $commentId, streamId: $projectId) { - ...LinkableComment + project(id: $projectId) { + comment(id: $commentId) { + id + ...LinkableComment + } } } `) @@ -26,7 +29,7 @@ export default defineNuxtRouteMiddleware(async (to) => { }) .catch(convertThrowIntoFetchResult) - const comment = res.data?.comment + const comment = res.data?.project?.comment if (!comment) { return abortNavigation( createError({ diff --git a/packages/server/assets/accessrequests/typedefs/accessrequests.graphql b/packages/server/assets/accessrequests/typedefs/accessrequests.graphql index f7b779c47..4353cc3de 100644 --- a/packages/server/assets/accessrequests/typedefs/accessrequests.graphql +++ b/packages/server/assets/accessrequests/typedefs/accessrequests.graphql @@ -5,10 +5,19 @@ extend type Query { streamAccessRequest(streamId: String!): StreamAccessRequest @hasServerRole(role: SERVER_GUEST) @deprecated( - reason: "Part of the old API surface and will be removed in the future." + reason: "Part of the old API surface and will be removed in the future. Use User.projectAccessRequest instead." ) } +extend type User { + """ + Get pending project access request, that the user made + """ + projectAccessRequest(projectId: String!): ProjectAccessRequest + @hasServerRole(role: SERVER_GUEST) + @isOwner +} + extend type Stream { """ Pending stream access requests @@ -16,10 +25,33 @@ extend type Stream { pendingAccessRequests: [StreamAccessRequest!] @hasStreamRole(role: STREAM_OWNER) @deprecated( - reason: "Part of the old API surface and will be removed in the future." + reason: "Part of the old API surface and will be removed in the future. Use Project.pendingAccessRequests instead." ) } +extend type Project { + """ + Pending project access requests + """ + pendingAccessRequests: [ProjectAccessRequest!] @hasStreamRole(role: STREAM_OWNER) +} + +type ProjectAccessRequestMutations { + """ + Request access to a specific project + """ + create(projectId: String!): ProjectAccessRequest! + + """ + Accept or decline a project access request. Must be a project owner to invoke this. + """ + use( + requestId: String! + accept: Boolean! + role: StreamRole! = STREAM_CONTRIBUTOR + ): Project! +} + extend type Mutation { """ Accept or decline a stream access request. Must be a stream owner to invoke this. @@ -32,7 +64,7 @@ extend type Mutation { @hasServerRole(role: SERVER_GUEST) @hasScope(scope: "users:invite") @deprecated( - reason: "Part of the old API surface and will be removed in the future." + reason: "Part of the old API surface and will be removed in the future. Use ProjectAccessRequestMutations.use instead." ) """ @@ -42,10 +74,19 @@ extend type Mutation { @hasServerRole(role: SERVER_GUEST) @hasScope(scope: "users:invite") @deprecated( - reason: "Part of the old API surface and will be removed in the future." + reason: "Part of the old API surface and will be removed in the future. Use ProjectAccessRequestMutations.create instead." ) } +extend type ProjectMutations { + """ + Access request related mutations + """ + accessRequestMutations: ProjectAccessRequestMutations! + @hasServerRole(role: SERVER_GUEST) + @hasScope(scope: "users:invite") +} + """ Created when a user requests to become a contributor on a stream """ @@ -60,3 +101,18 @@ type StreamAccessRequest { stream: Stream! createdAt: DateTime! } + +""" +Created when a user requests to become a contributor on a project +""" +type ProjectAccessRequest { + id: ID! + requester: LimitedUser! + requesterId: String! + projectId: String! + """ + Can only be selected if authed user has proper access + """ + project: Project! + createdAt: DateTime! +} diff --git a/packages/server/assets/comments/typedefs/comments.gql b/packages/server/assets/comments/typedefs/comments.gql index 11b828307..af6b2da82 100644 --- a/packages/server/assets/comments/typedefs/comments.gql +++ b/packages/server/assets/comments/typedefs/comments.gql @@ -1,8 +1,9 @@ extend type Query { comment(id: String!, streamId: String!): Comment @deprecated( - reason: "Part of the old API surface and will be removed in the future." + reason: "Part of the old API surface and will be removed in the future. Use Project.comment instead." ) + """ This query can be used in the following ways: - get all the comments for a stream: **do not pass in any resource identifiers**. @@ -27,6 +28,11 @@ extend type Project { limit: Int! = 25 filter: ProjectCommentsFilter ): ProjectCommentCollection! + + """ + Get specific project comment/thread by ID + """ + comment(id: String!): Comment } extend type Version { diff --git a/packages/server/assets/core/typedefs/branchesAndCommits.graphql b/packages/server/assets/core/typedefs/branchesAndCommits.graphql index 8e61c50bb..189de297b 100644 --- a/packages/server/assets/core/typedefs/branchesAndCommits.graphql +++ b/packages/server/assets/core/typedefs/branchesAndCommits.graphql @@ -13,7 +13,7 @@ extend type Stream { ) branch(name: String = "main"): Branch @deprecated( - reason: "Part of the old API surface and will be removed in the future. Use Project.model instead." + reason: "Part of the old API surface and will be removed in the future. Use Project.model or Project.modelByName instead." ) } @@ -106,7 +106,7 @@ extend type Mutation { @hasServerRole(role: SERVER_GUEST) @hasScope(scope: "streams:write") @deprecated( - reason: "Part of the old API surface and will be removed in the future." + reason: "Part of the old API surface and will be removed in the future. Use VersionMutations.create instead." ) commitUpdate(commit: CommitUpdateInput!): Boolean! @@ -120,7 +120,7 @@ extend type Mutation { @hasServerRole(role: SERVER_GUEST) @hasScope(scope: "streams:read") @deprecated( - reason: "Part of the old API surface and will be removed in the future." + reason: "Part of the old API surface and will be removed in the future. Use VersionMutations.markReceived instead." ) commitDelete(commit: CommitDeleteInput!): Boolean! diff --git a/packages/server/assets/core/typedefs/modelsAndVersions.graphql b/packages/server/assets/core/typedefs/modelsAndVersions.graphql index 523291221..a10b78598 100644 --- a/packages/server/assets/core/typedefs/modelsAndVersions.graphql +++ b/packages/server/assets/core/typedefs/modelsAndVersions.graphql @@ -40,6 +40,11 @@ extend type Project { Retrieve a specific project version by its ID """ version(id: String!): Version + + """ + Retrieve a specific project model by its ID + """ + modelByName(name: String!): Model! } extend type User { @@ -174,10 +179,29 @@ input UpdateVersionInput { message: String } +input CreateVersionInput { + projectId: String! + modelId: String! + objectId: String! + message: String + sourceApplication: String + totalChildrenCount: Int + parents: [String!] +} + +input MarkReceivedVersionInput { + projectId: String! + versionId: String! + sourceApplication: String! + message: String +} + type VersionMutations { moveToModel(input: MoveVersionsInput!): Model! delete(input: DeleteVersionsInput!): Boolean! update(input: UpdateVersionInput!): Version! + create(input: CreateVersionInput!): Version! + markReceived(input: MarkReceivedVersionInput!): Boolean! } extend type Mutation { diff --git a/packages/server/assets/core/typedefs/objects.graphql b/packages/server/assets/core/typedefs/objects.graphql index 3118b318a..1905d8d79 100644 --- a/packages/server/assets/core/typedefs/objects.graphql +++ b/packages/server/assets/core/typedefs/objects.graphql @@ -1,14 +1,18 @@ extend type Stream { object(id: String!): Object @deprecated( - reason: "Part of the old API surface and will be removed in the future." + reason: "Part of the old API surface and will be removed in the future. Use Project.object instead." ) } +extend type Project { + object(id: String!): Object +} + type Object { id: String! speckleType: String - applicationId: String + applicationId: String @deprecated(reason: "Not implemented.") createdAt: DateTime totalChildrenCount: Int """ @@ -32,11 +36,13 @@ type Object { type ObjectCollection { totalCount: Int! cursor: String - objects: [Object]! + objects: [Object!]! } extend type Mutation { - objectCreate(objectInput: ObjectCreateInput!): [String]! + objectCreate(objectInput: ObjectCreateInput!): [String!]! + @hasServerRole(role: SERVER_GUEST) + @hasScope(scope: "streams:write") @deprecated( reason: "Part of the old API surface and will be removed in the future." ) diff --git a/packages/server/assets/core/typedefs/projects.graphql b/packages/server/assets/core/typedefs/projects.graphql index 2249a29f8..77c1e70fe 100644 --- a/packages/server/assets/core/typedefs/projects.graphql +++ b/packages/server/assets/core/typedefs/projects.graphql @@ -99,6 +99,11 @@ type ProjectMutations { """ delete(id: String!): Boolean! @hasServerRole(role: SERVER_USER) + """ + Batch delete projects + """ + batchDelete(ids: [String!]!): Boolean! @hasServerRole(role: SERVER_ADMIN) + """ Updates an existing project """ diff --git a/packages/server/assets/core/typedefs/streams.graphql b/packages/server/assets/core/typedefs/streams.graphql index fb1662215..57f425cfd 100644 --- a/packages/server/assets/core/typedefs/streams.graphql +++ b/packages/server/assets/core/typedefs/streams.graphql @@ -206,7 +206,7 @@ extend type Mutation { streamsDelete(ids: [String!]): Boolean! @hasServerRole(role: SERVER_ADMIN) @deprecated( - reason: "Part of the old API surface and will be removed in the future." + reason: "Part of the old API surface and will be removed in the future. Use ProjectMutations.batchDelete instead." ) """ diff --git a/packages/server/codegen.yml b/packages/server/codegen.yml index 8341f73f1..a16b12af1 100644 --- a/packages/server/codegen.yml +++ b/packages/server/codegen.yml @@ -13,11 +13,14 @@ generates: Stream: '@/modules/core/helpers/graphTypes#StreamGraphQLReturn' Commit: '@/modules/core/helpers/graphTypes#CommitGraphQLReturn' Project: '@/modules/core/helpers/graphTypes#ProjectGraphQLReturn' + Object: '@/modules/core/helpers/graphTypes#ObjectGraphQLReturn' Version: '@/modules/core/helpers/graphTypes#VersionGraphQLReturn' ServerInvite: '@/modules/core/helpers/graphTypes#ServerInviteGraphQLReturnType' Model: '@/modules/core/helpers/graphTypes#ModelGraphQLReturn' ModelsTreeItem: '@/modules/core/helpers/graphTypes#ModelsTreeItemGraphQLReturn' StreamAccessRequest: '@/modules/accessrequests/helpers/graphTypes#StreamAccessRequestGraphQLReturn' + ProjectAccessRequest: '@/modules/accessrequests/helpers/graphTypes#ProjectAccessRequestGraphQLReturn' + ProjectAccessRequestMutations: '@/modules/core/helpers/graphTypes#MutationsObjectGraphQLReturn' LimitedUser: '@/modules/core/helpers/graphTypes#LimitedUserGraphQLReturn' ActiveUserMutations: '@/modules/core/helpers/graphTypes#MutationsObjectGraphQLReturn' ProjectMutations: '@/modules/core/helpers/graphTypes#MutationsObjectGraphQLReturn' diff --git a/packages/server/modules/accessrequests/graph/resolvers/index.ts b/packages/server/modules/accessrequests/graph/resolvers/index.ts index d63a054cc..cf1d6e8f4 100644 --- a/packages/server/modules/accessrequests/graph/resolvers/index.ts +++ b/packages/server/modules/accessrequests/graph/resolvers/index.ts @@ -1,7 +1,12 @@ +import { AccessRequestType } from '@/modules/accessrequests/repositories' import { + getPendingProjectRequests, getPendingStreamRequests, + getUserProjectAccessRequest, getUserStreamAccessRequest, + processPendingProjectRequest, processPendingStreamRequest, + requestProjectAccess, requestStreamAccess } from '@/modules/accessrequests/services/stream' import { Resolvers } from '@/modules/core/graph/generated/graphql' @@ -35,6 +40,35 @@ const resolvers: Resolvers = { return await requestStreamAccess(userId, streamId) } }, + ProjectMutations: { + accessRequestMutations: () => ({}) + }, + ProjectAccessRequestMutations: { + async create(_parent, args, ctx) { + const { userId } = ctx + const { projectId } = args + return await requestProjectAccess(userId!, projectId) + }, + async use(_parent, args, ctx) { + const { userId, resourceAccessRules } = ctx + const { requestId, accept, role } = args + + const usedReq = await processPendingProjectRequest( + userId!, + requestId, + accept, + mapStreamRoleToValue(role), + resourceAccessRules + ) + + const project = await ctx.loaders.streams.getStream.load(usedReq.resourceId) + if (!project) { + throw new LogicError('Unexpectedly unable to find request project') + } + + return project + } + }, Query: { async streamAccessRequest(_, args, ctx) { const { streamId } = args @@ -44,12 +78,26 @@ const resolvers: Resolvers = { return await getUserStreamAccessRequest(userId, streamId) } }, + User: { + async projectAccessRequest(parent, args) { + const { id: userId } = parent + const { projectId } = args + + return await getUserProjectAccessRequest(userId, projectId) + } + }, Stream: { async pendingAccessRequests(parent) { const { id } = parent return await getPendingStreamRequests(id) } }, + Project: { + async pendingAccessRequests(parent) { + const { id } = parent + return await getPendingProjectRequests(id) + } + }, StreamAccessRequest: { async requester(parent, _args, ctx) { const { requesterId } = parent @@ -77,6 +125,45 @@ const resolvers: Resolvers = { return stream } + }, + ProjectAccessRequest: { + async requester(parent, _args, ctx) { + const { requesterId } = parent + const user = await ctx.loaders.users.getUser.load(requesterId) + if (!user) { + throw new LogicError('Unable to find requester') + } + + return user + }, + async projectId(parent) { + const { resourceId, resourceType } = parent + if (resourceType !== AccessRequestType.Stream) { + throw new LogicError('Unexpectedly returned invalid resource type') + } + + return resourceId + }, + async project(parent, _args, ctx) { + const { resourceId, resourceType } = parent + if (resourceType !== AccessRequestType.Stream) { + throw new LogicError('Unexpectedly returned invalid resource type') + } + + const project = await ctx.loaders.streams.getStream.load(resourceId) + if (!project) { + throw new LogicError('Unable to find request project') + } + + await validateStreamAccess( + ctx.userId, + project.id, + Roles.Stream.Reviewer, + ctx.resourceAccessRules + ) + + return project + } } } diff --git a/packages/server/modules/accessrequests/helpers/graphTypes.ts b/packages/server/modules/accessrequests/helpers/graphTypes.ts index 9ac35d112..2f1946a80 100644 --- a/packages/server/modules/accessrequests/helpers/graphTypes.ts +++ b/packages/server/modules/accessrequests/helpers/graphTypes.ts @@ -1,6 +1,9 @@ +import { StreamAccessRequestRecord } from '@/modules/accessrequests/repositories' import { StreamAccessRequest } from '@/modules/core/graph/generated/graphql' export type StreamAccessRequestGraphQLReturn = Omit< StreamAccessRequest, 'requester' | 'stream' > + +export type ProjectAccessRequestGraphQLReturn = StreamAccessRequestRecord diff --git a/packages/server/modules/accessrequests/services/stream.ts b/packages/server/modules/accessrequests/services/stream.ts index f5126abf9..a1b03a719 100644 --- a/packages/server/modules/accessrequests/services/stream.ts +++ b/packages/server/modules/accessrequests/services/stream.ts @@ -12,7 +12,8 @@ import { getPendingAccessRequest, getPendingAccessRequests, getUsersPendingAccessRequest, - ServerAccessRequestRecord + ServerAccessRequestRecord, + StreamAccessRequestRecord } from '@/modules/accessrequests/repositories' import { StreamInvalidAccessError } from '@/modules/core/errors/stream' import { TokenResourceIdentifier } from '@/modules/core/domain/tokens/types' @@ -36,44 +37,52 @@ function buildStreamAccessRequestGraphQLReturn( } } +export async function getUserProjectAccessRequest( + userId: string, + projectId: string +): Promise> { + const req = await getUsersPendingAccessRequest( + userId, + AccessRequestType.Stream, + projectId + ) + return req || null +} + export async function getUserStreamAccessRequest( userId: string, streamId: string ): Promise> { - const req = await getUsersPendingAccessRequest( - userId, - AccessRequestType.Stream, - streamId - ) + const req = await getUserProjectAccessRequest(userId, streamId) if (!req) return null return buildStreamAccessRequestGraphQLReturn(req) } /** - * Create new stream access request + * Create new project access request */ -export async function requestStreamAccess(userId: string, streamId: string) { +export async function requestProjectAccess(userId: string, projectId: string) { const [stream, existingRequest] = await Promise.all([ - getStream({ userId, streamId }), - getUserStreamAccessRequest(userId, streamId) + getStream({ userId, streamId: projectId }), + getUserStreamAccessRequest(userId, projectId) ]) if (existingRequest) { throw new AccessRequestCreationError( - 'User already has a pending access request for this stream' + 'User already has a pending access request for this resource' ) } if (!stream) { throw new AccessRequestCreationError( - "Can't request access to a non-existant stream" + "Can't request access to a non-existant resource" ) } if (stream.role) { throw new AccessRequestCreationError( - 'User already has access to the specified stream' + 'User already has access to the specified resource' ) } @@ -81,23 +90,40 @@ export async function requestStreamAccess(userId: string, streamId: string) { id: generateId(), requesterId: userId, resourceType: AccessRequestType.Stream, - resourceId: streamId + resourceId: projectId }) await AccessRequestsEmitter.emit(AccessRequestsEmitter.events.Created, { request: req }) + return req +} + +/** + * Create new stream access request + */ +export async function requestStreamAccess(userId: string, streamId: string) { + const req = await requestProjectAccess(userId, streamId) return buildStreamAccessRequestGraphQLReturn(req) } +/** + * Get pending project access requests + */ +export async function getPendingProjectRequests( + projectId: string +): Promise { + return await getPendingAccessRequests(AccessRequestType.Stream, projectId) +} + /** * Get pending stream access requests */ export async function getPendingStreamRequests( streamId: string ): Promise { - const reqs = await getPendingAccessRequests(AccessRequestType.Stream, streamId) + const reqs = await getPendingProjectRequests(streamId) return reqs.map(buildStreamAccessRequestGraphQLReturn) } @@ -152,4 +178,8 @@ export async function processPendingStreamRequest( approved: accept ? { role } : undefined, finalizedBy: userId }) + + return req } + +export const processPendingProjectRequest = processPendingStreamRequest diff --git a/packages/server/modules/accessrequests/tests/projectAccessRequests.spec.ts b/packages/server/modules/accessrequests/tests/projectAccessRequests.spec.ts new file mode 100644 index 000000000..b98a73c24 --- /dev/null +++ b/packages/server/modules/accessrequests/tests/projectAccessRequests.spec.ts @@ -0,0 +1,417 @@ +import { + deleteRequestById, + getPendingAccessRequest +} from '@/modules/accessrequests/repositories' +import { requestProjectAccess } from '@/modules/accessrequests/services/stream' +import { ActionTypes } from '@/modules/activitystream/helpers/types' +import { + ServerAccessRequests, + StreamActivity, + Streams, + Users +} from '@/modules/core/dbSchema' +import { StreamAccessUpdateError } from '@/modules/core/errors/stream' +import { mapStreamRoleToValue } from '@/modules/core/helpers/graphTypes' +import { Roles } from '@/modules/core/helpers/mainConstants' +import { getStreamCollaborators } from '@/modules/core/repositories/streams' +import { + addOrUpdateStreamCollaborator, + removeStreamCollaborator +} from '@/modules/core/services/streams/streamAccessService' +import { NotificationType } from '@/modules/notifications/helpers/types' +import { BasicTestUser, createTestUsers } from '@/test/authHelper' +import { + CreateProjectAccessRequestDocument, + GetActiveUserFullProjectAccessRequestDocument, + GetActiveUserProjectAccessRequestDocument, + GetPendingProjectAccessRequestsDocument, + StreamRole, + UseProjectAccessRequestDocument +} from '@/test/graphql/generated/graphql' +import { testApolloServer, TestApolloServer } from '@/test/graphqlHelper' +import { truncateTables } from '@/test/hooks' +import { EmailSendingServiceMock } from '@/test/mocks/global' +import { + buildNotificationsStateTracker, + NotificationsStateManager +} from '@/test/notificationsHelper' +import { getStreamActivities } from '@/test/speckle-helpers/activityStreamHelper' +import { BasicTestStream, createTestStreams } from '@/test/speckle-helpers/streamHelper' +import { expect } from 'chai' +import { noop } from 'lodash' + +const isNotCollaboratorError = (e: unknown) => + e instanceof StreamAccessUpdateError && + e.message.includes('User is not a stream collaborator') + +const createReqAndGetId = async (userId: string, streamId: string) => { + const createReqRes = await requestProjectAccess(userId, streamId) + return createReqRes.id +} + +const cleanup = async () => { + await truncateTables([Streams.name, ServerAccessRequests.name, Users.name]) +} + +describe('Project access requests', () => { + let apollo: TestApolloServer + let notificationsStateManager: NotificationsStateManager + + const me: BasicTestUser = { + name: 'hello itsa me', + email: '', + id: '' + } + + const otherGuy: BasicTestUser = { + name: 'and im the other guy, hi!', + email: '', + id: '' + } + + const anotherGuy: BasicTestUser = { + name: 'and im another guy lol', + email: '', + id: '' + } + + const otherGuysPrivateStream: BasicTestStream = { + name: 'other guys test stream #1', + isPublic: false, + ownerId: '', + id: '' + } + + const otherGuysPublicStream: BasicTestStream = { + name: 'other guys public test stream #2', + isPublic: true, + ownerId: '', + id: '' + } + + const myPrivateStream: BasicTestStream = { + name: 'this is my private stream #1', + isPublic: false, + ownerId: '', + id: '' + } + + before(async () => { + await cleanup() + await createTestUsers([me, otherGuy, anotherGuy]) + await createTestStreams([ + [otherGuysPrivateStream, otherGuy], + [otherGuysPublicStream, otherGuy], + [myPrivateStream, me] + ]) + apollo = await testApolloServer({ + authUserId: me.id + }) + notificationsStateManager = buildNotificationsStateTracker() + }) + + after(async () => { + notificationsStateManager.destroy() + }) + + const createReq = async (projectId: string) => + await apollo.execute(CreateProjectAccessRequestDocument, { + projectId + }) + + const getActiveUserReq = async (projectId: string) => + await apollo.execute(GetActiveUserProjectAccessRequestDocument, { + projectId + }) + + const getPendingProjectReqs = async (projectId: string) => + await apollo.execute(GetPendingProjectAccessRequestsDocument, { + projectId + }) + + const getFullActiveUserAccessRequest = async (projectId: string) => + await apollo.execute(GetActiveUserFullProjectAccessRequestDocument, { + projectId + }) + + const useReq = async ( + requestId: string, + accept: boolean, + role: StreamRole = StreamRole.StreamContributor + ) => + await apollo.execute(UseProjectAccessRequestDocument, { + requestId, + accept, + role + }) + + describe('when being created', () => { + beforeEach(async () => { + await truncateTables([ServerAccessRequests.name, StreamActivity.name]) + }) + + afterEach(async () => { + // Ensure me doesnt have any roles on stream1 + await removeStreamCollaborator(otherGuysPrivateStream.id, me.id, me.id).catch( + (e) => { + if (!isNotCollaboratorError(e)) throw e + } + ) + }) + + it('operation succeeds', async () => { + const sendEmailCall = EmailSendingServiceMock.hijackFunction( + 'sendEmail', + async () => true + ) + + const waitForAck = notificationsStateManager.waitForAck( + (e) => e.result?.type === NotificationType.NewStreamAccessRequest + ) + + const results = await createReq(otherGuysPrivateStream.id) + + // req gets created + expect(results).to.not.haveGraphQLErrors() + expect(results.data?.projectMutations.accessRequestMutations.create.id).to.be.ok + expect(results.data?.projectMutations.accessRequestMutations.create.createdAt).to + .be.ok + expect(results.data?.projectMutations.accessRequestMutations.create.requesterId) + .to.be.ok + expect( + results.data?.projectMutations.accessRequestMutations.create.requester.id + ).to.eq(results.data?.projectMutations.accessRequestMutations.create.requesterId) + expect(results.data?.projectMutations.accessRequestMutations.create.projectId).to + .be.ok + + await waitForAck + + // email gets sent out + expect(sendEmailCall.args?.[0]?.[0]).to.be.ok + const emailParams = sendEmailCall.args[0][0] + + expect(emailParams.subject).to.contain('A user requested access to your project') + expect(emailParams.html).to.be.ok + expect(emailParams.text).to.be.ok + expect(emailParams.to).to.eq(otherGuy.email) + + // activity stream item inserted + const streamActivity = await getStreamActivities(otherGuysPrivateStream.id, { + actionType: ActionTypes.Stream.AccessRequestSent, + userId: me.id + }) + expect(streamActivity).to.have.lengthOf(1) + }) + + it('operation fails if request already exists', async () => { + const firstResults = await createReq(otherGuysPrivateStream.id) + expect(firstResults).to.not.haveGraphQLErrors() + expect(firstResults.data?.projectMutations.accessRequestMutations.create.id).to.be + .ok + + const secondResults = await createReq(otherGuysPrivateStream.id) + expect(secondResults).to.haveGraphQLErrors('already has a pending access request') + expect(secondResults.data?.projectMutations.accessRequestMutations.create.id).to + .be.not.ok + }) + + it('operation fails if stream is nonexistant', async () => { + const secondResults = await createReq('abcdef123') + expect(secondResults).to.haveGraphQLErrors('non-existant resource') + expect(secondResults.data?.projectMutations.accessRequestMutations.create.id).to + .be.not.ok + }) + + it('operation fails if user already has a role on the stream', async () => { + await addOrUpdateStreamCollaborator( + otherGuysPrivateStream.id, + me.id, + Roles.Stream.Contributor, + otherGuy.id + ) + + const secondResults = await createReq(otherGuysPrivateStream.id) + expect(secondResults).to.haveGraphQLErrors('user already has access') + expect(secondResults.data?.projectMutations.accessRequestMutations.create.id).to + .be.not.ok + }) + }) + + describe('when being read', () => { + let myRequestId: string + // eslint-disable-next-line @typescript-eslint/no-unused-vars + let myPublicReqId: string + // eslint-disable-next-line @typescript-eslint/no-unused-vars + let anotherGuysRequestId: string + + beforeEach(async () => { + await truncateTables([ServerAccessRequests.name]) + + const [myNewReqId, anotherGuysNewReqId, myNewPublicReqId] = await Promise.all([ + createReqAndGetId(me.id, otherGuysPrivateStream.id), + createReqAndGetId(anotherGuy.id, otherGuysPrivateStream.id), + createReqAndGetId(me.id, otherGuysPublicStream.id) + ]) + myRequestId = myNewReqId + anotherGuysRequestId = anotherGuysNewReqId + myPublicReqId = myNewPublicReqId + }) + + it('returns the request correctly', async () => { + const results = await getActiveUserReq(otherGuysPrivateStream.id) + expect(results).to.not.haveGraphQLErrors() + expect(results.data?.activeUser?.projectAccessRequest?.id).to.eq(myRequestId) + expect(results.data?.activeUser?.projectAccessRequest?.createdAt).to.be.ok + expect(results.data?.activeUser?.projectAccessRequest?.requesterId).to.be.ok + expect(results.data?.activeUser?.projectAccessRequest?.requester.id).to.eq( + results.data?.activeUser?.projectAccessRequest?.requesterId + ) + expect(results.data?.activeUser?.projectAccessRequest?.projectId).to.be.ok + }) + + it('returns null if no req found', async () => { + await deleteRequestById(myRequestId) + + const results = await getActiveUserReq(otherGuysPrivateStream.id) + expect(results).to.not.haveGraphQLErrors() + expect(results.data?.activeUser?.projectAccessRequest).to.eq(null) + }) + + it('throws error if attempting to read private stream metadata before has access to it', async () => { + const results = await getFullActiveUserAccessRequest(otherGuysPrivateStream.id) + + expect(results).to.haveGraphQLErrors( + 'User does not have required access to stream' + ) + }) + + it('doesnt throw if attempting to read stream metadata on accessible stream', async () => { + const results = await getFullActiveUserAccessRequest(otherGuysPublicStream.id) + + expect(results).to.not.haveGraphQLErrors() + expect(results.data?.activeUser?.projectAccessRequest?.project.id).to.be.ok + }) + }) + + describe('when being read from a stream', () => { + before(async () => { + await truncateTables([ServerAccessRequests.name]) + + await addOrUpdateStreamCollaborator( + otherGuysPublicStream.id, + me.id, + Roles.Stream.Contributor, + otherGuy.id + ) + await Promise.all([ + createReqAndGetId(otherGuy.id, myPrivateStream.id), + createReqAndGetId(anotherGuy.id, myPrivateStream.id) + ]) + }) + + after(async () => { + await removeStreamCollaborator(otherGuysPublicStream.id, me.id, me.id).catch(noop) + }) + + it(`operation fails if reading from a non-owned stream`, async () => { + const results = await getPendingProjectReqs(otherGuysPublicStream.id) + expect(results).to.haveGraphQLErrors('not authorized') + expect(results.data?.project?.pendingAccessRequests).to.be.not.ok + expect(results.data?.project?.id).to.be.ok + }) + + it('operation succeeds', async () => { + const results = await getPendingProjectReqs(myPrivateStream.id) + expect(results).to.not.haveGraphQLErrors() + + expect(results.data?.project?.pendingAccessRequests).to.have.lengthOf(2) + + for (const pendingReq of results.data!.project!.pendingAccessRequests!) { + expect(pendingReq.id).to.be.ok + expect(pendingReq.createdAt).to.be.ok + expect(pendingReq.requesterId).to.be.ok + expect(pendingReq.projectId).to.be.ok + expect(pendingReq.project.id).to.eq(results.data!.project!.id) + expect(pendingReq.requester.id).to.eq(pendingReq.requesterId) + expect([otherGuy.id, anotherGuy.id].includes(pendingReq.requesterId)).to.be.true + } + }) + }) + + describe('when being processed', () => { + let validReqId: string + + beforeEach(async () => { + await truncateTables([ServerAccessRequests.name, StreamActivity.name]) + await removeStreamCollaborator( + myPrivateStream.id, + otherGuy.id, + otherGuy.id + ).catch((e) => { + if (!isNotCollaboratorError(e)) throw e + }) + validReqId = await createReqAndGetId(otherGuy.id, myPrivateStream.id) + }) + + it('processing fails when pointing to nonexistant req', async () => { + const results = await useReq('abcd', true) + expect(results).to.haveGraphQLErrors('no request with this id exists') + expect(results.data?.projectMutations.accessRequestMutations.use).to.be.not.ok + }) + + it('processing fails when pointing to a req the user doesnt have access to', async () => { + const inaccessibleReqId = await createReqAndGetId( + anotherGuy.id, + otherGuysPrivateStream.id + ) + + const results = await useReq(inaccessibleReqId, true) + expect(results).to.haveGraphQLErrors('you must own the stream') + expect(results.data?.projectMutations.accessRequestMutations.use).to.be.not.ok + }) + + const validProcessingDataSet = [ + { display: 'declining', accept: false }, + { display: 'approving', accept: true }, + { + display: 'approving with custom role', + accept: true, + role: StreamRole.StreamReviewer + } + ] + validProcessingDataSet.forEach(({ display, accept, role }) => { + it(`${display} works`, async () => { + const results = await useReq(validReqId, accept, role) + expect(results).to.not.haveGraphQLErrors() + expect(results.data?.projectMutations.accessRequestMutations.use).to.be.ok + + // req should be deleted + const req = await getPendingAccessRequest(validReqId) + expect(req).to.not.be.ok + + // activity stream item should be inserted + if (accept) { + const streamActivity = await getStreamActivities(myPrivateStream.id, { + actionType: ActionTypes.Stream.PermissionsAdd, + userId: me.id + }) + expect(streamActivity).to.have.lengthOf(1) + + const collaborators = await getStreamCollaborators(myPrivateStream.id) + const newCollaborator = collaborators.find((c) => c.id === otherGuy.id) + + expect(newCollaborator).to.be.ok + expect(newCollaborator?.streamRole).to.eq( + role ? mapStreamRoleToValue(role) : Roles.Stream.Contributor + ) + } else { + const streamActivity = await getStreamActivities(myPrivateStream.id, { + actionType: ActionTypes.Stream.AccessRequestDeclined, + userId: me.id + }) + expect(streamActivity).to.have.lengthOf(1) + } + }) + }) + }) +}) diff --git a/packages/server/modules/accessrequests/tests/streamAccessRequests.spec.ts b/packages/server/modules/accessrequests/tests/streamAccessRequests.spec.ts index dda4e9481..2fe6c5cc0 100644 --- a/packages/server/modules/accessrequests/tests/streamAccessRequests.spec.ts +++ b/packages/server/modules/accessrequests/tests/streamAccessRequests.spec.ts @@ -194,7 +194,7 @@ describe('Stream access requests', () => { it('operation fails if stream is nonexistant', async () => { const secondResults = await createReq('abcdef123') - expect(secondResults).to.haveGraphQLErrors('non-existant stream') + expect(secondResults).to.haveGraphQLErrors('non-existant resource') expect(secondResults.data?.streamAccessRequestCreate.id).to.be.not.ok }) diff --git a/packages/server/modules/comments/graph/resolvers/comments.js b/packages/server/modules/comments/graph/resolvers/comments.js index fdc4addf6..fd60bbc71 100644 --- a/packages/server/modules/comments/graph/resolvers/comments.js +++ b/packages/server/modules/comments/graph/resolvers/comments.js @@ -5,7 +5,6 @@ const { getStream } = require('@/modules/core/services/streams') const { Roles } = require('@/modules/core/helpers/mainConstants') const { - getComment, getComments, getResourceCommentCount, createComment, @@ -15,6 +14,7 @@ const { editComment, streamResourceCheck } = require('@/modules/comments/services/index') +const { getComment } = require('@/modules/comments/repositories/comments') const { ensureCommentSchema } = require('@/modules/comments/services/commentTextService') @@ -62,19 +62,27 @@ const { convertLegacyDataToState } = require('@/modules/comments/services/data') +const getStreamComment = async ({ streamId, commentId }, ctx) => { + await authorizeProjectCommentsAccess({ + projectId: streamId, + authCtx: ctx + }) + + const comment = await getComment({ id: commentId, userId: ctx.userId }) + if (comment.streamId !== streamId) + throw new ApolloForbiddenError('You do not have access to this comment.') + + return comment +} + /** @type {import('@/modules/core/graph/generated/graphql').Resolvers} */ module.exports = { Query: { - async comment(parent, args, context) { - await authorizeProjectCommentsAccess({ - projectId: args.streamId, - authCtx: context - }) - - const comment = await getComment({ id: args.id, userId: context.userId }) - if (comment.streamId !== args.streamId) - throw new ApolloForbiddenError('You do not have access to this comment.') - return comment + async comment(_parent, args, context) { + return await getStreamComment( + { streamId: args.streamId, commentId: args.id }, + context + ) }, async comments(parent, args, context) { @@ -210,6 +218,12 @@ module.exports = { threadsOnly: true } }) + }, + async comment(parent, args, context) { + return await getStreamComment( + { streamId: parent.id, commentId: args.id }, + context + ) } }, Version: { diff --git a/packages/server/modules/comments/tests/projectComments.spec.ts b/packages/server/modules/comments/tests/projectComments.spec.ts new file mode 100644 index 000000000..44382bfd7 --- /dev/null +++ b/packages/server/modules/comments/tests/projectComments.spec.ts @@ -0,0 +1,91 @@ +import { BasicTestUser, createTestUsers } from '@/test/authHelper' +import { + CreateCommentInput, + CreateProjectCommentDocument +} from '@/test/graphql/generated/graphql' +import { testApolloServer, TestApolloServer } from '@/test/graphqlHelper' +import { beforeEachContext } from '@/test/hooks' +import { + BasicTestBranch, + createTestBranches +} from '@/test/speckle-helpers/branchHelper' +import { BasicTestCommit, createTestCommits } from '@/test/speckle-helpers/commitHelper' +import { BasicTestStream, createTestStreams } from '@/test/speckle-helpers/streamHelper' +import { SpeckleViewer } from '@speckle/shared' +import { RichTextEditor } from '@speckle/shared' +import { expect } from 'chai' + +const resourceUrlBuilder = SpeckleViewer.ViewerRoute.resourceBuilder + +describe('Project Comments', () => { + const me: BasicTestUser = { + name: 'hello itsa me', + email: '', + id: '' + } + const myStream: BasicTestStream = { + name: 'this is my great stream #1', + isPublic: true, + ownerId: '', + id: '' + } + const myBranch: BasicTestBranch = { + name: 'nice branch!!', + streamId: '', + id: '', + authorId: '' + } + const myCommit: BasicTestCommit = { + id: '', + objectId: '', + streamId: '', + authorId: '', + message: 'this is my nice commit :)))', + branchName: myBranch.name + } + + before(async () => { + await beforeEachContext() + await createTestUsers([me]) + await createTestStreams([[myStream, me]]) + await createTestBranches([{ branch: myBranch, stream: myStream, owner: me }]) + await createTestCommits([myCommit], { stream: myStream, owner: me }) + }) + + describe('in GraphQL API', () => { + let apollo: TestApolloServer + + before(async () => { + apollo = await testApolloServer({ + authUserId: me.id + }) + }) + + const createProjectComment = async (input: CreateCommentInput) => + await apollo.execute(CreateProjectCommentDocument, { input }) + + it('can be created', async () => { + const input: CreateCommentInput = { + projectId: myStream.id, + resourceIdString: resourceUrlBuilder() + .addModel(myBranch.id, myCommit.id) + .toString(), + content: { + doc: RichTextEditor.convertBasicStringToDocument('hello world') + } + } + + const res = await createProjectComment(input) + + expect(res).to.not.haveGraphQLErrors() + expect(res.data?.commentMutations.create.id).to.be.ok + expect(res.data?.commentMutations.create.rawText).to.equal('hello world') + expect(res.data?.commentMutations.create.text.doc).to.be.ok + expect(res.data?.commentMutations.create.authorId).to.equal(me.id) + }) + + describe('after creation', () => { + it.skip('can be retrieved through Project.comment') + }) + }) +}) diff --git a/packages/server/modules/core/errors/commit.ts b/packages/server/modules/core/errors/commit.ts index 55d9d4ba7..1d2003b48 100644 --- a/packages/server/modules/core/errors/commit.ts +++ b/packages/server/modules/core/errors/commit.ts @@ -15,6 +15,11 @@ export class CommitCreateError extends BaseError { static code = 'COMMIT_CREATE_ERROR' } +export class CommitReceiveError extends BaseError { + static defaultMessage = 'An issue occurred while receiving a commit' + static code = 'COMMIT_RECEIVE_ERROR' +} + export class CommitUpdateError extends BaseError { static defaultMessage = 'An issue occurred while updating a commit' static code = 'COMMIT_UPDATE_ERROR' diff --git a/packages/server/modules/core/graph/generated/graphql.ts b/packages/server/modules/core/graph/generated/graphql.ts index a96f17263..2f289df5b 100644 --- a/packages/server/modules/core/graph/generated/graphql.ts +++ b/packages/server/modules/core/graph/generated/graphql.ts @@ -1,6 +1,6 @@ import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql'; -import { StreamGraphQLReturn, CommitGraphQLReturn, ProjectGraphQLReturn, VersionGraphQLReturn, ServerInviteGraphQLReturnType, ModelGraphQLReturn, ModelsTreeItemGraphQLReturn, LimitedUserGraphQLReturn, MutationsObjectGraphQLReturn, GraphQLEmptyReturn } from '@/modules/core/helpers/graphTypes'; -import { StreamAccessRequestGraphQLReturn } from '@/modules/accessrequests/helpers/graphTypes'; +import { StreamGraphQLReturn, CommitGraphQLReturn, ProjectGraphQLReturn, ObjectGraphQLReturn, VersionGraphQLReturn, ServerInviteGraphQLReturnType, ModelGraphQLReturn, ModelsTreeItemGraphQLReturn, MutationsObjectGraphQLReturn, LimitedUserGraphQLReturn, GraphQLEmptyReturn } from '@/modules/core/helpers/graphTypes'; +import { StreamAccessRequestGraphQLReturn, ProjectAccessRequestGraphQLReturn } from '@/modules/accessrequests/helpers/graphTypes'; import { CommentReplyAuthorCollectionGraphQLReturn, CommentGraphQLReturn } from '@/modules/comments/helpers/graphTypes'; import { PendingStreamCollaboratorGraphQLReturn } from '@/modules/serverinvites/helpers/graphTypes'; import { FileUploadGraphQLReturn } from '@/modules/fileuploads/helpers/types'; @@ -26,7 +26,6 @@ export type Scalars = { BigInt: { input: bigint; output: bigint; } /** A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. */ DateTime: { input: Date; output: Date; } - EmailAddress: { input: any; output: any; } /** The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ JSONObject: { input: Record; output: Record; } }; @@ -811,6 +810,16 @@ export type CreateModelInput = { projectId: Scalars['ID']['input']; }; +export type CreateVersionInput = { + message?: InputMaybe; + modelId: Scalars['String']['input']; + objectId: Scalars['String']['input']; + parents?: InputMaybe>; + projectId: Scalars['String']['input']; + sourceApplication?: InputMaybe; + totalChildrenCount?: InputMaybe; +}; + export type DeleteModelInput = { id: Scalars['ID']['input']; projectId: Scalars['ID']['input']; @@ -1001,6 +1010,13 @@ export type LimitedUserTimelineArgs = { limit?: Scalars['Int']['input']; }; +export type MarkReceivedVersionInput = { + message?: InputMaybe; + projectId: Scalars['String']['input']; + sourceApplication: Scalars['String']['input']; + versionId: Scalars['String']['input']; +}; + export type Model = { __typename?: 'Model'; author: LimitedUser; @@ -1170,11 +1186,11 @@ export type Mutation = { * @deprecated Use commentMutations version */ commentView: Scalars['Boolean']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.create instead. */ commitCreate: Scalars['String']['output']; /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.delete instead. */ commitDelete: Scalars['Boolean']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.markReceived instead. */ commitReceive: Scalars['Boolean']['output']; /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.update/moveToModel instead. */ commitUpdate: Scalars['Boolean']['output']; @@ -1200,7 +1216,7 @@ export type Mutation = { inviteResend: Scalars['Boolean']['output']; modelMutations: ModelMutations; /** @deprecated Part of the old API surface and will be removed in the future. */ - objectCreate: Array>; + objectCreate: Array; projectMutations: ProjectMutations; /** (Re-)send the account verification e-mail */ requestVerification: Scalars['Boolean']['output']; @@ -1212,12 +1228,12 @@ export type Mutation = { serverInviteCreate: Scalars['Boolean']['output']; /** * Request access to a specific stream - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use ProjectAccessRequestMutations.create instead. */ streamAccessRequestCreate: StreamAccessRequest; /** * Accept or decline a stream access request. Must be a stream owner to invoke this. - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use ProjectAccessRequestMutations.use instead. */ streamAccessRequestUse: Scalars['Boolean']['output']; /** @@ -1274,7 +1290,7 @@ export type Mutation = { * @deprecated Part of the old API surface and will be removed in the future. Use ProjectMutations.updateRole instead. */ streamUpdatePermission?: Maybe; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use ProjectMutations.batchDelete instead. */ streamsDelete: Scalars['Boolean']['output']; /** * Used for broadcasting real time typing status in comment threads. Does not persist any info. @@ -1591,6 +1607,7 @@ export type MutationWebhookUpdateArgs = { export type Object = { __typename?: 'Object'; + /** @deprecated Not implemented. */ applicationId?: Maybe; /** * Get any objects that this object references. In the case of commits, this will give you a commit's constituent objects. @@ -1630,7 +1647,7 @@ export type ObjectChildrenArgs = { export type ObjectCollection = { __typename?: 'ObjectCollection'; cursor?: Maybe; - objects: Array>; + objects: Array; totalCount: Scalars['Int']['output']; }; @@ -1691,6 +1708,8 @@ export type Project = { blob?: Maybe; /** Get the metadata collection of blobs stored for this stream. */ blobs?: Maybe; + /** Get specific project comment/thread by ID */ + comment?: Maybe; /** All comment threads in this project */ commentThreads: ProjectCommentCollection; createdAt: Scalars['DateTime']['output']; @@ -1700,6 +1719,8 @@ export type Project = { invitedTeam?: Maybe>; /** Returns a specific model by its ID */ model: Model; + /** Retrieve a specific project model by its ID */ + modelByName: Model; /** Return a model tree of children for the specified model name */ modelChildrenTree: Array; /** Returns a flat list of all models */ @@ -1710,6 +1731,9 @@ export type Project = { */ modelsTree: ModelsTreeItemCollection; name: Scalars['String']['output']; + object?: Maybe; + /** Pending project access requests */ + pendingAccessRequests?: Maybe>; /** Returns a list models that are being created from a file import */ pendingImportedModels: Array; /** Active user's role for this project. `null` if request is not authenticated, or the project is not explicitly shared with you. */ @@ -1753,6 +1777,11 @@ export type ProjectBlobsArgs = { }; +export type ProjectCommentArgs = { + id: Scalars['String']['input']; +}; + + export type ProjectCommentThreadsArgs = { cursor?: InputMaybe; filter?: InputMaybe; @@ -1765,6 +1794,11 @@ export type ProjectModelArgs = { }; +export type ProjectModelByNameArgs = { + name: Scalars['String']['input']; +}; + + export type ProjectModelChildrenTreeArgs = { fullName: Scalars['String']['input']; }; @@ -1784,6 +1818,11 @@ export type ProjectModelsTreeArgs = { }; +export type ProjectObjectArgs = { + id: Scalars['String']['input']; +}; + + export type ProjectPendingImportedModelsArgs = { limit?: InputMaybe; }; @@ -1810,6 +1849,38 @@ export type ProjectWebhooksArgs = { id?: InputMaybe; }; +/** Created when a user requests to become a contributor on a project */ +export type ProjectAccessRequest = { + __typename?: 'ProjectAccessRequest'; + createdAt: Scalars['DateTime']['output']; + id: Scalars['ID']['output']; + /** Can only be selected if authed user has proper access */ + project: Project; + projectId: Scalars['String']['output']; + requester: LimitedUser; + requesterId: Scalars['String']['output']; +}; + +export type ProjectAccessRequestMutations = { + __typename?: 'ProjectAccessRequestMutations'; + /** Request access to a specific project */ + create: ProjectAccessRequest; + /** Accept or decline a project access request. Must be a project owner to invoke this. */ + use: Project; +}; + + +export type ProjectAccessRequestMutationsCreateArgs = { + projectId: Scalars['String']['input']; +}; + + +export type ProjectAccessRequestMutationsUseArgs = { + accept: Scalars['Boolean']['input']; + requestId: Scalars['String']['input']; + role?: StreamRole; +}; + export type ProjectAutomationCreateInput = { enabled: Scalars['Boolean']['input']; name: Scalars['String']['input']; @@ -2052,7 +2123,11 @@ export enum ProjectModelsUpdatedMessageType { export type ProjectMutations = { __typename?: 'ProjectMutations'; + /** Access request related mutations */ + accessRequestMutations: ProjectAccessRequestMutations; automationMutations: ProjectAutomationMutations; + /** Batch delete projects */ + batchDelete: Scalars['Boolean']['output']; /** Create new project */ create: Project; /** @@ -2078,6 +2153,11 @@ export type ProjectMutationsAutomationMutationsArgs = { }; +export type ProjectMutationsBatchDeleteArgs = { + ids: Array; +}; + + export type ProjectMutationsCreateArgs = { input?: InputMaybe; }; @@ -2241,7 +2321,7 @@ export type Query = { automateFunctions: AutomateFunctionCollection; /** Part of the automation/function creation handshake mechanism */ automateValidateAuthCode: Scalars['Boolean']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use Project.comment instead. */ comment?: Maybe; /** * This query can be used in the following ways: @@ -2280,7 +2360,7 @@ export type Query = { stream?: Maybe; /** * Get authed user's stream access request - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use User.projectAccessRequest instead. */ streamAccessRequest?: Maybe; /** @@ -2645,7 +2725,7 @@ export type Stream = { * @deprecated Part of the old API surface and will be removed in the future. Use Project.blobs instead. */ blobs?: Maybe; - /** @deprecated Part of the old API surface and will be removed in the future. Use Project.model instead. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use Project.model or Project.modelByName instead. */ branch?: Maybe; /** @deprecated Part of the old API surface and will be removed in the future. Use Project.models or Project.modelsTree instead. */ branches?: Maybe; @@ -2690,11 +2770,11 @@ export type Stream = { /** Whether the stream can be viewed by non-contributors */ isPublic: Scalars['Boolean']['output']; name: Scalars['String']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use Project.object instead. */ object?: Maybe; /** * Pending stream access requests - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use Project.pendingAccessRequests instead. */ pendingAccessRequests?: Maybe>; /** Collaborators who have been invited, but not yet accepted. */ @@ -3198,6 +3278,8 @@ export type User = { name: Scalars['String']['output']; notificationPreferences: Scalars['JSONObject']['output']; profiles?: Maybe; + /** Get pending project access request, that the user made */ + projectAccessRequest?: Maybe; /** Get all invitations to projects that the active user has */ projectInvites: Array; /** Get projects that the user participates in */ @@ -3263,6 +3345,15 @@ export type UserFavoriteStreamsArgs = { }; +/** + * Full user type, should only be used in the context of admin operations or + * when a user is reading/writing info about himself + */ +export type UserProjectAccessRequestArgs = { + projectId: Scalars['String']['input']; +}; + + /** * Full user type, should only be used in the context of admin operations or * when a user is reading/writing info about himself @@ -3407,18 +3498,30 @@ export type VersionCreatedTriggerDefinition = { export type VersionMutations = { __typename?: 'VersionMutations'; + create: Version; delete: Scalars['Boolean']['output']; + markReceived: Scalars['Boolean']['output']; moveToModel: Model; requestGendoAIRender: Scalars['Boolean']['output']; update: Version; }; +export type VersionMutationsCreateArgs = { + input: CreateVersionInput; +}; + + export type VersionMutationsDeleteArgs = { input: DeleteVersionsInput; }; +export type VersionMutationsMarkReceivedArgs = { + input: MarkReceivedVersionInput; +}; + + export type VersionMutationsMoveToModelArgs = { input: MoveVersionsInput; }; @@ -3700,13 +3803,13 @@ export type ResolversTypes = { CreateCommentInput: CreateCommentInput; CreateCommentReplyInput: CreateCommentReplyInput; CreateModelInput: CreateModelInput; + CreateVersionInput: CreateVersionInput; DateTime: ResolverTypeWrapper; DeleteModelInput: DeleteModelInput; DeleteVersionsInput: DeleteVersionsInput; DiscoverableStreamsSortType: DiscoverableStreamsSortType; DiscoverableStreamsSortingInput: DiscoverableStreamsSortingInput; EditCommentInput: EditCommentInput; - EmailAddress: ResolverTypeWrapper; FileUpload: ResolverTypeWrapper; Float: ResolverTypeWrapper; GendoAIRender: ResolverTypeWrapper; @@ -3717,6 +3820,7 @@ export type ResolversTypes = { JSONObject: ResolverTypeWrapper; LegacyCommentViewerData: ResolverTypeWrapper; LimitedUser: ResolverTypeWrapper; + MarkReceivedVersionInput: MarkReceivedVersionInput; Model: ResolverTypeWrapper; ModelCollection: ResolverTypeWrapper & { items: Array }>; ModelMutations: ResolverTypeWrapper; @@ -3725,13 +3829,15 @@ export type ResolversTypes = { ModelsTreeItemCollection: ResolverTypeWrapper & { items: Array }>; MoveVersionsInput: MoveVersionsInput; Mutation: ResolverTypeWrapper<{}>; - Object: ResolverTypeWrapper; - ObjectCollection: ResolverTypeWrapper; + Object: ResolverTypeWrapper; + ObjectCollection: ResolverTypeWrapper & { objects: Array }>; ObjectCreateInput: ObjectCreateInput; PasswordStrengthCheckFeedback: ResolverTypeWrapper; PasswordStrengthCheckResults: ResolverTypeWrapper; PendingStreamCollaborator: ResolverTypeWrapper; Project: ResolverTypeWrapper; + ProjectAccessRequest: ResolverTypeWrapper; + ProjectAccessRequestMutations: ResolverTypeWrapper; ProjectAutomationCreateInput: ProjectAutomationCreateInput; ProjectAutomationMutations: ResolverTypeWrapper; ProjectAutomationRevisionCreateInput: ProjectAutomationRevisionCreateInput; @@ -3813,7 +3919,7 @@ export type ResolversTypes = { UpdateAutomateFunctionInput: UpdateAutomateFunctionInput; UpdateModelInput: UpdateModelInput; UpdateVersionInput: UpdateVersionInput; - User: ResolverTypeWrapper & { automateInfo: ResolversTypes['UserAutomateInfo'], commits?: Maybe, favoriteStreams: ResolversTypes['StreamCollection'], projectInvites: Array, projects: ResolversTypes['ProjectCollection'], streams: ResolversTypes['StreamCollection'] }>; + User: ResolverTypeWrapper & { automateInfo: ResolversTypes['UserAutomateInfo'], commits?: Maybe, favoriteStreams: ResolversTypes['StreamCollection'], projectAccessRequest?: Maybe, projectInvites: Array, projects: ResolversTypes['ProjectCollection'], streams: ResolversTypes['StreamCollection'] }>; UserAutomateInfo: ResolverTypeWrapper; UserDeleteInput: UserDeleteInput; UserProjectsFilter: UserProjectsFilter; @@ -3915,12 +4021,12 @@ export type ResolversParentTypes = { CreateCommentInput: CreateCommentInput; CreateCommentReplyInput: CreateCommentReplyInput; CreateModelInput: CreateModelInput; + CreateVersionInput: CreateVersionInput; DateTime: Scalars['DateTime']['output']; DeleteModelInput: DeleteModelInput; DeleteVersionsInput: DeleteVersionsInput; DiscoverableStreamsSortingInput: DiscoverableStreamsSortingInput; EditCommentInput: EditCommentInput; - EmailAddress: Scalars['EmailAddress']['output']; FileUpload: FileUploadGraphQLReturn; Float: Scalars['Float']['output']; GendoAIRender: GendoAiRender; @@ -3931,6 +4037,7 @@ export type ResolversParentTypes = { JSONObject: Scalars['JSONObject']['output']; LegacyCommentViewerData: LegacyCommentViewerData; LimitedUser: LimitedUserGraphQLReturn; + MarkReceivedVersionInput: MarkReceivedVersionInput; Model: ModelGraphQLReturn; ModelCollection: Omit & { items: Array }; ModelMutations: MutationsObjectGraphQLReturn; @@ -3939,13 +4046,15 @@ export type ResolversParentTypes = { ModelsTreeItemCollection: Omit & { items: Array }; MoveVersionsInput: MoveVersionsInput; Mutation: {}; - Object: Object; - ObjectCollection: ObjectCollection; + Object: ObjectGraphQLReturn; + ObjectCollection: Omit & { objects: Array }; ObjectCreateInput: ObjectCreateInput; PasswordStrengthCheckFeedback: PasswordStrengthCheckFeedback; PasswordStrengthCheckResults: PasswordStrengthCheckResults; PendingStreamCollaborator: PendingStreamCollaboratorGraphQLReturn; Project: ProjectGraphQLReturn; + ProjectAccessRequest: ProjectAccessRequestGraphQLReturn; + ProjectAccessRequestMutations: MutationsObjectGraphQLReturn; ProjectAutomationCreateInput: ProjectAutomationCreateInput; ProjectAutomationMutations: ProjectAutomationMutationsGraphQLReturn; ProjectAutomationRevisionCreateInput: ProjectAutomationRevisionCreateInput; @@ -4012,7 +4121,7 @@ export type ResolversParentTypes = { UpdateAutomateFunctionInput: UpdateAutomateFunctionInput; UpdateModelInput: UpdateModelInput; UpdateVersionInput: UpdateVersionInput; - User: Omit & { automateInfo: ResolversParentTypes['UserAutomateInfo'], commits?: Maybe, favoriteStreams: ResolversParentTypes['StreamCollection'], projectInvites: Array, projects: ResolversParentTypes['ProjectCollection'], streams: ResolversParentTypes['StreamCollection'] }; + User: Omit & { automateInfo: ResolversParentTypes['UserAutomateInfo'], commits?: Maybe, favoriteStreams: ResolversParentTypes['StreamCollection'], projectAccessRequest?: Maybe, projectInvites: Array, projects: ResolversParentTypes['ProjectCollection'], streams: ResolversParentTypes['StreamCollection'] }; UserAutomateInfo: UserAutomateInfoGraphQLReturn; UserDeleteInput: UserDeleteInput; UserProjectsFilter: UserProjectsFilter; @@ -4459,10 +4568,6 @@ export interface DateTimeScalarConfig extends GraphQLScalarTypeConfig { - name: 'EmailAddress'; -} - export type FileUploadResolvers = { branchName?: Resolver; convertedCommitId?: Resolver, ParentType, ContextType>; @@ -4618,7 +4723,7 @@ export type MutationResolvers>; inviteResend?: Resolver>; modelMutations?: Resolver; - objectCreate?: Resolver>, ParentType, ContextType, RequireFields>; + objectCreate?: Resolver, ParentType, ContextType, RequireFields>; projectMutations?: Resolver; requestVerification?: Resolver; requestVerificationByEmail?: Resolver>; @@ -4665,7 +4770,7 @@ export type ObjectResolvers = { cursor?: Resolver, ParentType, ContextType>; - objects?: Resolver>, ParentType, ContextType>; + objects?: Resolver, ParentType, ContextType>; totalCount?: Resolver; __isTypeOf?: IsTypeOfResolverFn; }; @@ -4703,16 +4808,20 @@ export type ProjectResolvers>; blob?: Resolver, ParentType, ContextType, RequireFields>; blobs?: Resolver, ParentType, ContextType, RequireFields>; + comment?: Resolver, ParentType, ContextType, RequireFields>; commentThreads?: Resolver>; createdAt?: Resolver; description?: Resolver, ParentType, ContextType>; id?: Resolver; invitedTeam?: Resolver>, ParentType, ContextType>; model?: Resolver>; + modelByName?: Resolver>; modelChildrenTree?: Resolver, ParentType, ContextType, RequireFields>; models?: Resolver>; modelsTree?: Resolver>; name?: Resolver; + object?: Resolver, ParentType, ContextType, RequireFields>; + pendingAccessRequests?: Resolver>, ParentType, ContextType>; pendingImportedModels?: Resolver, ParentType, ContextType, RequireFields>; role?: Resolver, ParentType, ContextType>; sourceApps?: Resolver, ParentType, ContextType>; @@ -4726,6 +4835,22 @@ export type ProjectResolvers; }; +export type ProjectAccessRequestResolvers = { + createdAt?: Resolver; + id?: Resolver; + project?: Resolver; + projectId?: Resolver; + requester?: Resolver; + requesterId?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + +export type ProjectAccessRequestMutationsResolvers = { + create?: Resolver>; + use?: Resolver>; + __isTypeOf?: IsTypeOfResolverFn; +}; + export type ProjectAutomationMutationsResolvers = { create?: Resolver>; createRevision?: Resolver>; @@ -4796,7 +4921,9 @@ export type ProjectModelsUpdatedMessageResolvers = { + accessRequestMutations?: Resolver; automationMutations?: Resolver>; + batchDelete?: Resolver>; create?: Resolver>; createForOnboarding?: Resolver; delete?: Resolver>; @@ -5144,6 +5271,7 @@ export type UserResolvers; notificationPreferences?: Resolver; profiles?: Resolver, ParentType, ContextType>; + projectAccessRequest?: Resolver, ParentType, ContextType, RequireFields>; projectInvites?: Resolver, ParentType, ContextType>; projects?: Resolver>; role?: Resolver, ParentType, ContextType>; @@ -5213,7 +5341,9 @@ export type VersionCreatedTriggerDefinitionResolvers = { + create?: Resolver>; delete?: Resolver>; + markReceived?: Resolver>; moveToModel?: Resolver>; requestGendoAIRender?: Resolver>; update?: Resolver>; @@ -5325,7 +5455,6 @@ export type Resolvers = { CommitCollection?: CommitCollectionResolvers; CountOnlyCollection?: CountOnlyCollectionResolvers; DateTime?: GraphQLScalarType; - EmailAddress?: GraphQLScalarType; FileUpload?: FileUploadResolvers; GendoAIRender?: GendoAiRenderResolvers; GendoAIRenderCollection?: GendoAiRenderCollectionResolvers; @@ -5344,6 +5473,8 @@ export type Resolvers = { PasswordStrengthCheckResults?: PasswordStrengthCheckResultsResolvers; PendingStreamCollaborator?: PendingStreamCollaboratorResolvers; Project?: ProjectResolvers; + ProjectAccessRequest?: ProjectAccessRequestResolvers; + ProjectAccessRequestMutations?: ProjectAccessRequestMutationsResolvers; ProjectAutomationMutations?: ProjectAutomationMutationsResolvers; ProjectAutomationsUpdatedMessage?: ProjectAutomationsUpdatedMessageResolvers; ProjectCollaborator?: ProjectCollaboratorResolvers; diff --git a/packages/server/modules/core/graph/resolvers/commits.js b/packages/server/modules/core/graph/resolvers/commits.js index e82512ea9..4b086f2e5 100644 --- a/packages/server/modules/core/graph/resolvers/commits.js +++ b/packages/server/modules/core/graph/resolvers/commits.js @@ -22,13 +22,9 @@ const { const { createCommitByBranchName, updateCommitAndNotify, - deleteCommitAndNotify + deleteCommitAndNotify, + markCommitReceivedAndNotify } = require('@/modules/core/services/commit/management') -const { - addCommitReceivedActivity -} = require('@/modules/activitystream/services/commitActivity') - -const { getUser } = require('../../services/users') const { RateLimitError } = require('@/modules/core/errors/ratelimit') const { @@ -231,18 +227,12 @@ module.exports = { context.resourceAccessRules ) - const commit = await getCommitById({ - streamId: args.input.streamId, - id: args.input.commitId + await markCommitReceivedAndNotify({ + input: args.input, + userId: context.userId }) - const user = await getUser(context.userId) - if (commit && user) { - await addCommitReceivedActivity({ input: args.input, userId: user.id }) - return true - } - - return false + return true }, async commitDelete(_parent, args, context) { diff --git a/packages/server/modules/core/graph/resolvers/models.ts b/packages/server/modules/core/graph/resolvers/models.ts index fdb62977a..144f662b9 100644 --- a/packages/server/modules/core/graph/resolvers/models.ts +++ b/packages/server/modules/core/graph/resolvers/models.ts @@ -58,6 +58,16 @@ export = { return model }, + async modelByName(parent, args, ctx) { + const model = await ctx.loaders.streams.getStreamBranchByName + .forStream(parent.id) + .load(args.name) + if (!model) { + throw new BranchNotFoundError('Model not found') + } + + return model + }, async modelsTree(parent, args) { return await getProjectTopLevelModelsTree(parent.id, args) }, diff --git a/packages/server/modules/core/graph/resolvers/objects.js b/packages/server/modules/core/graph/resolvers/objects.ts similarity index 65% rename from packages/server/modules/core/graph/resolvers/objects.js rename to packages/server/modules/core/graph/resolvers/objects.ts index 4f9955cd2..4c692c359 100644 --- a/packages/server/modules/core/graph/resolvers/objects.js +++ b/packages/server/modules/core/graph/resolvers/objects.ts @@ -1,24 +1,26 @@ -'use strict' -const { validateScopes, authorizeResolver } = require('@/modules/shared') +import { authorizeResolver } from '@/modules/shared' -const { +import { createObjects, - getObject, getObjectChildren, getObjectChildrenQuery -} = require('../../services/objects') -const { Roles, Scopes } = require('@speckle/shared') -const { throwForNotHavingServerRole } = require('@/modules/shared/authz') +} from '../../services/objects' -module.exports = { +import { Roles } from '@speckle/shared' +import { Resolvers } from '@/modules/core/graph/generated/graphql' +import { getObject } from '@/modules/core/repositories/objects' + +const getStreamObject: NonNullable['object'] = + async function object(parent, args) { + return (await getObject(args.id, parent.id)) || null + } + +export = { Stream: { - async object(parent, args) { - const obj = await getObject({ streamId: parent.id, objectId: args.id }) - if (!obj) return null - - obj.streamId = parent.id - return obj - } + object: getStreamObject + }, + Project: { + object: getStreamObject }, Object: { async children(parent, args) { @@ -34,7 +36,7 @@ module.exports = { }) result.objects.forEach((x) => (x.streamId = parent.streamId)) return { - totalCount: parent.totalChildrenCount || '0', + totalCount: parent.totalChildrenCount || 0, cursor: result.cursor, objects: result.objects } @@ -56,9 +58,7 @@ module.exports = { } }, Mutation: { - async objectCreate(parent, args, context) { - await throwForNotHavingServerRole(context, Roles.Server.Guest) - await validateScopes(context.scopes, Scopes.Streams.Write) + async objectCreate(_parent, args, context) { await authorizeResolver( context.userId, args.objectInput.streamId, @@ -73,4 +73,4 @@ module.exports = { return ids } } -} +} as Resolvers diff --git a/packages/server/modules/core/graph/resolvers/projects.ts b/packages/server/modules/core/graph/resolvers/projects.ts index a817b8def..37f65ea62 100644 --- a/packages/server/modules/core/graph/resolvers/projects.ts +++ b/packages/server/modules/core/graph/resolvers/projects.ts @@ -89,6 +89,16 @@ export = { projectMutations: () => ({}) }, ProjectMutations: { + async batchDelete(_parent, args, ctx) { + const results = await Promise.all( + args.ids.map((id) => + deleteStreamAndNotify(id, ctx.userId!, ctx.resourceAccessRules, { + skipAccessChecks: true + }) + ) + ) + return results.every((res) => res === true) + }, async delete(_parent, { id }, { userId, resourceAccessRules }) { return await deleteStreamAndNotify(id, userId!, resourceAccessRules) }, diff --git a/packages/server/modules/core/graph/resolvers/versions.ts b/packages/server/modules/core/graph/resolvers/versions.ts index 28c448682..4b2e96df1 100644 --- a/packages/server/modules/core/graph/resolvers/versions.ts +++ b/packages/server/modules/core/graph/resolvers/versions.ts @@ -11,7 +11,16 @@ import { batchMoveCommits } from '@/modules/core/services/commit/batchCommitActions' import { CommitUpdateError } from '@/modules/core/errors/commit' -import { updateCommitAndNotify } from '@/modules/core/services/commit/management' +import { + createCommitByBranchId, + markCommitReceivedAndNotify, + updateCommitAndNotify +} from '@/modules/core/services/commit/management' +import { + getRateLimitResult, + isRateLimitBreached +} from '@/modules/core/services/ratelimiter' +import { RateLimitError } from '@/modules/core/errors/ratelimit' export = { Project: { @@ -62,6 +71,47 @@ export = { ctx.resourceAccessRules ) return await updateCommitAndNotify(args.input, ctx.userId!) + }, + async create(_parent, args, ctx) { + await authorizeResolver( + ctx.userId, + args.input.projectId, + Roles.Stream.Contributor, + ctx.resourceAccessRules + ) + + const rateLimitResult = await getRateLimitResult('COMMIT_CREATE', ctx.userId!) + if (isRateLimitBreached(rateLimitResult)) { + throw new RateLimitError(rateLimitResult) + } + + const commit = await createCommitByBranchId({ + authorId: ctx.userId!, + streamId: args.input.projectId, + branchId: args.input.modelId, + message: args.input.message || null, + sourceApplication: args.input.sourceApplication || null, + objectId: args.input.objectId, + parents: args.input.parents || [] + }) + + return commit + }, + + async markReceived(_parent, args, ctx) { + await authorizeResolver( + ctx.userId, + args.input.projectId, + Roles.Stream.Reviewer, + ctx.resourceAccessRules + ) + + await markCommitReceivedAndNotify({ + input: args.input, + userId: ctx.userId! + }) + + return true } }, Subscription: { diff --git a/packages/server/modules/core/graph/scalars.js b/packages/server/modules/core/graph/scalars.js index 232636712..0ade33177 100644 --- a/packages/server/modules/core/graph/scalars.js +++ b/packages/server/modules/core/graph/scalars.js @@ -13,8 +13,6 @@ exports.scalarResolvers = { exports.scalarSchemas = ` scalar DateTime -scalar EmailAddress - scalar BigInt scalar JSONObject diff --git a/packages/server/modules/core/helpers/graphTypes.ts b/packages/server/modules/core/helpers/graphTypes.ts index b0d3bbd65..4fa52463c 100644 --- a/packages/server/modules/core/helpers/graphTypes.ts +++ b/packages/server/modules/core/helpers/graphTypes.ts @@ -7,7 +7,12 @@ import { Commit } from '@/modules/core/graph/generated/graphql' import { Roles, ServerRoles, StreamRoles } from '@/modules/core/helpers/mainConstants' -import { BranchRecord, CommitRecord, StreamRecord } from '@/modules/core/helpers/types' +import { + BranchRecord, + CommitRecord, + ObjectRecord, + StreamRecord +} from '@/modules/core/helpers/types' import { Nullable } from '@speckle/shared' /** @@ -72,6 +77,8 @@ export type ModelsTreeItemGraphQLReturn = Omit} + */ async createObjects(streamId, objects) { // TODO: Switch to knex batch inserting functionality // see http://knexjs.org/#Utility-BatchInsert @@ -248,6 +251,9 @@ module.exports = { return ids }, + /** + * @returns {Promise>} + */ async getObject({ streamId, objectId }) { const res = await Objects().where({ streamId, id: objectId }).select('*').first() if (!res) return null @@ -288,6 +294,9 @@ module.exports = { return q.stream({ highWaterMark: 500 }) }, + /** + * @returns {Promise<{objects: import('@/modules/core/helpers/types').ObjectRecord[], cursor: string | null}>} + */ async getObjectChildren({ streamId, objectId, limit, depth, select, cursor }) { limit = parseInt(limit) || 50 depth = parseInt(depth) || 1000 @@ -370,8 +379,13 @@ module.exports = { return { objects: rows, cursor: lastId } }, - // This query is inefficient on larger sets (n * 10k objects) as we need to return the total count on an arbitrarily (user) defined selection of objects. - // A possible future optimisation route would be to cache the total count of a query (as objects are immutable, it will not change) on a first run, and, if found on a subsequent round, do a simpler query and merge the total count result. + /** + * + * This query is inefficient on larger sets (n * 10k objects) as we need to return the total count on an arbitrarily (user) defined selection of objects. + * A possible future optimisation route would be to cache the total count of a query (as objects are immutable, it will not change) on a first run, and, if found on a subsequent round, do a simpler query and merge the total count result. + * @param {*} param0 + * @returns {Promise<{objects: import('@/modules/core/helpers/types').ObjectRecord[], cursor: string | null, totalCount: number}>} + */ async getObjectChildrenQuery({ streamId, objectId, diff --git a/packages/server/modules/core/services/streams/streamAccessService.js b/packages/server/modules/core/services/streams/streamAccessService.js index 1e1c281ad..937ac5d15 100644 --- a/packages/server/modules/core/services/streams/streamAccessService.js +++ b/packages/server/modules/core/services/streams/streamAccessService.js @@ -41,7 +41,7 @@ async function isStreamCollaborator(userId, streamId) { * @param {string} [userId] If falsy, will throw for non-public streams * @param {string} streamId * @param {string} [expectedRole] Defaults to reviewer - * @param {import('@/modules/serverinvites/services/operations').TokenResourceIdentifier[] | undefined | null} [userResourceAccessLimits] + * @param {import('@/modules/core/domain/tokens/types').TokenResourceIdentifier[] | undefined | null} [userResourceAccessLimits] * @returns {Promise} */ async function validateStreamAccess( @@ -90,7 +90,7 @@ async function validateStreamAccess( * @param {string} streamId * @param {string} userId ID of user that should be removed * @param {string} removedById ID of user that is doing the removing - * @param {import('@/modules/serverinvites/services/operations').TokenResourceIdentifier[] | undefined | null} [removerResourceAccessRules] Resource access rules (if any) for the user doing the removing + * @param {import('@/modules/core/domain/tokens/types').TokenResourceIdentifier[] | undefined | null} [removerResourceAccessRules] Resource access rules (if any) for the user doing the removing */ async function removeStreamCollaborator( streamId, @@ -134,7 +134,7 @@ async function removeStreamCollaborator( * @param {string} userId ID of user who is being added * @param {string} role * @param {string} addedById ID of user who is adding the new collaborator - * @param {import('@/modules/serverinvites/services/operations').TokenResourceIdentifier[] | undefined | null} [adderResourceAccessRules] Resource access rules (if any) for the user doing the adding + * @param {import('@/modules/core/domain/tokens/types').TokenResourceIdentifier[] | undefined | null} [adderResourceAccessRules] Resource access rules (if any) for the user doing the adding * @param {{ * fromInvite?: boolean, * }} param4 diff --git a/packages/server/modules/core/tests/models.spec.ts b/packages/server/modules/core/tests/models.spec.ts new file mode 100644 index 000000000..799f5cb37 --- /dev/null +++ b/packages/server/modules/core/tests/models.spec.ts @@ -0,0 +1,89 @@ +import { BasicTestUser, createTestUsers } from '@/test/authHelper' +import { + CreateModelInput, + CreateProjectModelDocument, + FindProjectModelByNameDocument +} from '@/test/graphql/generated/graphql' +import { testApolloServer, TestApolloServer } from '@/test/graphqlHelper' +import { beforeEachContext } from '@/test/hooks' +import { BasicTestStream, createTestStreams } from '@/test/speckle-helpers/streamHelper' +import { expect } from 'chai' +import { omit } from 'lodash' +import { before, describe } from 'mocha' + +describe('Models', () => { + const me: BasicTestUser = { + name: 'hello itsa me', + email: '', + id: '' + } + + const myPrivateStream: BasicTestStream = { + name: 'this is my private stream #1', + isPublic: false, + ownerId: '', + id: '' + } + + before(async () => { + await beforeEachContext() + await createTestUsers([me]) + await createTestStreams([[myPrivateStream, me]]) + }) + + describe('in GraphQL API', () => { + let apollo: TestApolloServer + + const createModel = async (input: CreateModelInput) => + await apollo.execute(CreateProjectModelDocument, { + input + }) + + before(async () => { + apollo = await testApolloServer({ + authUserId: me.id + }) + }) + + it('can be created', async () => { + const input: CreateModelInput = { + projectId: myPrivateStream.id, + name: 'my first model', + description: 'ayyooo' + } + const res = await createModel(input) + + expect(res).to.not.haveGraphQLErrors() + expect(res.data?.modelMutations.create.id).to.be.ok + expect(res.data?.modelMutations.create.name).to.equal(input.name) + expect(res.data?.modelMutations.create.description).to.equal(input.description) + }) + + describe('after creation', () => { + let firstModel: CreateModelInput & { id: string } + + before(async () => { + firstModel = { + projectId: myPrivateStream.id, + name: 'anutha model #1', + description: 'ayyooo!!', + id: '' + } + const res = await createModel(omit(firstModel, ['id'])) + firstModel.id = res.data!.modelMutations.create.id + expect(firstModel.id).to.be.ok + }) + + it('can be found by name', async () => { + const res = await apollo.execute(FindProjectModelByNameDocument, { + projectId: myPrivateStream.id, + name: firstModel.name + }) + + expect(res).to.not.haveGraphQLErrors() + expect(res.data?.project.modelByName.id).to.equal(firstModel.id) + expect(res.data?.project.modelByName.name).to.equal(firstModel.name) + }) + }) + }) +}) diff --git a/packages/server/modules/core/tests/projects.spec.ts b/packages/server/modules/core/tests/projects.spec.ts new file mode 100644 index 000000000..61fa5b7e3 --- /dev/null +++ b/packages/server/modules/core/tests/projects.spec.ts @@ -0,0 +1,132 @@ +import { before, describe } from 'mocha' +import { expect } from 'chai' +import { BasicTestUser, createTestUsers } from '@/test/authHelper' +import { BasicTestStream, createTestStreams } from '@/test/speckle-helpers/streamHelper' +import { beforeEachContext } from '@/test/hooks' +import { testApolloServer, TestApolloServer } from '@/test/graphqlHelper' +import { + BatchDeleteProjectsDocument, + CreateProjectDocument, + GetProjectObjectDocument, + ProjectCreateInput +} from '@/test/graphql/generated/graphql' +import { createTestObject } from '@/test/speckle-helpers/commitHelper' +import { times } from 'lodash' +import { Roles } from '@speckle/shared' + +describe('Projects', () => { + const me: BasicTestUser = { + name: 'hello itsa me', + email: '', + id: '' + } + + const otherUser: BasicTestUser = { + name: 'hello itsa some otha guy', + email: '', + id: '' + } + + before(async () => { + await beforeEachContext() + await createTestUsers([me, otherUser]) + }) + + describe('in GraphQL API', () => { + let apollo: TestApolloServer + + before(async () => { + apollo = await testApolloServer({ + authUserId: me.id + }) + }) + + it('can be created', async () => { + const input: ProjectCreateInput = { + name: 'my first project', + description: 'ayyooo' + } + const res = await apollo.execute(CreateProjectDocument, { + input + }) + + expect(res).to.not.haveGraphQLErrors() + expect(res.data?.projectMutations.create.id).to.be.ok + expect(res.data?.projectMutations.create.name).to.equal(input.name) + expect(res.data?.projectMutations.create.description).to.equal(input.description) + }) + + describe('after creation', () => { + const myStream: BasicTestStream = { + name: 'this is my great stream #1', + isPublic: true, + ownerId: '', + id: '' + } + + const getMyStreamObject = async (objectId: string) => + await apollo.execute(GetProjectObjectDocument, { + projectId: myStream.id, + objectId + }) + + before(async () => { + await createTestStreams([[myStream, me]]) + }) + + it('returns null if querying for a non-existant object()', async () => { + const res = await getMyStreamObject('non-existant-object-id') + + expect(res).to.not.haveGraphQLErrors() + expect(res.data?.project.object).to.be.null + }) + + it('can have their objects retrieved through object()', async () => { + const objectId = await createTestObject({ projectId: myStream.id }) + const res = await getMyStreamObject(objectId) + + expect(res).to.not.haveGraphQLErrors() + expect(res.data?.project.object?.id).to.equal(objectId) + }) + }) + + describe('when doing batch deletion', () => { + const createOtherGuyProjectBatch = async () => { + const projects: BasicTestStream[] = times(3, () => ({ + id: '', + ownerId: otherUser.id, + name: `project ${Math.random()}`, + isPublic: false + })) + + await createTestStreams(projects.map((p) => [p, me])) + return projects.map((p) => p.id) + } + + const batchDeleteProjects = async (ids: string[], asAdmin?: boolean) => + await apollo.execute( + BatchDeleteProjectsDocument, + { ids }, + { + context: asAdmin ? { role: Roles.Server.Admin } : undefined + } + ) + + it("it doesn't work if user is not an admin", async () => { + const projectIds = await createOtherGuyProjectBatch() + const res = await batchDeleteProjects(projectIds) + + expect(res.data).to.not.be.ok + expect(res).to.haveGraphQLErrors('You do not have the required server role') + }) + + it('works if user is an admin, even for not owned projects', async () => { + const projectIds = await createOtherGuyProjectBatch() + const res = await batchDeleteProjects(projectIds, true) + + expect(res).to.not.haveGraphQLErrors() + expect(res.data?.projectMutations.batchDelete).to.be.true + }) + }) + }) +}) diff --git a/packages/server/modules/core/tests/versions.spec.ts b/packages/server/modules/core/tests/versions.spec.ts new file mode 100644 index 000000000..befd80c1a --- /dev/null +++ b/packages/server/modules/core/tests/versions.spec.ts @@ -0,0 +1,126 @@ +import { ActionTypes } from '@/modules/activitystream/helpers/types' +import { BasicTestUser, createTestUsers } from '@/test/authHelper' +import { + CreateProjectVersionDocument, + CreateVersionInput, + MarkProjectVersionReceivedDocument, + MarkReceivedVersionInput +} from '@/test/graphql/generated/graphql' +import { testApolloServer, TestApolloServer } from '@/test/graphqlHelper' +import { beforeEachContext } from '@/test/hooks' +import { getStreamActivities } from '@/test/speckle-helpers/activityStreamHelper' +import { + BasicTestBranch, + createTestBranches +} from '@/test/speckle-helpers/branchHelper' +import { createTestObject } from '@/test/speckle-helpers/commitHelper' +import { BasicTestStream, createTestStreams } from '@/test/speckle-helpers/streamHelper' +import { expect } from 'chai' +import { omit } from 'lodash' +import { before, describe } from 'mocha' + +describe('Versions', () => { + const me: BasicTestUser = { + name: 'hello itsa me', + email: '', + id: '' + } + + const myPrivateStream: BasicTestStream = { + name: 'this is my private stream #1', + isPublic: false, + ownerId: '', + id: '' + } + + const myBranch: BasicTestBranch = { + name: 'my branchy #1', + streamId: '', + id: '', + authorId: '' + } + + before(async () => { + await beforeEachContext() + await createTestUsers([me]) + await createTestStreams([[myPrivateStream, me]]) + await createTestBranches([{ branch: myBranch, stream: myPrivateStream, owner: me }]) + }) + + describe('in GraphQL API', () => { + let apollo: TestApolloServer + let objectId: string + + const createVersion = async (input: CreateVersionInput) => + await apollo.execute(CreateProjectVersionDocument, { input }) + + before(async () => { + apollo = await testApolloServer({ + authUserId: me.id + }) + objectId = await createTestObject({ projectId: myPrivateStream.id }) + }) + + it('can be created', async () => { + const input: CreateVersionInput = { + projectId: myPrivateStream.id, + modelId: myBranch.id, + objectId, + message: 'Yoooo!', + sourceApplication: 'tests', + parents: [] + } + const res = await createVersion(input) + + expect(res).to.not.haveGraphQLErrors() + expect(res.data?.versionMutations.create.id).to.be.ok + expect(res.data?.versionMutations.create.message).to.eq(input.message) + expect(res.data?.versionMutations.create.sourceApplication).to.eq( + input.sourceApplication + ) + expect(res.data?.versionMutations.create.model.id).to.eq(myBranch.id) + expect(res.data?.versionMutations.create.referencedObject).to.eq(objectId) + }) + + describe('after creation', () => { + let firstVersion: CreateVersionInput & { id: string } + + before(async () => { + firstVersion = { + projectId: myPrivateStream.id, + modelId: myBranch.id, + objectId, + message: 'welcome #1', + sourceApplication: 'testsz', + parents: [], + id: '' + } + const res = await createVersion(omit(firstVersion, ['id'])) + firstVersion.id = res.data!.versionMutations.create.id + expect(firstVersion.id).to.be.ok + }) + + it('can be marked as received', async () => { + const input: MarkReceivedVersionInput = { + versionId: firstVersion.id, + projectId: myPrivateStream.id, + sourceApplication: 'booo', + message: 'hey hihihi' + } + const res = await apollo.execute(MarkProjectVersionReceivedDocument, { + input + }) + + expect(res).to.not.haveGraphQLErrors() + expect(res.data?.versionMutations.markReceived).to.be.true + + const activities = await getStreamActivities(myPrivateStream.id, { + actionType: ActionTypes.Commit.Receive, + userId: me.id + }) + expect(activities).to.have.length(1) + expect(activities[0].info?.message).to.eq(input.message) + }) + }) + }) +}) diff --git a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts index 2961fc922..f5be26a29 100644 --- a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts +++ b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts @@ -16,7 +16,6 @@ export type Scalars = { BigInt: { input: bigint; output: bigint; } /** A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. */ DateTime: { input: string; output: string; } - EmailAddress: { input: any; output: any; } /** The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ JSONObject: { input: Record; output: Record; } }; @@ -801,6 +800,16 @@ export type CreateModelInput = { projectId: Scalars['ID']['input']; }; +export type CreateVersionInput = { + message?: InputMaybe; + modelId: Scalars['String']['input']; + objectId: Scalars['String']['input']; + parents?: InputMaybe>; + projectId: Scalars['String']['input']; + sourceApplication?: InputMaybe; + totalChildrenCount?: InputMaybe; +}; + export type DeleteModelInput = { id: Scalars['ID']['input']; projectId: Scalars['ID']['input']; @@ -991,6 +1000,13 @@ export type LimitedUserTimelineArgs = { limit?: Scalars['Int']['input']; }; +export type MarkReceivedVersionInput = { + message?: InputMaybe; + projectId: Scalars['String']['input']; + sourceApplication: Scalars['String']['input']; + versionId: Scalars['String']['input']; +}; + export type Model = { __typename?: 'Model'; author: LimitedUser; @@ -1160,11 +1176,11 @@ export type Mutation = { * @deprecated Use commentMutations version */ commentView: Scalars['Boolean']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.create instead. */ commitCreate: Scalars['String']['output']; /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.delete instead. */ commitDelete: Scalars['Boolean']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.markReceived instead. */ commitReceive: Scalars['Boolean']['output']; /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.update/moveToModel instead. */ commitUpdate: Scalars['Boolean']['output']; @@ -1190,7 +1206,7 @@ export type Mutation = { inviteResend: Scalars['Boolean']['output']; modelMutations: ModelMutations; /** @deprecated Part of the old API surface and will be removed in the future. */ - objectCreate: Array>; + objectCreate: Array; projectMutations: ProjectMutations; /** (Re-)send the account verification e-mail */ requestVerification: Scalars['Boolean']['output']; @@ -1202,12 +1218,12 @@ export type Mutation = { serverInviteCreate: Scalars['Boolean']['output']; /** * Request access to a specific stream - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use ProjectAccessRequestMutations.create instead. */ streamAccessRequestCreate: StreamAccessRequest; /** * Accept or decline a stream access request. Must be a stream owner to invoke this. - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use ProjectAccessRequestMutations.use instead. */ streamAccessRequestUse: Scalars['Boolean']['output']; /** @@ -1264,7 +1280,7 @@ export type Mutation = { * @deprecated Part of the old API surface and will be removed in the future. Use ProjectMutations.updateRole instead. */ streamUpdatePermission?: Maybe; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use ProjectMutations.batchDelete instead. */ streamsDelete: Scalars['Boolean']['output']; /** * Used for broadcasting real time typing status in comment threads. Does not persist any info. @@ -1581,6 +1597,7 @@ export type MutationWebhookUpdateArgs = { export type Object = { __typename?: 'Object'; + /** @deprecated Not implemented. */ applicationId?: Maybe; /** * Get any objects that this object references. In the case of commits, this will give you a commit's constituent objects. @@ -1620,7 +1637,7 @@ export type ObjectChildrenArgs = { export type ObjectCollection = { __typename?: 'ObjectCollection'; cursor?: Maybe; - objects: Array>; + objects: Array; totalCount: Scalars['Int']['output']; }; @@ -1681,6 +1698,8 @@ export type Project = { blob?: Maybe; /** Get the metadata collection of blobs stored for this stream. */ blobs?: Maybe; + /** Get specific project comment/thread by ID */ + comment?: Maybe; /** All comment threads in this project */ commentThreads: ProjectCommentCollection; createdAt: Scalars['DateTime']['output']; @@ -1690,6 +1709,8 @@ export type Project = { invitedTeam?: Maybe>; /** Returns a specific model by its ID */ model: Model; + /** Retrieve a specific project model by its ID */ + modelByName: Model; /** Return a model tree of children for the specified model name */ modelChildrenTree: Array; /** Returns a flat list of all models */ @@ -1700,6 +1721,9 @@ export type Project = { */ modelsTree: ModelsTreeItemCollection; name: Scalars['String']['output']; + object?: Maybe; + /** Pending project access requests */ + pendingAccessRequests?: Maybe>; /** Returns a list models that are being created from a file import */ pendingImportedModels: Array; /** Active user's role for this project. `null` if request is not authenticated, or the project is not explicitly shared with you. */ @@ -1743,6 +1767,11 @@ export type ProjectBlobsArgs = { }; +export type ProjectCommentArgs = { + id: Scalars['String']['input']; +}; + + export type ProjectCommentThreadsArgs = { cursor?: InputMaybe; filter?: InputMaybe; @@ -1755,6 +1784,11 @@ export type ProjectModelArgs = { }; +export type ProjectModelByNameArgs = { + name: Scalars['String']['input']; +}; + + export type ProjectModelChildrenTreeArgs = { fullName: Scalars['String']['input']; }; @@ -1774,6 +1808,11 @@ export type ProjectModelsTreeArgs = { }; +export type ProjectObjectArgs = { + id: Scalars['String']['input']; +}; + + export type ProjectPendingImportedModelsArgs = { limit?: InputMaybe; }; @@ -1800,6 +1839,38 @@ export type ProjectWebhooksArgs = { id?: InputMaybe; }; +/** Created when a user requests to become a contributor on a project */ +export type ProjectAccessRequest = { + __typename?: 'ProjectAccessRequest'; + createdAt: Scalars['DateTime']['output']; + id: Scalars['ID']['output']; + /** Can only be selected if authed user has proper access */ + project: Project; + projectId: Scalars['String']['output']; + requester: LimitedUser; + requesterId: Scalars['String']['output']; +}; + +export type ProjectAccessRequestMutations = { + __typename?: 'ProjectAccessRequestMutations'; + /** Request access to a specific project */ + create: ProjectAccessRequest; + /** Accept or decline a project access request. Must be a project owner to invoke this. */ + use: Project; +}; + + +export type ProjectAccessRequestMutationsCreateArgs = { + projectId: Scalars['String']['input']; +}; + + +export type ProjectAccessRequestMutationsUseArgs = { + accept: Scalars['Boolean']['input']; + requestId: Scalars['String']['input']; + role?: StreamRole; +}; + export type ProjectAutomationCreateInput = { enabled: Scalars['Boolean']['input']; name: Scalars['String']['input']; @@ -2042,7 +2113,11 @@ export enum ProjectModelsUpdatedMessageType { export type ProjectMutations = { __typename?: 'ProjectMutations'; + /** Access request related mutations */ + accessRequestMutations: ProjectAccessRequestMutations; automationMutations: ProjectAutomationMutations; + /** Batch delete projects */ + batchDelete: Scalars['Boolean']['output']; /** Create new project */ create: Project; /** @@ -2068,6 +2143,11 @@ export type ProjectMutationsAutomationMutationsArgs = { }; +export type ProjectMutationsBatchDeleteArgs = { + ids: Array; +}; + + export type ProjectMutationsCreateArgs = { input?: InputMaybe; }; @@ -2231,7 +2311,7 @@ export type Query = { automateFunctions: AutomateFunctionCollection; /** Part of the automation/function creation handshake mechanism */ automateValidateAuthCode: Scalars['Boolean']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use Project.comment instead. */ comment?: Maybe; /** * This query can be used in the following ways: @@ -2270,7 +2350,7 @@ export type Query = { stream?: Maybe; /** * Get authed user's stream access request - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use User.projectAccessRequest instead. */ streamAccessRequest?: Maybe; /** @@ -2635,7 +2715,7 @@ export type Stream = { * @deprecated Part of the old API surface and will be removed in the future. Use Project.blobs instead. */ blobs?: Maybe; - /** @deprecated Part of the old API surface and will be removed in the future. Use Project.model instead. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use Project.model or Project.modelByName instead. */ branch?: Maybe; /** @deprecated Part of the old API surface and will be removed in the future. Use Project.models or Project.modelsTree instead. */ branches?: Maybe; @@ -2680,11 +2760,11 @@ export type Stream = { /** Whether the stream can be viewed by non-contributors */ isPublic: Scalars['Boolean']['output']; name: Scalars['String']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use Project.object instead. */ object?: Maybe; /** * Pending stream access requests - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use Project.pendingAccessRequests instead. */ pendingAccessRequests?: Maybe>; /** Collaborators who have been invited, but not yet accepted. */ @@ -3188,6 +3268,8 @@ export type User = { name: Scalars['String']['output']; notificationPreferences: Scalars['JSONObject']['output']; profiles?: Maybe; + /** Get pending project access request, that the user made */ + projectAccessRequest?: Maybe; /** Get all invitations to projects that the active user has */ projectInvites: Array; /** Get projects that the user participates in */ @@ -3253,6 +3335,15 @@ export type UserFavoriteStreamsArgs = { }; +/** + * Full user type, should only be used in the context of admin operations or + * when a user is reading/writing info about himself + */ +export type UserProjectAccessRequestArgs = { + projectId: Scalars['String']['input']; +}; + + /** * Full user type, should only be used in the context of admin operations or * when a user is reading/writing info about himself @@ -3397,18 +3488,30 @@ export type VersionCreatedTriggerDefinition = { export type VersionMutations = { __typename?: 'VersionMutations'; + create: Version; delete: Scalars['Boolean']['output']; + markReceived: Scalars['Boolean']['output']; moveToModel: Model; requestGendoAIRender: Scalars['Boolean']['output']; update: Version; }; +export type VersionMutationsCreateArgs = { + input: CreateVersionInput; +}; + + export type VersionMutationsDeleteArgs = { input: DeleteVersionsInput; }; +export type VersionMutationsMarkReceivedArgs = { + input: MarkReceivedVersionInput; +}; + + export type VersionMutationsMoveToModelArgs = { input: MoveVersionsInput; }; diff --git a/packages/server/modules/shared/index.js b/packages/server/modules/shared/index.js index 52880b47a..b79d62508 100644 --- a/packages/server/modules/shared/index.js +++ b/packages/server/modules/shared/index.js @@ -66,7 +66,7 @@ const getUserAclEntry = async ({ aclTableName, userId, resourceId }) => { * @param {string | null | undefined} userId * @param {string} resourceId * @param {string} requiredRole - * @param {import('@/modules/serverinvites/services/operations').TokenResourceIdentifier[] | undefined | null} [userResourceAccessLimits] + * @param {import('@/modules/core/domain/tokens/types').TokenResourceIdentifier[] | undefined | null} [userResourceAccessLimits] */ async function authorizeResolver( userId, diff --git a/packages/server/test/graphql/generated/graphql.ts b/packages/server/test/graphql/generated/graphql.ts index ae89c3c50..8aa3a9bdc 100644 --- a/packages/server/test/graphql/generated/graphql.ts +++ b/packages/server/test/graphql/generated/graphql.ts @@ -17,7 +17,6 @@ export type Scalars = { BigInt: { input: bigint; output: bigint; } /** A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. */ DateTime: { input: string; output: string; } - EmailAddress: { input: any; output: any; } /** The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). */ JSONObject: { input: Record; output: Record; } }; @@ -802,6 +801,16 @@ export type CreateModelInput = { projectId: Scalars['ID']['input']; }; +export type CreateVersionInput = { + message?: InputMaybe; + modelId: Scalars['String']['input']; + objectId: Scalars['String']['input']; + parents?: InputMaybe>; + projectId: Scalars['String']['input']; + sourceApplication?: InputMaybe; + totalChildrenCount?: InputMaybe; +}; + export type DeleteModelInput = { id: Scalars['ID']['input']; projectId: Scalars['ID']['input']; @@ -992,6 +1001,13 @@ export type LimitedUserTimelineArgs = { limit?: Scalars['Int']['input']; }; +export type MarkReceivedVersionInput = { + message?: InputMaybe; + projectId: Scalars['String']['input']; + sourceApplication: Scalars['String']['input']; + versionId: Scalars['String']['input']; +}; + export type Model = { __typename?: 'Model'; author: LimitedUser; @@ -1161,11 +1177,11 @@ export type Mutation = { * @deprecated Use commentMutations version */ commentView: Scalars['Boolean']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.create instead. */ commitCreate: Scalars['String']['output']; /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.delete instead. */ commitDelete: Scalars['Boolean']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.markReceived instead. */ commitReceive: Scalars['Boolean']['output']; /** @deprecated Part of the old API surface and will be removed in the future. Use VersionMutations.update/moveToModel instead. */ commitUpdate: Scalars['Boolean']['output']; @@ -1191,7 +1207,7 @@ export type Mutation = { inviteResend: Scalars['Boolean']['output']; modelMutations: ModelMutations; /** @deprecated Part of the old API surface and will be removed in the future. */ - objectCreate: Array>; + objectCreate: Array; projectMutations: ProjectMutations; /** (Re-)send the account verification e-mail */ requestVerification: Scalars['Boolean']['output']; @@ -1203,12 +1219,12 @@ export type Mutation = { serverInviteCreate: Scalars['Boolean']['output']; /** * Request access to a specific stream - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use ProjectAccessRequestMutations.create instead. */ streamAccessRequestCreate: StreamAccessRequest; /** * Accept or decline a stream access request. Must be a stream owner to invoke this. - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use ProjectAccessRequestMutations.use instead. */ streamAccessRequestUse: Scalars['Boolean']['output']; /** @@ -1265,7 +1281,7 @@ export type Mutation = { * @deprecated Part of the old API surface and will be removed in the future. Use ProjectMutations.updateRole instead. */ streamUpdatePermission?: Maybe; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use ProjectMutations.batchDelete instead. */ streamsDelete: Scalars['Boolean']['output']; /** * Used for broadcasting real time typing status in comment threads. Does not persist any info. @@ -1582,6 +1598,7 @@ export type MutationWebhookUpdateArgs = { export type Object = { __typename?: 'Object'; + /** @deprecated Not implemented. */ applicationId?: Maybe; /** * Get any objects that this object references. In the case of commits, this will give you a commit's constituent objects. @@ -1621,7 +1638,7 @@ export type ObjectChildrenArgs = { export type ObjectCollection = { __typename?: 'ObjectCollection'; cursor?: Maybe; - objects: Array>; + objects: Array; totalCount: Scalars['Int']['output']; }; @@ -1682,6 +1699,8 @@ export type Project = { blob?: Maybe; /** Get the metadata collection of blobs stored for this stream. */ blobs?: Maybe; + /** Get specific project comment/thread by ID */ + comment?: Maybe; /** All comment threads in this project */ commentThreads: ProjectCommentCollection; createdAt: Scalars['DateTime']['output']; @@ -1691,6 +1710,8 @@ export type Project = { invitedTeam?: Maybe>; /** Returns a specific model by its ID */ model: Model; + /** Retrieve a specific project model by its ID */ + modelByName: Model; /** Return a model tree of children for the specified model name */ modelChildrenTree: Array; /** Returns a flat list of all models */ @@ -1701,6 +1722,9 @@ export type Project = { */ modelsTree: ModelsTreeItemCollection; name: Scalars['String']['output']; + object?: Maybe; + /** Pending project access requests */ + pendingAccessRequests?: Maybe>; /** Returns a list models that are being created from a file import */ pendingImportedModels: Array; /** Active user's role for this project. `null` if request is not authenticated, or the project is not explicitly shared with you. */ @@ -1744,6 +1768,11 @@ export type ProjectBlobsArgs = { }; +export type ProjectCommentArgs = { + id: Scalars['String']['input']; +}; + + export type ProjectCommentThreadsArgs = { cursor?: InputMaybe; filter?: InputMaybe; @@ -1756,6 +1785,11 @@ export type ProjectModelArgs = { }; +export type ProjectModelByNameArgs = { + name: Scalars['String']['input']; +}; + + export type ProjectModelChildrenTreeArgs = { fullName: Scalars['String']['input']; }; @@ -1775,6 +1809,11 @@ export type ProjectModelsTreeArgs = { }; +export type ProjectObjectArgs = { + id: Scalars['String']['input']; +}; + + export type ProjectPendingImportedModelsArgs = { limit?: InputMaybe; }; @@ -1801,6 +1840,38 @@ export type ProjectWebhooksArgs = { id?: InputMaybe; }; +/** Created when a user requests to become a contributor on a project */ +export type ProjectAccessRequest = { + __typename?: 'ProjectAccessRequest'; + createdAt: Scalars['DateTime']['output']; + id: Scalars['ID']['output']; + /** Can only be selected if authed user has proper access */ + project: Project; + projectId: Scalars['String']['output']; + requester: LimitedUser; + requesterId: Scalars['String']['output']; +}; + +export type ProjectAccessRequestMutations = { + __typename?: 'ProjectAccessRequestMutations'; + /** Request access to a specific project */ + create: ProjectAccessRequest; + /** Accept or decline a project access request. Must be a project owner to invoke this. */ + use: Project; +}; + + +export type ProjectAccessRequestMutationsCreateArgs = { + projectId: Scalars['String']['input']; +}; + + +export type ProjectAccessRequestMutationsUseArgs = { + accept: Scalars['Boolean']['input']; + requestId: Scalars['String']['input']; + role?: StreamRole; +}; + export type ProjectAutomationCreateInput = { enabled: Scalars['Boolean']['input']; name: Scalars['String']['input']; @@ -2043,7 +2114,11 @@ export enum ProjectModelsUpdatedMessageType { export type ProjectMutations = { __typename?: 'ProjectMutations'; + /** Access request related mutations */ + accessRequestMutations: ProjectAccessRequestMutations; automationMutations: ProjectAutomationMutations; + /** Batch delete projects */ + batchDelete: Scalars['Boolean']['output']; /** Create new project */ create: Project; /** @@ -2069,6 +2144,11 @@ export type ProjectMutationsAutomationMutationsArgs = { }; +export type ProjectMutationsBatchDeleteArgs = { + ids: Array; +}; + + export type ProjectMutationsCreateArgs = { input?: InputMaybe; }; @@ -2232,7 +2312,7 @@ export type Query = { automateFunctions: AutomateFunctionCollection; /** Part of the automation/function creation handshake mechanism */ automateValidateAuthCode: Scalars['Boolean']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use Project.comment instead. */ comment?: Maybe; /** * This query can be used in the following ways: @@ -2271,7 +2351,7 @@ export type Query = { stream?: Maybe; /** * Get authed user's stream access request - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use User.projectAccessRequest instead. */ streamAccessRequest?: Maybe; /** @@ -2636,7 +2716,7 @@ export type Stream = { * @deprecated Part of the old API surface and will be removed in the future. Use Project.blobs instead. */ blobs?: Maybe; - /** @deprecated Part of the old API surface and will be removed in the future. Use Project.model instead. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use Project.model or Project.modelByName instead. */ branch?: Maybe; /** @deprecated Part of the old API surface and will be removed in the future. Use Project.models or Project.modelsTree instead. */ branches?: Maybe; @@ -2681,11 +2761,11 @@ export type Stream = { /** Whether the stream can be viewed by non-contributors */ isPublic: Scalars['Boolean']['output']; name: Scalars['String']['output']; - /** @deprecated Part of the old API surface and will be removed in the future. */ + /** @deprecated Part of the old API surface and will be removed in the future. Use Project.object instead. */ object?: Maybe; /** * Pending stream access requests - * @deprecated Part of the old API surface and will be removed in the future. + * @deprecated Part of the old API surface and will be removed in the future. Use Project.pendingAccessRequests instead. */ pendingAccessRequests?: Maybe>; /** Collaborators who have been invited, but not yet accepted. */ @@ -3189,6 +3269,8 @@ export type User = { name: Scalars['String']['output']; notificationPreferences: Scalars['JSONObject']['output']; profiles?: Maybe; + /** Get pending project access request, that the user made */ + projectAccessRequest?: Maybe; /** Get all invitations to projects that the active user has */ projectInvites: Array; /** Get projects that the user participates in */ @@ -3254,6 +3336,15 @@ export type UserFavoriteStreamsArgs = { }; +/** + * Full user type, should only be used in the context of admin operations or + * when a user is reading/writing info about himself + */ +export type UserProjectAccessRequestArgs = { + projectId: Scalars['String']['input']; +}; + + /** * Full user type, should only be used in the context of admin operations or * when a user is reading/writing info about himself @@ -3398,18 +3489,30 @@ export type VersionCreatedTriggerDefinition = { export type VersionMutations = { __typename?: 'VersionMutations'; + create: Version; delete: Scalars['Boolean']['output']; + markReceived: Scalars['Boolean']['output']; moveToModel: Model; requestGendoAIRender: Scalars['Boolean']['output']; update: Version; }; +export type VersionMutationsCreateArgs = { + input: CreateVersionInput; +}; + + export type VersionMutationsDeleteArgs = { input: DeleteVersionsInput; }; +export type VersionMutationsMarkReceivedArgs = { + input: MarkReceivedVersionInput; +}; + + export type VersionMutationsMoveToModelArgs = { input: MoveVersionsInput; }; @@ -3714,6 +3817,67 @@ export type DeleteCommitsMutationVariables = Exact<{ export type DeleteCommitsMutation = { __typename?: 'Mutation', commitsDelete: boolean }; +export type CreateProjectModelMutationVariables = Exact<{ + input: CreateModelInput; +}>; + + +export type CreateProjectModelMutation = { __typename?: 'Mutation', modelMutations: { __typename?: 'ModelMutations', create: { __typename?: 'Model', id: string, name: string, description?: string | null } } }; + +export type FindProjectModelByNameQueryVariables = Exact<{ + projectId: Scalars['String']['input']; + name: Scalars['String']['input']; +}>; + + +export type FindProjectModelByNameQuery = { __typename?: 'Query', project: { __typename?: 'Project', modelByName: { __typename?: 'Model', id: string, name: string, description?: string | null } } }; + +export type BasicProjectAccessRequestFieldsFragment = { __typename?: 'ProjectAccessRequest', id: string, requesterId: string, projectId: string, createdAt: string, requester: { __typename?: 'LimitedUser', id: string, name: string } }; + +export type CreateProjectAccessRequestMutationVariables = Exact<{ + projectId: Scalars['String']['input']; +}>; + + +export type CreateProjectAccessRequestMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', accessRequestMutations: { __typename?: 'ProjectAccessRequestMutations', create: { __typename?: 'ProjectAccessRequest', id: string, requesterId: string, projectId: string, createdAt: string, requester: { __typename?: 'LimitedUser', id: string, name: string } } } } }; + +export type GetActiveUserProjectAccessRequestQueryVariables = Exact<{ + projectId: Scalars['String']['input']; +}>; + + +export type GetActiveUserProjectAccessRequestQuery = { __typename?: 'Query', activeUser?: { __typename?: 'User', projectAccessRequest?: { __typename?: 'ProjectAccessRequest', id: string, requesterId: string, projectId: string, createdAt: string, requester: { __typename?: 'LimitedUser', id: string, name: string } } | null } | null }; + +export type GetActiveUserFullProjectAccessRequestQueryVariables = Exact<{ + projectId: Scalars['String']['input']; +}>; + + +export type GetActiveUserFullProjectAccessRequestQuery = { __typename?: 'Query', activeUser?: { __typename?: 'User', projectAccessRequest?: { __typename?: 'ProjectAccessRequest', id: string, requesterId: string, projectId: string, createdAt: string, project: { __typename?: 'Project', id: string, name: string }, requester: { __typename?: 'LimitedUser', id: string, name: string } } | null } | null }; + +export type GetPendingProjectAccessRequestsQueryVariables = Exact<{ + projectId: Scalars['String']['input']; +}>; + + +export type GetPendingProjectAccessRequestsQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, name: string, pendingAccessRequests?: Array<{ __typename?: 'ProjectAccessRequest', id: string, requesterId: string, projectId: string, createdAt: string, project: { __typename?: 'Project', id: string, name: string }, requester: { __typename?: 'LimitedUser', id: string, name: string } }> | null } }; + +export type UseProjectAccessRequestMutationVariables = Exact<{ + requestId: Scalars['String']['input']; + accept: Scalars['Boolean']['input']; + role?: StreamRole; +}>; + + +export type UseProjectAccessRequestMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', accessRequestMutations: { __typename?: 'ProjectAccessRequestMutations', use: { __typename?: 'Project', id: string } } } }; + +export type CreateProjectCommentMutationVariables = Exact<{ + input: CreateCommentInput; +}>; + + +export type CreateProjectCommentMutation = { __typename?: 'Mutation', commentMutations: { __typename?: 'CommentMutations', create: { __typename?: 'Comment', id: string, rawText: string, authorId: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record | null } } } }; + export type BasicProjectFieldsFragment = { __typename?: 'Project', id: string, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, role?: string | null, createdAt: string, updatedAt: string }; export type AdminProjectListQueryVariables = Exact<{ @@ -3727,6 +3891,28 @@ export type AdminProjectListQueryVariables = Exact<{ export type AdminProjectListQuery = { __typename?: 'Query', admin: { __typename?: 'AdminQueries', projectList: { __typename?: 'ProjectCollection', cursor?: string | null, totalCount: number, items: Array<{ __typename?: 'Project', id: string, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, role?: string | null, createdAt: string, updatedAt: string }> } } }; +export type GetProjectObjectQueryVariables = Exact<{ + projectId: Scalars['String']['input']; + objectId: Scalars['String']['input']; +}>; + + +export type GetProjectObjectQuery = { __typename?: 'Query', project: { __typename?: 'Project', object?: { __typename?: 'Object', id: string, createdAt?: string | null } | null } }; + +export type CreateProjectMutationVariables = Exact<{ + input: ProjectCreateInput; +}>; + + +export type CreateProjectMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', create: { __typename?: 'Project', id: string, name: string, description?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, role?: string | null, createdAt: string, updatedAt: string } } }; + +export type BatchDeleteProjectsMutationVariables = Exact<{ + ids: Array | Scalars['String']['input']; +}>; + + +export type BatchDeleteProjectsMutation = { __typename?: 'Mutation', projectMutations: { __typename?: 'ProjectMutations', batchDelete: boolean } }; + export type CreateServerInviteMutationVariables = Exact<{ input: ServerInviteCreateInput; }>; @@ -3907,11 +4093,26 @@ export type RequestVerificationMutationVariables = Exact<{ [key: string]: never; export type RequestVerificationMutation = { __typename?: 'Mutation', requestVerification: boolean }; +export type CreateProjectVersionMutationVariables = Exact<{ + input: CreateVersionInput; +}>; + + +export type CreateProjectVersionMutation = { __typename?: 'Mutation', versionMutations: { __typename?: 'VersionMutations', create: { __typename?: 'Version', id: string, message?: string | null, sourceApplication?: string | null, referencedObject: string, model: { __typename?: 'Model', id: string } } } }; + +export type MarkProjectVersionReceivedMutationVariables = Exact<{ + input: MarkReceivedVersionInput; +}>; + + +export type MarkProjectVersionReceivedMutation = { __typename?: 'Mutation', versionMutations: { __typename?: 'VersionMutations', markReceived: boolean } }; + export const BasicStreamAccessRequestFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicStreamAccessRequestFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"StreamAccessRequest"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"requester"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"requesterId"}},{"kind":"Field","name":{"kind":"Name","value":"streamId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]} as unknown as DocumentNode; export const TestAutomateFunctionFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TestAutomateFunction"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"repo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"owner"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"isFeatured"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"releases"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"5"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"versionTag"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"inputSchema"}},{"kind":"Field","name":{"kind":"Name","value":"commitId"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"automationCount"}},{"kind":"Field","name":{"kind":"Name","value":"supportedSourceApps"}},{"kind":"Field","name":{"kind":"Name","value":"tags"}}]}}]} as unknown as DocumentNode; export const TestAutomationFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"TestAutomation"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Automation"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"enabled"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"runs"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"trigger"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"VersionCreatedTrigger"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"version"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"model"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"functionRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"statusMessage"}},{"kind":"Field","name":{"kind":"Name","value":"contextView"}},{"kind":"Field","name":{"kind":"Name","value":"function"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"elapsed"}},{"kind":"Field","name":{"kind":"Name","value":"results"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"currentRevision"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"triggerDefinitions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"VersionCreatedTriggerDefinition"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"functions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"parameters"}},{"kind":"Field","name":{"kind":"Name","value":"release"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"function"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"versionTag"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"inputSchema"}},{"kind":"Field","name":{"kind":"Name","value":"commitId"}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const CommentWithRepliesFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CommentWithReplies"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Comment"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"rawText"}},{"kind":"Field","name":{"kind":"Name","value":"text"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"doc"}},{"kind":"Field","name":{"kind":"Name","value":"attachments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fileName"}},{"kind":"Field","name":{"kind":"Name","value":"streamId"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"replies"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"10"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"text"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"doc"}},{"kind":"Field","name":{"kind":"Name","value":"attachments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fileName"}},{"kind":"Field","name":{"kind":"Name","value":"streamId"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const BaseCommitFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BaseCommitFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Commit"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"authorName"}},{"kind":"Field","name":{"kind":"Name","value":"authorId"}},{"kind":"Field","name":{"kind":"Name","value":"authorAvatar"}},{"kind":"Field","name":{"kind":"Name","value":"streamId"}},{"kind":"Field","name":{"kind":"Name","value":"streamName"}},{"kind":"Field","name":{"kind":"Name","value":"sourceApplication"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"referencedObject"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"commentCount"}}]}}]} as unknown as DocumentNode; +export const BasicProjectAccessRequestFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicProjectAccessRequestFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectAccessRequest"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"requester"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"requesterId"}},{"kind":"Field","name":{"kind":"Name","value":"projectId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]} as unknown as DocumentNode; export const BasicProjectFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicProjectFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"allowPublicComments"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; export const StreamInviteDataFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"StreamInviteData"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"PendingStreamCollaborator"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"inviteId"}},{"kind":"Field","name":{"kind":"Name","value":"streamId"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"token"}},{"kind":"Field","name":{"kind":"Name","value":"invitedBy"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"bio"}},{"kind":"Field","name":{"kind":"Name","value":"company"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"verified"}}]}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"bio"}},{"kind":"Field","name":{"kind":"Name","value":"company"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"verified"}}]}}]}}]} as unknown as DocumentNode; export const BasicStreamFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicStreamFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Stream"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"isPublic"}},{"kind":"Field","name":{"kind":"Name","value":"isDiscoverable"}},{"kind":"Field","name":{"kind":"Name","value":"allowPublicComments"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; @@ -3938,7 +4139,18 @@ export const ReadOtherUsersCommitsDocument = {"kind":"Document","definitions":[{ export const ReadStreamBranchCommitsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ReadStreamBranchCommits"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"branchName"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},"defaultValue":{"kind":"IntValue","value":"10"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stream"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"streamId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"branch"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"branchName"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"commits"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BaseCommitFields"}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BaseCommitFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Commit"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"authorName"}},{"kind":"Field","name":{"kind":"Name","value":"authorId"}},{"kind":"Field","name":{"kind":"Name","value":"authorAvatar"}},{"kind":"Field","name":{"kind":"Name","value":"streamId"}},{"kind":"Field","name":{"kind":"Name","value":"streamName"}},{"kind":"Field","name":{"kind":"Name","value":"sourceApplication"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"referencedObject"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"commentCount"}}]}}]} as unknown as DocumentNode; export const MoveCommitsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"MoveCommits"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CommitsMoveInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"commitsMove"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode; export const DeleteCommitsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteCommits"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CommitsDeleteInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"commitsDelete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode; +export const CreateProjectModelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateProjectModel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateModelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}}]}}]}}]}}]} as unknown as DocumentNode; +export const FindProjectModelByNameDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindProjectModelByName"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"name"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelByName"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"name"},"value":{"kind":"Variable","name":{"kind":"Name","value":"name"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}}]}}]}}]}}]} as unknown as DocumentNode; +export const CreateProjectAccessRequestDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateProjectAccessRequest"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"accessRequestMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"projectId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicProjectAccessRequestFields"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicProjectAccessRequestFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectAccessRequest"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"requester"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"requesterId"}},{"kind":"Field","name":{"kind":"Name","value":"projectId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]} as unknown as DocumentNode; +export const GetActiveUserProjectAccessRequestDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetActiveUserProjectAccessRequest"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectAccessRequest"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"projectId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicProjectAccessRequestFields"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicProjectAccessRequestFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectAccessRequest"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"requester"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"requesterId"}},{"kind":"Field","name":{"kind":"Name","value":"projectId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]} as unknown as DocumentNode; +export const GetActiveUserFullProjectAccessRequestDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetActiveUserFullProjectAccessRequest"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectAccessRequest"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"projectId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicProjectAccessRequestFields"}},{"kind":"Field","name":{"kind":"Name","value":"project"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicProjectAccessRequestFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectAccessRequest"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"requester"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"requesterId"}},{"kind":"Field","name":{"kind":"Name","value":"projectId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]} as unknown as DocumentNode; +export const GetPendingProjectAccessRequestsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetPendingProjectAccessRequests"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"pendingAccessRequests"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicProjectAccessRequestFields"}},{"kind":"Field","name":{"kind":"Name","value":"project"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicProjectAccessRequestFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectAccessRequest"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"requester"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"requesterId"}},{"kind":"Field","name":{"kind":"Name","value":"projectId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]} as unknown as DocumentNode; +export const UseProjectAccessRequestDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UseProjectAccessRequest"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"requestId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"accept"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"role"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"StreamRole"}}},"defaultValue":{"kind":"EnumValue","value":"STREAM_CONTRIBUTOR"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"accessRequestMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"use"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"requestId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"requestId"}}},{"kind":"Argument","name":{"kind":"Name","value":"accept"},"value":{"kind":"Variable","name":{"kind":"Name","value":"accept"}}},{"kind":"Argument","name":{"kind":"Name","value":"role"},"value":{"kind":"Variable","name":{"kind":"Name","value":"role"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]}}]} as unknown as DocumentNode; +export const CreateProjectCommentDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateProjectComment"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateCommentInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"commentMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"rawText"}},{"kind":"Field","name":{"kind":"Name","value":"text"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"doc"}}]}},{"kind":"Field","name":{"kind":"Name","value":"authorId"}}]}}]}}]}}]} as unknown as DocumentNode; export const AdminProjectListDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AdminProjectList"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"query"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"visibility"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},"defaultValue":{"kind":"IntValue","value":"25"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}},"defaultValue":{"kind":"NullValue"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"admin"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectList"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"query"},"value":{"kind":"Variable","name":{"kind":"Name","value":"query"}}},{"kind":"Argument","name":{"kind":"Name","value":"orderBy"},"value":{"kind":"Variable","name":{"kind":"Name","value":"orderBy"}}},{"kind":"Argument","name":{"kind":"Name","value":"visibility"},"value":{"kind":"Variable","name":{"kind":"Name","value":"visibility"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicProjectFields"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicProjectFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"allowPublicComments"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; +export const GetProjectObjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetProjectObject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"objectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"object"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"objectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}}]}}]}}]}}]} as unknown as DocumentNode; +export const CreateProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateProject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectCreateInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BasicProjectFields"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BasicProjectFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"allowPublicComments"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; +export const BatchDeleteProjectsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"BatchDeleteProjects"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"ids"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"batchDelete"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"ids"},"value":{"kind":"Variable","name":{"kind":"Name","value":"ids"}}}]}]}}]}}]} as unknown as DocumentNode; export const CreateServerInviteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateServerInvite"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ServerInviteCreateInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serverInviteCreate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode; export const CreateStreamInviteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateStreamInvite"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"StreamInviteCreateInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"streamInviteCreate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode; export const ResendInviteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"ResendInvite"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"inviteResend"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"inviteId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"inviteId"}}}]}]}}]} as unknown as DocumentNode; @@ -3962,4 +4174,6 @@ export const GetActiveUserDocument = {"kind":"Document","definitions":[{"kind":" export const GetOtherUserDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetOtherUser"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"otherUser"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"BaseLimitedUserFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"BaseLimitedUserFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"LimitedUser"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"bio"}},{"kind":"Field","name":{"kind":"Name","value":"company"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"verified"}}]}}]} as unknown as DocumentNode; export const GetAdminUsersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetAdminUsers"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},"defaultValue":{"kind":"IntValue","value":"25"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"offset"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},"defaultValue":{"kind":"IntValue","value":"0"}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"query"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}},"defaultValue":{"kind":"NullValue"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"adminUsers"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}},{"kind":"Argument","name":{"kind":"Name","value":"offset"},"value":{"kind":"Variable","name":{"kind":"Name","value":"offset"}}},{"kind":"Argument","name":{"kind":"Name","value":"query"},"value":{"kind":"Variable","name":{"kind":"Name","value":"query"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"registeredUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"invitedUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"invitedBy"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const GetPendingEmailVerificationStatusDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetPendingEmailVerificationStatus"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasPendingVerification"}}]}}]}}]} as unknown as DocumentNode; -export const RequestVerificationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RequestVerification"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"requestVerification"}}]}}]} as unknown as DocumentNode; \ No newline at end of file +export const RequestVerificationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RequestVerification"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"requestVerification"}}]}}]} as unknown as DocumentNode; +export const CreateProjectVersionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateProjectVersion"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateVersionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"versionMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"sourceApplication"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"referencedObject"}}]}}]}}]}}]} as unknown as DocumentNode; +export const MarkProjectVersionReceivedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"MarkProjectVersionReceived"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"MarkReceivedVersionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"versionMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"markReceived"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file diff --git a/packages/server/test/graphql/models.ts b/packages/server/test/graphql/models.ts new file mode 100644 index 000000000..82459405b --- /dev/null +++ b/packages/server/test/graphql/models.ts @@ -0,0 +1,25 @@ +import { gql } from 'apollo-server-express' + +export const createProjectModelQuery = gql` + mutation CreateProjectModel($input: CreateModelInput!) { + modelMutations { + create(input: $input) { + id + name + description + } + } + } +` + +export const findProjectModelByNameQuery = gql` + query FindProjectModelByName($projectId: String!, $name: String!) { + project(id: $projectId) { + modelByName(name: $name) { + id + name + description + } + } + } +` diff --git a/packages/server/test/graphql/projectAccessRequests.ts b/packages/server/test/graphql/projectAccessRequests.ts new file mode 100644 index 000000000..751f7813f --- /dev/null +++ b/packages/server/test/graphql/projectAccessRequests.ts @@ -0,0 +1,90 @@ +import { gql } from 'apollo-server-express' + +const basicProjectAccessRequestFragment = gql` + fragment BasicProjectAccessRequestFields on ProjectAccessRequest { + id + requester { + id + name + } + requesterId + projectId + createdAt + } +` + +export const createProjectAccessRequestMutation = gql` + mutation CreateProjectAccessRequest($projectId: String!) { + projectMutations { + accessRequestMutations { + create(projectId: $projectId) { + ...BasicProjectAccessRequestFields + } + } + } + } + + ${basicProjectAccessRequestFragment} +` + +export const getActiveUserProjectAccessRequestQuery = gql` + query GetActiveUserProjectAccessRequest($projectId: String!) { + activeUser { + projectAccessRequest(projectId: $projectId) { + ...BasicProjectAccessRequestFields + } + } + } + + ${basicProjectAccessRequestFragment} +` + +export const getActiveUserFullProjectAccessRequestQuery = gql` + query GetActiveUserFullProjectAccessRequest($projectId: String!) { + activeUser { + projectAccessRequest(projectId: $projectId) { + ...BasicProjectAccessRequestFields + project { + id + name + } + } + } + } + + ${basicProjectAccessRequestFragment} +` + +export const getPendingProjectAccessRequestsQuery = gql` + query GetPendingProjectAccessRequests($projectId: String!) { + project(id: $projectId) { + id + name + pendingAccessRequests { + ...BasicProjectAccessRequestFields + project { + id + name + } + } + } + } + + ${basicProjectAccessRequestFragment} +` + +export const useProjectAccessRequestMutation = gql` + mutation UseProjectAccessRequest( + $requestId: String! + $accept: Boolean! + $role: StreamRole! = STREAM_CONTRIBUTOR + ) { + projectMutations { + accessRequestMutations { + use(requestId: $requestId, accept: $accept, role: $role) { + id + } + } + } + } +` diff --git a/packages/server/test/graphql/projectComments.ts b/packages/server/test/graphql/projectComments.ts new file mode 100644 index 000000000..3ee81c4a0 --- /dev/null +++ b/packages/server/test/graphql/projectComments.ts @@ -0,0 +1,16 @@ +import { gql } from 'apollo-server-express' + +export const createProjectCommentMutation = gql` + mutation CreateProjectComment($input: CreateCommentInput!) { + commentMutations { + create(input: $input) { + id + rawText + text { + doc + } + authorId + } + } + } +` diff --git a/packages/server/test/graphql/projects.ts b/packages/server/test/graphql/projects.ts index ed2d8ebdd..0212a4b4c 100644 --- a/packages/server/test/graphql/projects.ts +++ b/packages/server/test/graphql/projects.ts @@ -13,15 +13,7 @@ export const basicProjectFieldsFragment = gql` } ` -/** - * query: String - orderBy: String - visibility: String - limit: Int! = 25 - cursor: String = null - */ - -export const adminProjectList = gql` +export const adminProjectListQuery = gql` query AdminProjectList( $query: String $orderBy: String @@ -48,3 +40,34 @@ export const adminProjectList = gql` ${basicProjectFieldsFragment} ` + +export const getProjectObjectQuery = gql` + query GetProjectObject($projectId: String!, $objectId: String!) { + project(id: $projectId) { + object(id: $objectId) { + id + createdAt + } + } + } +` + +export const createProjectMutation = gql` + mutation CreateProject($input: ProjectCreateInput!) { + projectMutations { + create(input: $input) { + ...BasicProjectFields + } + } + } + + ${basicProjectFieldsFragment} +` + +export const batchDeleteProjectsMutation = gql` + mutation BatchDeleteProjects($ids: [String!]!) { + projectMutations { + batchDelete(ids: $ids) + } + } +` diff --git a/packages/server/test/graphql/versions.ts b/packages/server/test/graphql/versions.ts new file mode 100644 index 000000000..c8ab20e89 --- /dev/null +++ b/packages/server/test/graphql/versions.ts @@ -0,0 +1,25 @@ +import { gql } from 'apollo-server-express' + +export const createProjectVersionMutation = gql` + mutation CreateProjectVersion($input: CreateVersionInput!) { + versionMutations { + create(input: $input) { + id + message + sourceApplication + model { + id + } + referencedObject + } + } + } +` + +export const markProjectVersionReceivedMutation = gql` + mutation MarkProjectVersionReceived($input: MarkReceivedVersionInput!) { + versionMutations { + markReceived(input: $input) + } + } +` diff --git a/packages/server/test/graphqlHelper.ts b/packages/server/test/graphqlHelper.ts index 4109747fd..0741f9717 100644 --- a/packages/server/test/graphqlHelper.ts +++ b/packages/server/test/graphqlHelper.ts @@ -7,6 +7,8 @@ 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' type TypedGraphqlResponse> = GraphQLResponse & { data: Nullable @@ -51,10 +53,26 @@ export const createTestContext = ( /** * Utilities that make it easier to test against an Apollo Server instance */ -export const testApolloServer = async (params?: { context?: GraphQLContext }) => { - const instance = params?.context +export const testApolloServer = async (params?: { + context?: GraphQLContext + /** + * If set, will create an authed context w/ all scopes and Server.User role for thies user id + */ + authUserId?: string +}) => { + const initialCtx: GraphQLContext | undefined = params?.authUserId + ? createTestContext({ + auth: true, + userId: params.authUserId, + role: Roles.Server.User, + token: 'asd', + scopes: AllScopes + }) + : params?.context + + const instance = initialCtx ? await buildApolloServer({ - context: params.context + context: initialCtx }) : await buildUnauthenticatedApolloServer() @@ -77,7 +95,7 @@ export const testApolloServer = async (params?: { context?: GraphQLContext }) => const realInstance = options?.context ? await buildApolloServer({ context: createTestContext({ - ...(params?.context || {}), + ...(initialCtx || {}), ...options.context }) }) diff --git a/packages/server/test/speckle-helpers/branchHelper.ts b/packages/server/test/speckle-helpers/branchHelper.ts new file mode 100644 index 000000000..fdd71959e --- /dev/null +++ b/packages/server/test/speckle-helpers/branchHelper.ts @@ -0,0 +1,44 @@ +import { createBranch } from '@/modules/core/services/branches' +import { BasicTestUser } from '@/test/authHelper' +import { BasicTestStream } from '@/test/speckle-helpers/streamHelper' +import { omit } from 'lodash' + +export type BasicTestBranch = { + name: string + description?: string + /** + * The ID of the stream. Will be filled in by createTestBranch(). + */ + streamId: string + /** + * The ID of the owner. Will be filled in by createTestBranch(). + */ + authorId: string + + /** + * The ID of the branch. Will be filled in by createTestBranch(). + */ + id: string +} + +export async function createTestBranch(params: { + branch: BasicTestBranch + stream: BasicTestStream + owner: BasicTestUser +}) { + const { branch, stream, owner } = params + branch.streamId = stream.id + branch.authorId = owner.id + + const id = await createBranch({ + ...omit(branch, ['id']), + description: branch.description || null + }) + branch.id = id +} + +export async function createTestBranches( + branches: Array[0]> +) { + await Promise.all(branches.map((p) => createTestBranch(p))) +} diff --git a/packages/server/test/speckle-helpers/commitHelper.ts b/packages/server/test/speckle-helpers/commitHelper.ts index b851bdae2..f474574aa 100644 --- a/packages/server/test/speckle-helpers/commitHelper.ts +++ b/packages/server/test/speckle-helpers/commitHelper.ts @@ -1,5 +1,7 @@ import { createCommitByBranchName } from '@/modules/core/services/commits' import { createObject } from '@/modules/core/services/objects' +import { BasicTestUser } from '@/test/authHelper' +import { BasicTestStream } from '@/test/speckle-helpers/streamHelper' export type BasicTestCommit = { /** @@ -10,7 +12,13 @@ export type BasicTestCommit = { * Can be left empty, will be filled on creation */ objectId: string + /** + * Can be left empty, will be filled on creation if stream passed in + */ streamId: string + /** + * Can be left empty, will be filled on creation if owner passed in + */ authorId: string /** * Defaults to 'main' @@ -27,6 +35,10 @@ export type BasicTestCommit = { parents?: string[] } +export async function createTestObject(params: { projectId: string }) { + return await createObject(params.projectId, { foo: 'bar' }) +} + /** * Ensure all commits have objectId set */ @@ -42,13 +54,23 @@ async function ensureObjects(commits: BasicTestCommit[]) { /** * Create test commits */ -export async function createTestCommits(commits: BasicTestCommit[]) { +export async function createTestCommits( + commits: BasicTestCommit[], + options?: Partial<{ owner: BasicTestUser; stream: BasicTestStream }> +) { + const { owner, stream } = options || {} + + commits.forEach((c) => { + if (owner) c.authorId = owner.id + if (stream) c.streamId = stream.id + }) + await ensureObjects(commits) await Promise.all( commits.map((c) => createCommitByBranchName({ streamId: c.streamId, - branchName: 'main', + branchName: c.branchName || 'main', message: c.message || 'this message is auto generated', sourceApplication: 'tests', objectId: c.objectId, @@ -60,6 +82,9 @@ export async function createTestCommits(commits: BasicTestCommit[]) { ) } -export async function createTestCommit(commit: BasicTestCommit) { - await createTestCommits([commit]) +export async function createTestCommit( + commit: BasicTestCommit, + options?: Partial<{ owner: BasicTestUser; stream: BasicTestStream }> +) { + await createTestCommits([commit], options) } diff --git a/packages/server/test/speckle-helpers/streamHelper.ts b/packages/server/test/speckle-helpers/streamHelper.ts index 82b53a031..ed9852f0b 100644 --- a/packages/server/test/speckle-helpers/streamHelper.ts +++ b/packages/server/test/speckle-helpers/streamHelper.ts @@ -9,7 +9,7 @@ export type BasicTestStream = { name: string isPublic: boolean /** - * The ID of the owner user + * The ID of the owner user. Will be filled in by createTestStream(). */ ownerId: string /**