@sentio/sdk 2.39.4-rc.7 → 2.39.4-rc.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/lib/store/codegen.d.ts +0 -2
  2. package/lib/store/codegen.d.ts.map +1 -1
  3. package/lib/store/codegen.js +137 -170
  4. package/lib/store/codegen.js.map +1 -1
  5. package/lib/store/convert.d.ts +9 -9
  6. package/lib/store/convert.d.ts.map +1 -1
  7. package/lib/store/convert.js +64 -27
  8. package/lib/store/convert.js.map +1 -1
  9. package/lib/store/decorators.d.ts +24 -7
  10. package/lib/store/decorators.d.ts.map +1 -1
  11. package/lib/store/decorators.js +160 -16
  12. package/lib/store/decorators.js.map +1 -1
  13. package/lib/store/index.d.ts +0 -1
  14. package/lib/store/index.d.ts.map +1 -1
  15. package/lib/store/index.js +0 -1
  16. package/lib/store/index.js.map +1 -1
  17. package/lib/store/schema.d.ts.map +1 -1
  18. package/lib/store/schema.js +38 -0
  19. package/lib/store/schema.js.map +1 -1
  20. package/lib/store/store.d.ts +10 -4
  21. package/lib/store/store.d.ts.map +1 -1
  22. package/lib/store/store.js +41 -19
  23. package/lib/store/store.js.map +1 -1
  24. package/lib/store/types.d.ts +21 -2
  25. package/lib/store/types.d.ts.map +1 -1
  26. package/lib/store/types.js +14 -1
  27. package/lib/store/types.js.map +1 -1
  28. package/package.json +4 -3
  29. package/src/store/codegen.ts +171 -196
  30. package/src/store/convert.ts +73 -28
  31. package/src/store/decorators.ts +185 -16
  32. package/src/store/index.ts +0 -1
  33. package/src/store/schema.ts +40 -0
  34. package/src/store/store.ts +55 -24
  35. package/src/store/types.ts +24 -2
  36. package/lib/store/entity.d.ts +0 -23
  37. package/lib/store/entity.d.ts.map +0 -1
  38. package/lib/store/entity.js +0 -70
  39. package/lib/store/entity.js.map +0 -1
  40. package/src/store/entity.ts +0 -84
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/store/types.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/store/types.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,MAAM;IAEI;IADZ,IAAI,CAAI;IACjB,YAAqB,MAAS;QAAT,WAAM,GAAN,MAAM,CAAG;IAAG,CAAC;CACnC;AAID,MAAM,UAAU,MAAM,CAAyB,MAAS;IACtD,OAAO,IAAI,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,CAAA;AACnC,CAAC;AAMD,MAAM,YAAY,GAAG,IAAI,MAAM,CAAe,IAAI,CAAC,CAAA;AAEnD,MAAM,EAAE,GAAG,MAAM,CAAC;IAChB,IAAI,EAAE,YAAY;CACnB,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentio/sdk",
3
- "version": "2.39.4-rc.7",
3
+ "version": "2.39.4-rc.9",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -77,13 +77,14 @@
77
77
  "prettier": "^3.2.4",
78
78
  "prettier2": "npm:prettier@2.8.8",
79
79
  "radash": "^12.0.0",
80
+ "reflect-metadata": "^0.2.2",
80
81
  "superstruct_solana": "npm:superstruct@^0.14.2",
81
82
  "typechain": "^8.3.2",
82
83
  "typedoc": "^0.25.7",
83
84
  "utility-types": "^3.11.0",
84
85
  "yaml": "^2.3.4",
85
- "@sentio/protos": "2.39.4-rc.7",
86
- "@sentio/runtime": "^2.39.4-rc.7"
86
+ "@sentio/protos": "2.39.4-rc.9",
87
+ "@sentio/runtime": "^2.39.4-rc.9"
87
88
  },
