initial commit
Some checks failed
CI / Go — node-agent tests (push) Has been cancelled
CI / Go — edge-gateway build (push) Has been cancelled
CI / Node — lint, typecheck, test, build (push) Has been cancelled

This commit is contained in:
smueller
2026-06-26 10:45:08 +02:00
commit e37ea87b35
118 changed files with 7726 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
import { z } from 'zod';
export const problemDetailsSchema = z.object({
type: z.string().url().or(z.literal('about:blank')),
title: z.string(),
status: z.number().int(),
detail: z.string().optional(),
instance: z.string().optional(),
errors: z
.array(
z.object({
field: z.string().optional(),
message: z.string(),
}),
)
.optional(),
});
export type ProblemDetails = z.infer<typeof problemDetailsSchema>;
export function createProblemDetails(
input: Omit<ProblemDetails, 'type'> & { type?: string },
): ProblemDetails {
return problemDetailsSchema.parse({
type: input.type ?? 'about:blank',
title: input.title,
status: input.status,
detail: input.detail,
instance: input.instance,
errors: input.errors,
});
}

View File

@@ -0,0 +1,22 @@
import { z } from 'zod';
export const healthStatusSchema = z.enum(['ok', 'degraded', 'error']);
export const healthCheckSchema = z.object({
name: z.string(),
status: healthStatusSchema,
message: z.string().optional(),
durationMs: z.number().nonnegative().optional(),
});
export const healthResponseSchema = z.object({
status: healthStatusSchema,
service: z.string(),
version: z.string().optional(),
timestamp: z.string().datetime(),
checks: z.array(healthCheckSchema).optional(),
});
export type HealthStatus = z.infer<typeof healthStatusSchema>;
export type HealthCheck = z.infer<typeof healthCheckSchema>;
export type HealthResponse = z.infer<typeof healthResponseSchema>;

View File

@@ -0,0 +1,23 @@
export {
healthStatusSchema,
healthCheckSchema,
healthResponseSchema,
type HealthStatus,
type HealthCheck,
type HealthResponse,
} from './health';
export {
problemDetailsSchema,
createProblemDetails,
type ProblemDetails,
} from './error';
export {
paginationQuerySchema,
paginationMetaSchema,
createPaginatedResponseSchema,
buildPaginationMeta,
type PaginationQuery,
type PaginationMeta,
} from './pagination';

View File

@@ -0,0 +1,43 @@
import { z } from 'zod';
export const paginationQuerySchema = z.object({
page: z.coerce.number().int().min(1).default(1),
pageSize: z.coerce.number().int().min(1).max(100).default(20),
sortBy: z.string().optional(),
sortOrder: z.enum(['asc', 'desc']).default('desc'),
});
export const paginationMetaSchema = z.object({
page: z.number().int().min(1),
pageSize: z.number().int().min(1),
totalItems: z.number().int().nonnegative(),
totalPages: z.number().int().nonnegative(),
hasNextPage: z.boolean(),
hasPreviousPage: z.boolean(),
});
export function createPaginatedResponseSchema<T extends z.ZodTypeAny>(itemSchema: T) {
return z.object({
data: z.array(itemSchema),
meta: paginationMetaSchema,
});
}
export type PaginationQuery = z.infer<typeof paginationQuerySchema>;
export type PaginationMeta = z.infer<typeof paginationMetaSchema>;
export function buildPaginationMeta(
page: number,
pageSize: number,
totalItems: number,
): PaginationMeta {
const totalPages = totalItems === 0 ? 0 : Math.ceil(totalItems / pageSize);
return paginationMetaSchema.parse({
page,
pageSize,
totalItems,
totalPages,
hasNextPage: page < totalPages,
hasPreviousPage: page > 1,
});
}