chore(gatekeeper): get workspace plan repository and dataloader function
This commit is contained in:
@@ -20,6 +20,10 @@ export type GetWorkspacePlan = (args: {
|
||||
workspaceId: string
|
||||
}) => Promise<WorkspacePlan | null>
|
||||
|
||||
export type GetWorkspacePlansByWorkspaceId = (args: {
|
||||
workspaceIds: string[]
|
||||
}) => Promise<Record<string, WorkspacePlan>>
|
||||
|
||||
export type GetWorkspaceWithPlan = (args: {
|
||||
workspaceId: string
|
||||
}) => Promise<Optional<Workspace & { plan: Nullable<WorkspacePlan> }>>
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { 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 { WorkspacePlan } from '@speckle/shared'
|
||||
|
||||
const { FF_GATEKEEPER_MODULE_ENABLED } = getFeatureFlags()
|
||||
|
||||
@@ -17,6 +19,7 @@ const dataLoadersDefinition = defineRequestDataloaders(
|
||||
({ createLoader, deps: { db } }) => {
|
||||
const getWorkspacesUsersSeats = getWorkspacesUsersSeatsFactory({ db })
|
||||
const getProjectsUsersSeats = getProjectsUsersSeatsFactory({ db })
|
||||
const getWorkspacePlansByWorkspaceId = getWorkspacePlansByWorkspaceIdFactory({ db })
|
||||
|
||||
return {
|
||||
gatekeeper: {
|
||||
@@ -55,6 +58,22 @@ const dataLoadersDefinition = defineRequestDataloaders(
|
||||
{
|
||||
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
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ import {
|
||||
GetWorkspaceSubscriptions,
|
||||
UpsertTrialWorkspacePlan,
|
||||
UpsertUnpaidWorkspacePlan,
|
||||
GetWorkspaceWithPlan
|
||||
GetWorkspaceWithPlan,
|
||||
GetWorkspacePlansByWorkspaceId
|
||||
} from '@/modules/gatekeeper/domain/billing'
|
||||
import {
|
||||
ChangeExpiredTrialWorkspacePlanStatuses,
|
||||
@@ -93,6 +94,15 @@ export const getWorkspacePlanFactory =
|
||||
return workspacePlan ?? null
|
||||
}
|
||||
|
||||
export const getWorkspacePlansByWorkspaceIdFactory =
|
||||
({ db }: { db: Knex }): GetWorkspacePlansByWorkspaceId =>
|
||||
async ({ workspaceIds }) => {
|
||||
const results = await tables
|
||||
.workspacePlans(db)
|
||||
.whereIn(WorkspacePlans.col.workspaceId, workspaceIds)
|
||||
return results.reduce((acc, curr) => ({ ...acc, [curr.workspaceId]: curr }), {})
|
||||
}
|
||||
|
||||
export const upsertWorkspacePlanFactory =
|
||||
({ db }: { db: Knex }): UpsertWorkspacePlan =>
|
||||
async ({ workspacePlan }) => {
|
||||
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
import { db } from '@/db/knex'
|
||||
import { createRandomString } from '@/modules/core/helpers/testHelpers'
|
||||
import {
|
||||
getWorkspacePlansByWorkspaceIdFactory,
|
||||
upsertWorkspacePlanFactory
|
||||
} from '@/modules/gatekeeper/repositories/billing'
|
||||
import { createTestWorkspace } from '@/modules/workspaces/tests/helpers/creation'
|
||||
import { createTestUser } from '@/test/authHelper'
|
||||
import { PaidWorkspacePlans, PaidWorkspacePlanStatuses } from '@speckle/shared'
|
||||
import { expect } from 'chai'
|
||||
|
||||
describe('Module @gatekeeper', () => {
|
||||
const upsertWorkspacePlan = upsertWorkspacePlanFactory({ db })
|
||||
describe('Repositories WorkspacePlan', () => {
|
||||
describe('getWorkspacePlansByWorkspaceIdFactory should return a function that, ', () => {
|
||||
const getWorkspacePlansByWorkspaceId = getWorkspacePlansByWorkspaceIdFactory({
|
||||
db
|
||||
})
|
||||
it('should return a map of workspacePlans by their workspaceId', async () => {
|
||||
const now = new Date()
|
||||
const user = await createTestUser()
|
||||
const workspace1 = {
|
||||
id: '',
|
||||
name: createRandomString(),
|
||||
ownerId: user.id
|
||||
}
|
||||
await createTestWorkspace(workspace1, user)
|
||||
const plan1 = {
|
||||
workspaceId: workspace1.id,
|
||||
name: PaidWorkspacePlans.Team,
|
||||
createdAt: now,
|
||||
status: PaidWorkspacePlanStatuses.Valid
|
||||
}
|
||||
await upsertWorkspacePlan({
|
||||
workspacePlan: plan1
|
||||
})
|
||||
const workspace2 = {
|
||||
id: '',
|
||||
name: createRandomString(),
|
||||
ownerId: user.id
|
||||
}
|
||||
await createTestWorkspace(workspace2, user)
|
||||
const plan2 = {
|
||||
workspaceId: workspace2.id,
|
||||
name: PaidWorkspacePlans.Team,
|
||||
createdAt: now,
|
||||
status: PaidWorkspacePlanStatuses.Valid
|
||||
}
|
||||
await upsertWorkspacePlan({
|
||||
workspacePlan: plan2
|
||||
})
|
||||
|
||||
const results = await getWorkspacePlansByWorkspaceId({
|
||||
workspaceIds: [workspace1.id, workspace2.id]
|
||||
})
|
||||
|
||||
for (const [workspaceId, workspacePlan] of Object.entries(results)) {
|
||||
const { createdAt, ...plan } = workspacePlan
|
||||
expect(createdAt).to.not.eq(null)
|
||||
expect(plan.workspaceId).to.eq(workspaceId)
|
||||
expect(plan).to.deep.eq(plan)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user