@@ -26,12 +26,13 @@ import { z } from "zod";
26
26
import { CallAquaFunctionConfig } from "./compilerSupport/callFunction.js" ;
27
27
import {
28
28
aqua2js ,
29
- SchemaValidationError ,
30
29
js2aqua ,
30
+ SchemaValidationError ,
31
31
wrapJsFunction ,
32
32
} from "./compilerSupport/conversions.js" ;
33
33
import { ServiceImpl , UserServiceImpl } from "./compilerSupport/types.js" ;
34
34
import { FluencePeer } from "./jsPeer/FluencePeer.js" ;
35
+ import { zip } from "./util/utils.js" ;
35
36
36
37
import { callAquaFunction , Fluence , registerService } from "./index.js" ;
37
38
@@ -74,59 +75,57 @@ export const v5_callFunction = async (
74
75
) ;
75
76
}
76
77
77
- const argNames = Object . keys (
78
- def . arrow . domain . tag === "nil" ? [ ] : def . arrow . domain . fields ,
79
- ) ;
78
+ const schemaFunctionArgs : Record < string , FunctionArg > =
79
+ def . arrow . domain . tag === "nil" ? { } : def . arrow . domain . fields ;
80
80
81
- const schemaArgCount = argNames . length ;
81
+ const schemaFunctionArgEntries = Object . entries ( schemaFunctionArgs ) ;
82
82
83
- type FunctionArg = SimpleTypes | ArrowWithoutCallbacks ;
83
+ const schemaArgCount = schemaFunctionArgEntries . length ;
84
84
85
- const schemaFunctionArgs : Record < string , FunctionArg > =
86
- def . arrow . domain . tag === "nil" ? { } : def . arrow . domain . fields ;
85
+ type FunctionArg = SimpleTypes | ArrowWithoutCallbacks ;
87
86
88
87
// if there are more args than expected in schema (schemaArgCount) then last arg is config
89
88
const config = schemaArgCount < rest . length ? rest . pop ( ) : undefined ;
90
89
91
90
validateAquaConfig ( config ) ;
92
91
93
92
const callArgs = Object . fromEntries < JSONValue | ServiceImpl [ string ] > (
94
- rest . slice ( 0 , schemaArgCount ) . map ( ( arg , i ) => {
95
- const argName = argNames [ i ] ;
96
- const argSchema = schemaFunctionArgs [ argName ] ;
93
+ zip ( rest . slice ( 0 , schemaArgCount ) , schemaFunctionArgEntries ) . map (
94
+ ( [ arg , [ argName , argType ] ] ) => {
95
+ if ( argType . tag === "arrow" ) {
96
+ if ( typeof arg !== "function" ) {
97
+ throw new SchemaValidationError (
98
+ [ argName ] ,
99
+ argType ,
100
+ "function" ,
101
+ arg ,
102
+ ) ;
103
+ }
104
+
105
+ return [ argName , wrapJsFunction ( arg , argType ) ] ;
106
+ }
97
107
98
- if ( argSchema . tag === "arrow" ) {
99
- if ( typeof arg !== "function" ) {
108
+ if ( typeof arg === "function" ) {
100
109
throw new SchemaValidationError (
101
110
[ argName ] ,
102
- argSchema ,
103
- "function" ,
111
+ argType ,
112
+ "non- function value " ,
104
113
arg ,
105
114
) ;
106
115
}
107
116
108
- return [ argName , wrapJsFunction ( arg , argSchema ) ] ;
109
- }
110
-
111
- if ( typeof arg === "function" ) {
112
- throw new SchemaValidationError (
113
- [ argName ] ,
114
- argSchema ,
115
- "non-function value" ,
116
- arg ,
117
- ) ;
118
- }
119
-
120
- return [ argName , js2aqua ( arg , argSchema , { path : [ def . functionName ] } ) ] ;
121
- } ) ,
117
+ return [ argName , js2aqua ( arg , argType , { path : [ def . functionName ] } ) ] ;
118
+ } ,
119
+ ) ,
122
120
) ;
123
121
124
122
const returnTypeVoid =
125
123
def . arrow . codomain . tag === "nil" || def . arrow . codomain . items . length === 0 ;
126
124
127
125
const returnSchema =
128
126
def . arrow . codomain . tag === "unlabeledProduct" &&
129
- def . arrow . codomain . items . length === 1
127
+ def . arrow . codomain . items . length === 1 &&
128
+ "0" in def . arrow . codomain . items
130
129
? def . arrow . codomain . items [ 0 ]
131
130
: def . arrow . codomain ;
132
131
@@ -145,7 +144,7 @@ export const v5_callFunction = async (
145
144
} ;
146
145
147
146
const getDefaultPeer = ( ) : FluencePeer => {
148
- if ( Fluence . defaultClient == null ) {
147
+ if ( Fluence . defaultClient === undefined ) {
149
148
throw new Error (
150
149
"Could not register Aqua service because the client is not initialized. Did you forget to call Fluence.connect()?" ,
151
150
) ;
@@ -155,7 +154,7 @@ const getDefaultPeer = (): FluencePeer => {
155
154
} ;
156
155
157
156
const getDefaultServiceId = ( def : ServiceDef ) => {
158
- if ( def . defaultServiceId == null ) {
157
+ if ( def . defaultServiceId === undefined ) {
159
158
throw new Error ( "Service ID is not provided" ) ;
160
159
}
161
160
@@ -204,13 +203,18 @@ export const v5_registerService = (
204
203
205
204
// Wrapping service functions, selecting only those listed in schema, to convert their args js -> aqua and backwards
206
205
const wrappedServiceImpl = Object . fromEntries (
207
- Object . keys ( serviceSchema ) . map ( ( schemaKey ) => {
206
+ Object . entries ( serviceSchema ) . map ( ( [ schemaKey , schemaValue ] ) => {
207
+ const serviceImplValue = serviceImpl [ schemaKey ] ;
208
+
209
+ if ( serviceImplValue === undefined ) {
210
+ throw new Error (
211
+ `Service function ${ schemaKey } listed in Aqua schema but wasn't provided in schema implementation object or class instance. Check that your Aqua service definition matches passed service implementation` ,
212
+ ) ;
213
+ }
214
+
208
215
return [
209
216
schemaKey ,
210
- wrapJsFunction (
211
- serviceImpl [ schemaKey ] . bind ( serviceImpl ) ,
212
- serviceSchema [ schemaKey ] ,
213
- ) ,
217
+ wrapJsFunction ( serviceImplValue . bind ( serviceImpl ) , schemaValue ) ,
214
218
] as const ;
215
219
} ) ,
216
220
) ;
0 commit comments