mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
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
This commit is contained in:
parent
a6178f45e2
commit
343602027d
17 changed files with 112 additions and 54 deletions
|
@ -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",
|
||||
|
|
|
@ -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']
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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<keyof UsageKey> = [
|
||||
'mauLimit',
|
||||
'organizationsEnabled',
|
||||
'organizationsLimit',
|
||||
'mfaEnabled',
|
||||
'enterpriseSsoLimit',
|
||||
'resourcesLimit',
|
||||
|
@ -39,7 +39,7 @@ export const usageKeys: Array<keyof UsageKey> = [
|
|||
|
||||
export const usageKeyPriceMap: Record<keyof UsageKey, number> = {
|
||||
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',
|
||||
|
|
|
@ -27,7 +27,7 @@ export const skuQuotaItemOrder: Array<keyof LogtoSkuQuota> = [
|
|||
'userRolesLimit',
|
||||
'machineToMachineRolesLimit',
|
||||
'scopesPerRoleLimit',
|
||||
'organizationsEnabled',
|
||||
'organizationsLimit',
|
||||
'auditLogsRetentionDays',
|
||||
'hooksLimit',
|
||||
'customJwtEnabled',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(() => {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<number>): boolean => {
|
||||
return quota === null || quota > 0;
|
||||
};
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -46,9 +46,9 @@ export default function organizationRoleRoutes<T extends ManagementApiRouter>(
|
|||
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'],
|
||||
})
|
||||
|
|
|
@ -20,9 +20,9 @@ export default function organizationScopeRoutes<T extends ManagementApiRouter>(
|
|||
) {
|
||||
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'],
|
||||
})
|
||||
|
|
|
@ -31,9 +31,9 @@ export default function organizationRoutes<T extends ManagementApiRouter>(
|
|||
|
||||
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'],
|
||||
})
|
||||
|
|
|
@ -21,27 +21,32 @@ export type Subscription = RouteResponseType<GetRoutes['/api/tenants/:tenantId/s
|
|||
*/
|
||||
export type SubscriptionQuota = Omit<
|
||||
RouteResponseType<GetRoutes['/api/tenants/:tenantId/subscription/quota']>,
|
||||
'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<GetRoutes['/api/tenants/:tenantId/subscription/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 ReportSubscriptionUpdatesUsageKey = RouteRequestBodyType<
|
||||
PostRoutes['/api/tenants/my/subscription/item-updates']
|
||||
>['usageKey'];
|
||||
export type ReportSubscriptionUpdatesUsageKey = Exclude<
|
||||
RouteRequestBodyType<PostRoutes['/api/tenants/my/subscription/item-updates']>['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',
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue