@@ -3,6 +3,8 @@ import forEach from "lodash/forEach";
33import hasProperty from "lodash/has" ;
44import isEmpty from "lodash/isEmpty" ;
55
6+ import { JSONSchema7Definition } from "json-schema" ;
7+
68import { JSONSchemasInterface } from "../JSONSchemasInterface" ;
79
810export * 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