@@ -12,7 +12,7 @@ import { RedisValue } from "./command";
12
12
export abstract class RedisTransform < T extends TSchema = TSchema > {
13
13
readonly schema : T ;
14
14
constructor ( schema : T ) {
15
- this . schema = createRedisTransform ( schema , this . constructor . name ) as any ;
15
+ this . schema = wrapSchemaForRedis ( schema , this . constructor . name ) as any ;
16
16
}
17
17
18
18
/**
@@ -34,37 +34,49 @@ export abstract class RedisTransform<T extends TSchema = TSchema> {
34
34
}
35
35
}
36
36
37
+ const wrappedSchemas = new WeakSet < TSchema > ( ) ;
38
+
37
39
/**
38
40
* Wrap the JavaScript types with Redis-targeted transform types.
39
41
*
40
42
* Note: The encode/decode methods are flipped, because TypeBox expects
41
43
* transform types to operate on input values, not output values.
42
44
*/
43
- function createRedisTransform ( schema : TSchema , instanceType ?: string ) {
45
+ function wrapSchemaForRedis ( schema : TSchema , instanceType ?: string ) {
46
+ if ( wrappedSchemas . has ( schema ) ) {
47
+ return schema ;
48
+ }
49
+
44
50
if ( instanceType === "RedisHash" ) {
45
51
if ( schema . type !== "object" || ! schema . properties ) {
46
52
throw new Error ( "RedisHash must have an object schema with properties" ) ;
47
53
}
48
54
const newSchema = { ...schema . properties } ;
49
55
for ( const field in schema . properties ) {
50
- newSchema [ field ] = createRedisTransform ( schema . properties [ field ] ) as any ;
56
+ newSchema [ field ] = wrapSchemaForRedis ( schema . properties [ field ] ) as any ;
51
57
}
52
- return Type . Object ( newSchema ) ;
53
- }
54
- if ( schema . type !== "string" && schema . type !== "uint8array" ) {
58
+ schema = Type . Object ( newSchema ) ;
59
+ } else if ( schema . type !== "string" && schema . type !== "uint8array" ) {
55
60
if ( schema . type === "number" ) {
56
- return Transform ( schema as TNumber )
61
+ schema = Transform ( schema as TNumber )
57
62
. Decode ( ( value ) => String ( value ) )
58
63
. Encode ( ( value ) => Number ( value ) ) ;
59
- }
60
- if ( schema . type === "boolean" ) {
61
- return Transform ( schema as TBoolean )
64
+ } else if ( schema . type === "boolean" ) {
65
+ schema = Transform ( schema as TBoolean )
62
66
. Decode ( ( value ) => ( value ? "1" : "0" ) )
63
- . Encode ( ( value ) => value === "1" ) ;
67
+ . Encode ( ( value ) => {
68
+ console . trace ( "TBoolean.encode:" , value ) ;
69
+ if ( value === "1" ) return true ;
70
+ if ( value === "0" ) return false ;
71
+ throw new Error ( "Invalid boolean value" ) ;
72
+ } ) ;
73
+ } else {
74
+ schema = Transform ( schema )
75
+ . Decode ( ( value ) => JSON . stringify ( value ) )
76
+ . Encode ( ( value ) => JSON . parse ( value ) ) ;
64
77
}
65
- return Transform ( schema )
66
- . Decode ( ( value ) => JSON . stringify ( value ) )
67
- . Encode ( ( value ) => JSON . parse ( value ) ) ;
68
78
}
79
+
80
+ wrappedSchemas . add ( schema ) ;
69
81
return schema ;
70
82
}
0 commit comments