|
1 |
| -import { |
2 |
| - type EntityRelationParams, |
3 |
| - Graph, |
4 |
| - type Id, |
5 |
| - type Op, |
6 |
| - type PropertiesParam, |
7 |
| - type RelationsParam, |
8 |
| -} from '@graphprotocol/grc-20'; |
9 |
| -import type { Entity } from '@graphprotocol/hypergraph'; |
10 |
| -import { store } from '@graphprotocol/hypergraph'; |
| 1 | +import { Graph, type Id, type Op, type PropertiesParam, type RelationsParam } from '@graphprotocol/grc-20'; |
| 2 | +import { Constants, type Entity, Utils } from '@graphprotocol/hypergraph'; |
| 3 | +import * as Option from 'effect/Option'; |
11 | 4 | import type * as Schema from 'effect/Schema';
|
| 5 | +import * as SchemaAST from 'effect/SchemaAST'; |
12 | 6 | import request, { gql } from 'graphql-request';
|
13 | 7 |
|
14 | 8 | export type PreparePublishParams<S extends Schema.Schema.AnyNoContext> = {
|
@@ -63,101 +57,70 @@ export const preparePublish = async <S extends Schema.Schema.AnyNoContext>({
|
63 | 57 | },
|
64 | 58 | );
|
65 | 59 |
|
66 |
| - const mapping = store.getSnapshot().context.mapping; |
67 |
| - const typeName = entity.type; |
68 |
| - const mappingEntry = mapping[typeName]; |
69 |
| - if (!mappingEntry) { |
70 |
| - throw new Error(`Mapping entry for ${typeName} not found`); |
71 |
| - } |
72 |
| - |
73 | 60 | const ops: Op[] = [];
|
74 | 61 | const values: PropertiesParam = [];
|
75 | 62 | const relations: RelationsParam = {};
|
76 |
| - const fields = entity.__schema.fields; |
| 63 | + const type = entity.__schema; |
77 | 64 |
|
78 | 65 | if (data?.entity === null) {
|
79 |
| - for (const [key, propertyId] of Object.entries(mappingEntry.properties || {})) { |
80 |
| - if (entity[key] === undefined) { |
81 |
| - if (TypeUtils.isOptional(fields[key])) { |
82 |
| - continue; |
83 |
| - } |
84 |
| - throw new Error(`Value for ${key} is undefined`); |
85 |
| - } |
86 |
| - let serializedValue: string = entity[key]; |
87 |
| - if (TypeUtils.isBooleanOrOptionalBooleanType(fields[key])) { |
88 |
| - serializedValue = Graph.serializeBoolean(entity[key]); |
89 |
| - } else if (TypeUtils.isDateOrOptionalDateType(fields[key])) { |
90 |
| - serializedValue = Graph.serializeDate(entity[key]); |
91 |
| - } else if (TypeUtils.isPointOrOptionalPointType(fields[key])) { |
92 |
| - serializedValue = Graph.serializePoint(entity[key]); |
93 |
| - } else if (TypeUtils.isNumberOrOptionalNumberType(fields[key])) { |
94 |
| - serializedValue = Graph.serializeNumber(entity[key]); |
95 |
| - } |
96 |
| - values.push({ property: propertyId, value: serializedValue }); |
97 |
| - } |
98 |
| - for (const [key, relationId] of Object.entries(mappingEntry.relations || {})) { |
99 |
| - // @ts-expect-error - TODO: fix the types error |
100 |
| - relations[relationId] = entity[key].map((relationEntity) => { |
101 |
| - const newRelation: EntityRelationParams = { toEntity: relationEntity.id }; |
102 |
| - if (relationEntity._relation.id) { |
103 |
| - newRelation.id = relationEntity._relation.id; |
| 66 | + const ast = type.ast as SchemaAST.TypeLiteral; |
| 67 | + |
| 68 | + const typeIds = SchemaAST.getAnnotation<string[]>(Constants.TypeIdsSymbol)(ast).pipe(Option.getOrElse(() => [])); |
| 69 | + |
| 70 | + for (const prop of ast.propertySignatures) { |
| 71 | + const propertyId = SchemaAST.getAnnotation<string>(Constants.PropertyIdSymbol)(prop.type); |
| 72 | + const propertyType = SchemaAST.getAnnotation<string>(Constants.PropertyTypeSymbol)(prop.type); |
| 73 | + if (!Option.isSome(propertyId) || !Option.isSome(propertyType)) continue; |
| 74 | + |
| 75 | + if (Utils.isRelation(prop.type)) { |
| 76 | + // @ts-expect-error any is ok here |
| 77 | + relations[propertyId.value] = entity[prop.name].map((relationEntity) => { |
| 78 | + const newRelation: Record<string, string> = { toEntity: relationEntity.id }; |
| 79 | + if (relationEntity._relation.id) { |
| 80 | + newRelation.id = relationEntity._relation.id; |
| 81 | + } |
| 82 | + if (relationEntity._relation.position) { |
| 83 | + newRelation.position = relationEntity._relation.position; |
| 84 | + } |
| 85 | + return newRelation; |
| 86 | + }); |
| 87 | + } else { |
| 88 | + if (entity[prop.name] === undefined) { |
| 89 | + if (prop.isOptional) { |
| 90 | + continue; |
| 91 | + } |
| 92 | + throw new Error(`Value for ${String(prop.name)} is undefined`); |
104 | 93 | }
|
105 |
| - if (relationEntity._relation.position) { |
106 |
| - newRelation.position = relationEntity._relation.position; |
| 94 | + let serializedValue: string = entity[prop.name]; |
| 95 | + if (propertyType.value === 'boolean') { |
| 96 | + serializedValue = Graph.serializeBoolean(entity[prop.name]); |
| 97 | + } else if (propertyType.value === 'date') { |
| 98 | + serializedValue = Graph.serializeDate(entity[prop.name]); |
| 99 | + } else if (propertyType.value === 'point') { |
| 100 | + serializedValue = Graph.serializePoint(entity[prop.name]); |
| 101 | + } else if (propertyType.value === 'number') { |
| 102 | + serializedValue = Graph.serializeNumber(entity[prop.name]); |
107 | 103 | }
|
108 |
| - return newRelation; |
109 |
| - }); |
| 104 | + values.push({ property: propertyId.value, value: serializedValue }); |
| 105 | + } |
110 | 106 | }
|
| 107 | + |
111 | 108 | const { ops: createOps } = Graph.createEntity({
|
112 | 109 | id: entity.id,
|
113 |
| - types: mappingEntry.typeIds, |
| 110 | + types: typeIds, |
114 | 111 | values,
|
115 | 112 | relations,
|
116 | 113 | });
|
117 | 114 | ops.push(...createOps);
|
118 | 115 | return { ops };
|
119 | 116 | }
|
120 | 117 |
|
121 |
| - if (data?.entity) { |
122 |
| - for (const [key, propertyId] of Object.entries(mappingEntry.properties || {})) { |
123 |
| - if (entity[key] === undefined) { |
124 |
| - if (TypeUtils.isOptional(fields[key])) { |
125 |
| - continue; |
126 |
| - } |
127 |
| - throw new Error(`Value for ${key} is undefined`); |
128 |
| - } |
129 |
| - |
130 |
| - const existingValueEntry = data.entity.valuesList.find((value) => value.propertyId === propertyId); |
131 |
| - let existingValue = existingValueEntry?.string; |
132 |
| - let serializedValue: string = entity[key]; |
133 |
| - if (TypeUtils.isBooleanOrOptionalBooleanType(fields[key])) { |
134 |
| - existingValue = |
135 |
| - existingValueEntry?.boolean !== undefined ? Graph.serializeBoolean(existingValueEntry.boolean) : undefined; |
136 |
| - serializedValue = Graph.serializeBoolean(entity[key]); |
137 |
| - } else if (TypeUtils.isDateOrOptionalDateType(fields[key])) { |
138 |
| - existingValue = existingValueEntry?.time; |
139 |
| - serializedValue = Graph.serializeDate(entity[key]); |
140 |
| - } else if (TypeUtils.isPointOrOptionalPointType(fields[key])) { |
141 |
| - existingValue = existingValueEntry?.point; |
142 |
| - serializedValue = Graph.serializePoint(entity[key]); |
143 |
| - } else if (TypeUtils.isNumberOrOptionalNumberType(fields[key])) { |
144 |
| - existingValue = |
145 |
| - existingValueEntry?.number !== undefined ? Graph.serializeNumber(existingValueEntry.number) : undefined; |
146 |
| - serializedValue = Graph.serializeNumber(entity[key]); |
147 |
| - } |
148 |
| - |
149 |
| - if (serializedValue !== existingValue) { |
150 |
| - values.push({ property: propertyId, value: serializedValue }); |
151 |
| - } |
152 |
| - } |
153 |
| - |
154 |
| - // TODO: handle added or removed relations |
155 |
| - // TODO: handle updated relations |
156 |
| - // TODO: handle added or removed types |
157 |
| - if (values.length > 0) { |
158 |
| - const { ops: updateEntityOps } = Graph.updateEntity({ id: entity.id, values }); |
159 |
| - ops.push(...updateEntityOps); |
160 |
| - } |
| 118 | + // TODO: handle added or removed relations |
| 119 | + // TODO: handle updated relations |
| 120 | + // TODO: handle added or removed types |
| 121 | + if (values.length > 0) { |
| 122 | + const { ops: updateEntityOps } = Graph.updateEntity({ id: entity.id, values }); |
| 123 | + ops.push(...updateEntityOps); |
161 | 124 | }
|
162 | 125 |
|
163 | 126 | return { ops };
|
|
0 commit comments