11import { type CreatePropertyParams , Graph , Id as Grc20Id , type Op } from '@graphprotocol/grc-20' ;
22import { Array as EffectArray , Schema as EffectSchema , pipe } from 'effect' ;
33
4+ import { namesAreUnique , toCamelCase , toPascalCase } from './Utils.js' ;
5+
46/**
57 * Mappings for a schema type and its properties/relations
68 *
@@ -24,16 +26,6 @@ export type MappingEntry = {
2426 [ key : string ] : Grc20Id . Id ;
2527 }
2628 | undefined ;
27- /**
28- * Record of schema type relation names to the `Id.Id` of the relation in the Knowledge Graph
29- *
30- * @since 0.0.1
31- */
32- relations ?:
33- | {
34- [ key : string ] : Grc20Id . Id ;
35- }
36- | undefined ;
3729} ;
3830
3931/**
@@ -55,10 +47,8 @@ export type MappingEntry = {
5547 * properties: {
5648 * name: Id.Id('3808e060-fb4a-4d08-8069-35b8c8a1902b'),
5749 * description: Id.Id('1f0d9007-8da2-4b28-ab9f-3bc0709f4837'),
50+ * speaker: Id.Id('a5fd07b1-120f-46c6-b46f-387ef98396a6')
5851 * },
59- * relations: {
60- * account: Id.Id('a5fd07b1-120f-46c6-b46f-387ef98396a6')
61- * }
6252 * }
6353 * }
6454 * ```
@@ -69,21 +59,43 @@ export type Mapping = {
6959 [ key : string ] : MappingEntry ;
7060} ;
7161
62+ /**
63+ * @since 0.0.1
64+ */
7265export type DataTypeRelation = `Relation(${string } )`;
66+ /**
67+ * @since 0.0.1
68+ */
7369export function isDataTypeRelation ( val : string ) : val is DataTypeRelation {
7470 return / ^ R e l a t i o n \( ( .+ ) \) $ / . test ( val ) ;
7571}
72+ /**
73+ * @since 0.0.1
74+ */
7675export const SchemaDataTypeRelation = EffectSchema . NonEmptyTrimmedString . pipe (
7776 EffectSchema . filter ( ( val ) => isDataTypeRelation ( val ) ) ,
7877) ;
78+ /**
79+ * @since 0.0.1
80+ */
7981export type SchemaDataTypeRelation = typeof SchemaDataTypeRelation . Type ;
80-
82+ /**
83+ * @since 0.0.1
84+ */
8185export const SchemaDataType = EffectSchema . Union (
8286 EffectSchema . Literal ( 'Text' , 'Number' , 'Boolean' , 'Date' , 'Point' , 'Url' ) ,
8387 SchemaDataTypeRelation ,
8488) ;
89+ /**
90+ * @since 0.0.1
91+ */
8592export type SchemaDataType = typeof SchemaDataType . Type ;
8693
94+ /**
95+ * Represents the user-built schema object to generate a `Mappings` definition for
96+ *
97+ * @since 0.0.1
98+ */
8799export const Schema = EffectSchema . Struct ( {
88100 types : EffectSchema . Array (
89101 EffectSchema . Struct ( {
@@ -95,9 +107,23 @@ export const Schema = EffectSchema.Struct({
95107 knowledgeGraphId : EffectSchema . NullOr ( EffectSchema . UUID ) ,
96108 dataType : SchemaDataType ,
97109 } ) ,
98- ) . pipe ( EffectSchema . minItems ( 1 ) ) ,
110+ ) . pipe (
111+ EffectSchema . minItems ( 1 ) ,
112+ EffectSchema . filter ( namesAreUnique , {
113+ identifier : 'DuplicatePropertyNames' ,
114+ jsonSchema : { } ,
115+ description : 'The property.name must be unique across all properties in the type' ,
116+ } ) ,
117+ ) ,
118+ } ) ,
119+ ) . pipe (
120+ EffectSchema . minItems ( 1 ) ,
121+ EffectSchema . filter ( namesAreUnique , {
122+ identifier : 'DuplicateTypeNames' ,
123+ jsonSchema : { } ,
124+ description : 'The type.name must be unique across all types in the schema' ,
99125 } ) ,
100- ) . pipe ( EffectSchema . minItems ( 1 ) ) ,
126+ ) ,
101127} ) . annotations ( {
102128 identifier : 'typesync/Schema' ,
103129 title : 'TypeSync app Schema' ,
@@ -123,8 +149,27 @@ export const Schema = EffectSchema.Struct({
123149 } ,
124150 ] ,
125151} ) ;
152+ /**
153+ * @since 0.0.1
154+ */
126155export type Schema = typeof Schema . Type ;
156+ /**
157+ * @since 0.0.1
158+ */
159+ export const SchemaKnownDecoder = EffectSchema . decodeSync ( Schema ) ;
160+ /**
161+ * @since 0.0.1
162+ */
163+ export const SchemaUnknownDecoder = EffectSchema . decodeUnknownSync ( Schema ) ;
127164
165+ /**
166+ *
167+ *
168+ * @since 0.0.1
169+ *
170+ * @param schema user-built and submitted schema
171+ * @returns the generated [Mapping] definition from the submitted schema
172+ */
128173export async function generateMapping ( schema : Schema ) : Promise < Mapping > {
129174 const entries : Array < MappingEntry & { typeName : string } > = [ ] ;
130175 const ops : Array < Op > = [ ] ;
@@ -134,35 +179,45 @@ export async function generateMapping(schema: Schema): Promise<Mapping> {
134179 for ( const property of type . properties ) {
135180 if ( property . knowledgeGraphId ) {
136181 typePropertyIds . push ( { propName : property . name , id : Grc20Id . Id ( property . knowledgeGraphId ) } ) ;
182+
137183 continue ;
138184 }
139185 // create op for creating type property
186+ const dataType = mapSchemaDataTypeToGRC20PropDataType ( property . dataType ) ;
187+ if ( dataType === 'RELATION' ) {
188+ const { id, ops : createTypePropOp } = Graph . createProperty ( {
189+ name : property . name ,
190+ dataType : 'RELATION' ,
191+ relationValueTypes : [ ] ,
192+ properties : [ ] ,
193+ } ) ;
194+ typePropertyIds . push ( { propName : property . name , id } ) ;
195+ ops . push ( ...createTypePropOp ) ;
196+
197+ continue ;
198+ }
140199 const { id, ops : createTypePropOp } = Graph . createProperty ( {
141200 name : property . name ,
142201 dataType : mapSchemaDataTypeToGRC20PropDataType ( property . dataType ) ,
143202 } ) ;
144203 typePropertyIds . push ( { propName : property . name , id } ) ;
145- // add createProperty ops to array to submit in batch to KG
146204 ops . push ( ...createTypePropOp ) ;
147205 }
148206
149207 const properties : MappingEntry [ 'properties' ] = pipe (
150208 typePropertyIds ,
151209 EffectArray . reduce ( { } as NonNullable < MappingEntry [ 'properties' ] > , ( props , { propName, id } ) => {
152- props [ propName ] = id ;
210+ props [ toCamelCase ( propName ) ] = id ;
153211
154212 return props ;
155213 } ) ,
156214 ) ;
157215
158- const relations : MappingEntry [ 'relations' ] = undefined ;
159-
160216 if ( type . knowledgeGraphId ) {
161217 entries . push ( {
162- typeName : type . name ,
218+ typeName : toPascalCase ( type . name ) ,
163219 typeIds : [ Grc20Id . Id ( type . knowledgeGraphId ) ] ,
164220 properties,
165- relations,
166221 } ) ;
167222 continue ;
168223 }
@@ -174,14 +229,15 @@ export async function generateMapping(schema: Schema): Promise<Mapping> {
174229 ops . push ( ...createTypeOp ) ;
175230
176231 entries . push ( {
177- typeName : type . name ,
232+ typeName : toPascalCase ( type . name ) ,
178233 typeIds : [ id ] ,
179234 properties,
180- relations,
181235 } ) ;
182236 }
183237
184- // @todo send ops to Knowledge Graph
238+ /**
239+ * @todo publish the schema onchain to the Knowledge Graph with hypergraph connect app to the application space
240+ */
185241
186242 return pipe (
187243 entries ,
0 commit comments