Skip to content

Commit

Permalink
Merge pull request #46 from ashwin275/feature/api-dynamic-payload-sup…
Browse files Browse the repository at this point in the history
…port

feat: add dynamic payload support in schema controller
  • Loading branch information
ashwin275 authored Sep 27, 2024
2 parents 9c3feaa + de5e384 commit cddba89
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 10 deletions.
24 changes: 14 additions & 10 deletions src/controller/schema_controller.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import * as Cord from '@cord.network/sdk';
import express from 'express';
import 'reflect-metadata';

import { validateSchema } from '../utils/SchemaValidationUtils';
import { extractSchemaFields } from '../utils/SchemaUtils';
import { Schema } from '../entity/Schema';

import {
addDelegateAsRegistryDelegate,
authorIdentity,
Expand All @@ -22,18 +24,20 @@ export async function createSchema(
await addDelegateAsRegistryDelegate();
}

const data = req.body.schema;

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


const validationError = validateSchema(data);
if (validationError) {
return res.status(400).json({ error: validationError });
}

data = extractSchemaFields(data)


let newSchemaName = data.title + ':' + Cord.Utils.UUID.generate();
data.title = newSchemaName;
data.type = 'object';


let schemaDetails = await Cord.Schema.buildFromProperties(
data,
Expand Down
38 changes: 38 additions & 0 deletions src/types/Schema.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export type PropertyType =
| StringProperty
| NumberProperty
| BooleanProperty
| ArrayProperty
| ObjectProperty;

export interface StringProperty {
type: 'string';
enum?: string[];
format?: 'date' | 'time' | 'uri';
minLength?: number;
maxLength?: number;
}

export interface NumberProperty {
type: 'integer' | 'number';
enum?: number[];
minimum?: number;
maximum?: number;
}

export interface BooleanProperty {
type: 'boolean';
}

export interface ArrayProperty {
type: 'array';
items: PropertyType;
minItems?: number;
maxItems?: number;
}

export interface ObjectProperty {
type: 'object';
properties: Record<string, PropertyType>;
required?: string[];
}
72 changes: 72 additions & 0 deletions src/utils/SchemaUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { PropertyType ,ObjectProperty} from "../types/Schema.interface";


export function extractSchemaFields(schema: any) {
if (!schema || typeof schema !== 'object') {
throw new Error("Invalid schema: Schema must be a valid object.");
}


const extractProperty = (property: any): PropertyType => {
switch (property.type) {
case 'string': {
const { type, enum: enumValues, format, minLength, maxLength } = property;
return {
type,
...(enumValues && { enum: enumValues }),
...(format && { format }),
...(minLength && { minLength }),
...(maxLength && { maxLength })
};
}
case 'integer':
case 'number': {
const { type, enum: enumValues, minimum, maximum } = property;
return {
type,
...(enumValues && { enum: enumValues }),
...(minimum && { minimum }),
...(maximum && { maximum })
};
}
case 'array': {
const { type, items, minItems, maxItems } = property;
return {
type,
items: extractProperty(items),
...(minItems && { minItems }),
...(maxItems && { maxItems })
};
}
case 'object': {
const { type, properties, required } = property;
return {
type,
properties: Object.keys(properties).reduce((acc, key) => {
acc[key] = extractProperty(properties[key]);
return acc;
}, {} as ObjectProperty['properties']),
...(required && { required })
};
}
case 'boolean':
return { type: 'boolean' };
default:
throw new Error(`Unsupported property type: ${property.type}`);
}
};


const properties = Object.keys(schema.properties || {}).reduce((acc, key) => {
acc[key] = extractProperty(schema.properties[key]);
return acc;
}, {} as Record<string, PropertyType>);


return {
title: schema.title || schema.$id,
properties,
required: schema.required || [],
type: 'object',
};
}
11 changes: 11 additions & 0 deletions src/utils/SchemaValidationUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

export function validateSchema(data:any) {

if (!data) return "'schema' is required.";
if (!data.title && !data.$id) return "'title' or '$id' is required.";
if (!data.description) return "'description' is required.";
if (!data.properties) return "'properties' is required.";
if (Object.keys(data.properties).length === 0) return "'properties' must contain at least one property.";
return null;
}

0 comments on commit cddba89

Please sign in to comment.