@speckle/shared
Version:
Shared code between various Speckle JS packages
263 lines • 11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.isPlanFeature = exports.workspacePlanHasAccessToFeature = exports.workspaceReachedPlanLimit = exports.workspaceExceedsPlanLimit = exports.WorkspacePlanConfigs = exports.WorkspaceUnpaidPlanConfigs = exports.WorkspacePaidPlanConfigs = exports.WorkspacePlanFeaturesMetadata = exports.isWorkspaceFeatureFlagOn = exports.WorkspaceFeatureFlags = exports.WorkspacePlanFeatures = void 0;
const plans_js_1 = require("./plans.js");
/**
* WORKSPACE FEATURES
*/
exports.WorkspacePlanFeatures = {
// Core features pretty much available to everyone
AutomateBeta: 'automateBeta',
DomainDiscoverability: 'domainDiscoverability',
// Optional/plan specific
DomainSecurity: 'domainBasedSecurityPolicies',
SSO: 'oidcSso',
CustomDataRegion: 'workspaceDataRegionSpecificity',
HideSpeckleBranding: 'hideSpeckleBranding',
ExclusiveMembership: 'exclusiveMembership',
EmbedPrivateProjects: 'embedPrivateProjects',
SavedViews: 'savedViews'
};
// this const will be used as a bitwise flag for a per workspace feature access controller
// IMPORTANT: always use powers of 2 as the value of the object
// read more https://www.hendrik-erz.de/post/bitwise-flags-are-beautiful-and-heres-why
// this will make its way to the pricing plan and info setup at some point
// but for now its an internal only control
exports.WorkspaceFeatureFlags = {
none: 0,
dashboards: 1,
accIntegration: 2,
// High numbers for internal features
presentations: 64
};
const isWorkspaceFeatureFlagOn = ({ workspaceFeatureFlags, feature }) => (workspaceFeatureFlags & feature) === feature;
exports.isWorkspaceFeatureFlagOn = isWorkspaceFeatureFlagOn;
exports.WorkspacePlanFeaturesMetadata = {
[exports.WorkspacePlanFeatures.AutomateBeta]: {
displayName: 'Automate beta access',
description: 'Run custom automations on every new model version'
},
[exports.WorkspacePlanFeatures.DomainDiscoverability]: {
displayName: 'Domain discoverability',
description: 'Allow people to discover your workspace if they use a verified company email'
},
[exports.WorkspacePlanFeatures.DomainSecurity]: {
displayName: 'Domain protection',
description: 'Require workspace members to use a verified company email'
},
[exports.WorkspacePlanFeatures.SSO]: {
displayName: 'Single Sign-On (SSO)',
description: 'Require workspace members to authenticate with your SSO provider'
},
[exports.WorkspacePlanFeatures.CustomDataRegion]: {
displayName: 'Custom data residency',
description: 'Store your data in EU, UK, North America, or Asia Pacific'
},
[exports.WorkspacePlanFeatures.HideSpeckleBranding]: {
displayName: 'Customised viewer',
description: 'Hide the Speckle branding in embedded viewer'
},
[exports.WorkspacePlanFeatures.ExclusiveMembership]: {
displayName: 'Exclusive workspace membership',
description: 'Members of exclusive workspaces cannot join or create other workspaces'
},
[exports.WorkspacePlanFeatures.EmbedPrivateProjects]: {
displayName: 'Embed private projects',
description: 'Embed projects with visibility set to private or workspace'
},
[exports.WorkspacePlanFeatures.SavedViews]: {
displayName: 'Saved views',
description: 'Create and share saved views of your models'
}
};
const unlimited = {
projectCount: null,
modelCount: null,
versionsHistory: null,
commentHistory: null
};
const baseFeatures = [
exports.WorkspacePlanFeatures.AutomateBeta,
exports.WorkspacePlanFeatures.DomainDiscoverability,
exports.WorkspacePlanFeatures.EmbedPrivateProjects
];
const WorkspacePaidPlanConfigs = (params) => {
const finalBaseFeatures = [
...baseFeatures,
...(params.featureFlags?.FF_SAVED_VIEWS_ENABLED
? [exports.WorkspacePlanFeatures.SavedViews]
: [])
];
return {
[plans_js_1.PaidWorkspacePlans.Team]: {
plan: plans_js_1.PaidWorkspacePlans.Team,
features: [...finalBaseFeatures],
limits: {
projectCount: 5,
modelCount: 25,
versionsHistory: { value: 30, unit: 'day' },
commentHistory: { value: 30, unit: 'day' }
}
},
[plans_js_1.PaidWorkspacePlans.TeamUnlimited]: {
plan: plans_js_1.PaidWorkspacePlans.TeamUnlimited,
features: [...finalBaseFeatures],
limits: {
projectCount: null,
modelCount: null,
versionsHistory: { value: 30, unit: 'day' },
commentHistory: { value: 30, unit: 'day' }
}
},
[plans_js_1.PaidWorkspacePlans.Pro]: {
plan: plans_js_1.PaidWorkspacePlans.Pro,
features: [
...finalBaseFeatures,
exports.WorkspacePlanFeatures.DomainSecurity,
exports.WorkspacePlanFeatures.SSO,
exports.WorkspacePlanFeatures.CustomDataRegion,
exports.WorkspacePlanFeatures.HideSpeckleBranding
],
limits: {
projectCount: 10,
modelCount: 50,
versionsHistory: null,
commentHistory: null
}
},
[plans_js_1.PaidWorkspacePlans.ProUnlimited]: {
plan: plans_js_1.PaidWorkspacePlans.ProUnlimited,
features: [
...finalBaseFeatures,
exports.WorkspacePlanFeatures.DomainSecurity,
exports.WorkspacePlanFeatures.SSO,
exports.WorkspacePlanFeatures.CustomDataRegion,
exports.WorkspacePlanFeatures.HideSpeckleBranding
],
limits: {
projectCount: null,
modelCount: null,
versionsHistory: null,
commentHistory: null
}
}
};
};
exports.WorkspacePaidPlanConfigs = WorkspacePaidPlanConfigs;
const WorkspaceUnpaidPlanConfigs = (params) => {
const finalBaseFeatures = [
...baseFeatures,
...(params.featureFlags?.FF_SAVED_VIEWS_ENABLED
? [exports.WorkspacePlanFeatures.SavedViews]
: [])
];
return {
[plans_js_1.UnpaidWorkspacePlans.Enterprise]: {
plan: plans_js_1.UnpaidWorkspacePlans.Enterprise,
features: [
...finalBaseFeatures,
exports.WorkspacePlanFeatures.DomainSecurity,
exports.WorkspacePlanFeatures.SSO,
exports.WorkspacePlanFeatures.CustomDataRegion,
exports.WorkspacePlanFeatures.HideSpeckleBranding,
exports.WorkspacePlanFeatures.ExclusiveMembership
],
limits: unlimited
},
[plans_js_1.UnpaidWorkspacePlans.Unlimited]: {
plan: plans_js_1.UnpaidWorkspacePlans.Unlimited,
features: [
...finalBaseFeatures,
exports.WorkspacePlanFeatures.DomainSecurity,
exports.WorkspacePlanFeatures.SSO,
exports.WorkspacePlanFeatures.CustomDataRegion,
exports.WorkspacePlanFeatures.HideSpeckleBranding,
exports.WorkspacePlanFeatures.ExclusiveMembership
],
limits: unlimited
},
[plans_js_1.UnpaidWorkspacePlans.Academia]: {
plan: plans_js_1.UnpaidWorkspacePlans.Academia,
features: [
...finalBaseFeatures,
exports.WorkspacePlanFeatures.DomainSecurity,
exports.WorkspacePlanFeatures.SSO,
exports.WorkspacePlanFeatures.CustomDataRegion,
exports.WorkspacePlanFeatures.HideSpeckleBranding
],
limits: unlimited
},
[plans_js_1.UnpaidWorkspacePlans.TeamUnlimitedInvoiced]: {
...(0, exports.WorkspacePaidPlanConfigs)(params).teamUnlimited,
plan: plans_js_1.UnpaidWorkspacePlans.TeamUnlimitedInvoiced
},
[plans_js_1.UnpaidWorkspacePlans.ProUnlimitedInvoiced]: {
...(0, exports.WorkspacePaidPlanConfigs)(params).proUnlimited,
plan: plans_js_1.UnpaidWorkspacePlans.ProUnlimitedInvoiced
},
[plans_js_1.UnpaidWorkspacePlans.Free]: {
plan: plans_js_1.UnpaidWorkspacePlans.Free,
features: finalBaseFeatures,
limits: {
projectCount: 1,
modelCount: 5,
versionsHistory: { value: 7, unit: 'day' },
commentHistory: { value: 7, unit: 'day' }
}
}
};
};
exports.WorkspaceUnpaidPlanConfigs = WorkspaceUnpaidPlanConfigs;
const WorkspacePlanConfigs = (params) => ({
...(0, exports.WorkspacePaidPlanConfigs)(params),
...(0, exports.WorkspaceUnpaidPlanConfigs)(params)
});
exports.WorkspacePlanConfigs = WorkspacePlanConfigs;
/**
* Checks if a workspace exceeds its plan limits for projects and models
*/
const workspaceExceedsPlanLimit = (params) => {
const { plan, projectCount, modelCount, featureFlags } = params;
if (!plan)
return false;
const planConfig = (0, exports.WorkspacePlanConfigs)({ featureFlags })[plan];
if (!planConfig)
return false;
const limits = planConfig.limits;
if (!limits.projectCount || !limits.modelCount)
return false;
if (!projectCount || !modelCount)
return false;
return projectCount > limits.projectCount || modelCount > limits.modelCount;
};
exports.workspaceExceedsPlanLimit = workspaceExceedsPlanLimit;
/**
* Checks if a workspace reached its plan limits for projects and models
*/
const workspaceReachedPlanLimit = (params) => {
const { plan, projectCount, modelCount, featureFlags } = params;
if (!plan)
return false;
const planConfig = (0, exports.WorkspacePlanConfigs)({ featureFlags })[plan];
if (!planConfig)
return false;
const limits = planConfig.limits;
if (!limits.projectCount || !limits.modelCount)
return false;
return projectCount === limits.projectCount || modelCount === limits.modelCount;
};
exports.workspaceReachedPlanLimit = workspaceReachedPlanLimit;
const workspacePlanHasAccessToFeature = ({ plan, feature, featureFlags }) => {
const planConfig = (0, exports.WorkspacePlanConfigs)({ featureFlags })[plan];
const hasAccess = planConfig.features.includes(feature);
return hasAccess;
};
exports.workspacePlanHasAccessToFeature = workspacePlanHasAccessToFeature;
const isPlanFeature = (feature) => {
if (typeof feature === 'number') {
return false;
}
return Object.values(exports.WorkspacePlanFeatures).includes(feature);
};
exports.isPlanFeature = isPlanFeature;
//# sourceMappingURL=features.js.map