Files
speckle-server/packages/server/modules/gatekeeper/graph/dataloaders/index.ts
T
Kristaps Fabians Geikins a6287fc06d feat(fe2 & server): saved views foundation (list & view) + bits n bobs (#5163)
* init db migration

* WIP store view

* create service call

* WIP insertion

* insert sort of works

* moving code arounmd

* creation tests

* avoid duplicate entries

* fixes from main

* basic group retrieval works

* group filtering works

* WIP view listing

* filter by acl

* fixes + WIP single group retrieval

* wip pivot

* more pivot query fixes

* tests fixed after pivot

* views list tests

* fixing test command

* business plan only checks

* more tests for coverage

* .dts import fix

* cli fix

* anutha one

* auth policy tests for business plan access

* WIP saved views panel base

* BE listing adjustments

* WIP group rendering

* group render done

* WIP post create cache updates

* listing fine?

* my vs theirs

* auto open

* minor fixes

* click load omg

* nicely loading views

* type fix

* less spammy loading

* another type fix:

* more lint fix

* test fix

* codecov disable

* moar coverage

* fix sidebar flashin

* more test coverage

* more test cvoverage

* minor adfjustments

* adj

* saved view wipe fixes

* CSR viewer

* more improvements

* extra feature flag checks

* lint fix

* feature flags fix

* more test fixes
2025-08-05 11:52:50 +03:00

104 lines
3.5 KiB
TypeScript

import type { WorkspaceSeat } from '@/modules/gatekeeper/domain/billing'
import { getWorkspacePlansByWorkspaceIdFactory } from '@/modules/gatekeeper/repositories/billing'
import {
getProjectsUsersSeatsFactory,
getWorkspacesUsersSeatsFactory
} from '@/modules/gatekeeper/repositories/workspaceSeat'
import { getFeatureFlags } from '@/modules/shared/helpers/envHelper'
import { defineRequestDataloaders } from '@/modules/shared/helpers/graphqlHelper'
import type { WorkspaceLimits, WorkspacePlan } from '@speckle/shared'
import { WorkspacePaidPlanConfigs, WorkspaceUnpaidPlanConfigs } from '@speckle/shared'
const { FF_GATEKEEPER_MODULE_ENABLED } = getFeatureFlags()
declare module '@/modules/core/loaders' {
interface ModularizedDataLoaders
extends Partial<ReturnType<typeof dataLoadersDefinition>> {}
}
const dataLoadersDefinition = defineRequestDataloaders(
({ createLoader, deps: { db } }) => {
const getWorkspacesUsersSeats = getWorkspacesUsersSeatsFactory({ db })
const getProjectsUsersSeats = getProjectsUsersSeatsFactory({ db })
const getWorkspacePlansByWorkspaceId = getWorkspacePlansByWorkspaceIdFactory({ db })
return {
gatekeeper: {
getUserWorkspaceSeat: createLoader<
{ workspaceId: string; userId: string },
WorkspaceSeat | null,
string
>(
async (requests) => {
const results = await getWorkspacesUsersSeats({
requests: requests.slice()
})
return requests.map(
({ workspaceId, userId }) => results[workspaceId]?.[userId] || null
)
},
{
cacheKeyFn: ({ workspaceId, userId }) => `${workspaceId}-${userId}`
}
),
getUserProjectSeat: createLoader<
{ projectId: string; userId: string },
WorkspaceSeat | null,
string
>(
async (requests) => {
const results = await getProjectsUsersSeats({
requests: requests.slice()
})
return requests.map(
({ projectId, userId }) => results[projectId]?.[userId] || null
)
},
{
cacheKeyFn: ({ projectId, userId }) => `${projectId}-${userId}`
}
),
getWorkspacePlan: createLoader<
{ workspaceId: string },
WorkspacePlan | null,
string
>(
async (requests) => {
const results = await getWorkspacePlansByWorkspaceId({
workspaceIds: requests.map((request) => request.workspaceId)
})
return requests.map(({ workspaceId }) => results[workspaceId] || null)
},
{
cacheKeyFn: ({ workspaceId }) => workspaceId
}
),
getWorkspaceLimits: createLoader<string, WorkspaceLimits | null>(
async (workspaceIds) => {
const workspacePlans = await getWorkspacePlansByWorkspaceId({
workspaceIds: workspaceIds.slice()
})
const featureFlags = getFeatureFlags()
return workspaceIds.map((workspaceId) => {
const plan = workspacePlans[workspaceId]
if (!plan) return null
const config = {
...WorkspacePaidPlanConfigs({ featureFlags }),
...WorkspaceUnpaidPlanConfigs({ featureFlags })
}
return config[plan.name]?.limits || null
})
}
)
}
}
}
)
export default FF_GATEKEEPER_MODULE_ENABLED ? dataLoadersDefinition : undefined