88
89
  "peerDependencies": {
89
90
  "tsup": "npm:@sentio/tsup@^6.7.2"
@@ -1,7 +1,5 @@
1
1
  import {
2
- DirectiveNode,
3
2
  GraphQLEnumType,
4
- GraphQLField,
5
3
  GraphQLInterfaceType,
6
4
  GraphQLList,
7
5
  GraphQLNonNull,
@@ -9,10 +7,9 @@ import {
9
7
  GraphQLOutputType,
10
8
  GraphQLScalarType,
11
9
  GraphQLSchema,
12
- Kind,
13
- isObjectType,
14
- isInterfaceType,
15
- isListType
10
+ isEnumType,
11
+ isListType,
12
+ isNonNullType
16
13
  } from 'graphql'
17
14
  import * as fs from 'node:fs'
18
15
  import path from 'path'
@@ -20,6 +17,35 @@ import mkdirp from 'mkdirp'
20
17
  import { schemaFromFile } from './schema.js'
21
18
  import chalk from 'chalk'
22
19
 
20
+ interface Import {
21
+ module: string
22
+ types: string[]
23
+ importType?: boolean
24
+ }
25
+
26
+ interface Field {
27
+ name: string
28
+ type: string
29
+ annotations: string[]
30
+ }
31
+
32
+ interface Class {
33
+ name: string
34
+ fields: Field[]
35
+ annotations: string[]
36
+ interfaces: string[]
37
+ }
38
+
39
+ interface Interface {
40
+ name: string
41
+ fields: Field[]
42
+ }
43
+
44
+ interface Enum {
45
+ name: string
46
+ values: string[]
47
+ }
48
+
23
49
  export async function codegen(srcDir: string, outputDir: string) {
24
50
  for (const file of fs.readdirSync(srcDir)) {
25
51
  const f = path.join(srcDir, file)
@@ -33,27 +59,78 @@ export async function codegen(srcDir: string, outputDir: string) {
33
59
  }
34
60
  }
35
61
 
62
+ function addTypeAnnotations(ty: GraphQLOutputType, annotations: string[]) {
63
+ if (isNonNullType(ty)) {
64
+ annotations.push('@Required')
65
+ addTypeAnnotations(ty.ofType, annotations)
66
+ return
67
+ }
68
+
69
+ if (isRelationType(ty)) {
70
+ if (isListType(ty)) {
71
+ annotations.push(`@Many("${ty.ofType}")`)
72
+ } else {
73
+ annotations.push(`@One("${ty}")`)
74
+ }
75
+ } else if (isEnumType(ty)) {
76
+ annotations.push(`@Column("String${isNonNullType(ty) ? '!' : ''}")`)
77
+ } else {
78
+ if (isListType(ty)) {
79
+ if (isListType(ty.ofType)) {
80
+ annotations.push(`@ListColumn()`)
81
+ addTypeAnnotations(ty.ofType, annotations)
82
+ } else {
83
+ annotations.push(`@ListColumn("${ty.ofType}")`)
84
+ }
85
+ } else {
86
+ annotations.push(`@Column("${ty}")`)
87
+ }
88
+ }
89
+ }
90
+
36
91
  async function codegenInternal(schema: GraphQLSchema, source: string, target: string) {
37
- const results: string[] = [
38
- '/* Autogenerated file. Do not edit manually. */\n',
39
- '/* tslint:disable */',
40
- '/* eslint-disable */',
41
- "import { entity, derivedFrom, Timestamp, Int, Float, String, Bytes, Boolean, ID, Entity, Store } from '@sentio/sdk/store'",
42
- `import { BigDecimalConverter, BigIntConverter, IntConverter, StringConverter, IDConverter, BooleanConverter, BytesConverter, TimestampConverter, FloatConverter, StructConverter, required_, array_, enumerate_, objectId_ } from '@sentio/sdk/store'`,
43
- `import { DatabaseSchema, BigDecimal } from "@sentio/sdk"`,
44
- `type BigInt = bigint`
92
+ const imports: Import[] = [
93
+ {
94
+ module: '@sentio/sdk/store',
95
+ types: ['String', 'Int', 'BigInt', 'Float', 'ID', 'Bytes', 'Timestamp', 'Boolean'],
96
+ importType: true
97
+ },
98
+ {
99
+ module: '@sentio/sdk/store',
100
+ types: ['Entity', 'Required', 'One', 'Many', 'Column', 'ListColumn']
101
+ },
102
+ {
103
+ module: '@sentio/bigdecimal',
104
+ types: ['BigDecimal']
105
+ },
106
+ {
107
+ module: '@sentio/sdk',
108
+ types: ['DatabaseSchema']
109
+ }
45
110
  ]
46
- const entities: string[] = []
111
+ const enumns: Enum[] = []
112
+ const interfaces: Interface[] = []
113
+ const classes: Class[] = []
47
114
 
48
115
  for (const t of Object.values(schema.getTypeMap())) {
49
116
  if (t.name.startsWith('__')) {
50
117
  continue
51
118
  }
52
119
  if (t instanceof GraphQLEnumType) {
53
- results.push(genEnum(t))
120
+ enumns.push({
121
+ name: t.name,
122
+ values: t.getValues().map((v) => v.value)
123
+ })
54
124
  }
55
125
  if (t instanceof GraphQLInterfaceType) {
56
- results.push(genInterface(t))
126
+ interfaces.push({
127
+ name: t.name,
128
+ fields: Object.values(t.getFields()).map((f) => ({
129
+ name: f.name,
130
+ type: genType(f.type),
131
+ annotations: []
132
+ }))
133
+ })
57
134
  }
58
135
  }
59
136
  for (const t of Object.values(schema.getTypeMap())) {
@@ -62,20 +139,84 @@ async function codegenInternal(schema: GraphQLSchema, source: string, target: st
62
139
  }
63
140
 
64
141
  if (t instanceof GraphQLObjectType) {
65
- const entityContent = genEntity(t)
66
- results.push(entityContent)
67
- entities.push(t.name)
142
+ const fields: Field[] = []
143
+ for (const f of Object.values(t.getFields())) {
144
+ const type = genType(f.type)
145
+ const annotations: string[] = []
146
+ addTypeAnnotations(f.type, annotations)
147
+ if (isRelationType(f.type)) {
148
+ fields.push({
149
+ name: f.name,
150
+ type: `Promise<${type}>`,
151
+ annotations
152
+ })
153
+ const isMany = type.startsWith('Array')
154
+ fields.push({
155
+ name: f.name + 'ID' + (isMany ? 's' : ''),
156
+ type: isMany ? `Array<ID | undefined>` : `ID`,
157
+ annotations: []
158
+ })
159
+ } else {
160
+ fields.push({
161
+ name: f.name,
162
+ type: type,
163
+ annotations
164
+ })
165
+ }
166
+ }
167
+ classes.push({
168
+ name: t.name,
169
+ fields,
170
+ annotations: [`@Entity("${t.name}")`],
171
+ interfaces: t.getInterfaces().map((i) => i.name)
172
+ })
68
173
  }
69
174
  }
70
175
 
176
+ const template = `
177
+ /* Autogenerated file. Do not edit manually. */
178
+ /* tslint:disable */
179
+ /* eslint-disable */
180
+ ${imports.map((i) => `import ${i.importType ? 'type ' : ''}{ ${i.types.join(', ')} } from '${i.module}'`).join('\n')}
181
+
182
+ ${enumns
183
+ .map(
184
+ (e) => `export enum ${e.name} {
185
+ ${e.values.map((v) => `${v} = "${v}"`).join(', ')}
186
+ }`
187
+ )
188
+ .join('\n')}
189
+
190
+ ${interfaces
191
+ .map(
192
+ (i) => `export interface ${i.name} {
193
+ ${i.fields.map((f) => `\t${f.name}: ${f.type}`).join('\n')}
194
+ }`
195
+ )
196
+ .join('\n')}
197
+
198
+ ${classes
199
+ .map(
200
+ (c) => `
201
+ ${c.annotations.join('\n')}
202
+ export class ${c.name} ${c.interfaces.length > 0 ? `implements ${c.interfaces.join(', ')}` : ''} {
203
+ ${c.fields.map((f) => `${f.annotations.map((a) => `\n\t${a}`).join('')}\n\t${f.name}: ${f.type}`).join('\n')}
204
+
205
+ constructor(data: Partial<${c.name}>) {}
206
+
207
+ }`
208
+ )
209
+ .join('\n')}
210
+ `
211
+
71
212
  const contents =
72
- results.join('\n') +
213
+ template +
73
214
  `\n
74
215
  const source = \`${source.replaceAll('`', '`')}\`
75
216
  DatabaseSchema.register({
76
217
  source,
77
218
  entities: {
78
- ${entities.map((e) => `"${e}": ${e}`).join(',\n\t\t')}
219
+ ${classes.map((e) => `"${e.name}": ${e.name}`).join(',\n\t\t')}
79
220
  }
80
221
  })
81
222
  `
@@ -84,196 +225,30 @@ DatabaseSchema.register({
84
225
  fs.writeFileSync(target, contents)
85
226
  }
86
227
 
87
- const JsTypes: Record<string, string> = {
88
- ID: 'string',
89
- String: 'string',
90
- Int: 'number',
91
- Float: 'number',
92
- Boolean: 'boolean',
93
- BigInt: 'bigint',
94
- BigDecimal: 'BigDecimal',
95
- DateTime: 'Date',
96
- Json: 'any',
97
- Bytes: 'Uint8Array'
98
- }
99
- const graphqlTypes = Object.entries(JsTypes).reduce(
100
- (acc, [k, v]) => {
101
- acc[v] = k
102
- return acc
103
- },
104
- {} as Record<string, string>
105
- )
106
-
107
228
  function genType(type: GraphQLOutputType, required?: boolean): string {
108
229
  if (type instanceof GraphQLNonNull) {
109
230
  return genType(type.ofType, true)
110
231
  } else if (type instanceof GraphQLScalarType) {
111
232
  return required ? type.name : `${type.name} | undefined`
112
233
  } else if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType) {
113
- return type.name
234
+ return required ? type.name : `${type.name} | undefined`
114
235
  } else if (type instanceof GraphQLList) {
115
236
  return `Array<${genType(type.ofType)}>`
116
237
  } else if (type instanceof GraphQLEnumType) {
117
- return type.name
238
+ return required ? type.name : `${type.name} | undefined`
118
239
  } else {
119
240
  throw new Error('Unsupported type: ' + type)
120
241
  }
121
242
  }
122
243
 
123
- function isObject(type: GraphQLOutputType) {
244
+ function isRelationType(type: GraphQLOutputType): boolean {
124
245
  if (type instanceof GraphQLNonNull) {
125
- return isObject(type.ofType)
126
- } else if (type instanceof GraphQLList) {
127
- return isObject(type.ofType)
128
- }
129
- return isObjectType(type) || isInterfaceType(type)
130
- }
131
-
132
- function isList(type: GraphQLOutputType) {
133
- if (type instanceof GraphQLNonNull) {
134
- return isListType(type.ofType)
135
- } else {
136
- return isListType(type)
137
- }
138
- }
139
-
140
- function getElementType(type: GraphQLOutputType) {
141
- if (type instanceof GraphQLNonNull) {
142
- return getElementType(type.ofType)
246
+ return isRelationType(type.ofType)
247
+ } else if (type instanceof GraphQLObjectType || type instanceof GraphQLInterfaceType) {
248
+ return true
143
249
  } else if (type instanceof GraphQLList) {
144
- return type.ofType
145
- }
146
- return type
147
- }
148
-
149
- const getConverter = (t: GraphQLOutputType): string => {
150
- if (t instanceof GraphQLNonNull) {
151
- return `required_(${getConverter(t.ofType)})`
152
- }
153
- if (t instanceof GraphQLList) {
154
- return `array_(${getConverter(t.ofType)})`
155
- }
156
- if (t instanceof GraphQLEnumType) {
157
- return `enumerate_<${t.name}>(${t.name})`
158
- }
159
- if (isObject(t)) {
160
- return `objectId_<${genType(getElementType(t))}>()`
161
- }
162
- return `${t.name}Converter`
163
- }
164
-
165
- function genField(field: GraphQLField<any, any>) {
166
- const isNonNull = field.type instanceof GraphQLNonNull
167
- const directives = field.astNode?.directives?.map((d) => '\t' + directive2decorator(d) + '\n') || []
168
-
169
- const type = genType(field.type)
170
-
171
- if (isObject(field.type)) {
172
- const t = getElementType(field.type)
173
- const typeAsArg = isInterfaceType(t) ? `"${t}"` : genType(t)
174
-
175
- if (isList(field.type)) {
176
- const required = (field.type as GraphQLList<any>).ofType instanceof GraphQLNonNull
177
- const converter = required ? `array_(required_(IDConverter))` : `array_(IDConverter)`
178
- const returnType = required ? `ID[]` : `Array<ID | undefined>`
179
- return `${directives.join()}\tget ${field.name}(): Promise<${genType(t)}[]> { return this.getFieldObjectArray(${typeAsArg}, "${field.name}") as Promise<${genType(t)}[]> }
180
- set ${field.name}(value: ${type} | ID[]) { this.setObject("${field.name}", value) }
181
- get ${field.name}Ids(): ${returnType} { return this.get("${field.name}", ${converter}) }`
182
- }
183
-
184
- return `${directives.join()}\tget ${field.name}(): Promise<${genType(t)} | undefined> { return this.getObject(${typeAsArg},"${field.name}") as Promise<${genType(t)} | undefined> }
185
- set ${field.name}(value: ${type} | ID) { this.set("${field.name}", value, objectId_<${type}>()) }
186
- get ${field.name}Id(): ID | undefined { return this.get("${field.name}", IDConverter) }`
187
- }
188
-
189
- return `${directives.join()}\tget ${field.name}(): ${type} { return this.get("${field.name}", ${getConverter(field.type)}) }
190
- set ${field.name}(value: ${type}) { this.set("${field.name}", value, ${getConverter(field.type)}) }`
191
- }
192
-
193
- function genDataType(t: GraphQLObjectType<any, any>) {
194
- let output = `type ${t.name}Data = `
195
- const relationsFields = Object.values(t.getFields()).filter((f) => isObject(f.type))
196
- if (relationsFields.length > 0) {
197
- output += `Omit<${t.name}, ${relationsFields.map((f) => `"${f.name}"`).join(' | ')}>`
198
-
199
- output +=
200
- ' & {' +
201
- relationsFields
202
- .map((f) => {
203
- const type = genType(getElementType(f.type))
204
- return `${f.name}?: ${isList(f.type) ? `Array<ID|${type}>` : `ID | ${type}`}`
205
- })
206
- .join(', ') +
207
- '}'
250
+ return isRelationType(type.ofType)
208
251
  } else {
209
- output += `${t.name}`
210
- }
211
- return output
212
- }
213
-
214
- function genEntity(t: GraphQLObjectType<any, any>) {
215
- const decorators = t.astNode?.directives?.filter((d) => d.name.value != 'entity').map(directive2decorator) || []
216
-
217
- let impls = ''
218
- if (t.getInterfaces().length > 0) {
219
- impls +=
220
- ' implements ' +
221
- t
222
- .getInterfaces()
223
- .map((i) => i.name)
224
- .join(', ')
225
- }
226
-
227
- return `
228
- ${genDataType(t)}
229
- ${decorators.join('\n')}
230
- @entity("${t.name}")
231
- export class ${t.name} extends Entity${impls} {
232
- ${genConverters(t)}
233
- constructor(data: Partial<${t.name}Data>) {
234
- super(${t.name}.entityConverter.from(data))
235
- }
236
- ${Object.values(t.getFields()).map(genField).join('\n')}
237
- }`
238
- }
239
-
240
- function genConverters(t: GraphQLObjectType<any, any>) {
241
- const fields = Object.values(t.getFields())
242
- const converters = fields.map((f) => {
243
- const type = genType(f.type)
244
- const converter = getConverter(f.type)
245
- return `\t\t${f.name}: ${converter},`
246
- })
247
- return `static entityConverter = new StructConverter({\n ${converters.join('\n')} \n})`
248
- }
249
-
250
- function genInterface(t: GraphQLInterfaceType) {
251
- return `
252
- export interface ${t.name} {
253
- ${Object.values(t.getFields())
254
- .map((f) => `\t${f.name}: ${genType(f.type)}`)
255
- .join('\n')}
256
- }`
257
- }
258
-
259
- export function directive2decorator(directive: DirectiveNode) {
260
- let s = `@${directive.name.value}`
261
- if (directive.arguments?.length) {
262
- s += `(${directive.arguments
263
- ?.map((arg) => {
264
- return arg.value.kind === Kind.STRING ? `"${arg.value.value}"` : `${arg.value}`
265
- })
266
- .join(', ')})`
252
+ return false
267
253
  }
268
- return s
269
- }
270
-
271
- function genEnum(t: GraphQLEnumType) {
272
- return `
273
- export enum ${t.name} {
274
- ${t
275
- .getValues()
276
- .map((v) => `\t${v.name} = "${v.value}"`)
277
- .join(', ')}
278
- }`
279
254
  }
@@ -1,27 +1,35 @@
1
- import { RichStruct, RichValue, RichValue_NullValue } from '@sentio/protos'
2
- import { String, Int, Float, ID, Bytes, Timestamp, Boolean } from './types.js'
3
- import { Entity } from './entity.js'
1
+ import { RichValue, RichValue_NullValue } from '@sentio/protos'
2
+ import type { String, Int, Float, ID, Bytes, Timestamp, Boolean } from './types.js'
4
3
  import { BigDecimal } from '@sentio/bigdecimal'
5
4
 
6
5
  export interface ValueConverter<T> {
7
6
  from: (value: T) => RichValue
8
7
  to: (value: RichValue) => T
8
+ required?: boolean
9
+ isArray?: boolean
10
+ isRelation?: boolean
11
+ relationName?: string
9
12
  }
10
13
 
14
+ export const ValueRequiredError = new Error('Value is required but received null or undefined')
15
+
11
16
  export function required_<T>(converter: ValueConverter<T | undefined>): ValueConverter<T> {
17
+ const { from, to, ...rest } = converter
12
18
  return {
13
19
  from: (value: T | undefined) => {
14
20
  if (value == null) {
15
- throw new Error('Value is required but received null or undefined')
21
+ throw ValueRequiredError
16
22
  }
17
- return converter.from(value)
23
+ return from(value)
18
24
  },
19
25
  to: (value: RichValue) => {
20
26
  if (value == null || value.nullValue) {
21
- throw new Error('Value is required but received null')
27
+ throw ValueRequiredError
22
28
  }
23
- return converter.to(value)!
24
- }
29
+ return to(value)!
30
+ },
31
+ ...rest,
32
+ required: true
25
33
  }
26
34
  }
27
35
 
@@ -36,7 +44,10 @@ export function array_<T>(converter: ValueConverter<T>): ValueConverter<T[]> {
36
44
  },
37
45
  to: (value: RichValue) => {
38
46
  return value.listValue?.values.map(converter.to) || []
39
- }
47
+ },
48
+ isArray: true,
49
+ isRelation: converter.isRelation,
50
+ relationName: converter.relationName
40
51
  }
41
52
  }
42
53
 
@@ -58,7 +69,7 @@ export function enumerate_<T extends string | number>(values: Record<T, string>)
58
69
  }
59
70
  }
