Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76ea2d3df6 | ||
|
|
6c122c70e4 | ||
|
|
aca0f56dfe | ||
|
|
07ad643f4d | ||
|
|
f5b4625c8e | ||
|
|
ae8ad9785e | ||
|
|
b72b70d2a3 | ||
|
|
8d22df5123 | ||
|
|
2f7bdbfe1c | ||
|
|
1136b3a99b | ||
|
|
bf26f17fcd | ||
|
|
83b93e17da | ||
|
|
597b5fbc8d | ||
|
|
5412577519 |
No files matched your search
@@ -163,65 +163,3 @@ jobs:
|
||||
run: cp .env.example .env
|
||||
- name: Build
|
||||
run: pnpm turbo build --affected
|
||||
|
||||
memory-regression:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
- name: Build Docker image
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
platforms: linux/amd64
|
||||
context: .
|
||||
push: false
|
||||
load: true
|
||||
tags: homarr-memory-test
|
||||
network: host
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
env:
|
||||
SKIP_ENV_VALIDATION: true
|
||||
- name: Start container and measure memory
|
||||
run: |
|
||||
docker run -d --name homarr-mem-test -p 17575:7575 homarr-memory-test
|
||||
# Wait for container to be healthy (up to 60s)
|
||||
healthy=false
|
||||
for i in $(seq 1 30); do
|
||||
if curl -sf http://localhost:17575/api/health 2>/dev/null; then
|
||||
echo "Container healthy after $((i * 2))s"
|
||||
healthy=true
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
if [ "$healthy" != "true" ]; then
|
||||
echo "ERROR: Container never became healthy"
|
||||
docker logs homarr-mem-test --tail 50
|
||||
exit 1
|
||||
fi
|
||||
# Warm up: hit the dashboard page a few times
|
||||
for i in $(seq 1 5); do
|
||||
curl -sf http://localhost:17575/ > /dev/null 2>&1 || true
|
||||
sleep 2
|
||||
done
|
||||
# Measure RSS after warmup
|
||||
MEM_KB=$(docker stats --no-stream --format '{{.MemUsage}}' homarr-mem-test | sed 's| /.*||')
|
||||
echo "Raw memory: $MEM_KB"
|
||||
# Convert to numeric MB (handles GiB and MiB suffixes)
|
||||
MEM_NUM=$(echo "$MEM_KB" | awk '{
|
||||
if ($0 ~ /GiB/) { gsub(/GiB/,""); print $1 * 1024 }
|
||||
else if ($0 ~ /MiB/) { gsub(/MiB/,""); print $1 }
|
||||
else if ($0 ~ /KiB/) { gsub(/KiB/,""); print $1 / 1024 }
|
||||
else { print $1 / 1048576 }
|
||||
}')
|
||||
echo "Memory usage: ${MEM_NUM} MB"
|
||||
MAX_MB=700
|
||||
if awk "BEGIN {exit !($MEM_NUM > $MAX_MB)}"; then
|
||||
echo "ERROR: Memory usage ${MEM_NUM} MB exceeds ${MAX_MB} MB threshold"
|
||||
docker logs homarr-mem-test --tail 50
|
||||
exit 1
|
||||
fi
|
||||
echo "Memory check passed: ${MEM_NUM} MB <= ${MAX_MB} MB"
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
- uses: actions/setup-node@v6
|
||||
if: env.SKIP_RELEASE == 'false'
|
||||
with:
|
||||
node-version: 24.18.0
|
||||
node-version: 24.17.0
|
||||
package-manager-cache: false
|
||||
- run: npm i -g pnpm
|
||||
if: env.SKIP_RELEASE == 'false'
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
[tools]
|
||||
node = "24.18.0"
|
||||
node = "24.17.0"
|
||||
@@ -1,10 +1,3 @@
|
||||
## [1.68.1](https://github.com/homarr-labs/homarr/compare/v1.68.0...v1.68.1) (2026-06-30)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* make source maps opt-in to restore v1.67.0 memory baseline ([57ef0af](https://github.com/homarr-labs/homarr/commit/57ef0af4a252ea39727caeba7e13587dabc6254e)), closes [#6123](https://github.com/homarr-labs/homarr/issues/6123)
|
||||
* revert production source maps to restore v1.67.0 memory baseline ([60a69e3](https://github.com/homarr-labs/homarr/commit/60a69e31efc7168b8f4309daf75954d7730d883b)), closes [#6123](https://github.com/homarr-labs/homarr/issues/6123)
|
||||
|
||||
## [1.68.0](https://github.com/homarr-labs/homarr/compare/v1.67.0...v1.68.0) (2026-06-26)
|
||||
|
||||
### Features
|
||||
|
||||
+15
-1
@@ -1,4 +1,4 @@
|
||||
FROM node:24.18.0-alpine AS base
|
||||
FROM node:24.17.0-alpine AS base
|
||||
|
||||
FROM base AS builder
|
||||
RUN apk add --no-cache libc6-compat
|
||||
@@ -20,6 +20,17 @@ ARG DISABLE_REDIS_LOGS='true'
|
||||
|
||||
RUN corepack enable pnpm && pnpm build
|
||||
|
||||
# The standalone output tracing omits server chunk source maps (.next/server/**/*.map), which is
|
||||
# where production Node stack frames point. Copy the .map files into the standalone tree (preserving
|
||||
# directory structure) so the existing standalone COPY ships them, keeping traces readable.
|
||||
# See https://github.com/homarr-labs/homarr/issues/5891
|
||||
RUN cd apps/nextjs/.next/server && \
|
||||
find . -name '*.map' | while IFS= read -r map; do \
|
||||
dest="../standalone/apps/nextjs/.next/server/$map"; \
|
||||
mkdir -p "$(dirname "$dest")"; \
|
||||
cp "$map" "$dest"; \
|
||||
done
|
||||
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
|
||||
@@ -64,6 +75,9 @@ ENV DB_DRIVER='better-sqlite3'
|
||||
ENV AUTH_PROVIDERS='credentials'
|
||||
ENV REDIS_IS_EXTERNAL='false'
|
||||
ENV NODE_ENV='production'
|
||||
# Tell Node to symbolicate stack traces using the shipped .map files so production logs
|
||||
# show original source locations instead of minified frames, see https://github.com/homarr-labs/homarr/issues/5891
|
||||
ENV NODE_OPTIONS='--enable-source-maps'
|
||||
|
||||
ENTRYPOINT [ "/app/entrypoint.sh" ]
|
||||
CMD ["sh", "run.sh"]
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
title: 'FileFlows'
|
||||
description: "FileFlows is a distributed media processing system that allows you to encode, compress and process your media files across multiple nodes."
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
import { IntegrationHeader } from '@site/src/components/integrations/header';
|
||||
import { IntegrationCapabilites } from '@site/src/components/integrations/widgets';
|
||||
import { AddingIntegration } from '@site/src/components/integrations/adding';
|
||||
import {IntegrationSecrets} from '@site/src/components/integrations/secrets';
|
||||
import { IconTransform } from "@tabler/icons-react";
|
||||
import { fileFlowsIntegration } from '.';
|
||||
import { mediaTranscodingWidget } from '@site/docs/widgets/media-transcoding';
|
||||
|
||||
|
||||
<IntegrationHeader
|
||||
integration={fileFlowsIntegration}
|
||||
categories={['Media Transcoding']}
|
||||
/>
|
||||
|
||||
### Widgets & Capabilities
|
||||
<IntegrationCapabilites
|
||||
items={[{ widget: mediaTranscodingWidget }]}
|
||||
/>
|
||||
|
||||
### Adding the integration
|
||||
<AddingIntegration />
|
||||
|
||||
### Secrets
|
||||
<IntegrationSecrets secrets={[{
|
||||
credentials: ['apiKey'],
|
||||
steps: []
|
||||
}, {
|
||||
credentials: [],
|
||||
steps: []
|
||||
}]} />
|
||||
@@ -1,8 +0,0 @@
|
||||
import { IntegrationDefinition } from "@site/src/types";
|
||||
export const fileFlowsIntegration: IntegrationDefinition = {
|
||||
name: "FileFlows",
|
||||
description:
|
||||
"FileFlows is a distributed media processing system that allows you to encode, compress and process your media files across multiple nodes.",
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/png/fileflows.png",
|
||||
path: "../../integrations/fileflows",
|
||||
};
|
||||
@@ -31,6 +31,8 @@ const nextConfig: NextConfig = {
|
||||
},
|
||||
output: "standalone",
|
||||
reactStrictMode: true,
|
||||
// Ship browser source maps so production client stack traces are readable, see https://github.com/homarr-labs/homarr/issues/5891
|
||||
productionBrowserSourceMaps: true,
|
||||
// react compiler breaks mantine-react-table, so disabled for now
|
||||
//reactCompiler: true,
|
||||
/** We already do typechecking as separate tasks in CI */
|
||||
@@ -41,6 +43,8 @@ const nextConfig: NextConfig = {
|
||||
*/
|
||||
serverExternalPackages: ["dockerode", "isomorphic-dompurify", "jsdom", "better-sqlite3"],
|
||||
experimental: {
|
||||
// Ship server source maps so production Node stack traces in logs reference original source, see https://github.com/homarr-labs/homarr/issues/5891
|
||||
serverSourceMaps: true,
|
||||
optimizePackageImports: ["@mantine/core", "@mantine/hooks", "@tabler/icons-react"],
|
||||
turbopackFileSystemCacheForDev: true,
|
||||
preloadEntriesOnStart: false,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:24.18.0-trixie AS base
|
||||
FROM node:24.17.0-trixie AS base
|
||||
WORKDIR /app
|
||||
COPY package.json .
|
||||
COPY pnpm-lock.yaml .
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"better-sqlite3": "^12.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=24.18.0",
|
||||
"node": ">=24.17.0",
|
||||
"pnpm": ">=11.9.0"
|
||||
},
|
||||
"packageManager": "pnpm@11.9.0"
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "homarr",
|
||||
"version": "1.68.1",
|
||||
"version": "1.68.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "cross-env CI=true turbo build",
|
||||
@@ -61,7 +61,7 @@
|
||||
"vitest": "catalog:"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=24.18.0",
|
||||
"node": ">=24.17.0",
|
||||
"pnpm": ">=11.9.0"
|
||||
},
|
||||
"packageManager": "pnpm@11.9.0",
|
||||
|
||||
@@ -36,7 +36,6 @@ const integrationAliases: Partial<Record<IntegrationKind, readonly string[]>> =
|
||||
linuxServerIO: ["linuxserver"],
|
||||
coolify: ["coolify"],
|
||||
truenas: ["truenas"],
|
||||
fileFlows: ["fileflows"],
|
||||
};
|
||||
|
||||
export const matchIntegrationKind = (search: string): IntegrationKind | null => {
|
||||
|
||||
@@ -312,7 +312,6 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/integrations/dash-dot"
|
||||
| "/docs/integrations/glances"
|
||||
| "/docs/integrations/tdarr"
|
||||
| "/docs/integrations/fileflows"
|
||||
| "/docs/integrations/proxmox"
|
||||
| "/docs/integrations/nextcloud"
|
||||
| "/docs/integrations/unifi-controller"
|
||||
|
||||
@@ -27,7 +27,6 @@ export const integrationDocSlugs: Record<IntegrationKind, string | null> = {
|
||||
dashDot: "dash-dot",
|
||||
glances: "glances",
|
||||
tdarr: "tdarr",
|
||||
fileFlows: "fileflows",
|
||||
proxmox: "proxmox",
|
||||
nextcloud: "nextcloud",
|
||||
unifiController: "unifi-controller",
|
||||
|
||||
@@ -251,14 +251,6 @@ export const integrationDefs = {
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/tdarr"),
|
||||
defaultPort: 8265,
|
||||
},
|
||||
fileFlows: {
|
||||
name: "FileFlows",
|
||||
secretKinds: [[], ["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/png/fileflows.png",
|
||||
category: ["mediaTranscoding"],
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/fileflows"),
|
||||
defaultPort: 5000,
|
||||
},
|
||||
proxmox: {
|
||||
name: "Proxmox",
|
||||
secretKinds: [["username", "tokenId", "apiKey", "realm"]],
|
||||
|
||||
@@ -33,7 +33,6 @@ import { RadarrIntegration } from "../media-organizer/radarr/radarr-integration"
|
||||
import { ReadarrIntegration } from "../media-organizer/readarr/readarr-integration";
|
||||
import { SonarrIntegration } from "../media-organizer/sonarr/sonarr-integration";
|
||||
import { TdarrIntegration } from "../media-transcoding/tdarr-integration";
|
||||
import { FileFlowsIntegration } from "../media-transcoding/fileflows-integration";
|
||||
import { MockIntegration } from "../mock/mock-integration";
|
||||
import { NavidromeIntegration } from "../navidrome/navidrome-integration";
|
||||
import { NextcloudIntegration } from "../nextcloud/nextcloud.integration";
|
||||
@@ -110,7 +109,6 @@ export const integrationCreators = {
|
||||
readarr: ReadarrIntegration,
|
||||
dashDot: DashDotIntegration,
|
||||
tdarr: TdarrIntegration,
|
||||
fileFlows: FileFlowsIntegration,
|
||||
proxmox: ProxmoxIntegration,
|
||||
emby: EmbyIntegration,
|
||||
nextcloud: NextcloudIntegration,
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
import { fetchWithTrustedCertificatesAsync } from "@homarr/core/infrastructure/http";
|
||||
|
||||
import type { IntegrationTestingInput } from "../base/integration";
|
||||
import { Integration } from "../base/integration";
|
||||
import { TestConnectionError } from "../base/test-connection/test-connection-error";
|
||||
import type { TestingResult } from "../base/test-connection/test-connection-service";
|
||||
import type { IMediaTranscodingIntegration } from "../interfaces/media-transcoding/media-transcoding-integration";
|
||||
import type { TdarrQueue, TdarrStatistics, TdarrWorker } from "../interfaces/media-transcoding/media-transcoding-types";
|
||||
import {
|
||||
libraryStatusSchema,
|
||||
recentlyFinishedSchema,
|
||||
shrinkageGroupsSchema,
|
||||
statusResponseSchema,
|
||||
upcomingFilesSchema,
|
||||
workersResponseSchema,
|
||||
} from "./fileflows-validation-schemas";
|
||||
|
||||
export class FileFlowsIntegration extends Integration implements IMediaTranscodingIntegration {
|
||||
protected async testingAsync(input: IntegrationTestingInput): Promise<TestingResult> {
|
||||
const response = await input.fetchAsync(this.url("/api/system/version"), {
|
||||
method: "GET",
|
||||
headers: {
|
||||
accept: "application/json",
|
||||
...(super.hasSecretValue("apiKey") ? { "X-Api-Key": super.getSecretValue("apiKey") } : {}),
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) return TestConnectionError.StatusResult(response);
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
public async getStatisticsAsync(): Promise<TdarrStatistics> {
|
||||
const headerParams = {
|
||||
accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
...(super.hasSecretValue("apiKey") ? { "X-Api-Key": super.getSecretValue("apiKey") } : {}),
|
||||
};
|
||||
|
||||
const [statusData, libraryStatusData, shrinkageData] = await Promise.all([
|
||||
this.fetchStatusAsync(headerParams),
|
||||
this.fetchLibraryStatusAsync(headerParams),
|
||||
this.fetchShrinkageAsync(headerParams),
|
||||
]);
|
||||
|
||||
const failedCount = libraryStatusData
|
||||
.filter((item) => item.Status === 4)
|
||||
.reduce((sum, item) => sum + item.Count, 0);
|
||||
const processedCount = libraryStatusData
|
||||
.filter((item) => item.Status === 3)
|
||||
.reduce((sum, item) => sum + item.Count, 0);
|
||||
const queuedCount = libraryStatusData
|
||||
.filter((item) => item.Status === 1 || item.Status === 5)
|
||||
.reduce((sum, item) => sum + item.Count, 0);
|
||||
|
||||
const totalSavedSpace = Object.values(shrinkageData).reduce(
|
||||
(sum, group) => sum + Math.max(0, group.OriginalSize - group.FinalSize),
|
||||
0,
|
||||
);
|
||||
|
||||
const transcodeStatus = [
|
||||
{ name: "Processed", value: statusData.processed },
|
||||
{ name: "Queued", value: statusData.queue },
|
||||
{ name: "Processing", value: statusData.processing },
|
||||
{ name: "Failed", value: failedCount },
|
||||
];
|
||||
|
||||
return {
|
||||
libraryName: "All",
|
||||
totalFileCount: processedCount + queuedCount + statusData.processing + failedCount,
|
||||
totalTranscodeCount: statusData.processed,
|
||||
totalHealthCheckCount: 0,
|
||||
failedTranscodeCount: failedCount,
|
||||
failedHealthCheckCount: 0,
|
||||
stagedTranscodeCount: statusData.queue,
|
||||
stagedHealthCheckCount: 0,
|
||||
totalSavedSpace,
|
||||
transcodeStatus,
|
||||
healthCheckStatus: [],
|
||||
videoCodecs: [],
|
||||
videoContainers: [],
|
||||
videoResolutions: [],
|
||||
audioCodecs: [],
|
||||
audioContainers: [],
|
||||
};
|
||||
}
|
||||
|
||||
public async getWorkersAsync(): Promise<TdarrWorker[]> {
|
||||
const headerParams = {
|
||||
"Content-Type": "application/json",
|
||||
...(super.hasSecretValue("apiKey") ? { "X-Api-Key": super.getSecretValue("apiKey") } : {}),
|
||||
};
|
||||
|
||||
const url = this.url("/api/worker");
|
||||
const response = await fetchWithTrustedCertificatesAsync(url, {
|
||||
method: "GET",
|
||||
headers: headerParams,
|
||||
});
|
||||
|
||||
const workersData = await workersResponseSchema.parseAsync(await response.json());
|
||||
|
||||
return workersData.map((worker) => ({
|
||||
id: worker.Uid,
|
||||
filePath: worker.RelativeFile ?? "",
|
||||
fps: 0,
|
||||
percentage: worker.CurrentPartPercent,
|
||||
ETA: worker.ProcessingTime?.TotalSeconds ? `${Math.round(worker.ProcessingTime.TotalSeconds)}s` : "",
|
||||
jobType: worker.CurrentPartName ?? "Processing",
|
||||
status: "Processing",
|
||||
step: worker.CurrentPartName ?? "",
|
||||
originalSize: worker.LibraryFile?.OriginalSize ?? 0,
|
||||
estimatedSize: null,
|
||||
outputSize: null,
|
||||
}));
|
||||
}
|
||||
|
||||
public async getQueueAsync(firstItemIndex: number, pageSize: number): Promise<TdarrQueue> {
|
||||
const headerParams = {
|
||||
"Content-Type": "application/json",
|
||||
...(super.hasSecretValue("apiKey") ? { "X-Api-Key": super.getSecretValue("apiKey") } : {}),
|
||||
};
|
||||
|
||||
const [upcomingItems, recentlyFinishedItems] = await Promise.all([
|
||||
this.fetchUpcomingAsync(headerParams),
|
||||
this.fetchRecentlyFinishedAsync(headerParams),
|
||||
]);
|
||||
|
||||
const queueArray = [
|
||||
...upcomingItems.map((item) => ({
|
||||
id: item.Uid,
|
||||
healthCheck: "",
|
||||
transcode: item.Flow ?? "Default",
|
||||
filePath: item.RelativePath ?? item.Name ?? "",
|
||||
fileSize: item.OriginalSize ?? 0,
|
||||
container: "",
|
||||
codec: "",
|
||||
resolution: "",
|
||||
type: "transcode" as const,
|
||||
})),
|
||||
...recentlyFinishedItems.map((item) => ({
|
||||
id: item.Uid,
|
||||
healthCheck: "",
|
||||
transcode: item.Flow ?? "Default",
|
||||
filePath: item.RelativePath ?? item.Name ?? "",
|
||||
fileSize: item.FinalSize ?? item.OriginalSize ?? 0,
|
||||
container: "",
|
||||
codec: "",
|
||||
resolution: "",
|
||||
type: "health-check" as const,
|
||||
})),
|
||||
].slice(0, pageSize);
|
||||
|
||||
return {
|
||||
array: queueArray,
|
||||
totalCount: upcomingItems.length + recentlyFinishedItems.length,
|
||||
startIndex: firstItemIndex,
|
||||
endIndex: firstItemIndex + queueArray.length - 1,
|
||||
};
|
||||
}
|
||||
|
||||
private async fetchStatusAsync(headerParams: Record<string, string>) {
|
||||
const response = await fetchWithTrustedCertificatesAsync(this.url("/api/status"), {
|
||||
method: "GET",
|
||||
headers: headerParams,
|
||||
});
|
||||
return statusResponseSchema.parseAsync(await response.json());
|
||||
}
|
||||
|
||||
private async fetchLibraryStatusAsync(headerParams: Record<string, string>) {
|
||||
const response = await fetchWithTrustedCertificatesAsync(this.url("/api/library-file/status"), {
|
||||
method: "GET",
|
||||
headers: headerParams,
|
||||
});
|
||||
return libraryStatusSchema.parseAsync(await response.json());
|
||||
}
|
||||
|
||||
private async fetchShrinkageAsync(headerParams: Record<string, string>) {
|
||||
const response = await fetchWithTrustedCertificatesAsync(this.url("/api/library-file/shrinkage-groups"), {
|
||||
method: "GET",
|
||||
headers: headerParams,
|
||||
});
|
||||
return shrinkageGroupsSchema.parseAsync(await response.json());
|
||||
}
|
||||
|
||||
private async fetchUpcomingAsync(headerParams: Record<string, string>) {
|
||||
const response = await fetchWithTrustedCertificatesAsync(this.url("/api/library-file/upcoming"), {
|
||||
method: "GET",
|
||||
headers: headerParams,
|
||||
});
|
||||
return upcomingFilesSchema.parseAsync(await response.json());
|
||||
}
|
||||
|
||||
private async fetchRecentlyFinishedAsync(headerParams: Record<string, string>) {
|
||||
const response = await fetchWithTrustedCertificatesAsync(this.url("/api/library-file/recently-finished"), {
|
||||
method: "GET",
|
||||
headers: headerParams,
|
||||
});
|
||||
return recentlyFinishedSchema.parseAsync(await response.json());
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export const statusResponseSchema = z.object({
|
||||
queue: z.number(),
|
||||
processing: z.number(),
|
||||
processed: z.number(),
|
||||
processingFiles: z
|
||||
.array(
|
||||
z.object({
|
||||
name: z.string().nullable(),
|
||||
relativePath: z.string().nullable(),
|
||||
library: z.string().nullable(),
|
||||
step: z.string().nullable(),
|
||||
stepPercent: z.number(),
|
||||
}),
|
||||
)
|
||||
.optional()
|
||||
.transform((arr) => arr ?? []),
|
||||
});
|
||||
|
||||
export const libraryStatusSchema = z.array(
|
||||
z.object({
|
||||
Name: z.string().nullable(),
|
||||
Status: z.number(),
|
||||
Count: z.number(),
|
||||
}),
|
||||
);
|
||||
|
||||
export const shrinkageGroupsSchema = z.record(
|
||||
z.string(),
|
||||
z.object({
|
||||
Library: z.string().nullable(),
|
||||
OriginalSize: z.number(),
|
||||
FinalSize: z.number(),
|
||||
Items: z.number(),
|
||||
Difference: z.number().optional(),
|
||||
}),
|
||||
);
|
||||
|
||||
export const workersResponseSchema = z.array(
|
||||
z.object({
|
||||
Uid: z.string(),
|
||||
NodeName: z.string().nullable(),
|
||||
RelativeFile: z.string().nullable(),
|
||||
CurrentPart: z.number(),
|
||||
CurrentPartName: z.string().nullable(),
|
||||
CurrentPartPercent: z.number(),
|
||||
StartedAt: z.string(),
|
||||
LastUpdate: z.string(),
|
||||
ProcessingTime: z
|
||||
.object({
|
||||
TotalSeconds: z.number().optional(),
|
||||
})
|
||||
.optional(),
|
||||
LibraryFile: z
|
||||
.object({
|
||||
OriginalSize: z.number(),
|
||||
})
|
||||
.optional(),
|
||||
Library: z
|
||||
.object({
|
||||
Name: z.string().nullable(),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
);
|
||||
|
||||
export const upcomingFilesSchema = z.array(
|
||||
z.object({
|
||||
Uid: z.string(),
|
||||
Name: z.string().nullable(),
|
||||
RelativePath: z.string().nullable(),
|
||||
OriginalSize: z.number().nullable(),
|
||||
FinalSize: z.number().nullable(),
|
||||
Status: z.number(),
|
||||
Library: z.string().nullable(),
|
||||
Flow: z.string().nullable(),
|
||||
Node: z.string().nullable(),
|
||||
ProcessingTime: z
|
||||
.object({
|
||||
TotalSeconds: z.number().optional(),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
);
|
||||
|
||||
export const recentlyFinishedSchema = z.array(
|
||||
z.object({
|
||||
Uid: z.string(),
|
||||
Name: z.string().nullable(),
|
||||
RelativePath: z.string().nullable(),
|
||||
OriginalSize: z.number().nullable(),
|
||||
FinalSize: z.number().nullable(),
|
||||
Status: z.number(),
|
||||
Library: z.string().nullable(),
|
||||
Flow: z.string().nullable(),
|
||||
}),
|
||||
);
|
||||
Generated
+14
-29
@@ -337,8 +337,8 @@ catalogs:
|
||||
specifier: ^0.2.9
|
||||
version: 0.2.9
|
||||
dockerode:
|
||||
specifier: ^5.0.1
|
||||
version: 5.0.1
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
dotenv:
|
||||
specifier: ^17.4.2
|
||||
version: 17.4.2
|
||||
@@ -445,8 +445,8 @@ catalogs:
|
||||
specifier: ^1.18.0
|
||||
version: 1.18.0
|
||||
posthog-js:
|
||||
specifier: ^1.393.5
|
||||
version: 1.395.0
|
||||
specifier: ^1.393.4
|
||||
version: 1.393.4
|
||||
posthog-node:
|
||||
specifier: ^4.18.0
|
||||
version: 4.18.0
|
||||
@@ -1012,7 +1012,7 @@ importers:
|
||||
version: 1.18.0(postcss@8.5.15)
|
||||
posthog-js:
|
||||
specifier: 'catalog:'
|
||||
version: 1.395.0
|
||||
version: 1.393.4
|
||||
prismjs:
|
||||
specifier: 'catalog:'
|
||||
version: 1.30.0
|
||||
@@ -1771,7 +1771,7 @@ importers:
|
||||
version: link:../core
|
||||
dockerode:
|
||||
specifier: 'catalog:'
|
||||
version: 5.0.1
|
||||
version: 5.0.0
|
||||
devDependencies:
|
||||
'@homarr/tsconfig':
|
||||
specifier: workspace:^0.1.0
|
||||
@@ -6418,8 +6418,8 @@ packages:
|
||||
'@polka/url@1.0.0-next.25':
|
||||
resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==}
|
||||
|
||||
'@posthog/core@1.38.0':
|
||||
resolution: {integrity: sha512-QLrJh0hMVpEJXHNyiJR9YhvIO5tzLDedw4UHdvB+ub4fXHMtHCA8H44qgl11HWR3ajpjxtJ8hs3HyOGVF3Zc1w==}
|
||||
'@posthog/core@1.37.3':
|
||||
resolution: {integrity: sha512-Dvw4CTlRVH4K5ag/B8YIHgG4E27w43MCUsXpn1iKQHIggIMN3Shq9whG4Omm3OvXPF+VikBTmpyMKUjckPxw+g==}
|
||||
|
||||
'@posthog/types@1.391.1':
|
||||
resolution: {integrity: sha512-ASwd7Nf4pViqdYRYaNRyPYRVKWa1CcHUAUWR0XeQJLGdNnsWACBwe0sSieb/cHnKsRXjRwO/23KIY83lm/Ccpw==}
|
||||
@@ -9678,10 +9678,6 @@ packages:
|
||||
resolution: {integrity: sha512-C52mvJ+7lcyhWNfrzVfFsbTrBfy/ezE9FGEYLpu17FUeBcCkxERk9nN7uDl/478ynDiQ4U+5DbQC2vENHkVEtQ==}
|
||||
engines: {node: '>= 14.17'}
|
||||
|
||||
dockerode@5.0.1:
|
||||
resolution: {integrity: sha512-avsq/xk4YPIrn0CgleX5bjT9Y8IT1p9PxrNQ++RBQ2WEyFfHCTDsT9kmyxz+H/axnjAwg8wJWEIuPGOUuNupiA==}
|
||||
engines: {node: '>= 14.17'}
|
||||
|
||||
docusaurus-plugin-image-zoom@3.0.1:
|
||||
resolution: {integrity: sha512-mQrqA99VpoMQJNbi02qkWAMVNC4+kwc6zLLMNzraHAJlwn+HrlUmZSEDcTwgn+H4herYNxHKxveE2WsYy73eGw==}
|
||||
peerDependencies:
|
||||
@@ -13120,8 +13116,8 @@ packages:
|
||||
resolution: {integrity: sha512-Ray65LYEJrMMqDtsBUBXunEVP/g4wtATvq/xz9rchUoLy/9mSkkFgUko/8DVtGxgiP3vivpFMgfb9HpCuDrBHg==}
|
||||
engines: {node: '>=10.15.1'}
|
||||
|
||||
posthog-js@1.395.0:
|
||||
resolution: {integrity: sha512-5iTb00CGt2eQUUiBQysQiX89RAbCN6wK2sDNzvs9zv0alaY8mJ0ZySrUD3LQ+XyLhgM5pCpacBuUwChqiYDLDw==}
|
||||
posthog-js@1.393.4:
|
||||
resolution: {integrity: sha512-mOBSVQczEfyLnW3aFRbLXZEuE0Rfbmhqm9UCnuLeMFUUz0uYTkbnyhl5+Uc+BLSGfyiXHLf3nm2BqxYC+G/PXA==}
|
||||
|
||||
posthog-node@4.18.0:
|
||||
resolution: {integrity: sha512-XROs1h+DNatgKh/AlIlCtDxWzwrKdYDb2mOs58n4yN8BkGN9ewqeQwG5ApS4/IzwCb7HPttUkOVulkYatd2PIw==}
|
||||
@@ -17955,7 +17951,7 @@ snapshots:
|
||||
|
||||
'@esbuild-kit/core-utils@3.3.2':
|
||||
dependencies:
|
||||
esbuild: 0.28.1
|
||||
esbuild: 0.28.0
|
||||
source-map-support: 0.5.21
|
||||
|
||||
'@esbuild-kit/esm-loader@2.6.5':
|
||||
@@ -19901,7 +19897,7 @@ snapshots:
|
||||
|
||||
'@polka/url@1.0.0-next.25': {}
|
||||
|
||||
'@posthog/core@1.38.0':
|
||||
'@posthog/core@1.37.3':
|
||||
dependencies:
|
||||
'@posthog/types': 1.391.1
|
||||
|
||||
@@ -23483,17 +23479,6 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
dockerode@5.0.1:
|
||||
dependencies:
|
||||
'@balena/dockerignore': 1.0.2
|
||||
'@grpc/grpc-js': 1.12.5
|
||||
'@grpc/proto-loader': 0.7.13
|
||||
docker-modem: 5.0.7
|
||||
protobufjs: 7.4.0
|
||||
tar-fs: 2.1.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
docusaurus-plugin-image-zoom@3.0.1(@docusaurus/theme-classic@3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.3(@swc/helpers@0.5.15))(esbuild@0.28.1)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@swc/helpers@0.5.15)(esbuild@0.28.1)(postcss@8.5.15))(@rspack/core@1.7.11(@swc/helpers@0.5.15))(@swc/core@1.15.3(@swc/helpers@0.5.15))(@types/react@19.2.17)(esbuild@0.28.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@6.0.3)):
|
||||
dependencies:
|
||||
'@docusaurus/theme-classic': 3.10.1(@docusaurus/faster@3.10.1(@docusaurus/types@3.10.1(@swc/core@1.15.3(@swc/helpers@0.5.15))(esbuild@0.28.1)(postcss@8.5.15)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@swc/helpers@0.5.15)(esbuild@0.28.1)(postcss@8.5.15))(@rspack/core@1.7.11(@swc/helpers@0.5.15))(@swc/core@1.15.3(@swc/helpers@0.5.15))(@types/react@19.2.17)(esbuild@0.28.1)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@6.0.3)
|
||||
@@ -27420,9 +27405,9 @@ snapshots:
|
||||
|
||||
posthog-docusaurus@2.0.5: {}
|
||||
|
||||
posthog-js@1.395.0:
|
||||
posthog-js@1.393.4:
|
||||
dependencies:
|
||||
'@posthog/core': 1.38.0
|
||||
'@posthog/core': 1.37.3
|
||||
'@posthog/types': 1.391.1
|
||||
core-js: 3.49.0
|
||||
dompurify: 3.4.11
|
||||
|
||||
+2
-2
@@ -92,7 +92,7 @@ catalog:
|
||||
"@types/video.js": ^7.3.58
|
||||
"@types/ws": ^8.18.1
|
||||
"@types/xml2js": ^0.4.14
|
||||
posthog-js: ^1.393.5
|
||||
posthog-js: ^1.393.4
|
||||
posthog-node: ^4.18.0
|
||||
"@vitejs/plugin-react": ^6.0.3
|
||||
"@vitest/coverage-v8": ^4.1.9
|
||||
@@ -118,7 +118,7 @@ catalog:
|
||||
dayjs: ^1.11.21
|
||||
deepmerge: 4.3.1
|
||||
dns-caching: ^0.2.9
|
||||
dockerode: ^5.0.1
|
||||
dockerode: ^5.0.0
|
||||
dotenv: ^17.4.2
|
||||
dotenv-cli: ^11.0.0
|
||||
drizzle-kit: ^0.31.10
|
||||
|
||||
@@ -7,7 +7,7 @@ runs:
|
||||
- uses: pnpm/action-setup@v6
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24.18.0
|
||||
node-version: 24.17.0
|
||||
cache: "pnpm"
|
||||
|
||||
- shell: bash
|
||||
|
||||
Reference in new issue
Block a user