11import { FunctionInfo } from './FunctionInfo' ;
2- import { fromRpcHttp , fromTypedData , getNormalizedBindingData , getBindingDefinitions } from './converters' ;
2+ import { fromRpcHttp , fromTypedData , getNormalizedBindingData , getBindingDefinitions , fromRpcTraceContext } from './converters' ;
33import { AzureFunctionsRpcMessages as rpc } from '../azure-functions-language-worker-protobuf/src/rpc' ;
44import { Request , RequestProperties } from './http/Request' ;
55import { Response } from './http/Response' ;
66import LogLevel = rpc . RpcLog . Level ;
77import LogCategory = rpc . RpcLog . RpcLogCategory ;
8- import { Context , ExecutionContext , Logger , BindingDefinition , HttpRequest } from './public/Interfaces'
8+ import { Context , ExecutionContext , Logger , BindingDefinition , HttpRequest , TraceContext } from './public/Interfaces'
99
1010export function CreateContextAndInputs ( info : FunctionInfo , request : rpc . IInvocationRequest , logCallback : LogCallback , callback : ResultCallback ) {
11- let context = new InvocationContext ( info , request , logCallback , callback ) ;
12-
13- let bindings : Dict < any > = { } ;
14- let inputs : InputTypes [ ] = [ ] ;
15- let httpInput : RequestProperties | undefined ;
16- for ( let binding of < rpc . IParameterBinding [ ] > request . inputData ) {
17- if ( binding . data && binding . name ) {
18- let input : InputTypes ;
19- if ( binding . data && binding . data . http ) {
20- input = httpInput = fromRpcHttp ( binding . data . http ) ;
21- } else {
22- input = fromTypedData ( binding . data ) ;
23- }
24- bindings [ binding . name ] = input ;
25- inputs . push ( input ) ;
11+ let context = new InvocationContext ( info , request , logCallback , callback ) ;
12+
13+ let bindings : Dict < any > = { } ;
14+ let inputs : InputTypes [ ] = [ ] ;
15+ let httpInput : RequestProperties | undefined ;
16+ for ( let binding of < rpc . IParameterBinding [ ] > request . inputData ) {
17+ if ( binding . data && binding . name ) {
18+ let input : InputTypes ;
19+ if ( binding . data && binding . data . http ) {
20+ input = httpInput = fromRpcHttp ( binding . data . http ) ;
21+ } else {
22+ input = fromTypedData ( binding . data ) ;
23+ }
24+ bindings [ binding . name ] = input ;
25+ inputs . push ( input ) ;
26+ }
27+ }
28+
29+ context . bindings = bindings ;
30+ if ( httpInput ) {
31+ context . req = new Request ( httpInput ) ;
32+ context . res = new Response ( context . done ) ;
33+ }
34+ return {
35+ context : < Context > context ,
36+ inputs : inputs
2637 }
27- }
28-
29- context . bindings = bindings ;
30- if ( httpInput ) {
31- context . req = new Request ( httpInput ) ;
32- context . res = new Response ( context . done ) ;
33- }
34- return {
35- context : < Context > context ,
36- inputs : inputs
37- }
3838}
3939
4040class InvocationContext implements Context {
41- invocationId : string ;
42- executionContext : ExecutionContext ;
43- bindings : Dict < any > ;
44- bindingData : Dict < any > ;
45- bindingDefinitions : BindingDefinition [ ] ;
46- log : Logger ;
47- req ?: Request ;
48- res ?: Response ;
49- done : DoneCallback ;
50-
51- constructor ( info : FunctionInfo , request : rpc . IInvocationRequest , logCallback : LogCallback , callback : ResultCallback ) {
52- this . invocationId = < string > request . invocationId ;
53- const executionContext = {
54- invocationId : this . invocationId ,
55- functionName : < string > info . name ,
56- functionDirectory : < string > info . directory
57- } ;
58- this . executionContext = executionContext ;
59- this . bindings = { } ;
60- let _done = false ;
61- let _promise = false ;
62-
63- // Log message that is tied to function invocation
64- this . log = Object . assign (
65- < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Information , executionContext , ...args ) ,
66- {
67- error : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Error , executionContext , ...args ) ,
68- warn : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Warning , executionContext , ...args ) ,
69- info : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Information , executionContext , ...args ) ,
70- verbose : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Trace , executionContext , ...args )
71- }
72- ) ;
73-
74- this . bindingData = getNormalizedBindingData ( request ) ;
75- this . bindingDefinitions = getBindingDefinitions ( info ) ;
76-
77- // isPromise is a hidden parameter that we set to true in the event of a returned promise
78- this . done = ( err ?: any , result ?: any , isPromise ?: boolean ) => {
79- _promise = isPromise === true ;
80- if ( _done ) {
81- if ( _promise ) {
82- logCallback ( LogLevel . Error , LogCategory . User , "Error: Choose either to return a promise or call 'done'. Do not use both in your script." ) ;
83- } else {
84- logCallback ( LogLevel . Error , LogCategory . User , "Error: 'done' has already been called. Please check your script for extraneous calls to 'done'." ) ;
85- }
86- return ;
87- }
88- _done = true ;
89-
90- // Allow HTTP response from context.res if HTTP response is not defined from the context.bindings object
91- if ( info . httpOutputName && this . res && this . bindings [ info . httpOutputName ] === undefined ) {
92- this . bindings [ info . httpOutputName ] = this . res ;
93- }
94-
95- callback ( err , {
96- return : result ,
97- bindings : this . bindings
98- } ) ;
99- } ;
100- }
41+ invocationId : string ;
42+ executionContext : ExecutionContext ;
43+ bindings : Dict < any > ;
44+ bindingData : Dict < any > ;
45+ traceContext : TraceContext ;
46+ bindingDefinitions : BindingDefinition [ ] ;
47+ log : Logger ;
48+ req ?: Request ;
49+ res ?: Response ;
50+ done : DoneCallback ;
51+
52+ constructor ( info : FunctionInfo , request : rpc . IInvocationRequest , logCallback : LogCallback , callback : ResultCallback ) {
53+ this . invocationId = < string > request . invocationId ;
54+ this . traceContext = fromRpcTraceContext ( request . traceContext ) ;
55+ const executionContext = {
56+ invocationId : this . invocationId ,
57+ functionName : < string > info . name ,
58+ functionDirectory : < string > info . directory
59+ } ;
60+ this . executionContext = executionContext ;
61+ this . bindings = { } ;
62+ let _done = false ;
63+ let _promise = false ;
64+
65+ // Log message that is tied to function invocation
66+ this . log = Object . assign (
67+ < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Information , executionContext , ...args ) ,
68+ {
69+ error : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Error , executionContext , ...args ) ,
70+ warn : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Warning , executionContext , ...args ) ,
71+ info : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Information , executionContext , ...args ) ,
72+ verbose : < ILog > ( ...args : any [ ] ) => logWithAsyncCheck ( _done , logCallback , LogLevel . Trace , executionContext , ...args )
73+ }
74+ ) ;
75+
76+ this . bindingData = getNormalizedBindingData ( request ) ;
77+ this . bindingDefinitions = getBindingDefinitions ( info ) ;
78+
79+ // isPromise is a hidden parameter that we set to true in the event of a returned promise
80+ this . done = ( err ?: any , result ?: any , isPromise ?: boolean ) => {
81+ _promise = isPromise === true ;
82+ if ( _done ) {
83+ if ( _promise ) {
84+ logCallback ( LogLevel . Error , LogCategory . User , "Error: Choose either to return a promise or call 'done'. Do not use both in your script." ) ;
85+ } else {
86+ logCallback ( LogLevel . Error , LogCategory . User , "Error: 'done' has already been called. Please check your script for extraneous calls to 'done'." ) ;
87+ }
88+ return ;
89+ }
90+ _done = true ;
91+
92+ // Allow HTTP response from context.res if HTTP response is not defined from the context.bindings object
93+ if ( info . httpOutputName && this . res && this . bindings [ info . httpOutputName ] === undefined ) {
94+ this . bindings [ info . httpOutputName ] = this . res ;
95+ }
96+
97+ callback ( err , {
98+ return : result ,
99+ bindings : this . bindings
100+ } ) ;
101+ } ;
102+ }
101103}
102104
103105// Emit warning if trying to log after function execution is done.
104106function logWithAsyncCheck ( done : boolean , log : LogCallback , level : LogLevel , executionContext : ExecutionContext , ...args : any [ ] ) {
105- if ( done ) {
106- let badAsyncMsg = "Warning: Unexpected call to 'log' on the context object after function execution has completed. Please check for asynchronous calls that are not awaited or calls to 'done' made before function execution completes. " ;
107- badAsyncMsg += `Function name: ${ executionContext . functionName } . Invocation Id: ${ executionContext . invocationId } . ` ;
108- badAsyncMsg += `Learn more: https://go.microsoft.com/fwlink/?linkid=2097909 ` ;
109- log ( LogLevel . Warning , LogCategory . System , badAsyncMsg ) ;
110- }
111- return log ( level , LogCategory . User , ...args ) ;
107+ if ( done ) {
108+ let badAsyncMsg = "Warning: Unexpected call to 'log' on the context object after function execution has completed. Please check for asynchronous calls that are not awaited or calls to 'done' made before function execution completes. " ;
109+ badAsyncMsg += `Function name: ${ executionContext . functionName } . Invocation Id: ${ executionContext . invocationId } . ` ;
110+ badAsyncMsg += `Learn more: https://go.microsoft.com/fwlink/?linkid=2097909 ` ;
111+ log ( LogLevel . Warning , LogCategory . System , badAsyncMsg ) ;
112+ }
113+ return log ( level , LogCategory . User , ...args ) ;
112114}
113115
114116export interface InvocationResult {
115- return : any ;
116- bindings : Dict < any > ;
117+ return : any ;
118+ bindings : Dict < any > ;
117119}
118120
119121export type DoneCallback = ( err ?: Error | string , result ?: any ) => void ;
@@ -123,7 +125,7 @@ export type LogCallback = (level: LogLevel, category: rpc.RpcLog.RpcLogCategory,
123125export type ResultCallback = ( err ?: any , result ?: InvocationResult ) => void ;
124126
125127export interface Dict < T > {
126- [ key : string ] : T
128+ [ key : string ] : T
127129}
128130
129131// Allowed input types
0 commit comments