From 1d9b070ae8aeae71f6a00b15da00a23552a9d0b3 Mon Sep 17 00:00:00 2001 From: Kristaps Fabians Geikins Date: Thu, 22 Feb 2024 15:23:16 +0200 Subject: [PATCH] feat(server): project.version query for easier cross server sync --- .../lib/common/generated/gql/graphql.ts | 15 ++++++++++ .../core/typedefs/modelsAndVersions.graphql | 5 ++++ .../modules/core/graph/generated/graphql.ts | 8 +++++ .../modules/core/graph/resolvers/versions.ts | 7 +++++ .../server/modules/core/helpers/graphTypes.ts | 1 + packages/server/modules/core/loaders.ts | 30 +++++++++++++++++++ .../graph/generated/graphql.ts | 7 +++++ .../server/test/graphql/generated/graphql.ts | 7 +++++ 8 files changed, 80 insertions(+) diff --git a/packages/frontend-2/lib/common/generated/gql/graphql.ts b/packages/frontend-2/lib/common/generated/gql/graphql.ts index b34749c1e..c9496083d 100644 --- a/packages/frontend-2/lib/common/generated/gql/graphql.ts +++ b/packages/frontend-2/lib/common/generated/gql/graphql.ts @@ -1437,6 +1437,8 @@ export type Project = { sourceApps: Array; team: Array; updatedAt: Scalars['DateTime']; + /** Retrieve a specific project version by its ID */ + version?: Maybe; /** Returns a flat list of all project versions */ versions: VersionCollection; /** Return metadata about resources being requested in the viewer */ @@ -1482,6 +1484,11 @@ export type ProjectPendingImportedModelsArgs = { }; +export type ProjectVersionArgs = { + id: Scalars['String']; +}; + + export type ProjectVersionsArgs = { cursor?: InputMaybe; limit?: Scalars['Int']; @@ -2076,6 +2083,8 @@ export type ServerInfo = { description?: Maybe; guestModeEnabled: Scalars['Boolean']; inviteOnly?: Maybe; + /** Server relocation / migration info */ + migration?: Maybe; name: Scalars['String']; /** @deprecated Use role constants from the @speckle/shared npm package instead */ roles: Array; @@ -2109,6 +2118,12 @@ export type ServerInviteCreateInput = { serverRole?: InputMaybe; }; +export type ServerMigration = { + __typename?: 'ServerMigration'; + movedFrom?: Maybe; + movedTo?: Maybe; +}; + export enum ServerRole { ServerAdmin = 'SERVER_ADMIN', ServerArchivedUser = 'SERVER_ARCHIVED_USER', diff --git a/packages/server/assets/core/typedefs/modelsAndVersions.graphql b/packages/server/assets/core/typedefs/modelsAndVersions.graphql index c5ef23885..22073d5f8 100644 --- a/packages/server/assets/core/typedefs/modelsAndVersions.graphql +++ b/packages/server/assets/core/typedefs/modelsAndVersions.graphql @@ -35,6 +35,11 @@ extend type Project { Returns a flat list of all project versions """ versions(limit: Int! = 25, cursor: String): VersionCollection! + + """ + Retrieve a specific project version by its ID + """ + version(id: String!): Version } input ProjectModelsTreeFilter { diff --git a/packages/server/modules/core/graph/generated/graphql.ts b/packages/server/modules/core/graph/generated/graphql.ts index 87a7c82c4..d2a364ab8 100644 --- a/packages/server/modules/core/graph/generated/graphql.ts +++ b/packages/server/modules/core/graph/generated/graphql.ts @@ -1450,6 +1450,8 @@ export type Project = { sourceApps: Array; team: Array; updatedAt: Scalars['DateTime']; + /** Retrieve a specific project version by its ID */ + version?: Maybe; /** Returns a flat list of all project versions */ versions: VersionCollection; /** Return metadata about resources being requested in the viewer */ @@ -1495,6 +1497,11 @@ export type ProjectPendingImportedModelsArgs = { }; +export type ProjectVersionArgs = { + id: Scalars['String']; +}; + + export type ProjectVersionsArgs = { cursor?: InputMaybe; limit?: Scalars['Int']; @@ -3884,6 +3891,7 @@ export type ProjectResolvers, ParentType, ContextType>; team?: Resolver, ParentType, ContextType>; updatedAt?: Resolver; + version?: Resolver, ParentType, ContextType, RequireFields>; versions?: Resolver>; viewerResources?: Resolver, ParentType, ContextType, RequireFields>; visibility?: Resolver; diff --git a/packages/server/modules/core/graph/resolvers/versions.ts b/packages/server/modules/core/graph/resolvers/versions.ts index d6254de0b..f3f2012ec 100644 --- a/packages/server/modules/core/graph/resolvers/versions.ts +++ b/packages/server/modules/core/graph/resolvers/versions.ts @@ -14,6 +14,13 @@ import { CommitUpdateError } from '@/modules/core/errors/commit' import { updateCommitAndNotify } from '@/modules/core/services/commit/management' export = { + Project: { + async version(parent, args, ctx) { + return await ctx.loaders.streams.getStreamCommit + .forStream(parent.id) + .load(args.id) + } + }, Version: { async authorUser(parent, _args, ctx) { const { author } = parent diff --git a/packages/server/modules/core/helpers/graphTypes.ts b/packages/server/modules/core/helpers/graphTypes.ts index c989d2cd7..d9d82eadb 100644 --- a/packages/server/modules/core/helpers/graphTypes.ts +++ b/packages/server/modules/core/helpers/graphTypes.ts @@ -68,6 +68,7 @@ export type ProjectGraphQLReturn = StreamRecord & | 'allowPublicComments' | 'pendingImportedModels' | 'webhooks' + | 'version' > & { /** * Some queries resolve the role, some don't. If role isn't returned, no worries, it'll diff --git a/packages/server/modules/core/loaders.ts b/packages/server/modules/core/loaders.ts index 3c36a5660..bbea00529 100644 --- a/packages/server/modules/core/loaders.ts +++ b/packages/server/modules/core/loaders.ts @@ -26,6 +26,7 @@ import { Nullable } from '@/modules/shared/helpers/typeHelper' import { ServerInviteRecord } from '@/modules/serverinvites/helpers/types' import { getCommitBranches, + getCommits, getSpecificBranchCommits, getStreamCommitCounts } from '@/modules/core/repositories/commits' @@ -103,6 +104,35 @@ export function buildRequestLoaders( const loaders = { streams: { + /** + * Get a specific commit of a specific stream. Each stream ID technically has its own loader & + * thus its own query. + */ + getStreamCommit: (() => { + type CommitDataLoader = DataLoader> + const streamCommitLoaders = new Map() + return { + clearAll: () => streamCommitLoaders.clear(), + forStream(streamId: string): CommitDataLoader { + let loader = streamCommitLoaders.get(streamId) + if (!loader) { + loader = createLoader>( + async (commitIds) => { + const results = keyBy( + await getCommits(commitIds.slice(), { streamId }), + 'id' + ) + return commitIds.map((i) => results[i] || null) + } + ) + streamCommitLoaders.set(streamId, loader) + } + + return loader + } + } + })(), + /** * Get favorite metadata for a specific stream and user */ 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 18e6c952b..86606b889 100644 --- a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts +++ b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts @@ -1440,6 +1440,8 @@ export type Project = { sourceApps: Array; team: Array; updatedAt: Scalars['DateTime']; + /** Retrieve a specific project version by its ID */ + version?: Maybe; /** Returns a flat list of all project versions */ versions: VersionCollection; /** Return metadata about resources being requested in the viewer */ @@ -1485,6 +1487,11 @@ export type ProjectPendingImportedModelsArgs = { }; +export type ProjectVersionArgs = { + id: Scalars['String']; +}; + + export type ProjectVersionsArgs = { cursor?: InputMaybe; limit?: Scalars['Int']; diff --git a/packages/server/test/graphql/generated/graphql.ts b/packages/server/test/graphql/generated/graphql.ts index eea51a2f5..9ce39ef50 100644 --- a/packages/server/test/graphql/generated/graphql.ts +++ b/packages/server/test/graphql/generated/graphql.ts @@ -1441,6 +1441,8 @@ export type Project = { sourceApps: Array; team: Array; updatedAt: Scalars['DateTime']; + /** Retrieve a specific project version by its ID */ + version?: Maybe; /** Returns a flat list of all project versions */ versions: VersionCollection; /** Return metadata about resources being requested in the viewer */ @@ -1486,6 +1488,11 @@ export type ProjectPendingImportedModelsArgs = { }; +export type ProjectVersionArgs = { + id: Scalars['String']; +}; + + export type ProjectVersionsArgs = { cursor?: InputMaybe; limit?: Scalars['Int'];