diff --git a/src/models/polygonParts/aggregationLayerMetadata.ts b/src/models/polygonParts/aggregationLayerMetadata.ts deleted file mode 100644 index 3d2504d..0000000 --- a/src/models/polygonParts/aggregationLayerMetadata.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { GeoJSON, MultiPolygon, Polygon } from 'geojson'; -import type { IMetadataCommonModel } from '../layerMetadata/interfaces/metadataCommonModel'; -import type { ILayerMetadata } from '../layerMetadata/layerMetadata'; - -type NonNullableRecord> = { - [K in keyof T]-?: NonNullable; -}; - -type MakePolygonalRecord = NonNullable extends Q ? Record : never; - -export interface AggregationLayerMetadata - extends NonNullableRecord< - Pick< - ILayerMetadata, - | 'imagingTimeBeginUTC' - | 'imagingTimeEndUTC' - | 'maxResolutionDeg' - | 'minResolutionDeg' - | 'maxResolutionMeter' - | 'minResolutionMeter' - | 'maxHorizontalAccuracyCE90' - | 'minHorizontalAccuracyCE90' - | 'productBoundingBox' - > - >, - NonNullableRecord>, - MakePolygonalRecord {} diff --git a/src/models/polygonParts/index.ts b/src/models/polygonParts/index.ts index b4c2d04..cc8a4f5 100644 --- a/src/models/polygonParts/index.ts +++ b/src/models/polygonParts/index.ts @@ -1,2 +1 @@ -export type { AggregationLayerMetadata } from './aggregationLayerMetadata'; export * from './polygonPartRecord'; diff --git a/src/models/polygonParts/polygonPartRecord.ts b/src/models/polygonParts/polygonPartRecord.ts index 1ce1aff..0a9208d 100644 --- a/src/models/polygonParts/polygonPartRecord.ts +++ b/src/models/polygonParts/polygonPartRecord.ts @@ -1,13 +1,7 @@ import { Polygon } from 'geojson'; import { keys } from 'ts-transformer-keys'; import { graphql } from '../common/decorators/graphQL/graphql.decorator'; -import { - FieldCategory, - IFieldConfigInfo, - IPropFieldConfigInfo, - fieldConfig, - getFieldConfig, -} from '../common/decorators/fieldConfig/fieldConfig.decorator'; +import { FieldCategory, IPropFieldConfigInfo, fieldConfig, getFieldConfig } from '../common/decorators/fieldConfig/fieldConfig.decorator'; import { DataFileType, IPropSHPMapping, getInputDataMapping, inputDataMapping } from '../layerMetadata/decorators/property/shp.decorator'; import { catalogDB, getCatalogDBMapping, ORMColumnType } from '../layerMetadata/decorators/property/catalogDB.decorator'; import { getTsTypesMapping, tsTypes, TsTypes } from '../layerMetadata/decorators/property/tsTypes.decorator'; diff --git a/src/models/raster/constants.ts b/src/models/raster/constants.ts index bf8c7bf..1f07025 100644 --- a/src/models/raster/constants.ts +++ b/src/models/raster/constants.ts @@ -1,6 +1,21 @@ +/* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable @typescript-eslint/no-magic-numbers */ import { zoomLevelToResolutionDeg, zoomLevelToResolutionMeter } from '@map-colonies/mc-utils'; +export const RasterProductTypes = { + Orthophoto: 'Orthophoto', + OrthophotoHistory: 'OrthophotoHistory', + OrthophotoBest: 'OrthophotoBest', + RasterMap: 'RasterMap', + RasterMapBest: 'RasterMapBest', + RasterAid: 'RasterAid', + RasterAidBest: 'RasterAidBest', + RasterVector: 'RasterVector', + RasterVectorBest: 'RasterVectorBest', +} as const; + +export const RASTER_PRODUCT_TYPES = Object.values(RasterProductTypes); + export const VALIDATIONS = { boundingBox: { pattern: '^-?(0|[1-9]\\d*)(\\.\\d*)?,-?(0|[1-9]\\d*)(\\.\\d*)?,-?(0|[1-9]\\d*)(\\.\\d*)?,-?(0|[1-9]\\d*)(\\.\\d*)?$', @@ -36,4 +51,7 @@ export const VALIDATIONS = { sensor: { pattern: '^(?!\\s).+(? = z - .object( - { - footprint: z.custom(), - imagingTimeBeginUTC: z.coerce.date({ message: 'Imaging time begin UTC should be a datetime' }), - imagingTimeEndUTC: z.coerce.date({ message: 'Imaging time end UTC should be a datetime' }), - maxHorizontalAccuracyCE90: z - .number({ message: 'Max horizontal accuracy CE90 should be a number' }) - .min(VALIDATIONS.horizontalAccuracyCE90.min, { - message: `Max horizontal accuracy CE90 should not be less than ${VALIDATIONS.horizontalAccuracyCE90.min}`, - }) - .max(VALIDATIONS.horizontalAccuracyCE90.max, { - message: `Max horizontal accuracy CE90 should not be larger than ${VALIDATIONS.horizontalAccuracyCE90.max}`, - }), - maxResolutionDeg: z - .number({ message: 'Max resolution degree should be a number' }) - .min(VALIDATIONS.resolutionDeg.min as number, { - message: `Max resolution degree should not be less than ${VALIDATIONS.resolutionDeg.min as number}`, - }) - .max(VALIDATIONS.resolutionDeg.max as number, { - message: `Max resolution degree should not be larger than ${VALIDATIONS.resolutionDeg.max as number}`, - }), - maxResolutionMeter: z - .number({ message: 'Max resolution meter should be a number' }) - .min(VALIDATIONS.resolutionMeter.min as number, { - message: `Max resolution meter should not be less than ${VALIDATIONS.resolutionMeter.min as number}`, - }) - .max(VALIDATIONS.resolutionMeter.max as number, { - message: `Max resolution meter should not be larger than ${VALIDATIONS.resolutionMeter.max as number}`, - }), - minHorizontalAccuracyCE90: z - .number({ message: 'Min horizontal accuracy CE90 should be a number' }) - .min(VALIDATIONS.horizontalAccuracyCE90.min, { - message: `Min horizontal accuracy CE90 should not be less than ${VALIDATIONS.horizontalAccuracyCE90.min}`, - }) - .max(VALIDATIONS.horizontalAccuracyCE90.max, { - message: `Min horizontal accuracy CE90 should not be larger than ${VALIDATIONS.horizontalAccuracyCE90.max}`, - }), - minResolutionDeg: z - .number({ message: 'Min resolution degree should be a number' }) - .min(VALIDATIONS.resolutionDeg.min as number, { - message: `Min resolution degree should not be less than ${VALIDATIONS.resolutionDeg.min as number}`, - }) - .max(VALIDATIONS.resolutionDeg.max as number, { - message: `Min resolution degree should not be larger than ${VALIDATIONS.resolutionDeg.max as number}`, - }), - minResolutionMeter: z - .number({ message: 'Min resolution meter should be a number' }) - .min(VALIDATIONS.resolutionMeter.min as number, { - message: `Min resolution meter should not be less than ${VALIDATIONS.resolutionMeter.min as number}`, - }) - .max(VALIDATIONS.resolutionMeter.max as number, { - message: `Min resolution meter should not be larger than ${VALIDATIONS.resolutionMeter.max as number}`, - }), - productBoundingBox: z.string({ message: 'Product bounding box should be a string' }).regex(new RegExp(VALIDATIONS.boundingBox.pattern), { - message: 'Product bounding box must be of the shape min_x,min_y,max_x,max_y', - }), - sensors: z - .array( - z.string({ message: 'Sensors should be an array of strings' }).regex(new RegExp(VALIDATIONS.sensor.pattern), { - message: 'Sensors should be an array with items not starting or ending with whitespace characters', - }), - { message: 'Sensors should be an array' } - ) - .min(1, { message: 'Sensors should have an array length of at least 1' }), - }, - { message: 'Layer metadata should be an object' } - ) - .strict() - .refine( - (aggregationLayerMetadata) => - aggregationLayerMetadata.imagingTimeBeginUTC <= aggregationLayerMetadata.imagingTimeEndUTC && - aggregationLayerMetadata.imagingTimeEndUTC <= new Date(), - { - message: 'Imaging time begin UTC should be less than or equal to imaging time end UTC and both less than or equal to current timestamp', - } - ) - .refine((aggregationLayerMetadata) => aggregationLayerMetadata.minHorizontalAccuracyCE90 <= aggregationLayerMetadata.maxHorizontalAccuracyCE90, { - message: 'Min horizontal accuracy CE90 should be less than or equal to max horizontal accuracy CE90', - }) - .refine((aggregationLayerMetadata) => aggregationLayerMetadata.minResolutionDeg <= aggregationLayerMetadata.maxResolutionDeg, { - message: 'Min resolution degree should be less than or equal to max resolution degree', - }) - .refine((aggregationLayerMetadata) => aggregationLayerMetadata.minResolutionMeter <= aggregationLayerMetadata.maxResolutionMeter, { - message: 'Min resolution meter should be less than or equal to max resolution meter', - }) - .describe('aggregationLayerMetadataSchema'); diff --git a/src/models/raster/ingestion/zod/schemas/index.ts b/src/models/raster/ingestion/zod/schemas/index.ts index f09d169..1144e23 100644 --- a/src/models/raster/ingestion/zod/schemas/index.ts +++ b/src/models/raster/ingestion/zod/schemas/index.ts @@ -1,4 +1,3 @@ -export * from './aggregationLayerMetadata.schema'; export * from './inputFiles.schema'; export * from './metadata.schema'; -export * from './partData.schema'; +export * from './polygonParts.schema'; diff --git a/src/models/raster/ingestion/zod/schemas/metadata.schema.ts b/src/models/raster/ingestion/zod/schemas/metadata.schema.ts index 8894599..7f4dd03 100644 --- a/src/models/raster/ingestion/zod/schemas/metadata.schema.ts +++ b/src/models/raster/ingestion/zod/schemas/metadata.schema.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-magic-numbers */ -import { z } from 'zod'; +import { z, ZodType } from 'zod'; +import { MultiPolygon, Polygon } from 'geojson'; import { VALIDATIONS } from '../../../constants'; import { ProductType, Transparency } from '../../../../layerMetadata/enums'; @@ -25,3 +26,93 @@ export const updateMetadataSchema = z classification: z.string().regex(new RegExp(VALIDATIONS.classification.pattern)), }) .describe('updateMetadataSchema'); + +export const aggregationMetadataSchema = z + .object( + { + footprint: z.custom(), + imagingTimeBeginUTC: z.coerce.date({ message: 'Imaging time begin UTC should be a datetime' }), + imagingTimeEndUTC: z.coerce.date({ message: 'Imaging time end UTC should be a datetime' }), + maxHorizontalAccuracyCE90: z + .number({ message: 'Max horizontal accuracy CE90 should be a number' }) + .min(VALIDATIONS.horizontalAccuracyCE90.min, { + message: `Max horizontal accuracy CE90 should not be less than ${VALIDATIONS.horizontalAccuracyCE90.min}`, + }) + .max(VALIDATIONS.horizontalAccuracyCE90.max, { + message: `Max horizontal accuracy CE90 should not be larger than ${VALIDATIONS.horizontalAccuracyCE90.max}`, + }), + maxResolutionDeg: z + .number({ message: 'Max resolution degree should be a number' }) + .min(VALIDATIONS.resolutionDeg.min as number, { + message: `Max resolution degree should not be less than ${VALIDATIONS.resolutionDeg.min as number}`, + }) + .max(VALIDATIONS.resolutionDeg.max as number, { + message: `Max resolution degree should not be larger than ${VALIDATIONS.resolutionDeg.max as number}`, + }), + maxResolutionMeter: z + .number({ message: 'Max resolution meter should be a number' }) + .min(VALIDATIONS.resolutionMeter.min as number, { + message: `Max resolution meter should not be less than ${VALIDATIONS.resolutionMeter.min as number}`, + }) + .max(VALIDATIONS.resolutionMeter.max as number, { + message: `Max resolution meter should not be larger than ${VALIDATIONS.resolutionMeter.max as number}`, + }), + minHorizontalAccuracyCE90: z + .number({ message: 'Min horizontal accuracy CE90 should be a number' }) + .min(VALIDATIONS.horizontalAccuracyCE90.min, { + message: `Min horizontal accuracy CE90 should not be less than ${VALIDATIONS.horizontalAccuracyCE90.min}`, + }) + .max(VALIDATIONS.horizontalAccuracyCE90.max, { + message: `Min horizontal accuracy CE90 should not be larger than ${VALIDATIONS.horizontalAccuracyCE90.max}`, + }), + minResolutionDeg: z + .number({ message: 'Min resolution degree should be a number' }) + .min(VALIDATIONS.resolutionDeg.min as number, { + message: `Min resolution degree should not be less than ${VALIDATIONS.resolutionDeg.min as number}`, + }) + .max(VALIDATIONS.resolutionDeg.max as number, { + message: `Min resolution degree should not be larger than ${VALIDATIONS.resolutionDeg.max as number}`, + }), + minResolutionMeter: z + .number({ message: 'Min resolution meter should be a number' }) + .min(VALIDATIONS.resolutionMeter.min as number, { + message: `Min resolution meter should not be less than ${VALIDATIONS.resolutionMeter.min as number}`, + }) + .max(VALIDATIONS.resolutionMeter.max as number, { + message: `Min resolution meter should not be larger than ${VALIDATIONS.resolutionMeter.max as number}`, + }), + productBoundingBox: z.string({ message: 'Product bounding box should be a string' }).regex(new RegExp(VALIDATIONS.boundingBox.pattern), { + message: 'Product bounding box must be of the shape min_x,min_y,max_x,max_y', + }), + sensors: z + .array( + z.string({ message: 'Sensors should be an array of strings' }).regex(new RegExp(VALIDATIONS.sensor.pattern), { + message: 'Sensors should be an array with items not starting or ending with whitespace characters', + }), + { message: 'Sensors should be an array' } + ) + .min(1, { message: 'Sensors should have an array length of at least 1' }), + }, + { message: 'Layer metadata should be an object' } + ) + .strict() + .refine( + (aggregationLayerMetadata) => + aggregationLayerMetadata.imagingTimeBeginUTC <= aggregationLayerMetadata.imagingTimeEndUTC && + aggregationLayerMetadata.imagingTimeEndUTC <= new Date(), + { + message: 'Imaging time begin UTC should be less than or equal to imaging time end UTC and both less than or equal to current timestamp', + } + ) + .refine((aggregationLayerMetadata) => aggregationLayerMetadata.minHorizontalAccuracyCE90 <= aggregationLayerMetadata.maxHorizontalAccuracyCE90, { + message: 'Min horizontal accuracy CE90 should be less than or equal to max horizontal accuracy CE90', + }) + .refine((aggregationLayerMetadata) => aggregationLayerMetadata.minResolutionDeg <= aggregationLayerMetadata.maxResolutionDeg, { + message: 'Min resolution degree should be less than or equal to max resolution degree', + }) + .refine((aggregationLayerMetadata) => aggregationLayerMetadata.minResolutionMeter <= aggregationLayerMetadata.maxResolutionMeter, { + message: 'Min resolution meter should be less than or equal to max resolution meter', + }) + .describe('aggregationLayerMetadataSchema'); + +export type AggregationLayerMetadata = z.infer; diff --git a/src/models/raster/ingestion/zod/schemas/partData.schema.ts b/src/models/raster/ingestion/zod/schemas/polygonParts.schema.ts similarity index 84% rename from src/models/raster/ingestion/zod/schemas/partData.schema.ts rename to src/models/raster/ingestion/zod/schemas/polygonParts.schema.ts index 8bdc4be..e8ee064 100644 --- a/src/models/raster/ingestion/zod/schemas/partData.schema.ts +++ b/src/models/raster/ingestion/zod/schemas/polygonParts.schema.ts @@ -2,6 +2,7 @@ import type { Polygon } from 'geojson'; import { z } from 'zod'; import { VALIDATIONS } from '../../../constants'; +import { RASTER_PRODUCT_TYPES } from '../../../constants'; export const partSchema = z .object({ @@ -66,3 +67,19 @@ export const partSchema = z message: 'Imaging time begin UTC should be less than or equal to imaging time end UTC and both less than or equal to current timestamp', }) .describe('partSchema'); + +export const polygonPartsEntityNameSchema = z + .object({ + polygonPartsEntityName: z + .string() + .regex(new RegExp(VALIDATIONS.polygonPartsEntityName.pattern), { message: 'Polygon parts entity name should valid entity name' }) + .refine( + (value) => { + return RASTER_PRODUCT_TYPES.some((type) => value.endsWith(type.toLowerCase())); + }, + { message: 'Polygon parts entity name should end with one of the valid raster product types' } + ), + }) + .describe('polygonPartsEntityNameSchema'); + +export type PolygonPartsEntityName = z.infer; diff --git a/src/models/raster/types.ts b/src/models/raster/types.ts new file mode 100644 index 0000000..f3905aa --- /dev/null +++ b/src/models/raster/types.ts @@ -0,0 +1,3 @@ +import { RasterProductTypes } from './constants'; + +export type RasterProductTypes = (typeof RasterProductTypes)[keyof typeof RasterProductTypes];