mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
208 lines
7.3 KiB
TypeScript
208 lines
7.3 KiB
TypeScript
import { z } from 'zod';
|
|
import {
|
|
createBackendEntitySchema,
|
|
idSchema,
|
|
nonNegativeNumberSchema,
|
|
positiveNumberSchema,
|
|
} from '@/schemas/common';
|
|
|
|
/**
|
|
* Backend-aligned Resource Flow schemas
|
|
* Matches the Go backend domain.ResourceFlow struct and related types
|
|
*
|
|
* Uses Zod v4's composition and enum features for DRY code
|
|
*/
|
|
|
|
// ============================================================================
|
|
// Enum Schemas (using Zod v4's improved enum support)
|
|
// ============================================================================
|
|
|
|
export const resourceDirectionSchema = z
|
|
.enum(['input', 'output'])
|
|
.describe('Resource flow direction');
|
|
export type ResourceDirection = z.infer<typeof resourceDirectionSchema>;
|
|
|
|
export const resourceTypeSchema = z
|
|
.enum([
|
|
'heat',
|
|
'water',
|
|
'steam',
|
|
'CO2',
|
|
'biowaste',
|
|
'cooling',
|
|
'logistics',
|
|
'materials',
|
|
'service',
|
|
])
|
|
.describe('Type of resource');
|
|
export type ResourceType = z.infer<typeof resourceTypeSchema>;
|
|
|
|
export const precisionLevelSchema = z
|
|
.enum(['rough', 'estimated', 'measured'])
|
|
.describe('Precision level of measurement');
|
|
export type PrecisionLevel = z.infer<typeof precisionLevelSchema>;
|
|
|
|
export const sourceTypeSchema = z
|
|
.enum(['declared', 'device', 'calculated'])
|
|
.describe('Source of the data');
|
|
export type SourceType = z.infer<typeof sourceTypeSchema>;
|
|
|
|
export const physicalStateSchema = z
|
|
.enum(['solid', 'liquid', 'gas'])
|
|
.describe('Physical state of the resource');
|
|
export type PhysicalState = z.infer<typeof physicalStateSchema>;
|
|
|
|
// ============================================================================
|
|
// Composite Schemas
|
|
// ============================================================================
|
|
|
|
export const qualitySchema = z
|
|
.object({
|
|
temperature_celsius: z.number().optional().describe('Temperature in Celsius'),
|
|
pressure_bar: positiveNumberSchema.optional().describe('Pressure in bar'),
|
|
purity_pct: z.number().min(0).max(100).optional().describe('Purity percentage'),
|
|
grade: z.string().optional().describe('Quality grade'),
|
|
hazardousness: z.boolean().optional().describe('Whether resource is hazardous'),
|
|
composition: z.string().optional().describe('Chemical composition'),
|
|
physical_state: physicalStateSchema.optional(),
|
|
})
|
|
.describe('Quality specifications');
|
|
|
|
export type Quality = z.infer<typeof qualitySchema>;
|
|
|
|
export const quantitySchema = z
|
|
.object({
|
|
amount: positiveNumberSchema.describe('Amount of resource'),
|
|
unit: z.string().min(1).describe('Unit of measurement'),
|
|
temporal_unit: z.string().optional().describe('Temporal unit (e.g., per month)'),
|
|
variability: nonNegativeNumberSchema.optional().describe('Variability in amount'),
|
|
})
|
|
.describe('Quantity specifications');
|
|
|
|
export type Quantity = z.infer<typeof quantitySchema>;
|
|
|
|
export const economicDataSchema = z
|
|
.object({
|
|
cost_in: nonNegativeNumberSchema.optional().describe('Input cost'),
|
|
cost_out: nonNegativeNumberSchema.optional().describe('Output cost'),
|
|
waste_disposal_cost: nonNegativeNumberSchema.optional().describe('Waste disposal cost'),
|
|
primary_input_cost: nonNegativeNumberSchema.optional().describe('Primary input cost'),
|
|
transportation_cost: nonNegativeNumberSchema.optional().describe('Transportation cost'),
|
|
cost_sharing_fraction: z
|
|
.number()
|
|
.min(0)
|
|
.max(1)
|
|
.optional()
|
|
.describe('Cost sharing fraction (0-1)'),
|
|
})
|
|
.describe('Economic data');
|
|
|
|
export type EconomicData = z.infer<typeof economicDataSchema>;
|
|
|
|
export const constraintsSchema = z
|
|
.object({
|
|
max_distance_km: positiveNumberSchema.optional().describe('Maximum distance in kilometers'),
|
|
requires_permit: z.boolean().optional().describe('Whether permit is required'),
|
|
min_quality_threshold: z.string().optional().describe('Minimum quality threshold'),
|
|
regulatory_compliance: z.boolean().optional().describe('Regulatory compliance status'),
|
|
})
|
|
.describe('Constraints and requirements');
|
|
|
|
export type Constraints = z.infer<typeof constraintsSchema>;
|
|
|
|
export const timeRangeSchema = z
|
|
.object({
|
|
start: z
|
|
.string()
|
|
.regex(/^([0-1][0-9]|2[0-3]):[0-5][0-9]$/, {
|
|
error: 'Time must be in HH:MM format',
|
|
})
|
|
.describe('Start time (HH:MM)'),
|
|
end: z
|
|
.string()
|
|
.regex(/^([0-1][0-9]|2[0-3]):[0-5][0-9]$/, {
|
|
error: 'Time must be in HH:MM format',
|
|
})
|
|
.describe('End time (HH:MM)'),
|
|
})
|
|
.describe('Time range');
|
|
|
|
export type TimeRange = z.infer<typeof timeRangeSchema>;
|
|
|
|
export const timeProfileSchema = z
|
|
.object({
|
|
availability: z
|
|
.record(z.string(), timeRangeSchema)
|
|
.optional()
|
|
.describe('Availability by day of week'),
|
|
seasonality: z.array(z.string()).optional().describe('Months when available'),
|
|
supply_pattern: z
|
|
.enum(['continuous', 'batch', 'seasonal', 'on_demand', 'irregular'])
|
|
.optional()
|
|
.describe('Supply pattern'),
|
|
})
|
|
.describe('Time profile');
|
|
|
|
export type TimeProfile = z.infer<typeof timeProfileSchema>;
|
|
|
|
export const serviceDetailsSchema = z
|
|
.object({
|
|
domain: z
|
|
.string()
|
|
.optional()
|
|
.describe('Service domain (maintenance, consulting, transport, inspection)'),
|
|
mobility: z.enum(['on_site', 'remote']).optional().describe('Service mobility type'),
|
|
capacity_h_per_month: positiveNumberSchema.optional().describe('Capacity in hours per month'),
|
|
service_area_km: positiveNumberSchema.optional().describe('Service area radius in kilometers'),
|
|
})
|
|
.describe('Service details');
|
|
|
|
export type ServiceDetails = z.infer<typeof serviceDetailsSchema>;
|
|
|
|
// ============================================================================
|
|
// Main Resource Flow Schema
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Backend Resource Flow schema
|
|
* Uses Zod v4's composition features for DRY code
|
|
*/
|
|
export const backendResourceFlowSchema = createBackendEntitySchema({
|
|
OrganizationID: idSchema.describe('Organization ID'),
|
|
SiteID: idSchema.describe('Site ID'),
|
|
Direction: resourceDirectionSchema,
|
|
Type: resourceTypeSchema,
|
|
Quality: qualitySchema,
|
|
Quantity: quantitySchema,
|
|
TimeProfile: timeProfileSchema.optional(),
|
|
EconomicData: economicDataSchema.optional(),
|
|
Constraints: constraintsSchema.optional(),
|
|
ServiceDetails: serviceDetailsSchema.optional(),
|
|
PrecisionLevel: precisionLevelSchema.optional(),
|
|
SourceType: sourceTypeSchema.optional(),
|
|
DeviceSignature: z.string().optional().describe('Device signature for IoT data'),
|
|
});
|
|
|
|
export type BackendResourceFlow = z.infer<typeof backendResourceFlowSchema>;
|
|
|
|
/**
|
|
* Request schema for creating a resource flow
|
|
* Uses Zod v4's composition for consistency
|
|
*/
|
|
export const createResourceFlowRequestSchema = z.object({
|
|
organization_id: idSchema.describe('Organization ID'),
|
|
site_id: idSchema.describe('Site ID'),
|
|
direction: resourceDirectionSchema,
|
|
type: resourceTypeSchema,
|
|
quality: qualitySchema.optional(),
|
|
quantity: quantitySchema,
|
|
time_profile: timeProfileSchema.optional(),
|
|
economic_data: economicDataSchema.optional(),
|
|
constraints: constraintsSchema.optional(),
|
|
service_details: serviceDetailsSchema.optional(),
|
|
precision_level: precisionLevelSchema.optional(),
|
|
source_type: sourceTypeSchema.optional(),
|
|
});
|
|
|
|
export type CreateResourceFlowRequest = z.infer<typeof createResourceFlowRequestSchema>;
|