diff --git a/packages/console/package.json b/packages/console/package.json index d0db8ec553b5..08f625b33fb6 100644 --- a/packages/console/package.json +++ b/packages/console/package.json @@ -30,7 +30,7 @@ "@fontsource/roboto-mono": "^5.0.0", "@inkeep/cxkit-react": "^0.5.66", "@jest/types": "^29.5.0", - "@logto/cloud": "0.2.5-31c9868", + "@logto/cloud": "0.2.5-66a5752", "@logto/connector-kit": "workspace:^", "@logto/core-kit": "workspace:^", "@logto/language-kit": "workspace:^", diff --git a/packages/console/src/cloud/types/router.ts b/packages/console/src/cloud/types/router.ts index 89714e6eb1f4..80ae3075d68c 100644 --- a/packages/console/src/cloud/types/router.ts +++ b/packages/console/src/cloud/types/router.ts @@ -7,7 +7,7 @@ type GetTenantAuthRoutes = RouterRoutes['get']; export type GetArrayElementType = T extends Array ? U : never; -export type LogtoSkuResponse = GetArrayElementType>; +type CloudLogtoSkuResponse = GetArrayElementType>; export type Subscription = GuardedResponse; @@ -21,21 +21,31 @@ export type SubscriptionUsageResponse = GuardedResponse< GetRoutes['/api/tenants/:tenantId/subscription-usage'] >; +type InlineHookSubscriptionQuota = { + inlineHooksEnabled: boolean; +}; + export type SubscriptionQuota = Omit< SubscriptionUsageResponse['quota'], - // Since we are deprecation the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the quota keys for now to avoid confusion. + // Since we are deprecating the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the quota keys for now to avoid confusion. 'organizationsEnabled' ->; +> & + InlineHookSubscriptionQuota; + +export type LogtoSkuResponse = Omit & { + quota: CloudLogtoSkuResponse['quota'] & Partial; +}; export type SubscriptionCountBasedUsage = Omit< SubscriptionUsageResponse['usage'], - // Since we are deprecation the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the usage keys for now to avoid confusion. + // Since we are deprecating the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the usage keys for now to avoid confusion. 'organizationsEnabled' ->; +> & + InlineHookSubscriptionQuota; export type SubscriptionResourceScopeUsage = SubscriptionUsageResponse['resources']; export type SubscriptionRoleScopeUsage = Omit< SubscriptionUsageResponse['roles'], - // Since we are deprecation the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the quota keys for now to avoid confusion. + // Since we are deprecating the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the quota keys for now to avoid confusion. 'organizationsEnabled' >; diff --git a/packages/console/src/consts/plan-quotas.ts b/packages/console/src/consts/plan-quotas.ts index f716746861a6..42167489baeb 100644 --- a/packages/console/src/consts/plan-quotas.ts +++ b/packages/console/src/consts/plan-quotas.ts @@ -50,6 +50,8 @@ export const comingSoonSkuQuotaKeys: Array = []; */ export const hiddenQuotaDiffUsageKeys: Array = [ 'tokenLimit', + // Keep inline hooks hidden from the plan quota UI until it is ready to open after further testing. + 'inlineHooksEnabled', 'scopesPerResourceLimit', 'userRolesLimit', 'machineToMachineRolesLimit', diff --git a/packages/console/src/consts/quota-item-phrases.ts b/packages/console/src/consts/quota-item-phrases.ts index 524927bb2194..5eca743ea9a0 100644 --- a/packages/console/src/consts/quota-item-phrases.ts +++ b/packages/console/src/consts/quota-item-phrases.ts @@ -2,9 +2,14 @@ import { type TFuncKey } from 'i18next'; import { type LogtoSkuQuota } from '@/types/skus'; +type SkuQuotaItemPhraseKey = Exclude; + +export const isSkuQuotaItemPhraseKey = (key: keyof LogtoSkuQuota): key is SkuQuotaItemPhraseKey => + key !== 'inlineHooksEnabled'; + /* === for new pricing model === */ export const skuQuotaItemPhrasesMap: Record< - keyof LogtoSkuQuota, + SkuQuotaItemPhraseKey, TFuncKey<'translation', 'admin_console.subscription.quota_item'> > = { mauLimit: 'mau_limit.name', @@ -37,7 +42,7 @@ export const skuQuotaItemPhrasesMap: Record< }; export const skuQuotaItemUnlimitedPhrasesMap: Record< - keyof LogtoSkuQuota, + SkuQuotaItemPhraseKey, TFuncKey<'translation', 'admin_console.subscription.quota_item'> > = { mauLimit: 'mau_limit.unlimited', @@ -70,7 +75,7 @@ export const skuQuotaItemUnlimitedPhrasesMap: Record< }; export const skuQuotaItemLimitedPhrasesMap: Record< - keyof LogtoSkuQuota, + SkuQuotaItemPhraseKey, TFuncKey<'translation', 'admin_console.subscription.quota_item'> > = { mauLimit: 'mau_limit.limited', @@ -103,7 +108,7 @@ export const skuQuotaItemLimitedPhrasesMap: Record< }; export const skuQuotaItemNotEligiblePhrasesMap: Record< - keyof LogtoSkuQuota, + SkuQuotaItemPhraseKey, TFuncKey<'translation', 'admin_console.subscription.quota_item'> > = { mauLimit: 'mau_limit.not_eligible', diff --git a/packages/console/src/consts/tenants.ts b/packages/console/src/consts/tenants.ts index aa672869daf4..0ec4880447e8 100644 --- a/packages/console/src/consts/tenants.ts +++ b/packages/console/src/consts/tenants.ts @@ -85,12 +85,15 @@ export const defaultLogtoSku: LogtoSkuResponse = { thirdPartyApplicationsLimit: null, tenantMembersLimit: 20, customJwtEnabled: true, + inlineHooksEnabled: false, subjectTokenEnabled: true, bringYourUiEnabled: true, collectUserProfileEnabled: true, passkeySignInEnabled: true, idpInitiatedSsoEnabled: false, + samlApplicationsLimit: 3, securityFeaturesEnabled: true, + customDomainsLimit: 2, }, }; @@ -114,6 +117,7 @@ export const defaultSubscriptionQuota: SubscriptionQuota = { thirdPartyApplicationsLimit: 0, tenantMembersLimit: 1, customJwtEnabled: false, + inlineHooksEnabled: false, subjectTokenEnabled: false, bringYourUiEnabled: false, collectUserProfileEnabled: false, @@ -140,6 +144,7 @@ export const defaultSubscriptionUsage: SubscriptionCountBasedUsage = { thirdPartyApplicationsLimit: 0, tenantMembersLimit: 0, customJwtEnabled: false, + inlineHooksEnabled: false, bringYourUiEnabled: false, collectUserProfileEnabled: false, passkeySignInEnabled: false, diff --git a/packages/console/src/contexts/SubscriptionDataProvider/use-subscription-data.ts b/packages/console/src/contexts/SubscriptionDataProvider/use-subscription-data.ts index 82fe3de2b0c4..8ede5c73df67 100644 --- a/packages/console/src/contexts/SubscriptionDataProvider/use-subscription-data.ts +++ b/packages/console/src/contexts/SubscriptionDataProvider/use-subscription-data.ts @@ -3,7 +3,12 @@ import { useContext, useEffect, useMemo } from 'react'; import useSWR from 'swr'; import { useCloudApi } from '@/cloud/hooks/use-cloud-api'; -import { type LogtoSkuResponse, type SubscriptionUsageResponse } from '@/cloud/types/router'; +import { + type LogtoSkuResponse, + type SubscriptionCountBasedUsage, + type SubscriptionQuota, + type SubscriptionUsageResponse, +} from '@/cloud/types/router'; import { defaultLogtoSku, defaultTenantResponse, @@ -19,6 +24,20 @@ import useSubscription from '../../hooks/use-subscription'; import { type SubscriptionContext } from './types'; +const normalizeSubscriptionQuota = ( + quota?: SubscriptionUsageResponse['quota'] +): SubscriptionQuota => ({ + ...defaultSubscriptionQuota, + ...quota, +}); + +const normalizeSubscriptionUsage = ( + usage?: SubscriptionUsageResponse['usage'] +): SubscriptionCountBasedUsage => ({ + ...defaultSubscriptionUsage, + ...usage, +}); + const useSubscriptionData: () => SubscriptionContext & { isLoading: boolean } = () => { const cloudApi = useCloudApi(); @@ -58,6 +77,21 @@ const useSubscriptionData: () => SubscriptionContext & { isLoading: boolean } = const logtoSkus = useMemo(() => formatLogtoSkusResponses(fetchedLogtoSkus), [fetchedLogtoSkus]); + const currentSubscriptionQuota = useMemo( + () => normalizeSubscriptionQuota(subscriptionUsageData?.quota), + [subscriptionUsageData?.quota] + ); + + const currentSubscriptionBasicQuota = useMemo( + () => normalizeSubscriptionQuota(subscriptionUsageData?.basicQuota), + [subscriptionUsageData?.basicQuota] + ); + + const currentSubscriptionUsage = useMemo( + () => normalizeSubscriptionUsage(subscriptionUsageData?.usage), + [subscriptionUsageData?.usage] + ); + const currentSku = useMemo( () => logtoSkus.find((logtoSku) => logtoSku.id === currentTenant?.planId) ?? defaultLogtoSku, [currentTenant?.planId, logtoSkus] @@ -79,26 +113,26 @@ const useSubscriptionData: () => SubscriptionContext & { isLoading: boolean } = currentSubscription: currentSubscription ?? defaultTenantResponse.subscription, onCurrentSubscriptionUpdated: mutateSubscription, mutateSubscriptionQuotaAndUsages, - currentSubscriptionQuota: subscriptionUsageData?.quota ?? defaultSubscriptionQuota, - currentSubscriptionBasicQuota: subscriptionUsageData?.basicQuota ?? defaultSubscriptionQuota, - currentSubscriptionUsage: subscriptionUsageData?.usage ?? defaultSubscriptionUsage, + currentSubscriptionQuota, + currentSubscriptionBasicQuota, + currentSubscriptionUsage, currentSubscriptionResourceScopeUsage: subscriptionUsageData?.resources ?? {}, currentSubscriptionRoleScopeUsage: subscriptionUsageData?.roles ?? {}, }), [ currentSku, currentSubscription, + currentSubscriptionBasicQuota, + currentSubscriptionQuota, + currentSubscriptionUsage, isLogtoSkusLoading, isSubscriptionLoading, isSubscriptionUsageDataLoading, logtoSkus, mutateSubscription, mutateSubscriptionQuotaAndUsages, - subscriptionUsageData?.quota, - subscriptionUsageData?.basicQuota, subscriptionUsageData?.resources, subscriptionUsageData?.roles, - subscriptionUsageData?.usage, ] ); }; diff --git a/packages/console/src/pages/TenantSettings/Subscription/DowngradeConfirmModalContent/PlanQuotaDiffCard/PlanQuotaList/DiffQuotaItem/SkuQuotaItemPhrase.tsx b/packages/console/src/pages/TenantSettings/Subscription/DowngradeConfirmModalContent/PlanQuotaDiffCard/PlanQuotaList/DiffQuotaItem/SkuQuotaItemPhrase.tsx index b25f075ed667..549fc22a338b 100644 --- a/packages/console/src/pages/TenantSettings/Subscription/DowngradeConfirmModalContent/PlanQuotaDiffCard/PlanQuotaList/DiffQuotaItem/SkuQuotaItemPhrase.tsx +++ b/packages/console/src/pages/TenantSettings/Subscription/DowngradeConfirmModalContent/PlanQuotaDiffCard/PlanQuotaList/DiffQuotaItem/SkuQuotaItemPhrase.tsx @@ -4,6 +4,7 @@ import { skuQuotaItemUnlimitedPhrasesMap, skuQuotaItemPhrasesMap, skuQuotaItemLimitedPhrasesMap, + isSkuQuotaItemPhraseKey, } from '@/consts/quota-item-phrases'; import DynamicT from '@/ds-components/DynamicT'; import { type LogtoSkuQuota } from '@/types/skus'; @@ -16,6 +17,10 @@ type Props = { }; function SkuQuotaItemPhrase({ skuQuotaKey, skuQuotaValue }: Props) { + if (!isSkuQuotaItemPhraseKey(skuQuotaKey)) { + return null; + } + const isUnlimited = skuQuotaValue === null; const isNotCapable = skuQuotaValue === 0 || skuQuotaValue === false; const isLimited = Boolean(skuQuotaValue); diff --git a/packages/console/src/pages/TenantSettings/components/NotEligibleSwitchPlanModalContent/index.tsx b/packages/console/src/pages/TenantSettings/components/NotEligibleSwitchPlanModalContent/index.tsx index 8a9884ba0315..9747ca035359 100644 --- a/packages/console/src/pages/TenantSettings/components/NotEligibleSwitchPlanModalContent/index.tsx +++ b/packages/console/src/pages/TenantSettings/components/NotEligibleSwitchPlanModalContent/index.tsx @@ -7,6 +7,7 @@ import ContactUsPhraseLink from '@/components/ContactUsPhraseLink'; import SkuName from '@/components/SkuName'; import { skuQuotaItemOrder } from '@/consts/plan-quotas'; import { + isSkuQuotaItemPhraseKey, skuQuotaItemLimitedPhrasesMap, skuQuotaItemNotEligiblePhrasesMap, } from '@/consts/quota-item-phrases'; @@ -19,6 +20,7 @@ import styles from './index.module.scss'; const excludedSkuQuotaKeys = new Set([ 'auditLogsRetentionDays', + 'inlineHooksEnabled', 'ticketSupportResponseTime', ]); @@ -70,6 +72,7 @@ export function NotEligibleSwitchSkuModalContent({ {orderedEntries.map(([quotaKey, quotaValue]) => { if ( excludedSkuQuotaKeys.has(quotaKey) || + !isSkuQuotaItemPhraseKey(quotaKey) || quotaValue === null || // Unlimited items quotaValue === true // Eligible items ) { diff --git a/packages/console/src/types/skus.ts b/packages/console/src/types/skus.ts index 0b21d47dbe94..e46a866c9232 100644 --- a/packages/console/src/types/skus.ts +++ b/packages/console/src/types/skus.ts @@ -1,6 +1,6 @@ import { type SubscriptionQuota } from '@/cloud/types/router'; -// TODO: This is a copy from `@logto/cloud-models`, make a SSoT for this later +// This is a copy from `@logto/cloud-models`; make a SSoT for this later. export enum LogtoSkuType { Basic = 'Basic', AddOn = 'AddOn', diff --git a/packages/core/package.json b/packages/core/package.json index b312b726c716..807877d0a01a 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -105,7 +105,7 @@ "zod": "3.24.3" }, "devDependencies": { - "@logto/cloud": "0.2.5-31c9868", + "@logto/cloud": "0.2.5-66a5752", "@silverhand/eslint-config": "6.0.1", "@silverhand/ts-config": "6.0.0", "@types/adm-zip": "^0.5.5", diff --git a/packages/core/src/__mocks__/cloud-connection.ts b/packages/core/src/__mocks__/cloud-connection.ts index ffe23c8855d5..1d06a84d0499 100644 --- a/packages/core/src/__mocks__/cloud-connection.ts +++ b/packages/core/src/__mocks__/cloud-connection.ts @@ -53,6 +53,7 @@ export const mockQuota = { thirdPartyApplicationsLimit: 0, tenantMembersLimit: 1, customJwtEnabled: false, + inlineHooksEnabled: false, subjectTokenEnabled: false, bringYourUiEnabled: false, collectUserProfileEnabled: false, diff --git a/packages/core/src/queries/tenant-usage/types.ts b/packages/core/src/queries/tenant-usage/types.ts index f85c37218f5e..7a52cc0ec604 100644 --- a/packages/core/src/queries/tenant-usage/types.ts +++ b/packages/core/src/queries/tenant-usage/types.ts @@ -86,6 +86,7 @@ export const isSystemUsageKey = (key: UsageKey): key is SystemUsageKey => const quotaUsageKeyGuard = z.enum([ ...sharedUsageKeyGuard.options, 'customJwtEnabled', + 'inlineHooksEnabled', 'subjectTokenEnabled', 'bringYourUiEnabled', 'collectUserProfileEnabled', @@ -132,6 +133,7 @@ type BooleanQuotaUsageKey = { const booleanQuotaUsageKeyGuard = z.enum([ 'customJwtEnabled', + 'inlineHooksEnabled', 'subjectTokenEnabled', 'bringYourUiEnabled', 'collectUserProfileEnabled', diff --git a/packages/core/src/utils/subscription/index.ts b/packages/core/src/utils/subscription/index.ts index d5755167be6d..0f9c97aa49d9 100644 --- a/packages/core/src/utils/subscription/index.ts +++ b/packages/core/src/utils/subscription/index.ts @@ -19,9 +19,17 @@ export const getTenantSubscription = async ( // All the dates will be converted to the ISO 8601 format after json serialization. // Convert the dates to ISO 8601 format to match the exact type of the response. const { currentPeriodStart, currentPeriodEnd, ...rest } = subscription; + const inlineHooksEnabled = + 'inlineHooksEnabled' in rest.quota && typeof rest.quota.inlineHooksEnabled === 'boolean' + ? rest.quota.inlineHooksEnabled + : false; return { ...rest, + quota: { + ...rest.quota, + inlineHooksEnabled, + }, currentPeriodStart: new Date(currentPeriodStart).toISOString(), currentPeriodEnd: new Date(currentPeriodEnd).toISOString(), }; diff --git a/packages/core/src/utils/subscription/types.ts b/packages/core/src/utils/subscription/types.ts index aa07405c0a42..3b7352108348 100644 --- a/packages/core/src/utils/subscription/types.ts +++ b/packages/core/src/utils/subscription/types.ts @@ -11,14 +11,30 @@ type RouteResponseType = z.infer>; +type CompleteSubscription = RouteResponseType; +type CompleteSubscriptionUsage = RouteResponseType; + +type InlineHookSubscriptionQuota = { + inlineHooksEnabled: boolean; +}; + +export type SubscriptionQuota = Omit< + CompleteSubscriptionUsage['quota'], + | 'auditLogsRetentionDays' + // Since we are deprecating the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the usage keys for now to avoid confusion. + | 'organizationsEnabled' +> & + InlineHookSubscriptionQuota; + /** * The subscription data is fetched from the Cloud API. * All the dates are in ISO 8601 format, we need to manually fix the type to string here. */ export type Subscription = Omit< - RouteResponseType, + CompleteSubscription, | 'currentPeriodStart' | 'currentPeriodEnd' + | 'quota' /** * Temporarily omit `quotaScope` for backward compatibility. * When we require this field, implement the related logic here. @@ -28,30 +44,19 @@ export type Subscription = Omit< > & { currentPeriodStart: string; currentPeriodEnd: string; + quota: SubscriptionQuota; }; -type CompleteSubscriptionUsage = RouteResponseType; - -/** - * @remarks - * The `auditLogsRetentionDays` will be handled by cron job in Azure Functions, outdated audit logs will be removed automatically. - */ -export type SubscriptionQuota = Omit< - CompleteSubscriptionUsage['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. - | 'organizationsEnabled' ->; - export type SubscriptionUsage = Omit< CompleteSubscriptionUsage['usage'], - // Since we are deprecation the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the usage keys for now to avoid confusion. + // Since we are deprecating the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the usage keys for now to avoid confusion. 'organizationsEnabled' ->; +> & + InlineHookSubscriptionQuota; 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. + // Since we are deprecating the `organizationsEnabled` key soon (use `organizationsLimit` instead), we exclude it from the usage keys for now to avoid confusion. 'organizationsEnabled' >; @@ -102,6 +107,7 @@ const logtoSkuQuotaGuard = z.object({ hooksLimit: z.number().nullable(), auditLogsRetentionDays: z.number().nullable(), customJwtEnabled: z.boolean(), + inlineHooksEnabled: z.boolean(), subjectTokenEnabled: z.boolean(), bringYourUiEnabled: z.boolean(), collectUserProfileEnabled: z.boolean(), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d62653ac827d..f04101069355 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -147,7 +147,7 @@ importers: version: 6.0.1(eslint@8.57.0)(prettier@3.5.3)(typescript@5.5.3) '@silverhand/eslint-config-react': specifier: 6.0.2 - version: 6.0.2(eslint@8.57.0)(postcss@8.5.15)(prettier@3.5.3)(stylelint@15.11.0(typescript@5.5.3))(typescript@5.5.3) + version: 6.0.2(eslint@8.57.0)(postcss@8.5.14)(prettier@3.5.3)(stylelint@15.11.0(typescript@5.5.3))(typescript@5.5.3) '@silverhand/essentials': specifier: ^2.9.1 version: 2.9.2 @@ -3771,8 +3771,8 @@ importers: specifier: ^29.5.0 version: 29.6.3 '@logto/cloud': - specifier: 0.2.5-31c9868 - version: 0.2.5-31c9868(zod@3.24.3) + specifier: 0.2.5-66a5752 + version: 0.2.5-66a5752(zod@3.24.3) '@logto/connector-kit': specifier: workspace:^ version: link:../toolkit/connector-kit @@ -4303,8 +4303,8 @@ importers: version: 3.24.3 devDependencies: '@logto/cloud': - specifier: 0.2.5-31c9868 - version: 0.2.5-31c9868(zod@3.24.3) + specifier: 0.2.5-66a5752 + version: 0.2.5-66a5752(zod@3.24.3) '@silverhand/eslint-config': specifier: 6.0.1 version: 6.0.1(eslint@8.57.0)(prettier@3.5.3)(typescript@5.5.3) @@ -6578,6 +6578,10 @@ packages: resolution: {integrity: sha512-zjLFeCsZLejMdLV0TU/NRQ4epg0G8ZwykmHc2Ax6wBt6wOra5lGlNZHX+RvcC6B0U8mb9O7X5Qa9i8nfOWOz2w==} engines: {node: ^22.14.0} + '@logto/cloud@0.2.5-66a5752': + resolution: {integrity: sha512-r8F2KdcI2YscR4wHNv0FZF50AYLtoNCU1A7LaNbd/N+59y/uUWUD1LQShaNfnmZagl73LXRkUXZkoZoyjnOr7Q==} + engines: {node: ^22.14.0} + '@logto/js@5.1.0': resolution: {integrity: sha512-sOpGv31P6EKBhIGcVuso+aRFzIgOSy7OQO+UmpiABscsRloiOLKTzpUodnz1y3/khtTlmuwrClUricHc4Fxdjg==} @@ -7620,157 +7624,131 @@ packages: resolution: {integrity: sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-gnueabihf@4.62.0': resolution: {integrity: sha512-T1dMEQhXA/jkJ/jyMIw9IovK8bSUq7A8kLIlvZTb/6YIVsp2zLavr4F3oyllHWo7eIVJRyE5n3tUjQJEbE1IuQ==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.60.4': resolution: {integrity: sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm-musleabihf@4.62.0': resolution: {integrity: sha512-2as0LgT7qQpyceQq6VUJYnumUMUrgGQCWIiDIN9DE0/tglsk6o66uCB4f3djRawAltvfCNLyZZrsqbPA6inCsA==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.60.4': resolution: {integrity: sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-gnu@4.62.0': resolution: {integrity: sha512-bVURMg+6eNN9C/yc0aVjooZcwTTtYF4YW3xta5pP0//r3o1V8gXEHXWCndj47w/HhwsFroZrFhR+6uQP5T0n0g==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.60.4': resolution: {integrity: sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-musl@4.62.0': resolution: {integrity: sha512-Ful8pM/2yYI83PViWdFdpZhdI8HJ5qsXANe5atypbHDf+KIBBDsZsbyy8hbXnULVvW9NsTh5DHwbcBftyLTfiw==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.60.4': resolution: {integrity: sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-loong64-gnu@4.62.0': resolution: {integrity: sha512-9Gp/DgrkzfUBmNPVTyPTvay+4xEP7M/clXpj3efXBcm6uTIVIgDg4rqUpqKXvLEuFRVuEpSAOkhgNeecvaZ4Cg==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.60.4': resolution: {integrity: sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==} cpu: [loong64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loong64-musl@4.62.0': resolution: {integrity: sha512-m9tsJz54LUXkSYM8+8PG81B9IKK5r+2T0clMq4QrS16xFosufU7firBDAZEsDheDs7wTlP7h3++S7lMsU955HA==} cpu: [loong64] os: [linux] - libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.60.4': resolution: {integrity: sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-ppc64-gnu@4.62.0': resolution: {integrity: sha512-3UvJ5PNVU16aJf6M3tFI24pWzAl2/ynfbyRN3ICyQajK1lSkrnVYNnLz3v04J32qKa0FczJc22zeToc0lr2A3w==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.60.4': resolution: {integrity: sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==} cpu: [ppc64] os: [linux] - libc: [musl] '@rollup/rollup-linux-ppc64-musl@4.62.0': resolution: {integrity: sha512-vRWUAbYLGHBZS6Q8Msb2sfnf1fvJf+47t8l/TwOerM2qArzy+IeNMTHrYLHXh95h8MoatPHI5hhSZNs+mGXKPg==} cpu: [ppc64] os: [linux] - libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.60.4': resolution: {integrity: sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.62.0': resolution: {integrity: sha512-c00T5SYENHAt86cfW47URaP3Us5vLC/4QO7GYud1G5VNRffCwwCuBspwqYrriuJB+5m0WFzClCn9wed0FBjKvg==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.60.4': resolution: {integrity: sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-riscv64-musl@4.62.0': resolution: {integrity: sha512-krrCDilhXOwFkSkO3Wm9I/f9H0L92XHHwy2fwxjukxIbh0dem8gZqOW5Y8BsHrpJv5qwlRBV+Wl4ZFyRWhUpwg==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.60.4': resolution: {integrity: sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-s390x-gnu@4.62.0': resolution: {integrity: sha512-7pfYFSTc4/rUC/FtAI0Qp6QthDBCIi6/AuP1xYqFk5vanI6KnL5dWKP60OM/05LOsbwTmIcvr6eXC4CJuJ75IA==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.60.4': resolution: {integrity: sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.62.0': resolution: {integrity: sha512-7SDIalKeIpG0Ifogbbdn58HmSotYMlf23K3dCJEmiVd9Fg36Vmni82iPQec27N3wY4Bvbxftkxz6vSx9OcouTg==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.60.4': resolution: {integrity: sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-linux-x64-musl@4.62.0': resolution: {integrity: sha512-eRZevouTH2i1HeAVLqJuLnt256krQkGY0TN6WsTmsIhuzbh457HuWDMakKwmi0Cjadux983CoSr8Lim2QhUIFw==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-openbsd-x64@4.60.4': resolution: {integrity: sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==} @@ -8245,28 +8223,24 @@ packages: engines: {node: '>=10'} cpu: [arm64] os: [linux] - libc: [glibc] '@swc/core-linux-arm64-musl@1.3.52': resolution: {integrity: sha512-GCxNjTAborAmv4VV1AMZLyejHLGgIzu13tvLUFqybtU4jFxVbE2ZK4ZnPCfDlWN+eBwyRWk1oNFR2hH+66vaUQ==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - libc: [musl] '@swc/core-linux-x64-gnu@1.3.52': resolution: {integrity: sha512-mrvDBSkLI3Mza2qcu3uzB5JGwMBYDb1++UQ1VB0RXf2AR21/cCper4P44IpfdeqFz9XyXq18Sh3gblICUCGvig==} engines: {node: '>=10'} cpu: [x64] os: [linux] - libc: [glibc] '@swc/core-linux-x64-musl@1.3.52': resolution: {integrity: sha512-r9RIvKUQv7yBkpXz+QxPAucdoj8ymBlgIm5rLE0b5VmU7dlKBnpAmRBYaITdH6IXhF0pwuG+FHAd5elBcrkIwA==} engines: {node: '>=10'} cpu: [x64] os: [linux] - libc: [musl] '@swc/core-win32-arm64-msvc@1.3.52': resolution: {integrity: sha512-YRtEr7tDo0Wes3M2ZhigF4erUjWBXeFP+O+iz6ELBBmPG7B7m/lrA21eiW9/90YGnzi0iNo46shK6PfXuPhP+Q==} @@ -12477,28 +12451,24 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [glibc] lightningcss-linux-arm64-musl@1.25.1: resolution: {integrity: sha512-IhxVFJoTW8wq6yLvxdPvyHv4NjzcpN1B7gjxrY3uaykQNXPHNIpChLB52+wfH+yS58zm1PL4LemUp8u9Cfp6Bw==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] - libc: [musl] lightningcss-linux-x64-gnu@1.25.1: resolution: {integrity: sha512-RXIaru79KrREPEd6WLXfKfIp4QzoppZvD3x7vuTKkDA64PwTzKJ2jaC43RZHRt8BmyIkRRlmywNhTRMbmkPYpA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] lightningcss-linux-x64-musl@1.25.1: resolution: {integrity: sha512-TdcNqFsAENEEFr8fJWg0Y4fZ/nwuqTRsIr7W7t2wmDUlA8eSXVepeeONYcb+gtTj1RaXn/WgNLB45SFkz+XBZA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [musl] lightningcss-win32-x64-msvc@1.25.1: resolution: {integrity: sha512-9KZZkmmy9oGDSrnyHuxP6iMhbsgChUiu/NSgOx+U1I/wTngBStDf2i2aGRCHvFqj19HqqBEI4WuGVQBa2V6e0A==} @@ -17881,6 +17851,13 @@ snapshots: transitivePeerDependencies: - zod + '@logto/cloud@0.2.5-66a5752(zod@3.24.3)': + dependencies: + '@silverhand/essentials': 2.9.3 + '@withtyped/server': 0.14.0(zod@3.24.3) + transitivePeerDependencies: + - zod + '@logto/js@5.1.0': dependencies: '@silverhand/essentials': 2.9.3