From 343602027df7664eef81ca1af64d32563d5cea8b Mon Sep 17 00:00:00 2001 From: Darcy Ye Date: Thu, 12 Sep 2024 11:17:43 +0800 Subject: [PATCH] refactor: use orgsLimit instead of orgsEnabled as org quota key (#6570) * refactor: use orgsLimit instead of orgsEnabled as org quota key * refactor: implement getUsageByKey method * chore: undo logto email connector dependency update --- packages/console/package.json | 2 +- packages/console/src/cloud/types/router.ts | 18 ++++++-- .../src/components/PlanUsage/index.tsx | 41 ++++++++++++++++--- .../console/src/components/PlanUsage/utils.ts | 14 +++---- packages/console/src/consts/plan-quotas.ts | 2 +- .../console/src/consts/quota-item-phrases.ts | 8 ++-- packages/console/src/consts/tenants.ts | 6 +-- .../src/pages/OrganizationTemplate/index.tsx | 5 ++- .../CreateOrganizationModal/index.tsx | 6 ++- .../console/src/pages/Organizations/index.tsx | 5 ++- packages/console/src/utils/subscription.ts | 6 ++- packages/core/package.json | 2 +- .../src/routes/organization-role/index.ts | 4 +- .../src/routes/organization-scope/index.ts | 4 +- .../core/src/routes/organization/index.ts | 4 +- packages/core/src/utils/subscription/types.ts | 19 +++++---- pnpm-lock.yaml | 20 ++++----- 17 files changed, 112 insertions(+), 54 deletions(-) diff --git a/packages/console/package.json b/packages/console/package.json index 01a0ce381..0dccfd5cf 100644 --- a/packages/console/package.json +++ b/packages/console/package.json @@ -27,7 +27,7 @@ "devDependencies": { "@fontsource/roboto-mono": "^5.0.0", "@jest/types": "^29.5.0", - "@logto/cloud": "0.2.5-20fd0a2", + "@logto/cloud": "0.2.5-91ab76c", "@logto/connector-kit": "workspace:^4.0.0", "@logto/core-kit": "workspace:^2.5.0", "@logto/elements": "workspace:^0.0.0", diff --git a/packages/console/src/cloud/types/router.ts b/packages/console/src/cloud/types/router.ts index 1d907e8ec..88f6c6d5d 100644 --- a/packages/console/src/cloud/types/router.ts +++ b/packages/console/src/cloud/types/router.ts @@ -20,11 +20,23 @@ export type NewSubscriptionUsageResponse = GuardedResponse< GetRoutes['/api/tenants/:tenantId/subscription-usage'] >; /** The response of `GET /api/tenants/my/subscription/quota` has the same response type. */ -export type NewSubscriptionQuota = NewSubscriptionUsageResponse['quota']; +export type NewSubscriptionQuota = Omit< + NewSubscriptionUsageResponse['quota'], + // Since we are deprecation the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the quota keys for now to avoid confusion. + 'organizationsEnabled' +>; /** The response of `GET /api/tenants/my/subscription/usage` has the same response type. */ -export type NewSubscriptionCountBasedUsage = NewSubscriptionUsageResponse['usage']; +export type NewSubscriptionCountBasedUsage = Omit< + NewSubscriptionUsageResponse['usage'], + // Since we are deprecation the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the usage keys for now to avoid confusion. + 'organizationsEnabled' +>; export type NewSubscriptionResourceScopeUsage = NewSubscriptionUsageResponse['resources']; -export type NewSubscriptionRoleScopeUsage = NewSubscriptionUsageResponse['roles']; +export type NewSubscriptionRoleScopeUsage = Omit< + NewSubscriptionUsageResponse['roles'], + // Since we are deprecation the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the quota keys for now to avoid confusion. + 'organizationsEnabled' +>; export type NewSubscriptionPeriodicUsage = GuardedResponse< GetRoutes['/api/tenants/:tenantId/subscription/periodic-usage'] diff --git a/packages/console/src/components/PlanUsage/index.tsx b/packages/console/src/components/PlanUsage/index.tsx index 6dc5e5b34..c79fc2341 100644 --- a/packages/console/src/components/PlanUsage/index.tsx +++ b/packages/console/src/components/PlanUsage/index.tsx @@ -4,7 +4,10 @@ import classNames from 'classnames'; import dayjs from 'dayjs'; import { useContext, useMemo } from 'react'; -import { type NewSubscriptionPeriodicUsage } from '@/cloud/types/router'; +import { + type NewSubscriptionPeriodicUsage, + type NewSubscriptionCountBasedUsage, +} from '@/cloud/types/router'; import { SubscriptionDataContext } from '@/contexts/SubscriptionDataProvider'; import { TenantsContext } from '@/contexts/TenantsProvider'; import DynamicT from '@/ds-components/DynamicT'; @@ -12,12 +15,41 @@ import { formatPeriod } from '@/utils/subscription'; import PlanUsageCard, { type Props as PlanUsageCardProps } from './PlanUsageCard'; import styles from './index.module.scss'; -import { usageKeys, usageKeyPriceMap, usageKeyMap, titleKeyMap, tooltipKeyMap } from './utils'; +import { + type UsageKey, + usageKeys, + usageKeyPriceMap, + usageKeyMap, + titleKeyMap, + tooltipKeyMap, +} from './utils'; type Props = { readonly periodicUsage?: NewSubscriptionPeriodicUsage; }; +const getUsageByKey = ( + key: keyof UsageKey, + { + periodicUsage, + countBasedUsage, + }: { + periodicUsage: NewSubscriptionPeriodicUsage; + countBasedUsage: NewSubscriptionCountBasedUsage; + } +) => { + if (key === 'mauLimit' || key === 'tokenLimit') { + return periodicUsage[key]; + } + + // Show enabled status for organization feature. + if (key === 'organizationsLimit') { + return countBasedUsage[key] > 0; + } + + return countBasedUsage[key]; +}; + function PlanUsage({ periodicUsage: rawPeriodicUsage }: Props) { const { currentSubscriptionQuota, @@ -59,10 +91,7 @@ function PlanUsage({ periodicUsage: rawPeriodicUsage }: Props) { isAddOnAvailable || (onlyShowPeriodicUsage && (key === 'mauLimit' || key === 'tokenLimit')) ) .map((key) => ({ - usage: - key === 'mauLimit' || key === 'tokenLimit' - ? periodicUsage[key] - : currentSubscriptionUsage[key], + usage: getUsageByKey(key, { periodicUsage, countBasedUsage: currentSubscriptionUsage }), usageKey: `subscription.usage.${usageKeyMap[key]}`, titleKey: `subscription.usage.${titleKeyMap[key]}`, unitPrice: usageKeyPriceMap[key], diff --git a/packages/console/src/components/PlanUsage/utils.ts b/packages/console/src/components/PlanUsage/utils.ts index 39edb7ae2..08c6ca4a6 100644 --- a/packages/console/src/components/PlanUsage/utils.ts +++ b/packages/console/src/components/PlanUsage/utils.ts @@ -12,10 +12,10 @@ import { hooksAddOnUnitPrice, } from '@/consts/subscriptions'; -type UsageKey = Pick< +export type UsageKey = Pick< NewSubscriptionQuota, | 'mauLimit' - | 'organizationsEnabled' + | 'organizationsLimit' | 'mfaEnabled' | 'enterpriseSsoLimit' | 'resourcesLimit' @@ -28,7 +28,7 @@ type UsageKey = Pick< // We decide not to show `hooksLimit` usage in console for now. export const usageKeys: Array = [ 'mauLimit', - 'organizationsEnabled', + 'organizationsLimit', 'mfaEnabled', 'enterpriseSsoLimit', 'resourcesLimit', @@ -39,7 +39,7 @@ export const usageKeys: Array = [ export const usageKeyPriceMap: Record = { mauLimit: 0, - organizationsEnabled: organizationAddOnUnitPrice, + organizationsLimit: organizationAddOnUnitPrice, mfaEnabled: mfaAddOnUnitPrice, enterpriseSsoLimit: enterpriseSsoAddOnUnitPrice, resourcesLimit: resourceAddOnUnitPrice, @@ -54,7 +54,7 @@ export const usageKeyMap: Record< TFuncKey<'translation', 'admin_console.subscription.usage'> > = { mauLimit: 'mau.description', - organizationsEnabled: 'organizations.description', + organizationsLimit: 'organizations.description', mfaEnabled: 'mfa.description', enterpriseSsoLimit: 'enterprise_sso.description', resourcesLimit: 'api_resources.description', @@ -69,7 +69,7 @@ export const titleKeyMap: Record< TFuncKey<'translation', 'admin_console.subscription.usage'> > = { mauLimit: 'mau.title', - organizationsEnabled: 'organizations.title', + organizationsLimit: 'organizations.title', mfaEnabled: 'mfa.title', enterpriseSsoLimit: 'enterprise_sso.title', resourcesLimit: 'api_resources.title', @@ -84,7 +84,7 @@ export const tooltipKeyMap: Record< TFuncKey<'translation', 'admin_console.subscription.usage'> > = { mauLimit: 'mau.tooltip', - organizationsEnabled: 'organizations.tooltip', + organizationsLimit: 'organizations.tooltip', mfaEnabled: 'mfa.tooltip', enterpriseSsoLimit: 'enterprise_sso.tooltip', resourcesLimit: 'api_resources.tooltip', diff --git a/packages/console/src/consts/plan-quotas.ts b/packages/console/src/consts/plan-quotas.ts index 7d03ae3cc..a5ba94407 100644 --- a/packages/console/src/consts/plan-quotas.ts +++ b/packages/console/src/consts/plan-quotas.ts @@ -27,7 +27,7 @@ export const skuQuotaItemOrder: Array = [ 'userRolesLimit', 'machineToMachineRolesLimit', 'scopesPerRoleLimit', - 'organizationsEnabled', + 'organizationsLimit', 'auditLogsRetentionDays', 'hooksLimit', 'customJwtEnabled', diff --git a/packages/console/src/consts/quota-item-phrases.ts b/packages/console/src/consts/quota-item-phrases.ts index 3b70c3fd1..e5cc2e296 100644 --- a/packages/console/src/consts/quota-item-phrases.ts +++ b/packages/console/src/consts/quota-item-phrases.ts @@ -22,7 +22,7 @@ export const skuQuotaItemPhrasesMap: Record< auditLogsRetentionDays: 'audit_logs_retention_days.name', ticketSupportResponseTime: 'email_ticket_support.name', mfaEnabled: 'mfa_enabled.name', - organizationsEnabled: 'organizations_enabled.name', + organizationsLimit: 'organizations_enabled.name', enterpriseSsoLimit: 'sso_enabled.name', tenantMembersLimit: 'tenant_members_limit.name', customJwtEnabled: 'custom_jwt_enabled.name', @@ -49,7 +49,7 @@ export const skuQuotaItemUnlimitedPhrasesMap: Record< auditLogsRetentionDays: 'audit_logs_retention_days.unlimited', ticketSupportResponseTime: 'email_ticket_support.unlimited', mfaEnabled: 'mfa_enabled.unlimited', - organizationsEnabled: 'organizations_enabled.unlimited', + organizationsLimit: 'organizations_enabled.unlimited', enterpriseSsoLimit: 'sso_enabled.unlimited', tenantMembersLimit: 'tenant_members_limit.unlimited', customJwtEnabled: 'custom_jwt_enabled.unlimited', @@ -76,7 +76,7 @@ export const skuQuotaItemLimitedPhrasesMap: Record< auditLogsRetentionDays: 'audit_logs_retention_days.limited', ticketSupportResponseTime: 'email_ticket_support.limited', mfaEnabled: 'mfa_enabled.limited', - organizationsEnabled: 'organizations_enabled.limited', + organizationsLimit: 'organizations_enabled.limited', enterpriseSsoLimit: 'sso_enabled.limited', tenantMembersLimit: 'tenant_members_limit.limited', customJwtEnabled: 'custom_jwt_enabled.limited', @@ -103,7 +103,7 @@ export const skuQuotaItemNotEligiblePhrasesMap: Record< auditLogsRetentionDays: 'audit_logs_retention_days.not_eligible', ticketSupportResponseTime: 'email_ticket_support.not_eligible', mfaEnabled: 'mfa_enabled.not_eligible', - organizationsEnabled: 'organizations_enabled.not_eligible', + organizationsLimit: 'organizations_enabled.not_eligible', enterpriseSsoLimit: 'sso_enabled.not_eligible', tenantMembersLimit: 'tenant_members_limit.not_eligible', customJwtEnabled: 'custom_jwt_enabled.not_eligible', diff --git a/packages/console/src/consts/tenants.ts b/packages/console/src/consts/tenants.ts index 5024bb2c4..4dc1a0f0d 100644 --- a/packages/console/src/consts/tenants.ts +++ b/packages/console/src/consts/tenants.ts @@ -112,7 +112,7 @@ export const defaultLogtoSku: LogtoSkuResponse = { hooksLimit: null, auditLogsRetentionDays: 14, mfaEnabled: true, - organizationsEnabled: true, + organizationsLimit: null, enterpriseSsoLimit: null, thirdPartyApplicationsLimit: null, tenantMembersLimit: 20, @@ -137,7 +137,7 @@ export const defaultSubscriptionQuota: NewSubscriptionQuota = { hooksLimit: 1, auditLogsRetentionDays: 3, mfaEnabled: false, - organizationsEnabled: false, + organizationsLimit: 0, enterpriseSsoLimit: 0, thirdPartyApplicationsLimit: 0, tenantMembersLimit: 1, @@ -157,7 +157,7 @@ export const defaultSubscriptionUsage: NewSubscriptionCountBasedUsage = { scopesPerRoleLimit: 0, hooksLimit: 0, mfaEnabled: false, - organizationsEnabled: false, + organizationsLimit: 0, enterpriseSsoLimit: 0, thirdPartyApplicationsLimit: 0, tenantMembersLimit: 0, diff --git a/packages/console/src/pages/OrganizationTemplate/index.tsx b/packages/console/src/pages/OrganizationTemplate/index.tsx index 1d94ae4a9..a5552acd9 100644 --- a/packages/console/src/pages/OrganizationTemplate/index.tsx +++ b/packages/console/src/pages/OrganizationTemplate/index.tsx @@ -22,6 +22,7 @@ import TablePlaceholder from '@/ds-components/Table/TablePlaceholder'; import useDocumentationUrl from '@/hooks/use-documentation-url'; import useTenantPathname from '@/hooks/use-tenant-pathname'; import pageLayout from '@/scss/page-layout.module.scss'; +import { isFeatureEnabled } from '@/utils/subscription'; import Introduction from '../Organizations/Introduction'; @@ -38,7 +39,9 @@ function OrganizationTemplate() { } = useContext(SubscriptionDataContext); const { isDevTenant } = useContext(TenantsContext); const isOrganizationsDisabled = - isCloud && !currentSubscriptionQuota.organizationsEnabled && planId !== ReservedPlanId.Pro; + isCloud && + !isFeatureEnabled(currentSubscriptionQuota.organizationsLimit) && + planId !== ReservedPlanId.Pro; const { navigate } = useTenantPathname(); const handleUpgradePlan = useCallback(() => { diff --git a/packages/console/src/pages/Organizations/CreateOrganizationModal/index.tsx b/packages/console/src/pages/Organizations/CreateOrganizationModal/index.tsx index e1b5a23c5..c3b7374ab 100644 --- a/packages/console/src/pages/Organizations/CreateOrganizationModal/index.tsx +++ b/packages/console/src/pages/Organizations/CreateOrganizationModal/index.tsx @@ -21,7 +21,7 @@ import useApi from '@/hooks/use-api'; import useUserPreferences from '@/hooks/use-user-preferences'; import modalStyles from '@/scss/modal.module.scss'; import { trySubmitSafe } from '@/utils/form'; -import { isPaidPlan } from '@/utils/subscription'; +import { isPaidPlan, isFeatureEnabled } from '@/utils/subscription'; import styles from './index.module.scss'; @@ -42,7 +42,9 @@ function CreateOrganizationModal({ isOpen, onClose }: Props) { update, } = useUserPreferences(); const isOrganizationsDisabled = - isCloud && !currentSubscriptionQuota.organizationsEnabled && planId !== ReservedPlanId.Pro; + isCloud && + !isFeatureEnabled(currentSubscriptionQuota.organizationsLimit) && + planId !== ReservedPlanId.Pro; const { reset, diff --git a/packages/console/src/pages/Organizations/index.tsx b/packages/console/src/pages/Organizations/index.tsx index 39d13fee0..c640f8bee 100644 --- a/packages/console/src/pages/Organizations/index.tsx +++ b/packages/console/src/pages/Organizations/index.tsx @@ -15,6 +15,7 @@ import CardTitle from '@/ds-components/CardTitle'; import useDocumentationUrl from '@/hooks/use-documentation-url'; import useTenantPathname from '@/hooks/use-tenant-pathname'; import pageLayout from '@/scss/page-layout.module.scss'; +import { isFeatureEnabled } from '@/utils/subscription'; import CreateOrganizationModal from './CreateOrganizationModal'; import OrganizationsTable from './OrganizationsTable'; @@ -35,7 +36,9 @@ function Organizations() { const [isCreating, setIsCreating] = useState(false); const isOrganizationsDisabled = - isCloud && !currentSubscriptionQuota.organizationsEnabled && planId !== ReservedPlanId.Pro; + isCloud && + !isFeatureEnabled(currentSubscriptionQuota.organizationsLimit) && + planId !== ReservedPlanId.Pro; const upgradePlan = useCallback(() => { navigate(subscriptionPage); diff --git a/packages/console/src/utils/subscription.ts b/packages/console/src/utils/subscription.ts index 31e3ac19d..84f54d882 100644 --- a/packages/console/src/utils/subscription.ts +++ b/packages/console/src/utils/subscription.ts @@ -1,5 +1,5 @@ import { ReservedPlanId } from '@logto/schemas'; -import { conditional, trySafe } from '@silverhand/essentials'; +import { conditional, trySafe, type Nullable } from '@silverhand/essentials'; import { ResponseError } from '@withtyped/client'; import dayjs from 'dayjs'; @@ -98,3 +98,7 @@ export const pickupFeaturedLogtoSkus = (logtoSkus: LogtoSkuResponse[]): LogtoSku export const isPaidPlan = (planId: string, isEnterprisePlan: boolean) => planId === ReservedPlanId.Pro || isEnterprisePlan; + +export const isFeatureEnabled = (quota: Nullable): boolean => { + return quota === null || quota > 0; +}; diff --git a/packages/core/package.json b/packages/core/package.json index 511c484db..1fb465941 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -97,7 +97,7 @@ "zod": "^3.23.8" }, "devDependencies": { - "@logto/cloud": "0.2.5-20fd0a2", + "@logto/cloud": "0.2.5-91ab76c", "@silverhand/eslint-config": "6.0.1", "@silverhand/ts-config": "6.0.0", "@types/adm-zip": "^0.5.5", diff --git a/packages/core/src/routes/organization-role/index.ts b/packages/core/src/routes/organization-role/index.ts index c617f5557..ff700c676 100644 --- a/packages/core/src/routes/organization-role/index.ts +++ b/packages/core/src/routes/organization-role/index.ts @@ -46,9 +46,9 @@ export default function organizationRoleRoutes( ManagementApiRouterContext >(OrganizationRoles, roles, { middlewares: condArray( - koaQuotaGuard({ key: 'organizationsEnabled', quota, methods: ['POST', 'PUT'] }), + koaQuotaGuard({ key: 'organizationsLimit', quota, methods: ['POST', 'PUT'] }), koaReportSubscriptionUpdates({ - key: 'organizationsEnabled', + key: 'organizationsLimit', quota, methods: ['POST', 'PUT', 'DELETE'], }) diff --git a/packages/core/src/routes/organization-scope/index.ts b/packages/core/src/routes/organization-scope/index.ts index e7a240ef1..d31a746fe 100644 --- a/packages/core/src/routes/organization-scope/index.ts +++ b/packages/core/src/routes/organization-scope/index.ts @@ -20,9 +20,9 @@ export default function organizationScopeRoutes( ) { const router = new SchemaRouter(OrganizationScopes, scopes, { middlewares: condArray( - koaQuotaGuard({ key: 'organizationsEnabled', quota, methods: ['POST', 'PUT'] }), + koaQuotaGuard({ key: 'organizationsLimit', quota, methods: ['POST', 'PUT'] }), koaReportSubscriptionUpdates({ - key: 'organizationsEnabled', + key: 'organizationsLimit', quota, methods: ['POST', 'PUT', 'DELETE'], }) diff --git a/packages/core/src/routes/organization/index.ts b/packages/core/src/routes/organization/index.ts index bc6c5d821..45cdcc16d 100644 --- a/packages/core/src/routes/organization/index.ts +++ b/packages/core/src/routes/organization/index.ts @@ -31,9 +31,9 @@ export default function organizationRoutes( const router = new SchemaRouter(Organizations, organizations, { middlewares: condArray( - koaQuotaGuard({ key: 'organizationsEnabled', quota, methods: ['POST', 'PUT'] }), + koaQuotaGuard({ key: 'organizationsLimit', quota, methods: ['POST', 'PUT'] }), koaReportSubscriptionUpdates({ - key: 'organizationsEnabled', + key: 'organizationsLimit', quota, methods: ['POST', 'PUT', 'DELETE'], }) diff --git a/packages/core/src/utils/subscription/types.ts b/packages/core/src/utils/subscription/types.ts index d429c1fce..1d8dfd104 100644 --- a/packages/core/src/utils/subscription/types.ts +++ b/packages/core/src/utils/subscription/types.ts @@ -21,27 +21,32 @@ export type Subscription = RouteResponseType, - 'auditLogsRetentionDays' + // Since we are deprecation the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the usage keys for now to avoid confusion. + 'auditLogsRetentionDays' | 'organizationsEnabled' >; /** * The type of the response of the `GET /api/tenants/:tenantId/subscription/usage` endpoint. * It is the same as the response type of `GET /api/tenants/my/subscription/usage` endpoint. */ -export type SubscriptionUsage = RouteResponseType< - GetRoutes['/api/tenants/:tenantId/subscription/usage'] +export type SubscriptionUsage = Omit< + RouteResponseType, + // Since we are deprecation the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the usage keys for now to avoid confusion. + 'organizationsEnabled' >; -export type ReportSubscriptionUpdatesUsageKey = RouteRequestBodyType< - PostRoutes['/api/tenants/my/subscription/item-updates'] ->['usageKey']; +export type ReportSubscriptionUpdatesUsageKey = Exclude< + RouteRequestBodyType['usageKey'], + // Since we are deprecation the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the usage keys for now to avoid confusion. + 'organizationsEnabled' +>; // Have to manually define this variable since we can only get the literal union from the @logto/cloud/routes module. export const allReportSubscriptionUpdatesUsageKeys = Object.freeze([ 'machineToMachineLimit', 'resourcesLimit', 'mfaEnabled', - 'organizationsEnabled', + 'organizationsLimit', 'tenantMembersLimit', 'enterpriseSsoLimit', 'hooksLimit', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a189d24d1..064dd7d27 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2568,8 +2568,8 @@ importers: specifier: ^29.5.0 version: 29.5.0 '@logto/cloud': - specifier: 0.2.5-20fd0a2 - version: 0.2.5-20fd0a2(zod@3.23.8) + specifier: 0.2.5-91ab76c + version: 0.2.5-91ab76c(zod@3.23.8) '@logto/connector-kit': specifier: workspace:^4.0.0 version: link:../toolkit/connector-kit @@ -3064,8 +3064,8 @@ importers: version: 3.23.8 devDependencies: '@logto/cloud': - specifier: 0.2.5-20fd0a2 - version: 0.2.5-20fd0a2(zod@3.23.8) + specifier: 0.2.5-91ab76c + version: 0.2.5-91ab76c(zod@3.23.8) '@silverhand/eslint-config': specifier: 6.0.1 version: 6.0.1(eslint@8.57.0)(prettier@3.0.0)(typescript@5.5.3) @@ -5571,14 +5571,14 @@ packages: '@logto/client@2.7.2': resolution: {integrity: sha512-jsmuDl9QpXfR3uLEMPE67tvYoL5XcjJi+4yGqucYPjd4GH6SUHp3N9skk8C/OyygnKDPLY+ttwD0LaIbpGvn+Q==} - '@logto/cloud@0.2.5-20fd0a2': - resolution: {integrity: sha512-j0f2RDpi/OEI59WXKnih7QeFSywNFV91PkulZdmcGa8HCRNmht94siw+LILzheg6bzwfvHU/aN4tJYL1/Px1BA==} - engines: {node: ^20.9.0} - '@logto/cloud@0.2.5-582d792': resolution: {integrity: sha512-0fIZzqwyjQguTS0a5+XbgVZlGEB/MXIf6pbuBDkHh6JHlMTJ/XH041rWX+e+nMk5N7/Xk2XXS+d2RJUWumnmpw==} engines: {node: ^20.9.0} + '@logto/cloud@0.2.5-91ab76c': + resolution: {integrity: sha512-t/ZVrFICVxtqw6zh6/OJ+0VYt+fl+waNz77CdAJkhxC91KFMfojm4hWNrx1qTNSTUzg+gc/2p8cbKC9cH1ngeA==} + engines: {node: ^20.9.0} + '@logto/js@4.1.4': resolution: {integrity: sha512-6twud1nFBQmj89/aflzej6yD1QwXfPiYmRtyYuN4a7O9OaaW3X/kJBVwjKUn5NC9IUt+rd+jXsI3QJXENfaLAw==} @@ -15244,14 +15244,14 @@ snapshots: camelcase-keys: 7.0.2 jose: 5.6.3 - '@logto/cloud@0.2.5-20fd0a2(zod@3.23.8)': + '@logto/cloud@0.2.5-582d792(zod@3.23.8)': dependencies: '@silverhand/essentials': 2.9.1 '@withtyped/server': 0.14.0(zod@3.23.8) transitivePeerDependencies: - zod - '@logto/cloud@0.2.5-582d792(zod@3.23.8)': + '@logto/cloud@0.2.5-91ab76c(zod@3.23.8)': dependencies: '@silverhand/essentials': 2.9.1 '@withtyped/server': 0.14.0(zod@3.23.8)