From 1b6ecb1fb5f226b4cf1a27e4bd2f47f201610e06 Mon Sep 17 00:00:00 2001 From: Alex Grozav Date: Fri, 3 Oct 2025 16:32:26 +0300 Subject: [PATCH] refactor(editor): Add usage state schema and refactor `usage` APIs (no-changelog) (#20355) --- packages/@n8n/api-types/src/index.ts | 2 ++ .../api-types/src/schemas/usage.schema.ts | 25 +++++++++++++++++++ .../@n8n/rest-api-client/src/api/index.ts | 1 + .../rest-api-client}/src/api/usage.ts | 8 +++--- packages/frontend/editor-ui/src/Interface.ts | 22 ---------------- .../editor-ui/src/stores/usage.store.ts | 4 +-- .../editor-ui/src/views/WorkflowsView.test.ts | 2 +- 7 files changed, 35 insertions(+), 29 deletions(-) create mode 100644 packages/@n8n/api-types/src/schemas/usage.schema.ts rename packages/frontend/{editor-ui => @n8n/rest-api-client}/src/api/usage.ts (81%) diff --git a/packages/@n8n/api-types/src/index.ts b/packages/@n8n/api-types/src/index.ts index 37efd224bef..df4cf043206 100644 --- a/packages/@n8n/api-types/src/index.ts +++ b/packages/@n8n/api-types/src/index.ts @@ -74,3 +74,5 @@ export type { ExternalSecretsProviderProperty, ExternalSecretsProviderState, } from './schemas/external-secrets.schema'; + +export type { UsageState } from './schemas/usage.schema'; diff --git a/packages/@n8n/api-types/src/schemas/usage.schema.ts b/packages/@n8n/api-types/src/schemas/usage.schema.ts new file mode 100644 index 00000000000..b963d01b284 --- /dev/null +++ b/packages/@n8n/api-types/src/schemas/usage.schema.ts @@ -0,0 +1,25 @@ +import { z } from 'zod'; + +export const usageStateSchema = z.object({ + loading: z.boolean(), + data: z.object({ + usage: z.object({ + activeWorkflowTriggers: z.object({ + limit: z.number(), // -1 for unlimited, from license + value: z.number(), + warningThreshold: z.number(), + }), + workflowsHavingEvaluations: z.object({ + limit: z.number(), // -1 for unlimited, from license + value: z.number(), + }), + }), + license: z.object({ + planId: z.string(), // community + planName: z.string(), // defaults to Community + }), + managementToken: z.string().optional(), + }), +}); + +export type UsageState = z.infer; diff --git a/packages/frontend/@n8n/rest-api-client/src/api/index.ts b/packages/frontend/@n8n/rest-api-client/src/api/index.ts index 72370ec9db0..659a49d4c0e 100644 --- a/packages/frontend/@n8n/rest-api-client/src/api/index.ts +++ b/packages/frontend/@n8n/rest-api-client/src/api/index.ts @@ -19,6 +19,7 @@ export type * from './tags'; export * from './templates'; export * from './third-party-licenses'; export * from './ui'; +export * from './usage'; export * from './users'; export * from './versions'; export * from './webhooks'; diff --git a/packages/frontend/editor-ui/src/api/usage.ts b/packages/frontend/@n8n/rest-api-client/src/api/usage.ts similarity index 81% rename from packages/frontend/editor-ui/src/api/usage.ts rename to packages/frontend/@n8n/rest-api-client/src/api/usage.ts index f5682b00cd9..e2fc6446ff9 100644 --- a/packages/frontend/editor-ui/src/api/usage.ts +++ b/packages/frontend/@n8n/rest-api-client/src/api/usage.ts @@ -1,7 +1,7 @@ -import type { CommunityRegisteredRequestDto } from '@n8n/api-types'; -import { makeRestApiRequest } from '@n8n/rest-api-client'; -import type { UsageState } from '@/Interface'; -import type { IRestApiContext } from '@n8n/rest-api-client'; +import type { CommunityRegisteredRequestDto, UsageState } from '@n8n/api-types'; + +import type { IRestApiContext } from '../types'; +import { makeRestApiRequest } from '../utils'; export const getLicense = async (context: IRestApiContext): Promise => { return await makeRestApiRequest(context, 'GET', '/license'); diff --git a/packages/frontend/editor-ui/src/Interface.ts b/packages/frontend/editor-ui/src/Interface.ts index a18d7d0c24f..ab22a2c59e7 100644 --- a/packages/frontend/editor-ui/src/Interface.ts +++ b/packages/frontend/editor-ui/src/Interface.ts @@ -1008,28 +1008,6 @@ export type SchemaType = export type Schema = { type: SchemaType; key?: string; value: string | Schema[]; path: string }; -export type UsageState = { - loading: boolean; - data: { - usage: { - activeWorkflowTriggers: { - limit: number; // -1 for unlimited, from license - value: number; - warningThreshold: number; // hardcoded value in BE - }; - workflowsHavingEvaluations: { - limit: number; // -1 for unlimited, from license - value: number; - }; - }; - license: { - planId: string; // community - planName: string; // defaults to Community - }; - managementToken?: string; - }; -}; - export type NodeAuthenticationOption = { name: string; value: string; diff --git a/packages/frontend/editor-ui/src/stores/usage.store.ts b/packages/frontend/editor-ui/src/stores/usage.store.ts index 834629de4e3..4ebb9245c4e 100644 --- a/packages/frontend/editor-ui/src/stores/usage.store.ts +++ b/packages/frontend/editor-ui/src/stores/usage.store.ts @@ -1,7 +1,7 @@ import { computed, reactive } from 'vue'; import { defineStore } from 'pinia'; -import type { UsageState } from '@/Interface'; -import * as usageApi from '@/api/usage'; +import type { UsageState } from '@n8n/api-types'; +import * as usageApi from '@n8n/rest-api-client/api/usage'; import { useRootStore } from '@n8n/stores/useRootStore'; import { useSettingsStore } from '@/stores/settings.store'; diff --git a/packages/frontend/editor-ui/src/views/WorkflowsView.test.ts b/packages/frontend/editor-ui/src/views/WorkflowsView.test.ts index 5c2f43d6c9f..998184571db 100644 --- a/packages/frontend/editor-ui/src/views/WorkflowsView.test.ts +++ b/packages/frontend/editor-ui/src/views/WorkflowsView.test.ts @@ -70,7 +70,7 @@ const router = createRouter({ ], }); -vi.mock('@/api/usage', () => ({ +vi.mock('@n8n/rest-api-client/api/usage', () => ({ getLicense: vi.fn(), }));