-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* refactor: additional regex patterns and organize props alphabetically * refactor: use validation pattern * feat: aggregation zod schema * refactor: add time validation between begin, end and current timestamp * fix: openapi sensor regex pattern * fix: file name pattern validation * style: remove extra spaces * refactor: improve error messages * refactor: removed prefix of each error message * refactor: error messages for part data zod schema
- Loading branch information
Showing
6 changed files
with
168 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
92 changes: 92 additions & 0 deletions
92
src/models/raster/ingestion/zod/schemas/aggregationLayerMetadata.schema.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import type { MultiPolygon, Polygon } from 'geojson'; | ||
import { z, type ZodType } from 'zod'; | ||
import type { AggregationLayerMetadata } from '../../../../polygonParts/aggregationLayerMetadata'; | ||
import { VALIDATIONS } from '../../../constants'; | ||
|
||
export const aggregationLayerMetadataSchema: ZodType<AggregationLayerMetadata> = z | ||
.object( | ||
{ | ||
footprint: z.custom<Polygon | MultiPolygon>(), | ||
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'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export * from './partData.schema'; | ||
export * from './aggregationLayerMetadata.schema'; | ||
export * from './inputFiles.schema'; | ||
export * from './metadata.schema'; | ||
export * from './partData.schema'; |
75 changes: 56 additions & 19 deletions
75
src/models/raster/ingestion/zod/schemas/partData.schema.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,68 @@ | ||
/* eslint-disable @typescript-eslint/no-magic-numbers */ | ||
import type { Polygon } from 'geojson'; | ||
import { z } from 'zod'; | ||
import { Polygon } from 'geojson'; | ||
import { VALIDATIONS } from '../../../constants'; | ||
|
||
export const partSchema = z | ||
.object({ | ||
sourceId: z.string().optional(), | ||
sourceName: z.string().min(1), | ||
description: z.string().optional(), | ||
imagingTimeBeginUTC: z.coerce.date(), | ||
imagingTimeEndUTC: z.coerce.date(), | ||
sourceId: z.string({ message: 'Source id should be a string' }).optional(), | ||
sourceName: z.string({ message: 'Source name should be a string' }).min(1, { message: 'Source name should have length of at least 1' }), | ||
description: z.string({ message: 'Description should be a string' }).optional(), | ||
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' }), | ||
resolutionDegree: z | ||
.number() | ||
.min(VALIDATIONS.resolutionDeg.min as number) | ||
.max(VALIDATIONS.resolutionDeg.max as number), | ||
.number({ message: 'Resolution degree should be a number' }) | ||
.min(VALIDATIONS.resolutionDeg.min as number, { | ||
message: `Resolution degree should not be less than ${VALIDATIONS.resolutionDeg.min as number}`, | ||
}) | ||
.max(VALIDATIONS.resolutionDeg.max as number, { | ||
message: `Resolution degree should not be larger than ${VALIDATIONS.resolutionDeg.max as number}`, | ||
}), | ||
resolutionMeter: z | ||
.number() | ||
.min(VALIDATIONS.resolutionMeter.min as number) | ||
.max(VALIDATIONS.resolutionMeter.max as number), | ||
.number({ message: 'Resolution meter should be a number' }) | ||
.min(VALIDATIONS.resolutionMeter.min as number, { | ||
message: `Resolution meter should not be less than ${VALIDATIONS.resolutionMeter.min as number}`, | ||
}) | ||
.max(VALIDATIONS.resolutionMeter.max as number, { | ||
message: `Resolution meter should not be larger than ${VALIDATIONS.resolutionMeter.max as number}`, | ||
}), | ||
sourceResolutionMeter: z | ||
.number() | ||
.min(VALIDATIONS.resolutionMeter.min as number) | ||
.max(VALIDATIONS.resolutionMeter.max as number), | ||
horizontalAccuracyCE90: z.number().min(VALIDATIONS.horizontalAccuracyCE90.min).max(VALIDATIONS.horizontalAccuracyCE90.max), | ||
sensors: z.array(z.string().regex(new RegExp('^(?! ).+(?<! )$'))).min(1), | ||
countries: z.array(z.string().min(1)).optional(), | ||
cities: z.array(z.string().min(1)).optional(), | ||
.number({ message: 'Source resolution meter should be a number' }) | ||
.min(VALIDATIONS.resolutionMeter.min as number, { | ||
message: `Source resolution meter should not be less than ${VALIDATIONS.resolutionMeter.min as number}`, | ||
}) | ||
.max(VALIDATIONS.resolutionMeter.max as number, { | ||
message: `Source resolution meter should not be larger than ${VALIDATIONS.resolutionMeter.max as number}`, | ||
}), | ||
horizontalAccuracyCE90: z | ||
.number({ message: 'Horizontal accuracy CE90 should be a number' }) | ||
.min(VALIDATIONS.horizontalAccuracyCE90.min, { | ||
message: `Horizontal accuracy CE90 should not be less than ${VALIDATIONS.horizontalAccuracyCE90.min}`, | ||
}) | ||
.max(VALIDATIONS.horizontalAccuracyCE90.max, { | ||
message: `Horizontal accuracy CE90 should not be larger than ${VALIDATIONS.horizontalAccuracyCE90.max}`, | ||
}), | ||
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' }), | ||
countries: z | ||
.array(z.string({ message: 'Countries should be an array of strings' }).min(1, { message: 'Countries should have length of at least 1' }), { | ||
message: 'Countries should be an array', | ||
}) | ||
.optional(), | ||
cities: z | ||
.array(z.string({ message: 'Cities should be an array of strings' }).min(1, { message: 'Cities should have length of at least 1' }), { | ||
message: 'Cities should be an array', | ||
}) | ||
.optional(), | ||
footprint: z.custom<Polygon>(), | ||
}) | ||
.refine((part) => part.imagingTimeBeginUTC <= part.imagingTimeEndUTC && part.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', | ||
}) | ||
.describe('partSchema'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,4 +21,4 @@ components: | |
example: ['example.gpkg'] | ||
required: | ||
- originDirectory | ||
- fileNames | ||
- fileNames |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters