Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 58 additions & 26 deletions src/schemas/core/aggregation.schema.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import z from 'zod';
import z, { type ZodObject, type ZodType, type ZodTypeAny } from 'zod';
import { CORE_VALIDATIONS, INGESTION_VALIDATIONS } from '../../constants';
import type { SelectivePartial } from '../../utils/typeUtils';
import { featureSchema, multiPolygonSchema, polygonSchema } from './geo.schema';

export const aggregationFeaturePropertiesSchema = z
const aggregationPropertiesSchema = z
.object({
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' }),
Expand Down Expand Up @@ -68,28 +69,59 @@ export const aggregationFeaturePropertiesSchema = z
)
.min(1, { message: 'Sensors should have an array length of at least 1' }),
})
.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.maxHorizontalAccuracyCE90 <= aggregationLayerMetadata.minHorizontalAccuracyCE90, {
message: 'Max horizontal accuracy CE90 should be less than or equal to min horizontal accuracy CE90',
})
.refine((aggregationLayerMetadata) => aggregationLayerMetadata.maxResolutionDeg <= aggregationLayerMetadata.minResolutionDeg, {
message: 'Max resolution degree should be less than or equal to min resolution degree',
})
.refine((aggregationLayerMetadata) => aggregationLayerMetadata.maxResolutionMeter <= aggregationLayerMetadata.minResolutionMeter, {
message: 'Max resolution meter should be less than or equal to min resolution meter',
})
.describe('aggregationLayerMetadataSchema')
.describe('aggregationFeaturePropertiesSchema');
.strict();

type SpatialAggregationProperties = 'productBoundingBox' | 'sensors';
type AggregationProperties = SelectivePartial<z.infer<typeof aggregationPropertiesSchema>, SpatialAggregationProperties>;
type AggregationPropertiesZodSchemas = SelectivePartial<(typeof aggregationPropertiesSchema)['shape'], SpatialAggregationProperties>;

const aggregationFeaturePropertiesSchemaBuilder = <T extends AggregationProperties>(
input: ZodObject<AggregationPropertiesZodSchemas, 'strict', ZodTypeAny, T, T>
): ZodType<T> => {
return input
.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.maxHorizontalAccuracyCE90 <= aggregationLayerMetadata.minHorizontalAccuracyCE90, {
message: 'Max horizontal accuracy CE90 should be less than or equal to min horizontal accuracy CE90',
})
.refine((aggregationLayerMetadata) => aggregationLayerMetadata.maxResolutionDeg <= aggregationLayerMetadata.minResolutionDeg, {
message: 'Max resolution degree should be less than or equal to min resolution degree',
})
.refine(
(aggregationLayerMetadata): aggregationLayerMetadata is T =>
aggregationLayerMetadata.maxResolutionMeter <= aggregationLayerMetadata.minResolutionMeter,
{
message: 'Max resolution meter should be less than or equal to min resolution meter',
}
);
};

export const aggregationSpatialFeaturePropertiesSchema = aggregationFeaturePropertiesSchemaBuilder(aggregationPropertiesSchema).describe(
'aggregationSpatialFeaturePropertiesSchema'
);

export const aggregationNonSpatialFeaturePropertiesSchema = aggregationFeaturePropertiesSchemaBuilder(
aggregationPropertiesSchema.omit({ productBoundingBox: true })
).describe('aggregationNonSpatialFeaturePropertiesSchema');

export const aggregationSpatialFeatureSchema = featureSchema(
polygonSchema.or(multiPolygonSchema),
aggregationSpatialFeaturePropertiesSchema
).describe('aggregationSpatialFeatureSchema');

export const aggregationNonSpatialFeatureSchema = featureSchema(z.null(), aggregationNonSpatialFeaturePropertiesSchema).describe(
'aggregationNonSpatialFeatureSchema'
);

export const aggregationEmptyFeatureSchema = featureSchema(z.null(), z.null()).describe('aggregationEmptyFeatureSchema');

export const aggregationFeatureSchema = featureSchema(
polygonSchema.or(multiPolygonSchema).or(z.null()),
aggregationFeaturePropertiesSchema.or(z.null())
).describe('aggregationFeatureSchema');
export const aggregationFeatureSchema = aggregationSpatialFeatureSchema
.or(aggregationNonSpatialFeatureSchema)
.or(aggregationEmptyFeatureSchema)
.describe('aggregationFeatureSchema');
12 changes: 10 additions & 2 deletions src/types/core/metadata.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import z from 'zod';
import { IMetadataCommonModel, RecordStatus, TilesMimeFormat } from '@map-colonies/types';
import z from 'zod';
import { TileOutputFormat, Transparency } from '../../constants/core';
import { aggregationFeatureSchema } from '../../schemas';
import {
aggregationEmptyFeatureSchema,
aggregationFeatureSchema,
aggregationNonSpatialFeatureSchema,
aggregationSpatialFeatureSchema,
} from '../../schemas';

// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
export type RasterLayerMetadata = {
Expand Down Expand Up @@ -32,4 +37,7 @@ export type RasterLayerMetadata = {
productStatus?: RecordStatus;
} & IMetadataCommonModel;

export type AggregationSpatialFeature = z.infer<typeof aggregationSpatialFeatureSchema>;
export type AggregationNonSpatialFeature = z.infer<typeof aggregationNonSpatialFeatureSchema>;
export type AggregationEmptyFeature = z.infer<typeof aggregationEmptyFeatureSchema>;
export type AggregationFeature = z.infer<typeof aggregationFeatureSchema>;
4 changes: 4 additions & 0 deletions src/utils/typeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ export function pickEnum<T extends { [k: string]: string }, K extends keyof T>(e
});
return picked;
}

export type SelectivePartial<T extends Record<PropertyKey, unknown>, U extends keyof T> = Omit<T, U> & {
[K in U]?: T[K];
};