refactor(core): Dedup formatBytes and toMb into @n8n/utils (no-changelog) (#36218)

This commit is contained in:
Tomi Turtiainen
2026-08-18 07:52:24 +00:00
committed by GitHub
parent d40f592544
commit 34e1da0447
9 changed files with 36 additions and 34 deletions
@@ -0,0 +1,30 @@
import { formatBytes, toMb } from './bytes';
describe('formatBytes', () => {
test.each([
[0, '0B'],
[512, '512B'],
[1023, '1023B'],
[1024, '1KB'],
[1536, '2KB'],
[100 * 1024 + 44 * 1024, '144KB'],
[1024 * 1024 - 1, '1024KB'],
[1024 * 1024, '1MB'],
[5 * 1024 * 1024, '5MB'],
])('formats %i bytes as %s', (input, expected) => {
expect(formatBytes(input)).toBe(expected);
});
});
describe('toMb', () => {
test.each([
[0, 0],
[512 * 1024 - 1, 0],
[512 * 1024, 1],
[1024 * 1024, 1],
[1536 * 1024, 2],
[5 * 1024 * 1024, 5],
])('converts %i bytes to %i MB', (input, expected) => {
expect(toMb(input)).toBe(expected);
});
});
@@ -1,11 +1,11 @@
import { GlobalConfig } from '@n8n/config';
import { Service } from '@n8n/di';
import { toMb } from '@n8n/utils/number/bytes';
import { DataTableSizeStatus, DataTablesSizeData } from 'n8n-workflow';
import { Telemetry } from '@/telemetry';
import { DataTableValidationError } from './errors/data-table-validation.error';
import { toMb } from './utils/size-utils';
@Service()
export class DataTableSizeValidator {
@@ -2,6 +2,7 @@
import { Logger, safeJoinPath } from '@n8n/backend-common';
import { GlobalConfig } from '@n8n/config';
import { Service } from '@n8n/di';
import { formatBytes } from '@n8n/utils/number/bytes';
import type { Request, RequestHandler } from 'express';
import { mkdir, readdir, stat, unlink } from 'fs/promises';
import multer from 'multer';
@@ -18,7 +19,6 @@ import {
type MulterFilenameCallback,
type UploadMiddleware,
} from './types';
import { formatBytes } from './utils/size-utils';
const ALLOWED_EXTENSIONS = ['.csv'];
+1 -1
View File
@@ -3,6 +3,7 @@ import { inProduction, Logger, TypedEmitter } from '@n8n/backend-common';
import type { User } from '@n8n/db';
import { OnPubSubEvent, OnShutdown } from '@n8n/decorators';
import { Container, Service } from '@n8n/di';
import { toMb } from '@n8n/utils/number/bytes';
import type { Application } from 'express';
import { ServerResponse } from 'http';
import type { Server } from 'http';
@@ -241,7 +242,6 @@ export class Push extends TypedEmitter<PushEvents> {
const eventSizeBytes = new TextEncoder().encode(JSON.stringify(pushMsg.data)).length;
if (eventSizeBytes > MAX_PUBSUB_PAYLOAD_BYTES) {
const toMb = (bytes: number) => (bytes / (1024 * 1024)).toFixed(0);
const eventMb = toMb(eventSizeBytes);
const maxMb = toMb(MAX_PUBSUB_PAYLOAD_BYTES);
@@ -1,10 +1,4 @@
import {
isEmpty,
intersection,
isValidDate,
formatBytes,
abbreviateNumber,
} from '@/app/utils/typesUtils';
import { isEmpty, intersection, isValidDate, abbreviateNumber } from '@/app/utils/typesUtils';
describe('Types Utils', () => {
describe('isEmpty', () => {
@@ -47,22 +41,6 @@ describe('Types Utils', () => {
});
});
describe('formatBytes', () => {
test.each([
[0, '0B'],
[512, '512B'],
[1023, '1023B'],
[1024, '1KB'],
[1536, '2KB'],
[100 * 1024 + 44 * 1024, '144KB'],
[1024 * 1024 - 1, '1024KB'],
[1024 * 1024, '1MB'],
[5 * 1024 * 1024, '5MB'],
])('formats %i bytes as %s', (input, expected) => {
expect(formatBytes(input)).toBe(expected);
});
});
describe('abbreviateNumber', () => {
test.each([
[0, '0'],
@@ -75,12 +75,6 @@ export function toMegaBytes(bytes: number, decimalPlaces: number = 2): number {
return parseFloat(megabytes.toFixed(decimalPlaces));
}
export function formatBytes(sizeInBytes: number): string {
if (sizeInBytes < 1024) return `${sizeInBytes}B`;
if (sizeInBytes < 1024 * 1024) return `${Math.round(sizeInBytes / 1024)}KB`;
return `${Math.round(sizeInBytes / (1024 * 1024))}MB`;
}
export function shorten(s: string, limit: number, keep: number) {
if (s.length <= limit) {
return s;
@@ -4,7 +4,7 @@ import { N8nIcon } from '@n8n/design-system';
import { useRootStore } from '@n8n/stores/useRootStore';
import { useI18n } from '@n8n/i18n';
import type { ChatMessageAttachment } from '@/features/ai/shared/agentsChat/types';
import { formatBytes } from '@/app/utils/typesUtils';
import { formatBytes } from '@n8n/utils/number/bytes';
const props = defineProps<{
attachments: ChatMessageAttachment[];
@@ -11,7 +11,7 @@ import { useToast } from '@n8n/composables/useToast';
import { useMessage } from '@/app/composables/useMessage';
import { EnterpriseEditionFeature, MODAL_CONFIRM, VIEWS } from '@/app/constants';
import { convertToDisplayDate } from '@/app/utils/formatters/dateFormatter';
import { formatBytes } from '@/app/utils/typesUtils';
import { formatBytes } from '@n8n/utils/number/bytes';
import { useInjectWorkflowId } from '@/app/composables/useInjectWorkflowId';
import { getResourcePermissions } from '@n8n/permissions';
import { useSettingsStore } from '@n8n/stores/settings.store';