Skip to content

Commit 515ef1c

Browse files
authored
Merge pull request #70 from Exabyte-io/feat/SOF-6923
feat/SOF-6923
2 parents 3c75c5f + 1f85e42 commit 515ef1c

File tree

2 files changed

+124
-1
lines changed

2 files changed

+124
-1
lines changed

src/utils/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
sortKeysDeepForObject,
2828
stringifyObject,
2929
} from "./object";
30-
import { getSchemaWithDependencies } from "./schemas";
30+
import { getSchemaWithDependencies, buildNamedEntitySchema } from "./schemas";
3131
import { getSearchQuerySelector } from "./selector";
3232
import {
3333
convertArabicToRoman,
@@ -90,5 +90,6 @@ export {
9090
getFilesInDirectory,
9191
getDirectories,
9292
createObjectPathFromFilePath,
93+
buildNamedEntitySchema,
9394
findPreviousVersion,
9495
};

src/utils/schemas.ts

+122
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import forEach from "lodash/forEach";
33
import hasProperty from "lodash/has";
44
import isEmpty from "lodash/isEmpty";
55

6+
import { JSONSchema7Definition } from "json-schema";
7+
68
import { JSONSchemasInterface } from "../JSONSchemasInterface";
79

810
export * from "@exabyte-io/esse.js/lib/js/esse/schemaUtils";
@@ -170,3 +172,123 @@ export function getSchemaWithDependencies({
170172
...buildDependencies(nodes),
171173
};
172174
}
175+
176+
const DEFAULT_GENERATIVE_KEYS = ["name"];
177+
178+
interface NamedEntity {
179+
name: string;
180+
}
181+
182+
const baseSchema = (definitionName: string, enforceUnique = true): JSONSchema => {
183+
return {
184+
type: "array",
185+
items: {
186+
$ref: `#/definitions/${definitionName}`,
187+
},
188+
uniqueItems: enforceUnique,
189+
};
190+
};
191+
192+
const defaultNamedEntitySchema = (name: string) => {
193+
return {
194+
properties: {
195+
name: {
196+
type: "string",
197+
enum: [name],
198+
},
199+
},
200+
} as JSONSchema;
201+
};
202+
203+
/**
204+
* Retrieves an RJSF schema with an id matching the provided name
205+
*/
206+
export const schemaByNamedEntityName = (name: string): JSONSchema | undefined => {
207+
const translatedName = name.replace(/_/g, "-");
208+
const schema = JSONSchemasInterface.matchSchema({
209+
$id: {
210+
$regex: `${translatedName}$`,
211+
},
212+
});
213+
return schema;
214+
};
215+
216+
/*
217+
* Filters an RJSF schema for all the properties used to generate a new schema
218+
*/
219+
const filterForGenerativeProperties = (schema: JSONSchema) => {
220+
if (!schema.properties || typeof schema.properties !== "object") return {};
221+
const generativeFilter = ([propertyKey, property]: [string, JSONSchema7Definition]) => {
222+
return (
223+
(typeof property === "object" && // JSONSchema7Definition type allows for boolean
224+
property?.$comment &&
225+
property.$comment.includes("isGenerative:true")) ||
226+
DEFAULT_GENERATIVE_KEYS.includes(propertyKey)
227+
);
228+
};
229+
// @ts-ignore : JSONSchema6 and JSONSchema7 are incompatible
230+
const generativeProperties = Object.entries(schema.properties).filter(generativeFilter);
231+
const properties = Object.fromEntries(generativeProperties);
232+
return { properties, required: Object.keys(properties) } as JSONSchema; // all included fields are required based on isGenerative flag
233+
};
234+
235+
/*
236+
* Filters an RJSF schema for all the properties used to generate a new schema
237+
*/
238+
const buildNamedEntitiesDependencies = (entities: NamedEntity[]) => {
239+
return {
240+
dependencies: {
241+
name: {
242+
oneOf: entities.map((entity) => {
243+
const schema =
244+
schemaByNamedEntityName(entity.name) ||
245+
defaultNamedEntitySchema(entity.name);
246+
return {
247+
248+
...filterForGenerativeProperties(schema),
249+
};
250+
}),
251+
},
252+
},
253+
};
254+
};
255+
256+
/**
257+
* Generates an RJSF definition with a list of subschemas as enumerated options
258+
*/
259+
const buildNamedEntitiesDefinitions = (
260+
entities: NamedEntity[],
261+
defaultEntity: NamedEntity,
262+
entityType: string,
263+
) => {
264+
if (!Array.isArray(entities) || entities.length < 1) return {};
265+
return {
266+
definitions: {
267+
[entityType]: {
268+
properties: {
269+
name: {
270+
type: "string",
271+
enum: entities.map((entity) => entity.name),
272+
default: defaultEntity.name || entities[0].name,
273+
},
274+
},
275+
...buildNamedEntitiesDependencies(entities),
276+
},
277+
},
278+
};
279+
};
280+
281+
/*
282+
* Generates an RJSF scheme with a list of subschemas as enumerated options
283+
*/
284+
export const buildNamedEntitySchema = (
285+
entities: NamedEntity[],
286+
defaultEntity: NamedEntity,
287+
entityType: string,
288+
enforceUnique = true,
289+
): JSONSchema => {
290+
return {
291+
...buildNamedEntitiesDefinitions(entities, defaultEntity, entityType),
292+
...baseSchema(entityType, enforceUnique),
293+
} as JSONSchema;
294+
};

0 commit comments

Comments
 (0)