Add system updates page to admin section
Add a new API endpoint and UI section for checking system updates, including internationalized locale strings and necessary dependency updates. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 1e6de894-7c78-4557-b01a-a2c1c01f4155 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/1WKAcHk Replit-Helium-Checkpoint-Created: true
This commit is contained in:
@@ -9,6 +9,32 @@ export interface HealthStatus {
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface SystemVersionInfo {
|
||||
version: string;
|
||||
build: string;
|
||||
}
|
||||
|
||||
export type SystemVersionResponseStatus =
|
||||
(typeof SystemVersionResponseStatus)[keyof typeof SystemVersionResponseStatus];
|
||||
|
||||
export const SystemVersionResponseStatus = {
|
||||
"up-to-date": "up-to-date",
|
||||
"update-available": "update-available",
|
||||
"not-configured": "not-configured",
|
||||
error: "error",
|
||||
} as const;
|
||||
|
||||
export interface SystemVersionResponse {
|
||||
current: SystemVersionInfo;
|
||||
latest: SystemVersionInfo | null;
|
||||
status: SystemVersionResponseStatus;
|
||||
/** @nullable */
|
||||
errorMessage: string | null;
|
||||
/** @nullable */
|
||||
checkedAt: string | null;
|
||||
configured: boolean;
|
||||
}
|
||||
|
||||
export interface ErrorResponse {
|
||||
error: string;
|
||||
}
|
||||
|
||||
@@ -110,6 +110,7 @@ import type {
|
||||
ServiceOrder,
|
||||
SubscribePushBody,
|
||||
SuccessResponse,
|
||||
SystemVersionResponse,
|
||||
UnsubscribePushBody,
|
||||
UpdateAppBody,
|
||||
UpdateAppSettingsBody,
|
||||
@@ -217,6 +218,86 @@ export function useHealthCheck<
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the local build version (read from version.json embedded at
|
||||
build time) and, if `LATEST_VERSION_URL` is configured on the
|
||||
server, the latest published version fetched from that URL. Admin
|
||||
only. Never performs an update — pure read.
|
||||
|
||||
* @summary Get current and latest system version
|
||||
*/
|
||||
export const getGetSystemVersionUrl = () => {
|
||||
return `/api/system/version`;
|
||||
};
|
||||
|
||||
export const getSystemVersion = async (
|
||||
options?: RequestInit,
|
||||
): Promise<SystemVersionResponse> => {
|
||||
return customFetch<SystemVersionResponse>(getGetSystemVersionUrl(), {
|
||||
...options,
|
||||
method: "GET",
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetSystemVersionQueryKey = () => {
|
||||
return [`/api/system/version`] as const;
|
||||
};
|
||||
|
||||
export const getGetSystemVersionQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof getSystemVersion>>,
|
||||
TError = ErrorType<unknown>,
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getSystemVersion>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
}) => {
|
||||
const { query: queryOptions, request: requestOptions } = options ?? {};
|
||||
|
||||
const queryKey = queryOptions?.queryKey ?? getGetSystemVersionQueryKey();
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof getSystemVersion>>
|
||||
> = ({ signal }) => getSystemVersion({ signal, ...requestOptions });
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getSystemVersion>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type GetSystemVersionQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getSystemVersion>>
|
||||
>;
|
||||
export type GetSystemVersionQueryError = ErrorType<unknown>;
|
||||
|
||||
/**
|
||||
* @summary Get current and latest system version
|
||||
*/
|
||||
|
||||
export function useGetSystemVersion<
|
||||
TData = Awaited<ReturnType<typeof getSystemVersion>>,
|
||||
TError = ErrorType<unknown>,
|
||||
>(options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getSystemVersion>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
request?: SecondParameter<typeof customFetch>;
|
||||
}): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getGetSystemVersionQueryOptions(options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Register a new user
|
||||
*/
|
||||
|
||||
@@ -30,6 +30,8 @@ tags:
|
||||
description: Object storage upload and serving endpoints
|
||||
- name: audit
|
||||
description: Admin audit log
|
||||
- name: system
|
||||
description: System metadata (version, update availability)
|
||||
|
||||
paths:
|
||||
/healthz:
|
||||
@@ -45,6 +47,24 @@ paths:
|
||||
schema:
|
||||
$ref: "#/components/schemas/HealthStatus"
|
||||
|
||||
/system/version:
|
||||
get:
|
||||
operationId: getSystemVersion
|
||||
tags: [system]
|
||||
summary: Get current and latest system version
|
||||
description: |
|
||||
Returns the local build version (read from version.json embedded at
|
||||
build time) and, if `LATEST_VERSION_URL` is configured on the
|
||||
server, the latest published version fetched from that URL. Admin
|
||||
only. Never performs an update — pure read.
|
||||
responses:
|
||||
"200":
|
||||
description: System version info
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/SystemVersionResponse"
|
||||
|
||||
# Auth
|
||||
/auth/register:
|
||||
post:
|
||||
@@ -2927,6 +2947,44 @@ components:
|
||||
required:
|
||||
- status
|
||||
|
||||
SystemVersionInfo:
|
||||
type: object
|
||||
properties:
|
||||
version:
|
||||
type: string
|
||||
build:
|
||||
type: string
|
||||
required:
|
||||
- version
|
||||
- build
|
||||
|
||||
SystemVersionResponse:
|
||||
type: object
|
||||
properties:
|
||||
current:
|
||||
$ref: "#/components/schemas/SystemVersionInfo"
|
||||
latest:
|
||||
oneOf:
|
||||
- $ref: "#/components/schemas/SystemVersionInfo"
|
||||
- type: "null"
|
||||
status:
|
||||
type: string
|
||||
enum: [up-to-date, update-available, not-configured, error]
|
||||
errorMessage:
|
||||
type: ["string", "null"]
|
||||
checkedAt:
|
||||
type: ["string", "null"]
|
||||
format: date-time
|
||||
configured:
|
||||
type: boolean
|
||||
required:
|
||||
- current
|
||||
- latest
|
||||
- status
|
||||
- errorMessage
|
||||
- checkedAt
|
||||
- configured
|
||||
|
||||
ErrorResponse:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -14,6 +14,37 @@ export const HealthCheckResponse = zod.object({
|
||||
status: zod.string(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the local build version (read from version.json embedded at
|
||||
build time) and, if `LATEST_VERSION_URL` is configured on the
|
||||
server, the latest published version fetched from that URL. Admin
|
||||
only. Never performs an update — pure read.
|
||||
|
||||
* @summary Get current and latest system version
|
||||
*/
|
||||
export const GetSystemVersionResponse = zod.object({
|
||||
current: zod.object({
|
||||
version: zod.string(),
|
||||
build: zod.string(),
|
||||
}),
|
||||
latest: zod.union([
|
||||
zod.object({
|
||||
version: zod.string(),
|
||||
build: zod.string(),
|
||||
}),
|
||||
zod.null(),
|
||||
]),
|
||||
status: zod.enum([
|
||||
"up-to-date",
|
||||
"update-available",
|
||||
"not-configured",
|
||||
"error",
|
||||
]),
|
||||
errorMessage: zod.string().nullable(),
|
||||
checkedAt: zod.coerce.date().nullable(),
|
||||
configured: zod.boolean(),
|
||||
});
|
||||
|
||||
/**
|
||||
* @summary Register a new user
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user