60
71
 
61
- export function objectId_<T>(): ValueConverter<T | ID> {
72
+ export function objectId_<T>(entityName: string): ValueConverter<T | ID> {
62
73
  return {
63
74
  from: (value: T | ID) => {
64
75
  if (typeof value == 'string') {
@@ -66,9 +77,16 @@ export function objectId_<T>(): ValueConverter<T | ID> {
66
77
  stringValue: value
67
78
  }
68
79
  }
69
- if (value instanceof Entity) {
80
+ if (value instanceof Uint8Array) {
81
+ return {
82
+ stringValue: `0x${Buffer.from(value).toString('hex')}`
83
+ }
84
+ }
85
+
86
+ if (typeof value == 'object') {
87
+ const entity = value as any
70
88
  return {
71
- stringValue: value.id
89
+ stringValue: entity.id.toString()
72
90
  }
73
91
  }
74
92
  return {
@@ -77,7 +95,9 @@ export function objectId_<T>(): ValueConverter<T | ID> {
77
95
  },
78
96
  to(v) {
79
97
  return v.stringValue as T | ID
80
- }
98
+ },
99
+ isRelation: true,
100
+ relationName: entityName
81
101
  }
82
102
  }
83
103
 
@@ -178,7 +198,33 @@ export const BytesConverter: ValueConverter<Bytes | undefined> = {
178
198
  }
179
199
  }
180
200
 
181
- export const IDConverter: ValueConverter<ID | undefined> = StringConverter
201
+ export const IDConverter: ValueConverter<ID | undefined> = {
202
+ from(value: ID | undefined): RichValue {
203
+ if (typeof value == 'string') {
204
+ return {
205
+ stringValue: value
206
+ }
207
+ }
208
+ if (value instanceof Uint8Array) {
209
+ return {
210
+ stringValue: `0x${Buffer.from(value).toString('hex')}`
211
+ }
212
+ }
213
+ return {
214
+ nullValue: RichValue_NullValue.NULL_VALUE
215
+ }
216
+ },
217
+ to(value: RichValue): ID | undefined {
218
+ if (value.stringValue) {
219
+ return value.stringValue as ID
220
+ }
221
+ if (value.bytesValue) {
222
+ const v = `0x${Buffer.from(value.bytesValue).toString('hex')}`
223
+ return v as ID
224
+ }
225
+ return undefined
226
+ }
227
+ }
182
228
 
183
229
  export const BigDecimalConverter: ValueConverter<BigDecimal | undefined> = {
184
230
  from: (value?: BigDecimal): RichValue => {
@@ -236,20 +282,6 @@ export const BigIntConverter: ValueConverter<bigint | undefined> = {
236
282
  }
237
283
  }
238
284
 
239
- export class StructConverter<T extends Entity> {
240
- constructor(private converters: Record<string, ValueConverter<any>>) {}
241
-
242
- from(data: any): RichStruct {
243
- const fields: Record<string, RichValue> = {}
244
- for (const [field, value] of Object.entries(data)) {
245
- if (this.converters[field] !== undefined) {
246
- fields[field] = this.converters[field].from(value)
247
- }
248
- }
249
- return { fields }
250
- }
251
- }
252
-
253
285
  export function bytesToBigInt(bytes: Uint8Array) {
254
286
  let intValue = BigInt(0)
255
287
  for (let i = 0; i < bytes.length; i++) {
@@ -274,3 +306,16 @@ export function toBigInteger(a: bigint) {
274
306
  data: new Uint8Array(buffer)
275
307
  }
276
308
  }
309
+
310
+ export const TypeConverters: Record<string, ValueConverter<any>> = {
311
+ BigDecimal: BigDecimalConverter,
312
+ BigInt: BigIntConverter,
313
+ String: StringConverter,
314
+ Boolean: BooleanConverter,
315
+ Uint8Array: BytesConverter,
316
+ ID: IDConverter,
317
+ Bytes: BytesConverter,
318
+ Int: IntConverter,
319
+ Float: FloatConverter,
320
+ Timestamp: TimestampConverter
321
+ }