Skip to content

Commit de5e384

Browse files
Ashwin Raj ckAshwin Raj ck
authored andcommitted
feat: add dynamic payload support in schema controller
1 parent 831f93b commit de5e384

File tree

4 files changed

+135
-10
lines changed

4 files changed

+135
-10
lines changed

src/controller/schema_controller.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import * as Cord from '@cord.network/sdk';
22
import express from 'express';
33
import { getConnection } from 'typeorm';
44
import 'reflect-metadata';
5-
5+
import { validateSchema } from '../utils/SchemaValidationUtils';
6+
import { extractSchemaFields } from '../utils/SchemaUtils';
67
import { Schema } from '../entity/Schema';
8+
79
import {
810
addDelegateAsRegistryDelegate,
911
authorIdentity,
@@ -22,18 +24,20 @@ export async function createSchema(
2224
await addDelegateAsRegistryDelegate();
2325
}
2426

25-
const data = req.body.schema;
26-
27-
if (!data || !data.properties) {
28-
return res.status(400).json({
29-
error:
30-
"'schema' is a required field in the form of key-value pair, with title and description",
31-
});
32-
}
27+
let data = req.body.schema?.schema || req.body.schema || null;
3328

29+
30+
const validationError = validateSchema(data);
31+
if (validationError) {
32+
return res.status(400).json({ error: validationError });
33+
}
34+
35+
data = extractSchemaFields(data)
36+
37+
3438
let newSchemaName = data.title + ':' + Cord.Utils.UUID.generate();
3539
data.title = newSchemaName;
36-
data.type = 'object';
40+
3741

3842
let schemaDetails = await Cord.Schema.buildFromProperties(
3943
data,

src/types/Schema.interface.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
export type PropertyType =
2+
| StringProperty
3+
| NumberProperty
4+
| BooleanProperty
5+
| ArrayProperty
6+
| ObjectProperty;
7+
8+
export interface StringProperty {
9+
type: 'string';
10+
enum?: string[];
11+
format?: 'date' | 'time' | 'uri';
12+
minLength?: number;
13+
maxLength?: number;
14+
}
15+
16+
export interface NumberProperty {
17+
type: 'integer' | 'number';
18+
enum?: number[];
19+
minimum?: number;
20+
maximum?: number;
21+
}
22+
23+
export interface BooleanProperty {
24+
type: 'boolean';
25+
}
26+
27+
export interface ArrayProperty {
28+
type: 'array';
29+
items: PropertyType;
30+
minItems?: number;
31+
maxItems?: number;
32+
}
33+
34+
export interface ObjectProperty {
35+
type: 'object';
36+
properties: Record<string, PropertyType>;
37+
required?: string[];
38+
}

src/utils/SchemaUtils.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { PropertyType ,ObjectProperty} from "../types/Schema.interface";
2+
3+
4+
export function extractSchemaFields(schema: any) {
5+
if (!schema || typeof schema !== 'object') {
6+
throw new Error("Invalid schema: Schema must be a valid object.");
7+
}
8+
9+
10+
const extractProperty = (property: any): PropertyType => {
11+
switch (property.type) {
12+
case 'string': {
13+
const { type, enum: enumValues, format, minLength, maxLength } = property;
14+
return {
15+
type,
16+
...(enumValues && { enum: enumValues }),
17+
...(format && { format }),
18+
...(minLength && { minLength }),
19+
...(maxLength && { maxLength })
20+
};
21+
}
22+
case 'integer':
23+
case 'number': {
24+
const { type, enum: enumValues, minimum, maximum } = property;
25+
return {
26+
type,
27+
...(enumValues && { enum: enumValues }),
28+
...(minimum && { minimum }),
29+
...(maximum && { maximum })
30+
};
31+
}
32+
case 'array': {
33+
const { type, items, minItems, maxItems } = property;
34+
return {
35+
type,
36+
items: extractProperty(items),
37+
...(minItems && { minItems }),
38+
...(maxItems && { maxItems })
39+
};
40+
}
41+
case 'object': {
42+
const { type, properties, required } = property;
43+
return {
44+
type,
45+
properties: Object.keys(properties).reduce((acc, key) => {
46+
acc[key] = extractProperty(properties[key]);
47+
return acc;
48+
}, {} as ObjectProperty['properties']),
49+
...(required && { required })
50+
};
51+
}
52+
case 'boolean':
53+
return { type: 'boolean' };
54+
default:
55+
throw new Error(`Unsupported property type: ${property.type}`);
56+
}
57+
};
58+
59+
60+
const properties = Object.keys(schema.properties || {}).reduce((acc, key) => {
61+
acc[key] = extractProperty(schema.properties[key]);
62+
return acc;
63+
}, {} as Record<string, PropertyType>);
64+
65+
66+
return {
67+
title: schema.title || schema.$id,
68+
properties,
69+
required: schema.required || [],
70+
type: 'object',
71+
};
72+
}

src/utils/SchemaValidationUtils.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
export function validateSchema(data:any) {
3+
4+
if (!data) return "'schema' is required.";
5+
if (!data.title && !data.$id) return "'title' or '$id' is required.";
6+
if (!data.description) return "'description' is required.";
7+
if (!data.properties) return "'properties' is required.";
8+
if (Object.keys(data.properties).length === 0) return "'properties' must contain at least one property.";
9+
return null;
10+
}
11+

0 commit comments

Comments
 (0)