fix(versions): object history hidden when quering by project (#4884)

This commit is contained in:
Daniel Gak Anagrov
2025-06-04 10:44:08 +02:00
committed by GitHub
parent 17f5b872d5
commit 460245a71b
11 changed files with 279 additions and 43 deletions
@@ -92,7 +92,7 @@ import {
CommitWithStreamBranchMetadata
} from '@/modules/core/domain/commits/types'
import { logger } from '@/observability/logging'
import { getLastVersionByProjectIdFactory } from '@/modules/core/repositories/versions'
import { getLastVersionsByProjectIdFactory } from '@/modules/core/repositories/versions'
import { StreamRoles } from '@speckle/shared'
declare module '@/modules/core/loaders' {
@@ -137,7 +137,7 @@ const dataLoadersDefinition = defineRequestDataloaders(
const getStreamsSourceApps = getStreamsSourceAppsFactory({ db })
const getUsers = getUsersFactory({ db })
const getStreamsCollaborators = getStreamsCollaboratorsFactory({ db })
const getLastVersionByProjectId = getLastVersionByProjectIdFactory({ db })
const getLastestVersionsByProjectId = getLastVersionsByProjectIdFactory({ db })
const getStreamsCollaboratorCounts = getStreamsCollaboratorCountsFactory({
db
})
@@ -371,11 +371,11 @@ const dataLoadersDefinition = defineRequestDataloaders(
}
}
})(),
getLastVersion: createLoader<string, Nullable<CommitRecord>>(
getLatestVersions: createLoader<string, Array<CommitRecord>>(
async (projectIds) => {
const results = keyBy(
await getLastVersionByProjectId({ projectIds }),
(c) => c.projectId
await getLastestVersionsByProjectId({ projectIds }),
(c) => c[0].projectId
)
return projectIds.map((projectId) => results[projectId] || null)
}
@@ -134,18 +134,23 @@ export = {
project
})
let lastVersion: Version | null
let latestVersion: Version | null = null
let latestVersions: Array<Version> | null = null
if (getTypeFromPath(info) === 'Model') {
lastVersion = await ctx.loaders
latestVersion = await ctx.loaders
.forRegion({ db: projectDB })
.branches.getLatestCommit.load(parent.branchId)
} else {
lastVersion = await ctx.loaders
latestVersions = await ctx.loaders
.forRegion({ db: projectDB })
.streams.getLastVersion.load(parent.streamId)
.streams.getLatestVersions.load(parent.streamId)
}
if (lastVersion?.id === parent.id) return parent.referencedObject
if (
latestVersion?.id === parent.id ||
latestVersions?.find((lv) => lv.id === parent.id)
)
return parent.referencedObject
if (isBeyondLimit) return null
return parent.referencedObject
}
@@ -1,31 +1,26 @@
import { Commits, knex, StreamCommits } from '@/modules/core/dbSchema'
import { BranchCommits, knex, Branches, Commits } from '@/modules/core/dbSchema'
import { Version } from '@/modules/core/domain/commits/types'
import { Knex } from 'knex'
import { groupBy } from 'lodash'
const tables = {
versions: (db: Knex) => db<Version>(Commits.name)
}
export const getLastVersionByProjectIdFactory =
export const getLastVersionsByProjectIdFactory =
({ db }: { db: Knex }) =>
async ({
projectIds
}: {
projectIds: readonly string[]
}): Promise<Record<string, Version & { projectId: string }>> => {
const results = await tables
.versions(db)
.join(StreamCommits.name, StreamCommits.col.commitId, Commits.col.id)
.whereIn(StreamCommits.col.streamId, projectIds)
.distinctOn(StreamCommits.col.streamId)
.select([...Commits.cols, knex.raw(`stream_commits."streamId" as "projectId"`)])
}): Promise<Record<string, Array<Version & { projectId: string }>>> => {
const res = await db(Branches.name)
.whereIn(Branches.col.streamId, projectIds)
.join(BranchCommits.name, BranchCommits.col.branchId, Branches.col.id)
.join(Commits.name, Commits.col.id, BranchCommits.col.commitId)
.distinctOn(Branches.col.id)
.select([...Commits.cols, knex.raw(`branches."streamId" as "projectId"`)])
.orderBy([
{ column: StreamCommits.col.streamId, order: 'desc' },
{ column: Commits.col.createdAt, order: 'desc' }
{ column: Branches.col.id, order: 'desc' },
{ column: Commits.col.createdAt, order: 'desc' },
{ column: Commits.col.id, order: 'desc' }
])
return results.reduce<Record<string, Version & { projectId: string }>>(
(acc, curr) => ({ ...acc, [curr.projectId]: curr }),
{}
)
return groupBy(res, 'projectId')
}
@@ -2,8 +2,11 @@ import cryptoRandomString from 'crypto-random-string'
import { Project } from '@/modules/core/domain/streams/types'
import { ProjectRecordVisibility } from '@/modules/core/helpers/types'
import { assign } from 'lodash'
import { BasicTestCommit } from '@/test/speckle-helpers/commitHelper'
import { BasicTestBranch } from '@/test/speckle-helpers/branchHelper'
import { BasicTestStream } from '@/test/speckle-helpers/streamHelper'
export const buildBasicTestProject = (overrides?: Partial<Project>): Project =>
export const buildTestProject = (overrides?: Partial<Project>): Project =>
assign(
{
id: cryptoRandomString({ length: 10 }),
@@ -19,3 +22,47 @@ export const buildBasicTestProject = (overrides?: Partial<Project>): Project =>
},
overrides
)
export const buildBasicTestProject = (
overrides?: Partial<BasicTestStream>
): BasicTestStream =>
assign(
{
name: cryptoRandomString({ length: 10 }),
isPublic: true,
ownerId: cryptoRandomString({ length: 10 }),
id: cryptoRandomString({ length: 10 })
},
overrides
)
export const buildBasicTestModel = (
overrides?: Partial<BasicTestBranch>
): BasicTestBranch =>
assign(
{
name: cryptoRandomString({ length: 10 }),
description: cryptoRandomString({ length: 10 }),
streamId: cryptoRandomString({ length: 10 }),
authorId: cryptoRandomString({ length: 10 }),
id: cryptoRandomString({ length: 10 })
},
overrides
)
export const buildBasicTestVersion = (
overrides?: Partial<BasicTestCommit>
): BasicTestCommit =>
assign(
{
id: cryptoRandomString({ length: 10 }),
objectId: cryptoRandomString({ length: 10 }),
streamId: cryptoRandomString({ length: 10 }),
authorId: cryptoRandomString({ length: 10 }),
branchId: cryptoRandomString({ length: 10 }),
branchName: cryptoRandomString({ length: 10 }),
message: cryptoRandomString({ length: 10 }),
createdAt: new Date()
},
overrides
)
@@ -3,7 +3,7 @@ import {
createRandomEmail,
createRandomString
} from '@/modules/core/helpers/testHelpers'
import { getLastVersionByProjectIdFactory } from '@/modules/core/repositories/versions'
import { getLastVersionsByProjectIdFactory } from '@/modules/core/repositories/versions'
import { createTestUser } from '@/test/authHelper'
import { BasicTestCommit, createTestCommit } from '@/test/speckle-helpers/commitHelper'
import { createTestStream } from '@/test/speckle-helpers/streamHelper'
@@ -11,7 +11,7 @@ import { expect } from 'chai'
describe('Versions repositories @core', () => {
describe('getLastVersionByProjectIdFactory returns a function that, ', () => {
const getLastVersionByProjectId = getLastVersionByProjectIdFactory({ db })
const getLastVersionsByProjectId = getLastVersionsByProjectIdFactory({ db })
it('should return the last version for each projectId', async () => {
const user = await createTestUser({
name: createRandomString(),
@@ -57,13 +57,13 @@ describe('Versions repositories @core', () => {
owner: user
})
const result = await getLastVersionByProjectId({
const result = await getLastVersionsByProjectId({
projectIds: [project1.id, project2.id]
})
const lastVersionProject1 = result[project1.id]
const lastVersionProject2 = result[project2.id]
expect(lastVersionProject1.projectId).to.eq(project1.id)
expect(lastVersionProject2.projectId).to.eq(project2.id)
expect(lastVersionProject1[0].projectId).to.eq(project1.id)
expect(lastVersionProject2[0].projectId).to.eq(project2.id)
})
})
})
@@ -17,6 +17,7 @@ import {
CreateProjectVersionDocument,
CreateWorkspaceDocument,
CreateWorkspaceProjectDocument,
GetProjectVersionsDocument,
GetProjectWithModelVersionsDocument,
GetProjectWithVersionsDocument
} from '@/test/graphql/generated/graphql'
@@ -42,13 +43,26 @@ import { WorkspaceReadOnlyError } from '@/modules/gatekeeper/errors/billing'
import { CreateVersionInput } from '@/modules/core/graph/generated/graphql'
import { getFeatureFlags } from '@/modules/shared/helpers/envHelper'
import { getEventBus } from '@/modules/shared/services/eventBus'
import { createTestUser, login } from '@/test/authHelper'
import { buildBasicTestUser, createTestUser, login } from '@/test/authHelper'
import { BasicTestStream, createTestStream } from '@/test/speckle-helpers/streamHelper'
import { BasicTestCommit, createTestCommit } from '@/test/speckle-helpers/commitHelper'
import {
BasicTestCommit,
createTestCommit,
createTestObject
} from '@/test/speckle-helpers/commitHelper'
import { BranchCommits, Commits, StreamCommits } from '@/modules/core/dbSchema'
import { BasicTestBranch, createTestBranch } from '@/test/speckle-helpers/branchHelper'
import dayjs from 'dayjs'
import { createTestWorkspace } from '@/modules/workspaces/tests/helpers/creation'
import {
buildBasicTestWorkspace,
createTestWorkspace
} from '@/modules/workspaces/tests/helpers/creation'
import {
buildBasicTestModel,
buildBasicTestProject,
buildBasicTestVersion
} from '@/modules/core/tests/helpers/creation'
import { Optional } from '@speckle/shared'
const getServerInfo = getServerInfoFactory({ db })
const getUser = legacyGetUserFactory({ db })
@@ -136,6 +150,156 @@ describe('Versions graphql @core', () => {
}
)
})
;(FF_BILLING_INTEGRATION_ENABLED ? describe : describe.skip)(
'version limit query @new-versions',
() => {
const updateCommitCreatedAtDate = async (
id: string,
createdAt: Date // Make the project read-only
) => await db('commits').update({ createdAt }).where({ id })
const user = buildBasicTestUser()
const workspace = buildBasicTestWorkspace()
const model1 = buildBasicTestModel()
const model2 = buildBasicTestModel()
const project = buildBasicTestProject()
const version1 = buildBasicTestVersion()
const version2 = buildBasicTestVersion()
const version3 = buildBasicTestVersion()
let objectId1: Optional<string> = undefined
let objectId2: Optional<string> = undefined
let objectId3: Optional<string> = undefined
before(async () => {
user.id = await createUser(user)
await createTestWorkspace(workspace, user, {
addPlan: { name: 'free', status: 'valid' }
})
project.workspaceId = workspace.id
await createTestStream(project, user)
await createTestBranch({
branch: model1,
stream: project,
owner: user
})
await createTestBranch({
branch: model2,
stream: project,
owner: user
})
objectId1 = await createTestObject({
projectId: project.id,
object: { test: 'a' }
})
objectId2 = await createTestObject({
projectId: project.id,
object: { test: 'b' }
})
objectId3 = await createTestObject({
projectId: project.id,
object: { test: 'c' }
})
version1.objectId = objectId1
version1.authorId = user.id
version1.branchName = model1.name
version1.branchId = model1.id
version1.streamId = project.id
version2.objectId = objectId2
version2.authorId = user.id
version2.branchName = model2.name
version2.branchId = model2.id
version2.streamId = project.id
version3.objectId = objectId3
version3.authorId = user.id
version3.branchName = model2.name // model 2 has 2 versions
version3.branchId = model2.id
version3.streamId = project.id
await createTestCommit(version1, { owner: user })
await createTestCommit(version2, { owner: user })
await createTestCommit(version3, { owner: user })
})
it('shows the referencedObject of all user versions', async () => {
const apollo = await testApolloServer({ authUserId: user.id })
await updateCommitCreatedAtDate(version1.id, new Date())
await updateCommitCreatedAtDate(version2.id, new Date())
await updateCommitCreatedAtDate(version3.id, new Date())
const res = await apollo.execute(GetProjectVersionsDocument, {
projectId: project.id
})
const versions = res.data?.project?.versions?.items
expect(res).to.not.haveGraphQLErrors()
expect(versions)
.to.be.a('array')
.and.to.have.lengthOf(3)
.and.to.deep.contain({
id: version1.id,
referencedObject: objectId1
})
.and.to.deep.contain({
id: version2.id,
referencedObject: objectId2
})
.and.to.deep.contain({
id: version3.id,
referencedObject: objectId3
})
})
it('hides those ones that are more than 7 day old', async () => {
const apollo = await testApolloServer({ authUserId: user.id })
const tenDaysAgo = dayjs().subtract(10, 'day').toDate()
await updateCommitCreatedAtDate(version1.id, new Date())
await updateCommitCreatedAtDate(version2.id, new Date())
await updateCommitCreatedAtDate(version3.id, tenDaysAgo)
const res = await apollo.execute(GetProjectVersionsDocument, {
projectId: project.id
})
const versions = res.data?.project?.versions?.items
expect(res).to.not.haveGraphQLErrors()
expect(versions).to.be.a('array').and.to.have.lengthOf(3).and.to.deep.contain({
id: version3.id,
referencedObject: null
})
})
it('does not hide the latest commit of a model even if its +7 days old', async () => {
const apollo = await testApolloServer({ authUserId: user.id })
const tenDaysAgo = dayjs().subtract(10, 'day').toDate()
const elevenDaysAgo = dayjs().subtract(11, 'day').toDate()
await updateCommitCreatedAtDate(version1.id, new Date())
await updateCommitCreatedAtDate(version2.id, tenDaysAgo)
await updateCommitCreatedAtDate(version3.id, elevenDaysAgo)
const res = await apollo.execute(GetProjectVersionsDocument, {
projectId: project.id
})
const versions = res.data?.project?.versions?.items
expect(res).to.not.haveGraphQLErrors()
expect(versions)
.to.be.a('array')
.and.to.have.lengthOf(3)
.and.to.deep.contain({
id: version2.id,
referencedObject: objectId2
})
.and.to.deep.contain({
id: version3.id,
referencedObject: null
})
})
}
)
;(FF_PERSONAL_PROJECTS_LIMITS_ENABLED ? describe : describe.skip)(
'Version.referencedObject',
() => {
@@ -1,4 +1,4 @@
import { buildBasicTestProject } from '@/modules/core/tests/helpers/creation'
import { buildTestProject } from '@/modules/core/tests/helpers/creation'
import {
buildMixpanelFake,
MixpanelFakeEventRecord
@@ -11,7 +11,7 @@ import { expect } from 'chai'
describe('fileuploadsTrackingFactory creates a function, that @fileuploads', () => {
const workspaceId = 'some_workspace_id'
const project = buildBasicTestProject({ workspaceId })
const project = buildTestProject({ workspaceId })
const user = buildTestUserWithOptionalRole()
const getProject = async () => project
const getUser = async () => user
@@ -45,7 +45,7 @@ describe('fileuploadsTrackingFactory creates a function, that @fileuploads', ()
})
it('does not include workspace_id if project does not belong to a workspace', async () => {
const projectWithoutWorkspace = buildBasicTestProject({ workspaceId: null })
const projectWithoutWorkspace = buildTestProject({ workspaceId: null })
const events: MixpanelFakeEventRecord = []
const workspaceTracking = fileuploadTrackingFactory({
getProject: async () => projectWithoutWorkspace,
@@ -29,6 +29,7 @@ export const getProjectLimitDateFactory = (deps: {
ctx: GraphQLContext
}): GetProjectLimitDate => {
const getProjectLimitDate = getProjectLimitDateFactoryBase({
// this one
getWorkspaceLimits: async ({ workspaceId }) =>
(await deps.ctx.loaders.gatekeeper?.getWorkspaceLimits.load(workspaceId)) || null,
getPersonalProjectLimits
@@ -6012,6 +6012,13 @@ export type GetProjectCollaboratorsQueryVariables = Exact<{
export type GetProjectCollaboratorsQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, team: Array<{ __typename?: 'ProjectCollaborator', id: string, role: string }> } };
export type GetProjectVersionsQueryVariables = Exact<{
projectId: Scalars['String']['input'];
}>;
export type GetProjectVersionsQuery = { __typename?: 'Query', project: { __typename?: 'Project', versions: { __typename?: 'VersionCollection', items: Array<{ __typename?: 'Version', id: string, referencedObject?: string | null }> } } };
export type CreateServerInviteMutationVariables = Exact<{
input: ServerInviteCreateInput;
}>;
@@ -6546,6 +6553,7 @@ export const CreateProjectDocument = {"kind":"Document","definitions":[{"kind":"
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<BatchDeleteProjectsMutation, BatchDeleteProjectsMutationVariables>;
export const UpdateProjectRoleDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateProjectRole"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectUpdateRoleInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateRole"},"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<UpdateProjectRoleMutation, UpdateProjectRoleMutationVariables>;
export const GetProjectCollaboratorsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetProjectCollaborators"},"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":"team"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}}]}}]}}]} as unknown as DocumentNode<GetProjectCollaboratorsQuery, GetProjectCollaboratorsQueryVariables>;
export const GetProjectVersionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetProjectVersions"},"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":"versions"},"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":"referencedObject"}}]}}]}}]}}]}}]} as unknown as DocumentNode<GetProjectVersionsQuery, GetProjectVersionsQueryVariables>;
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<CreateServerInviteMutation, CreateServerInviteMutationVariables>;
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<CreateStreamInviteMutation, CreateStreamInviteMutationVariables>;
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<ResendInviteMutation, ResendInviteMutationVariables>;
+13
View File
@@ -109,3 +109,16 @@ export const getProjectCollaboratorsQuery = gql`
}
}
`
export const getProjectVersionsQuery = gql`
query GetProjectVersions($projectId: String!) {
project(id: $projectId) {
versions {
items {
id
referencedObject
}
}
}
}
`
@@ -65,7 +65,10 @@ export type BasicTestCommit = {
createdAt?: Date
}
export async function createTestObject(params: { projectId: string }) {
export async function createTestObject(params: {
projectId: string
object?: Record<string, unknown>
}) {
const projectDb = await getProjectDbClient(params)
const createObject = createObjectFactory({
storeSingleObjectIfNotFoundFactory: storeSingleObjectIfNotFoundFactory({
@@ -75,7 +78,7 @@ export async function createTestObject(params: { projectId: string }) {
return await createObject({
streamId: params.projectId,
object: { foo: 'bar' }
object: params.object ?? { foo: 'bar' }
})
}