Merge pull request #3142 from specklesystems/fabians/core-ioc-9

chore(server): core IoC 9 - createBranchAndNotifyFactory
This commit is contained in:
Alessandro Magionami
2024-09-27 09:11:11 +02:00
committed by GitHub
17 changed files with 193 additions and 111 deletions
@@ -4,6 +4,7 @@ import { downloadProjectFactory } from '@/modules/cross-server-sync/services/pro
import { downloadCommitFactory } from '@/modules/cross-server-sync/services/commit'
import { getStream, getStreamCollaborators } from '@/modules/core/repositories/streams'
import {
createBranchFactory,
getBranchLatestCommitsFactory,
getStreamBranchByNameFactory,
getStreamBranchesByNameFactory
@@ -17,7 +18,7 @@ import {
createCommentThreadAndNotifyFactory
} from '@/modules/comments/services/management'
import { createStreamReturnRecord } from '@/modules/core/services/streams/management'
import { createBranchAndNotify } from '@/modules/core/services/branch/management'
import { createBranchAndNotifyFactory } from '@/modules/core/services/branch/management'
import { CommentsEmitter } from '@/modules/comments/events/emitter'
import {
addCommentCreatedActivity,
@@ -41,6 +42,7 @@ import {
} from '@/modules/comments/repositories/comments'
import { getBlobsFactory } from '@/modules/blobstorage/repositories'
import { validateInputAttachmentsFactory } from '@/modules/comments/services/commentTextService'
import { addBranchCreatedActivity } from '@/modules/activitystream/services/branchActivity'
const command: CommandModule<
unknown,
@@ -124,7 +126,11 @@ const command: CommandModule<
createStreamReturnRecord,
getUser,
getStreamBranchByName,
createBranchAndNotify
createBranchAndNotify: createBranchAndNotifyFactory({
getStreamBranchByName,
createBranch: createBranchFactory({ db }),
addBranchCreatedActivity
})
})
await downloadProject(argv, { logger: cliLogger })
}
@@ -1,6 +1,8 @@
import { Branch, ModelTreeItem } from '@/modules/core/domain/branches/types'
import { BranchLatestCommit } from '@/modules/core/domain/commits/types'
import {
BranchCreateInput,
CreateModelInput,
ModelsTreeItemCollection,
ProjectModelsArgs,
ProjectModelsTreeArgs
@@ -117,3 +119,15 @@ export type GetModelTreeItemsTotalCount = (
parentModelName: string
}>
) => Promise<number>
export type StoreBranch = (params: {
name: string
description: string | null
streamId: string
authorId: string
}) => Promise<Branch>
export type CreateBranchAndNotify = (
input: BranchCreateInput | CreateModelInput,
creatorId: string
) => Promise<Branch>
@@ -9,9 +9,9 @@ const {
const { authorizeResolver } = require('@/modules/shared')
const {
createBranchAndNotify,
updateBranchAndNotify,
deleteBranchAndNotify
deleteBranchAndNotify,
createBranchAndNotifyFactory
} = require('@/modules/core/services/branch/management')
const {
getPaginatedStreamBranches
@@ -21,9 +21,13 @@ const { getUserById } = require('../../services/users')
const { Roles } = require('@speckle/shared')
const {
getBranchByIdFactory,
getStreamBranchByNameFactory
getStreamBranchByNameFactory,
createBranchFactory
} = require('@/modules/core/repositories/branches')
const { db } = require('@/db/knex')
const {
addBranchCreatedActivity
} = require('@/modules/activitystream/services/branchActivity')
// subscription events
const BRANCH_CREATED = BranchPubsubEvents.BranchCreated
@@ -32,6 +36,11 @@ const BRANCH_DELETED = BranchPubsubEvents.BranchDeleted
const getBranchById = getBranchByIdFactory({ db })
const getStreamBranchByName = getStreamBranchByNameFactory({ db })
const createBranchAndNotify = createBranchAndNotifyFactory({
getStreamBranchByName,
createBranch: createBranchFactory({ db }),
addBranchCreatedActivity
})
/** @type {import('@/modules/core/graph/generated/graphql').Resolvers} */
module.exports = {
@@ -1,7 +1,7 @@
import { Roles } from '@speckle/shared'
import { Resolvers } from '@/modules/core/graph/generated/graphql'
import {
createBranchAndNotify,
createBranchAndNotifyFactory,
deleteBranchAndNotify,
updateBranchAndNotify
} from '@/modules/core/services/branch/management'
@@ -23,6 +23,7 @@ import {
ProjectSubscriptions
} from '@/modules/shared/utils/subscriptions'
import {
createBranchFactory,
getBranchLatestCommitsFactory,
getModelTreeItemsFactory,
getModelTreeItemsFilteredFactory,
@@ -30,6 +31,7 @@ import {
getModelTreeItemsTotalCountFactory,
getPaginatedProjectModelsItemsFactory,
getPaginatedProjectModelsTotalCountFactory,
getStreamBranchByNameFactory,
getStreamBranchesByNameFactory
} from '@/modules/core/repositories/branches'
import { BranchNotFoundError } from '@/modules/core/errors/branch'
@@ -40,6 +42,7 @@ import {
getSpecificBranchCommits
} from '@/modules/core/repositories/commits'
import { db } from '@/db/knex'
import { addBranchCreatedActivity } from '@/modules/activitystream/services/branchActivity'
const getViewerResourceGroups = getViewerResourceGroupsFactory({
getStreamObjects,
@@ -64,6 +67,11 @@ const getProjectTopLevelModelsTree = getProjectTopLevelModelsTreeFactory({
getModelTreeItems,
getModelTreeItemsTotalCount: getModelTreeItemsTotalCountFactory({ db })
})
const createBranchAndNotify = createBranchAndNotifyFactory({
getStreamBranchByName: getStreamBranchByNameFactory({ db }),
createBranch: createBranchFactory({ db }),
addBranchCreatedActivity
})
export = {
User: {
@@ -28,7 +28,8 @@ import {
GetPaginatedProjectModelsTotalCount,
GetStreamBranchByName,
GetStreamBranchesByName,
GetStructuredProjectModels
GetStructuredProjectModels,
StoreBranch
} from '@/modules/core/domain/branches/operations'
import { BranchLatestCommit } from '@/modules/core/domain/commits/types'
import { ModelTreeItem } from '@/modules/core/domain/branches/types'
@@ -640,30 +641,32 @@ export const validateBranchName = (name: string) => {
)
}
export async function createBranch(params: {
name: string
description: string | null
streamId: string
authorId: string
}) {
const { streamId, authorId, name, description } = params
export const createBranchFactory =
(deps: { db: Knex }): StoreBranch =>
async (params: {
name: string
description: string | null
streamId: string
authorId: string
}) => {
const { streamId, authorId, name, description } = params
const branch: Omit<BranchRecord, 'createdAt' | 'updatedAt'> = {
id: generateBranchId(),
streamId,
authorId,
name: name.toLowerCase(),
description
const branch: Omit<BranchRecord, 'createdAt' | 'updatedAt'> = {
id: generateBranchId(),
streamId,
authorId,
name: name.toLowerCase(),
description
}
validateBranchName(branch.name)
const results = await tables.branches(deps.db).insert(branch, '*')
const newBranch = results[0] as BranchRecord
return newBranch
}
validateBranchName(branch.name)
const results = await Branches.knex().insert(branch, '*')
const newBranch = results[0] as BranchRecord
return newBranch
}
export async function updateBranch(branchId: string, branch: Partial<BranchRecord>) {
if (branch.name) {
validateBranchName(branch.name)
@@ -19,10 +19,8 @@ import {
} from '@/modules/core/graph/generated/graphql'
import { BranchRecord } from '@/modules/core/helpers/types'
import {
createBranch,
deleteBranchById,
getBranchByIdFactory,
getStreamBranchByNameFactory,
updateBranch
} from '@/modules/core/repositories/branches'
import { getStream, markBranchStreamUpdated } from '@/modules/core/repositories/streams'
@@ -30,35 +28,40 @@ import { has } from 'lodash'
import { isBranchDeleteInput, isBranchUpdateInput } from '@/modules/core/helpers/branch'
import { ModelsEmitter } from '@/modules/core/events/modelsEmitter'
import { db } from '@/db/knex'
import {
CreateBranchAndNotify,
GetStreamBranchByName,
StoreBranch
} from '@/modules/core/domain/branches/operations'
const isBranchCreateInput = (
i: BranchCreateInput | CreateModelInput
): i is BranchCreateInput => has(i, 'streamId')
export async function createBranchAndNotify(
input: BranchCreateInput | CreateModelInput,
creatorId: string
) {
const streamId = isBranchCreateInput(input) ? input.streamId : input.projectId
const existingBranch = await getStreamBranchByNameFactory({ db })(
streamId,
input.name
)
if (existingBranch) {
throw new BranchCreateError('A branch with this name already exists')
export const createBranchAndNotifyFactory =
(deps: {
getStreamBranchByName: GetStreamBranchByName
createBranch: StoreBranch
addBranchCreatedActivity: typeof addBranchCreatedActivity
}): CreateBranchAndNotify =>
async (input: BranchCreateInput | CreateModelInput, creatorId: string) => {
const streamId = isBranchCreateInput(input) ? input.streamId : input.projectId
const existingBranch = await deps.getStreamBranchByName(streamId, input.name)
if (existingBranch) {
throw new BranchCreateError('A branch with this name already exists')
}
const branch = await deps.createBranch({
name: input.name,
description: input.description ?? null,
streamId: isBranchCreateInput(input) ? input.streamId : input.projectId,
authorId: creatorId
})
await deps.addBranchCreatedActivity({ branch })
return branch
}
const branch = await createBranch({
name: input.name,
description: input.description ?? null,
streamId: isBranchCreateInput(input) ? input.streamId : input.projectId,
authorId: creatorId
})
await addBranchCreatedActivity({ branch })
return branch
}
export async function updateBranchAndNotify(
input: BranchUpdateInput | UpdateModelInput,
userId: string
@@ -1,9 +1,6 @@
'use strict'
const knex = require('@/db/knex')
const {
getStreamBranchCount,
createBranch: createBranchInDb
} = require('@/modules/core/repositories/branches')
const { getStreamBranchCount } = require('@/modules/core/repositories/branches')
const {
updateBranchAndNotify,
deleteBranchAndNotify
@@ -12,14 +9,6 @@ const {
const Branches = () => knex('branches')
module.exports = {
/**
* @deprecated Use `createBranchAndNotify` or use the repository function directly
*/
async createBranch({ name, description, streamId, authorId }) {
const branch = await createBranchInDb({ name, description, streamId, authorId })
return branch.id
},
/**
* @deprecated Use 'updateBranchAndNotify'
*/
@@ -15,7 +15,7 @@ import {
} from '@/modules/core/graph/generated/graphql'
import { Roles } from '@/modules/core/helpers/mainConstants'
import {
createBranch,
createBranchFactory,
getStreamBranchByNameFactory
} from '@/modules/core/repositories/branches'
import {
@@ -150,7 +150,7 @@ export async function batchMoveCommits(
try {
const finalBranch =
branch ||
(await createBranch({
(await createBranchFactory({ db })({
name: targetBranch,
streamId: stream.id,
authorId: userId,
@@ -20,7 +20,6 @@ import {
getStream,
updateStream
} from '@/modules/core/repositories/streams'
import { createBranch } from '@/modules/core/services/branches'
import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation'
import {
StreamInvalidAccessError,
@@ -55,6 +54,7 @@ import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/se
import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents'
import { getEventBus } from '@/modules/shared/services/eventBus'
import { ProjectInviteResourceType } from '@/modules/serverinvites/domain/constants'
import { createBranchFactory } from '@/modules/core/repositories/branches'
export async function createStreamReturnRecord(
params: (StreamCreateInput | ProjectCreateInput) & {
@@ -80,7 +80,7 @@ export async function createStreamReturnRecord(
const streamId = stream.id
// Create a default main branch
await createBranch({
await createBranchFactory({ db })({
name: 'main',
description: 'default branch',
streamId,
@@ -1,8 +1,9 @@
import { buildApolloServer } from '@/app'
import { db } from '@/db/knex'
import { Commits, Streams, Users } from '@/modules/core/dbSchema'
import { Roles } from '@/modules/core/helpers/mainConstants'
import { createBranchFactory } from '@/modules/core/repositories/branches'
import { getCommits } from '@/modules/core/repositories/commits'
import { createBranch } from '@/modules/core/services/branches'
import { addOrUpdateStreamCollaborator } from '@/modules/core/services/streams/streamAccessService'
import { BasicTestUser, createTestUsers } from '@/test/authHelper'
import { deleteCommits, moveCommits } from '@/test/graphql/commits'
@@ -23,6 +24,8 @@ enum BatchActionType {
Delete
}
const createBranch = createBranchFactory({ db })
const cleanup = async () => {
await truncateTables([Streams.name, Users.name, Commits.name])
}
@@ -12,7 +12,6 @@ const { createUser } = require('../services/users')
const { createStream } = require('../services/streams')
const { createObject } = require('../services/objects')
const {
createBranch,
updateBranch,
getBranchesByStreamId,
deleteBranchById
@@ -22,12 +21,14 @@ const { createCommitByBranchName } = require('../services/commits')
const { deleteBranchAndNotify } = require('@/modules/core/services/branch/management')
const {
getBranchByIdFactory,
getStreamBranchByNameFactory
getStreamBranchByNameFactory,
createBranchFactory
} = require('@/modules/core/repositories/branches')
const Commits = () => knex('commits')
const getBranchById = getBranchByIdFactory({ db: knex })
const getStreamBranchByName = getStreamBranchByNameFactory({ db: knex })
const createBranch = createBranchFactory({ db: knex })
describe('Branches @core-branches', () => {
const user = {
@@ -57,11 +58,13 @@ describe('Branches @core-branches', () => {
const branch = { name: 'dim/dev' }
it('Should create a branch', async () => {
branch.id = await createBranch({
...branch,
streamId: stream.id,
authorId: user.id
})
branch.id = (
await createBranch({
...branch,
streamId: stream.id,
authorId: user.id
})
).id
expect(branch.id).to.be.not.null
expect(branch.id).to.be.a.string
})
@@ -127,11 +130,13 @@ describe('Branches @core-branches', () => {
})
it('Branch names should be case insensitive (always lowercase)', async () => {
const id = await createBranch({
name: 'CaseSensitive',
streamId: stream.id,
authorId: user.id
})
const id = (
await createBranch({
name: 'CaseSensitive',
streamId: stream.id,
authorId: user.id
})
).id
const b = await getStreamBranchByName(stream.id, 'casesensitive')
expect(b.name).to.equal('casesensitive')
@@ -192,11 +197,13 @@ describe('Branches @core-branches', () => {
it('Deleting a branch should delete the commit', async () => {
const branchName = 'pasta'
const branchId = await createBranch({
name: branchName,
streamId: stream.id,
authorId: user.id
})
const branchId = (
await createBranch({
name: branchName,
streamId: stream.id,
authorId: user.id
})
).id
const tempCommit = await createCommitByBranchName({
streamId: stream.id,
@@ -6,7 +6,6 @@ const { beforeEachContext } = require('@/test/hooks')
const { createUser } = require('../services/users')
const { createStream } = require('../services/streams')
const { createObject } = require('../services/objects')
const { createBranch } = require('../services/branches')
const {
createCommitByBranchName,
@@ -19,8 +18,25 @@ const {
getCommitsTotalCountByStreamId,
getCommitsByUserId
} = require('../services/commits')
const { createBranchAndNotify } = require('@/modules/core/services/branch/management')
const {
createBranchAndNotifyFactory
} = require('@/modules/core/services/branch/management')
const cryptoRandomString = require('crypto-random-string')
const {
createBranchFactory,
getStreamBranchByNameFactory
} = require('@/modules/core/repositories/branches')
const { db } = require('@/db/knex')
const {
addBranchCreatedActivity
} = require('@/modules/activitystream/services/branchActivity')
const createBranch = createBranchFactory({ db })
const createBranchAndNotify = createBranchAndNotifyFactory({
createBranch,
getStreamBranchByName: getStreamBranchByNameFactory({ db }),
addBranchCreatedActivity
})
describe('Commits @core-commits', () => {
const user = {
@@ -8,7 +8,7 @@ import {
grantPermissionsStream
} from '@/modules/core/services/streams'
import { createBranch, deleteBranchById } from '@/modules/core/services/branches'
import { deleteBranchById } from '@/modules/core/services/branches'
import { createObject } from '@/modules/core/services/objects'
import { createCommitByBranchName } from '@/modules/core/services/commits'
@@ -50,10 +50,14 @@ import {
ServerAndContext
} from '@/test/graphqlHelper'
import { buildApolloServer } from '@/app'
import { getStreamBranchByNameFactory } from '@/modules/core/repositories/branches'
import {
createBranchFactory,
getStreamBranchByNameFactory
} from '@/modules/core/repositories/branches'
import { db } from '@/db/knex'
const getStreamBranchByName = getStreamBranchByNameFactory({ db })
const createBranch = createBranchFactory({ db })
describe('Streams @core-streams', () => {
const userOne: BasicTestUser = {
@@ -27,7 +27,7 @@ const {
getStream
} = require('../services/streams')
const { createBranch, getBranchesByStreamId } = require('../services/branches')
const { getBranchesByStreamId } = require('../services/branches')
const {
createCommitByBranchName,
@@ -40,6 +40,10 @@ const { createObject } = require('../services/objects')
const { beforeEachContext } = require('@/test/hooks')
const { Scopes, Roles } = require('@speckle/shared')
const { createRandomEmail } = require('../helpers/testHelpers')
const { createBranchFactory } = require('@/modules/core/repositories/branches')
const { db } = require('@/db/knex')
const createBranch = createBranchFactory({ db })
describe('Actors & Tokens @user-services', () => {
const myTestActor = {
@@ -127,18 +131,22 @@ describe('Actors & Tokens @user-services', () => {
// create a branch for ballmer on the multiowner stream
const branch = { name: 'ballmer/dev' }
branch.id = await createBranch({
...branch,
streamId: multiOwnerStream.id,
authorId: ballmerUserId
})
branch.id = (
await createBranch({
...branch,
streamId: multiOwnerStream.id,
authorId: ballmerUserId
})
).id
const branchSecond = { name: 'steve/jobs' }
branchSecond.id = await createBranch({
...branchSecond,
streamId: multiOwnerStream.id,
authorId: myTestActor.id
})
branchSecond.id = (
await createBranch({
...branchSecond,
streamId: multiOwnerStream.id,
authorId: myTestActor.id
})
).id
// create an object and a commit around it on the multiowner stream
const objId = await createObject({
@@ -1,5 +1,6 @@
import { db } from '@/db/knex'
import { moduleLogger, crossServerSyncLogger } from '@/logging/logging'
import { addBranchCreatedActivity } from '@/modules/activitystream/services/branchActivity'
import {
addCommentCreatedActivity,
addReplyAddedActivity
@@ -19,6 +20,7 @@ import {
createCommentThreadAndNotifyFactory
} from '@/modules/comments/services/management'
import {
createBranchFactory,
getBranchLatestCommitsFactory,
getStreamBranchByNameFactory,
getStreamBranchesByNameFactory
@@ -35,7 +37,7 @@ import {
markOnboardingBaseStream
} from '@/modules/core/repositories/streams'
import { getFirstAdmin, getUser } from '@/modules/core/repositories/users'
import { createBranchAndNotify } from '@/modules/core/services/branch/management'
import { createBranchAndNotifyFactory } from '@/modules/core/services/branch/management'
import { createCommitByBranchId } from '@/modules/core/services/commit/management'
import {
getViewerResourceGroupsFactory,
@@ -107,7 +109,11 @@ const crossServerSyncModule: SpeckleModule = {
createStreamReturnRecord,
getUser,
getStreamBranchByName,
createBranchAndNotify
createBranchAndNotify: createBranchAndNotifyFactory({
createBranch: createBranchFactory({ db }),
getStreamBranchByName,
addBranchCreatedActivity
})
}),
markOnboardingBaseStream
})
@@ -11,12 +11,14 @@ import { CrossSyncProjectMetadataQuery } from '@/modules/cross-server-sync/graph
import { omit } from 'lodash'
import { getFrontendOrigin } from '@/modules/shared/helpers/envHelper'
import { createStreamReturnRecord } from '@/modules/core/services/streams/management'
import { createBranchAndNotify } from '@/modules/core/services/branch/management'
import {
DownloadCommit,
DownloadProject
} from '@/modules/cross-server-sync/domain/operations'
import { GetStreamBranchByName } from '@/modules/core/domain/branches/operations'
import {
CreateBranchAndNotify,
GetStreamBranchByName
} from '@/modules/core/domain/branches/operations'
type ProjectMetadata = Awaited<ReturnType<typeof getProjectMetadata>>
@@ -113,7 +115,7 @@ const getProjectMetadata = async (params: {
type EnsureBranchDeps = {
getStreamBranchByName: GetStreamBranchByName
createBranchAndNotify: typeof createBranchAndNotify
createBranchAndNotify: CreateBranchAndNotify
}
const ensureBranchFactory =
@@ -1,4 +1,5 @@
import { createBranch } from '@/modules/core/services/branches'
import { db } from '@/db/knex'
import { createBranchFactory } from '@/modules/core/repositories/branches'
import { BasicTestUser } from '@/test/authHelper'
import { BasicTestStream } from '@/test/speckle-helpers/streamHelper'
import { omit } from 'lodash'
@@ -30,10 +31,13 @@ export async function createTestBranch(params: {
branch.streamId = stream.id
branch.authorId = owner.id
const id = await createBranch({
...omit(branch, ['id']),
description: branch.description || null
})
const createBranch = createBranchFactory({ db })
const id = (
await createBranch({
...omit(branch, ['id']),
description: branch.description || null
})
).id
branch.id = id
}