import { WorkspaceEvents } from '@/modules/workspacesCore/domain/events' import { LimitedWorkspace, Workspace, WorkspaceAcl, WorkspaceDomain, WorkspaceJoinRequest, WorkspaceJoinRequestStatus, WorkspaceRegionAssignment, WorkspaceWithDomains, WorkspaceWithOptionalRole } from '@/modules/workspacesCore/domain/types' import { EventBusPayloads } from '@/modules/shared/services/eventBus' import { MaybeNullOrUndefined, Nullable, NullableKeysToOptional, Optional, PartialNullable, StreamRoles, WorkspaceRoles } from '@speckle/shared' import { WorkspaceCreationState } from '@/modules/workspaces/domain/types' import { WorkspaceTeam } from '@/modules/workspaces/domain/types' import { Stream } from '@/modules/core/domain/streams/types' import { TokenResourceIdentifier } from '@/modules/core/domain/tokens/types' import { ServerRegion } from '@/modules/multiregion/domain/types' import { SetOptional } from 'type-fest' import { WorkspaceSeat, WorkspaceSeatType } from '@/modules/gatekeeper/domain/billing' import { UserRecord } from '@/modules/core/helpers/userHelper' /** Workspace */ export type UpsertWorkspaceArgs = { workspace: Omit< SetOptional< NullableKeysToOptional, 'domainBasedMembershipProtectionEnabled' | 'discoverabilityEnabled' | 'slug' >, 'domains' > } export type UpsertWorkspace = (args: UpsertWorkspaceArgs) => Promise export type GetUserDiscoverableWorkspaces = (args: { domains: string[] userId: string }) => Promise // adding optional role to each workspace export type EligibleWorkspace = LimitedWorkspace & { role?: WorkspaceRoles }[] export type GetUsersCurrentAndEligibleToBecomeAMemberWorkspaces = (args: { domains: string[] userId: string }) => Promise export type GetWorkspace = (args: { workspaceId: string userId?: string }) => Promise export type GetWorkspaceBySlug = (args: { workspaceSlug: string userId?: string }) => Promise // Useful for dev purposes (e.g. CLI) export type GetWorkspaceBySlugOrId = (args: { workspaceSlugOrId: string }) => Promise export type GetWorkspaces = (args: { workspaceIds?: string[] userId?: string search?: string completed?: boolean }) => Promise export type GetAllWorkspaces = (args: { limit: number cursor: Nullable }) => Promise<{ items: Workspace[] cursor: Nullable }> export type GetWorkspacesBySlug = (args: { workspaceIds: string[] userId?: string }) => Promise export type GetWorkspacesNonComplete = (args: { createdAtBefore: Date }) => Promise<{ workspaceId: string }[]> export type StoreWorkspaceDomain = (args: { workspaceDomain: WorkspaceDomain }) => Promise export type GetWorkspaceDomains = (args: { workspaceIds: string[] }) => Promise type DeleteWorkspaceArgs = { workspaceId: string } export type CountDomainsByWorkspaceId = (args: { workspaceId: string }) => Promise export type DeleteWorkspaceDomain = (args: { id: string }) => Promise export type GetWorkspaceWithDomains = (args: { id: string }) => Promise export type DeleteWorkspace = (args: DeleteWorkspaceArgs) => Promise type CountWorkspacesArgs = { filter?: { search?: string } } export type QueryWorkspacesArgs = CountWorkspacesArgs & { limit: number cursor?: string } export type QueryWorkspaces = ( args: QueryWorkspacesArgs ) => Promise<{ items: Workspace[]; cursor: string | null }> export type CountWorkspaces = (args: CountWorkspacesArgs) => Promise export type GetProjectWorkspace = (args: { projectId: string }) => Promise /** Workspace Roles */ export type GetWorkspaceCollaboratorsBaseArgs = { workspaceId: string filter?: { /** * Optionally filter by workspace role(s) */ roles?: WorkspaceRoles[] /** * Optionally filter by user name or email */ search?: string seatType?: WorkspaceSeatType /** * Optionally filter by user id */ excludeUserIds?: string[] } hasAccessToEmail?: boolean } export type GetWorkspaceCollaboratorsArgs = GetWorkspaceCollaboratorsBaseArgs & { limit: number cursor?: string } export type GetWorkspaceCollaborators = ( args: GetWorkspaceCollaboratorsArgs ) => Promise<{ items: WorkspaceTeam; cursor: string | null }> export type GetWorkspaceCollaboratorsTotalCount = ( args: GetWorkspaceCollaboratorsBaseArgs ) => Promise type DeleteWorkspaceRoleArgs = { workspaceId: string userId: string } export type DeleteWorkspaceRole = ( args: DeleteWorkspaceRoleArgs ) => Promise type GetWorkspaceRolesArgs = { workspaceId: string } /** Get all roles in a given workspaces. */ export type GetWorkspaceRoles = (args: GetWorkspaceRolesArgs) => Promise type GetWorkspaceRoleForUserArgs = { userId: string workspaceId: string } /** Get role for given user in a specific workspace. */ export type GetWorkspaceRoleForUser = ( args: GetWorkspaceRoleForUserArgs ) => Promise type GetWorkspaceRolesForUserArgs = { userId: string } type GetWorkspaceRolesForUserOptions = { /** If provided, limit results to roles in given workspaces. */ workspaceIdFilter?: string[] } /** Get roles for given user across several (or all) workspaces. */ export type GetWorkspaceRolesForUser = ( args: GetWorkspaceRolesForUserArgs, options?: GetWorkspaceRolesForUserOptions ) => Promise export type GetWorkspacesRolesForUsers = ( reqs: Array<{ userId: string workspaceId: string }> ) => Promise<{ [workspaceId: string]: | { [userId: string]: WorkspaceAcl | undefined } | undefined }> /** Repository-level change to workspace acl record */ export type UpsertWorkspaceRole = (args: WorkspaceAcl) => Promise /** Service-level change with protection against invalid role changes */ export type AddOrUpdateWorkspaceRole = ( args: Pick & { /** * Only add or upgrade role, prevent downgrades */ preventRoleDowngrade?: boolean /** * Whether to skip event emit */ skipEvent?: boolean updatedByUserId: string /** * Optionally set Workspace seat type to ensure */ seatType?: WorkspaceSeatType } ) => Promise export type GetWorkspaceRoleToDefaultProjectRoleMapping = (args: { workspaceId: string }) => Promise<{ allowed: { [workspaceRole in WorkspaceRoles]: StreamRoles[] } default: { [workspaceRole in WorkspaceRoles]: StreamRoles | null } }> export type GetWorkspaceSeatTypeToProjectRoleMapping = (args: { workspaceId: string }) => Promise<{ allowed: { [workspaceSeatType in WorkspaceSeatType]: StreamRoles[] } default: { [workspaceSeatType in WorkspaceSeatType]: StreamRoles } }> export type ValidateWorkspaceMemberProjectRole = (params: { workspaceId: string userId: string projectRole: StreamRoles /** * Instead of resolving actual workspace role/seatType, use this one. Useful when checking * if a planned workspace member will have valid access to a project */ workspaceAccess?: { role?: WorkspaceRoles seatType?: WorkspaceSeatType } }) => Promise /** Workspace Projects */ export type GetWorkspacesProjectsCounts = (params: { workspaceIds: string[] }) => Promise<{ [workspaceId: string]: number }> export type GetWorkspaceModelCount = (params: { workspaceId: string }) => Promise export type GetPaginatedWorkspaceProjectsArgs = { workspaceId: string /** * If set, will take the user's workspace role into account when fetching projects. * E.g. guests will only see projects they have explicit access to. */ userId?: string cursor?: MaybeNullOrUndefined /** * Defaults to 25, if unset */ limit?: MaybeNullOrUndefined filter?: MaybeNullOrUndefined< Partial<{ /** * Search for projects by name */ search: MaybeNullOrUndefined /** * Only get projects that the active user has an explicit role in */ withProjectRoleOnly: MaybeNullOrUndefined }> > } export type GetPaginatedWorkspaceProjectsItems = ( params: GetPaginatedWorkspaceProjectsArgs ) => Promise<{ items: Stream[] cursor: string | null }> export type GetPaginatedWorkspaceProjectsTotalCount = ( params: Omit ) => Promise export type GetPaginatedWorkspaceProjects = ( params: GetPaginatedWorkspaceProjectsArgs ) => Promise<{ cursor: string | null items: Stream[] totalCount: number }> /** Workspace Project Roles */ type GrantWorkspaceProjectRolesArgs = { projectId: string workspaceId: string } export type GrantWorkspaceProjectRoles = ( args: GrantWorkspaceProjectRolesArgs ) => Promise type UpdateWorkspaceProjectRoleArgs = { role: { projectId: string userId: string // Undefined or null role means delete role role?: Nullable } updater: { userId: string resourceAccessRules: MaybeNullOrUndefined } } export type UpdateWorkspaceProjectRole = ( args: UpdateWorkspaceProjectRoleArgs ) => Promise /** Events */ export type EmitWorkspaceEvent = < TEvent extends WorkspaceEvents & keyof EventBusPayloads >(args: { eventName: TEvent payload: EventBusPayloads[TEvent] }) => Promise export type CountWorkspaceRoleWithOptionalProjectRole = (args: { workspaceId: string workspaceRole: WorkspaceRoles projectRole?: StreamRoles skipUserIds?: string[] }) => Promise export type GetWorkspaceSeatCount = (args: { workspaceId: string type?: WorkspaceSeatType }) => Promise export type GetUserIdsWithRoleInWorkspace = ( args: { workspaceId: string workspaceRole: WorkspaceRoles }, options?: { limit?: number } ) => Promise type WorkspaceUpdateArgs = { workspaceId: string workspaceInput: PartialNullable> } export type UpdateWorkspace = ({ workspaceId, workspaceInput }: WorkspaceUpdateArgs) => Promise /** * Workspace regions */ export type GetAvailableRegions = (params: { workspaceId: string }) => Promise export type AssignWorkspaceRegion = (params: { workspaceId: string regionKey: string }) => Promise export type GetDefaultRegion = (params: { workspaceId: string }) => Promise> export type UpsertRegionAssignment = (params: { workspaceId: string regionKey: string }) => Promise export type GetWorkspaceCreationState = (params: { workspaceId: string }) => Promise export type UpsertWorkspaceCreationState = (params: { workspaceCreationState: WorkspaceCreationState }) => Promise export type UpdateWorkspaceJoinRequestStatus = (params: { workspaceId: string userId: string status: WorkspaceJoinRequestStatus }) => Promise export type CreateWorkspaceJoinRequest = (params: { workspaceJoinRequest: Omit }) => Promise export type SendWorkspaceJoinRequestReceivedEmail = (params: { workspace: Pick requester: { id: string; name: string; email: string } }) => Promise export type SendWorkspaceJoinRequestApprovedEmail = (params: { workspace: Pick requester: { id: string; name: string; email: string } }) => Promise export type SendWorkspaceJoinRequestDeniedEmail = (params: { workspace: Pick requester: { id: string; name: string; email: string } }) => Promise export type GetWorkspaceJoinRequest = ( params: Pick & Partial> ) => Promise export type ApproveWorkspaceJoinRequest = ( params: Pick & { approvedByUserId: string } ) => Promise export type DenyWorkspaceJoinRequest = ( params: Pick ) => Promise /** * Project regions */ /** * Updates project region and moves all regional data to target regional db */ export type UpdateProjectRegion = (params: { projectId: string regionKey: string }) => Promise /** * Given a count of objects successfully copied to another region, confirm that these counts * match the current state of the source project in its original region. */ export type ValidateProjectRegionCopy = (params: { projectId: string copiedRowCount: { models: number versions: number objects: number automations: number comments: number webhooks: number } }) => Promise<[boolean, Record]> export type CopyWorkspace = (params: { workspaceId: string }) => Promise export type CopyProjects = (params: { projectIds: string[] }) => Promise export type CopyProjectModels = (params: { projectIds: string[] }) => Promise> export type CopyProjectVersions = (params: { projectIds: string[] }) => Promise> export type CopyProjectObjects = (params: { projectIds: string[] }) => Promise> export type CopyProjectAutomations = (params: { projectIds: string[] }) => Promise> export type CountProjectModels = (params: { projectId: string }) => Promise export type CountProjectVersions = (params: { projectId: string }) => Promise export type CountProjectObjects = (params: { projectId: string }) => Promise export type CountProjectAutomations = (params: { projectId: string }) => Promise export type CountProjectComments = (params: { projectId: string }) => Promise export type CountProjectWebhooks = (params: { projectId: string }) => Promise export type AssignWorkspaceSeat = ( params: Pick & { type: WorkspaceSeatType assignedByUserId: string skipEvent?: boolean } ) => Promise export type EnsureValidWorkspaceRoleSeat = (params: { workspaceId: string userId: string role: WorkspaceRoles updatedByUserId: string skipEvent?: boolean }) => Promise export type CopyProjectComments = (params: { projectIds: string[] }) => Promise> export type CopyProjectWebhooks = (params: { projectIds: string[] }) => Promise> export type CopyProjectBlobs = (params: { projectIds: string[] }) => Promise> export type SetUserActiveWorkspace = (args: { userId: string workspaceSlug: string | null /** Is the user in a "personal project" outside of a workspace? */ isProjectsActive?: boolean }) => Promise export type IntersectProjectCollaboratorsAndWorkspaceCollaborators = (params: { projectId: string workspaceId: string }) => Promise