diff --git a/src/Context.ts b/src/Context.ts index a45e11d..457b0e4 100644 --- a/src/Context.ts +++ b/src/Context.ts @@ -10,7 +10,7 @@ import { Logger, TraceContext, } from '@azure/functions'; -import { RpcInvocationRequest, RpcLog, RpcParameterBinding } from '@azure/functions-core'; +import { RpcInvocationRequest, RpcLogLevel, RpcParameterBinding } from '@azure/functions-core'; import { v4 as uuid } from 'uuid'; import { convertKeysToCamelCase, @@ -107,11 +107,11 @@ class InvocationContext implements Context { this.bindings = {}; // Log message that is tied to function invocation - this.log = Object.assign((...args: any[]) => userLogCallback(RpcLog.Level.Information, ...args), { - error: (...args: any[]) => userLogCallback(RpcLog.Level.Error, ...args), - warn: (...args: any[]) => userLogCallback(RpcLog.Level.Warning, ...args), - info: (...args: any[]) => userLogCallback(RpcLog.Level.Information, ...args), - verbose: (...args: any[]) => userLogCallback(RpcLog.Level.Trace, ...args), + this.log = Object.assign((...args: any[]) => userLogCallback('information', ...args), { + error: (...args: any[]) => userLogCallback('error', ...args), + warn: (...args: any[]) => userLogCallback('warning', ...args), + info: (...args: any[]) => userLogCallback('information', ...args), + verbose: (...args: any[]) => userLogCallback('trace', ...args), }); this.bindingData = getNormalizedBindingData(request); @@ -130,7 +130,7 @@ export interface InvocationResult { export type DoneCallback = (err?: unknown, result?: any) => void; -export type UserLogCallback = (level: RpcLog.Level, ...args: any[]) => void; +export type UserLogCallback = (level: RpcLogLevel, ...args: any[]) => void; export interface Dict { [key: string]: T; diff --git a/src/FunctionInfo.ts b/src/FunctionInfo.ts index 6643f1a..6ddfd94 100644 --- a/src/FunctionInfo.ts +++ b/src/FunctionInfo.ts @@ -32,7 +32,7 @@ export class FunctionInfo { // determine output bindings & assign rpc converter (http has quirks) Object.keys(bindings) - .filter((name) => bindings[name].direction !== RpcBindingInfo.Direction.in) + .filter((name) => bindings[name].direction !== 'in') .forEach((name) => { const type = bindings[name].type; if (type && type.toLowerCase() === 'http') { diff --git a/src/InvocationModel.ts b/src/InvocationModel.ts index 4c8fbb0..646a5b3 100644 --- a/src/InvocationModel.ts +++ b/src/InvocationModel.ts @@ -7,7 +7,8 @@ import { CoreInvocationContext, InvocationArguments, RpcInvocationResponse, - RpcLog, + RpcLogCategory, + RpcLogLevel, RpcParameterBinding, } from '@azure/functions-core'; import { format } from 'util'; @@ -35,7 +36,7 @@ export class InvocationModel implements coreTypes.InvocationModel { const { context, inputs } = CreateContextAndInputs( this.#funcInfo, this.#coreCtx.request, - (level: RpcLog.Level, ...args: any[]) => this.#userLog(level, ...args), + (level: RpcLogLevel, ...args: any[]) => this.#userLog(level, ...args), this.#doneEmitter ); return { context, inputs }; @@ -142,23 +143,23 @@ export class InvocationModel implements coreTypes.InvocationModel { return response; } - #log(level: RpcLog.Level, logCategory: RpcLog.RpcLogCategory, ...args: any[]): void { + #log(level: RpcLogLevel, logCategory: RpcLogCategory, ...args: any[]): void { this.#coreCtx.log(level, logCategory, format.apply(null, <[any, any[]]>args)); } - #systemLog(level: RpcLog.Level, ...args: any[]) { - this.#log(level, RpcLog.RpcLogCategory.System, ...args); + #systemLog(level: RpcLogLevel, ...args: any[]) { + this.#log(level, 'system', ...args); } - #userLog(level: RpcLog.Level, ...args: any[]): void { + #userLog(level: RpcLogLevel, ...args: any[]): void { if (this.#isDone && this.#coreCtx.state !== 'postInvocationHooks') { 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. "; badAsyncMsg += `Function name: ${this.#funcInfo.name}. Invocation Id: ${this.#coreCtx.invocationId}. `; badAsyncMsg += `Learn more: ${asyncDoneLearnMoreLink}`; - this.#systemLog(RpcLog.Level.Warning, badAsyncMsg); + this.#systemLog('warning', badAsyncMsg); } - this.#log(level, RpcLog.RpcLogCategory.User, ...args); + this.#log(level, 'user', ...args); } #onDone(): void { @@ -166,7 +167,7 @@ export class InvocationModel implements coreTypes.InvocationModel { const message = this.#resultIsPromise ? `Error: Choose either to return a promise or call 'done'. Do not use both in your script. Learn more: ${asyncDoneLearnMoreLink}` : "Error: 'done' has already been called. Please check your script for extraneous calls to 'done'."; - this.#systemLog(RpcLog.Level.Error, message); + this.#systemLog('error', message); } this.#isDone = true; } diff --git a/src/converters/BindingConverters.ts b/src/converters/BindingConverters.ts index 84da110..6241c65 100644 --- a/src/converters/BindingConverters.ts +++ b/src/converters/BindingConverters.ts @@ -2,12 +2,10 @@ // Licensed under the MIT License. import { BindingDefinition, ContextBindingData } from '@azure/functions'; -import { RpcBindingInfo, RpcInvocationRequest } from '@azure/functions-core'; +import { RpcInvocationRequest } from '@azure/functions-core'; import { FunctionInfo } from '../FunctionInfo'; import { fromTypedData } from './RpcConverters'; -type BindingDirection = 'in' | 'out' | 'inout' | undefined; - export function getBindingDefinitions(info: FunctionInfo): BindingDefinition[] { const bindings = info.bindings; if (!bindings) { @@ -18,7 +16,7 @@ export function getBindingDefinitions(info: FunctionInfo): BindingDefinition[] { return { name: name, type: bindings[name].type || '', - direction: getDirectionName(bindings[name].direction), + direction: bindings[name].direction || undefined, }; }); } @@ -35,15 +33,6 @@ export function getNormalizedBindingData(request: RpcInvocationRequest): Context return bindingData; } -function getDirectionName(direction: RpcBindingInfo.Direction | null | undefined): BindingDirection { - const directionName = Object.keys(RpcBindingInfo.Direction).find((k) => RpcBindingInfo.Direction[k] === direction); - return isBindingDirection(directionName) ? (directionName as BindingDirection) : undefined; -} - -function isBindingDirection(input: string | undefined): boolean { - return input == 'in' || input == 'out' || input == 'inout'; -} - // Recursively convert keys of objects to camel case export function convertKeysToCamelCase(obj: any) { const output = {}; diff --git a/src/converters/RpcHttpConverters.ts b/src/converters/RpcHttpConverters.ts index 27b3354..db2ed9b 100644 --- a/src/converters/RpcHttpConverters.ts +++ b/src/converters/RpcHttpConverters.ts @@ -2,7 +2,13 @@ // Licensed under the MIT License. import { Cookie } from '@azure/functions'; -import { RpcHttpCookie, RpcHttpData, RpcNullableString, RpcTypedData } from '@azure/functions-core'; +import { + RpcHttpCookie, + RpcHttpCookieSameSite, + RpcHttpData, + RpcNullableString, + RpcTypedData, +} from '@azure/functions-core'; import { Dict } from '../Context'; import { fromTypedData, @@ -101,15 +107,15 @@ export function toRpcHttpCookieList(inputCookies: Cookie[]): RpcHttpCookie[] { */ function toRpcHttpCookie(inputCookie: Cookie): RpcHttpCookie { // Resolve RpcHttpCookie.SameSite enum, a one-off - let rpcSameSite: RpcHttpCookie.SameSite = RpcHttpCookie.SameSite.None; + let rpcSameSite: RpcHttpCookieSameSite = 'none'; if (inputCookie && inputCookie.sameSite) { const sameSite = inputCookie.sameSite.toLocaleLowerCase(); if (sameSite === 'lax') { - rpcSameSite = RpcHttpCookie.SameSite.Lax; + rpcSameSite = 'lax'; } else if (sameSite === 'strict') { - rpcSameSite = RpcHttpCookie.SameSite.Strict; + rpcSameSite = 'strict'; } else if (sameSite === 'none') { - rpcSameSite = RpcHttpCookie.SameSite.ExplicitNone; + rpcSameSite = 'explicitNone'; } } diff --git a/test/Context.test.ts b/test/Context.test.ts index 65e4af5..b850b4f 100644 --- a/test/Context.test.ts +++ b/test/Context.test.ts @@ -44,8 +44,8 @@ describe('Context', () => { bindings: { myTimer: { type: 'timerTrigger', - direction: 0, - dataType: 0, + direction: 'in', + dataType: 'undefined', }, }, }); @@ -70,8 +70,8 @@ describe('Context', () => { bindings: { req: { type: 'http', - direction: 0, - dataType: 1, + direction: 'in', + dataType: 'string', }, }, }); @@ -104,8 +104,8 @@ describe('Context', () => { bindings: { req: { type: 'http', - direction: 0, - dataType: 1, + direction: 'in', + dataType: 'string', }, }, }); @@ -157,8 +157,8 @@ describe('Context', () => { bindings: { req: { type: 'http', - direction: 0, - dataType: 1, + direction: 'in', + dataType: 'string', }, }, }); @@ -201,8 +201,8 @@ describe('Context', () => { bindings: { req: { type: 'http', - direction: 0, - dataType: 1, + direction: 'in', + dataType: 'string', }, }, }); diff --git a/test/FunctionInfo.test.ts b/test/FunctionInfo.test.ts index ca020d7..e085cbb 100644 --- a/test/FunctionInfo.test.ts +++ b/test/FunctionInfo.test.ts @@ -13,13 +13,13 @@ describe('FunctionInfo', () => { bindings: { req: { type: 'httpTrigger', - direction: 0, - dataType: 1, + direction: 'in', + dataType: 'string', }, $return: { type: 'http', - direction: 1, - dataType: 1, + direction: 'out', + dataType: 'string', }, }, }; @@ -33,8 +33,8 @@ describe('FunctionInfo', () => { bindings: { req: { type: 'httpTrigger', - direction: 0, - dataType: 1, + direction: 'in', + dataType: 'string', }, }, }; @@ -49,13 +49,13 @@ describe('FunctionInfo', () => { bindings: { input: { type: 'queue', - direction: 0, - dataType: 1, + direction: 'in', + dataType: 'string', }, $return: { type: 'queue', - direction: 1, - dataType: 1, + direction: 'out', + dataType: 'string', }, }, }; diff --git a/test/converters/BindingConverters.test.ts b/test/converters/BindingConverters.test.ts index 45196cc..5cd3898 100644 --- a/test/converters/BindingConverters.test.ts +++ b/test/converters/BindingConverters.test.ts @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. -import { RpcBindingInfo, RpcFunctionMetadata, RpcInvocationRequest, RpcTypedData } from '@azure/functions-core'; +import { RpcFunctionMetadata, RpcInvocationRequest, RpcTypedData } from '@azure/functions-core'; import { expect } from 'chai'; import { fromString } from 'long'; import 'mocha'; @@ -118,15 +118,15 @@ describe('Binding Converters', () => { bindings: { req: { type: 'httpTrigger', - direction: RpcBindingInfo.Direction.in, + direction: 'in', }, res: { type: 'http', - direction: RpcBindingInfo.Direction.out, + direction: 'out', }, firstQueueOutput: { type: 'queue', - direction: RpcBindingInfo.Direction.out, + direction: 'out', }, noDirection: { type: 'queue', diff --git a/test/converters/RpcHttpConverters.test.ts b/test/converters/RpcHttpConverters.test.ts index 0c5df45..3a6ca44 100644 --- a/test/converters/RpcHttpConverters.test.ts +++ b/test/converters/RpcHttpConverters.test.ts @@ -2,7 +2,6 @@ // Licensed under the MIT License. import { Cookie } from '@azure/functions'; -import { RpcHttpCookie } from '@azure/functions-core'; import { expect } from 'chai'; import 'mocha'; import { toRpcHttp, toRpcHttpCookieList } from '../../src/converters/RpcHttpConverters'; @@ -69,16 +68,16 @@ describe('Rpc Converters', () => { const rpcCookies = toRpcHttpCookieList(cookieInputs); expect(rpcCookies[0].name).to.equal('none-cookie'); - expect(rpcCookies[0].sameSite).to.equal(RpcHttpCookie.SameSite.ExplicitNone); + expect(rpcCookies[0].sameSite).to.equal('explicitNone'); expect(rpcCookies[1].name).to.equal('lax-cookie'); - expect(rpcCookies[1].sameSite).to.equal(RpcHttpCookie.SameSite.Lax); + expect(rpcCookies[1].sameSite).to.equal('lax'); expect(rpcCookies[2].name).to.equal('strict-cookie'); - expect(rpcCookies[2].sameSite).to.equal(RpcHttpCookie.SameSite.Strict); + expect(rpcCookies[2].sameSite).to.equal('strict'); expect(rpcCookies[3].name).to.equal('default-cookie'); - expect(rpcCookies[3].sameSite).to.equal(RpcHttpCookie.SameSite.None); + expect(rpcCookies[3].sameSite).to.equal('none'); }); it('throws on invalid input', () => { diff --git a/test/index.ts b/test/index.ts index 8b16e53..145f701 100644 --- a/test/index.ts +++ b/test/index.ts @@ -4,12 +4,9 @@ import * as globby from 'globby'; import * as Mocha from 'mocha'; import * as path from 'path'; -import { setupTestCoreApi } from './setupTestCoreApi'; export async function run(): Promise { try { - setupTestCoreApi(); - const options: Mocha.MochaOptions = { color: true, reporter: 'mocha-multi-reporters', diff --git a/test/setupTestCoreApi.ts b/test/setupTestCoreApi.ts deleted file mode 100644 index 2247d1f..0000000 --- a/test/setupTestCoreApi.ts +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. - -import Module = require('module'); - -export function setupTestCoreApi(): void { - const coreApi = { - RpcLog: { Level, RpcLogCategory }, - RpcHttpCookie: { SameSite }, - RpcBindingInfo: { Direction, DataType }, - }; - - Module.prototype.require = new Proxy(Module.prototype.require, { - apply(target, thisArg, argArray) { - if (argArray[0] === '@azure/functions-core') { - return coreApi; - } else { - return Reflect.apply(target, thisArg, argArray); - } - }, - }); -} - -enum Level { - Trace = 0, - Debug = 1, - Information = 2, - Warning = 3, - Error = 4, - Critical = 5, - None = 6, -} - -enum RpcLogCategory { - User = 0, - System = 1, - CustomMetric = 2, -} - -enum SameSite { - None = 0, - Lax = 1, - Strict = 2, - ExplicitNone = 3, -} - -enum Direction { - in = 0, - out = 1, - inout = 2, -} - -enum DataType { - undefined = 0, - string = 1, - binary = 2, - stream = 3, -} diff --git a/types-core/index.d.ts b/types-core/index.d.ts index cbed159..cf28299 100644 --- a/types-core/index.d.ts +++ b/types-core/index.d.ts @@ -213,7 +213,7 @@ declare module '@azure/functions-core' { /** * The recommended way to log information */ - log(level: RpcLog.Level, category: RpcLog.RpcLogCategory, message: string): void; + log(level: RpcLogLevel, category: RpcLogCategory, message: string): void; } type InvocationState = 'preInvocationHooks' | 'postInvocationHooks' | 'invocation'; @@ -286,7 +286,7 @@ declare module '@azure/functions-core' { } interface RpcStatusResult { - status?: RpcStatusResult.Status | null; + status?: RpcStatus | null; result?: string | null; @@ -295,20 +295,14 @@ declare module '@azure/functions-core' { logs?: RpcLog[] | null; } - namespace RpcStatusResult { - enum Status { - Failure = 0, - Success = 1, - Cancelled = 2, - } - } + type RpcStatus = 'failure' | 'success' | 'cancelled'; interface RpcLog { invocationId?: string | null; category?: string | null; - level?: RpcLog.Level | null; + level?: RpcLogLevel | null; message?: string | null; @@ -316,26 +310,12 @@ declare module '@azure/functions-core' { exception?: RpcException | null; - logCategory?: RpcLog.RpcLogCategory | null; + logCategory?: RpcLogCategory | null; } - namespace RpcLog { - enum Level { - Trace = 0, - Debug = 1, - Information = 2, - Warning = 3, - Error = 4, - Critical = 5, - None = 6, - } + type RpcLogLevel = 'trace' | 'debug' | 'information' | 'warning' | 'error' | 'critical' | 'none'; - enum RpcLogCategory { - User = 0, - System = 1, - CustomMetric = 2, - } - } + type RpcLogCategory = 'user' | 'system' | 'customMetric'; interface RpcException { source?: string | null; @@ -348,25 +328,14 @@ declare module '@azure/functions-core' { interface RpcBindingInfo { type?: string | null; - direction?: RpcBindingInfo.Direction | null; + direction?: RpcBindingDirection | null; - dataType?: RpcBindingInfo.DataType | null; + dataType?: RpcBindingDataType | null; } - namespace RpcBindingInfo { - enum Direction { - in = 0, - out = 1, - inout = 2, - } + type RpcBindingDirection = 'in' | 'out' | 'inout'; - enum DataType { - undefined = 0, - string = 1, - binary = 2, - stream = 3, - } - } + type RpcBindingDataType = 'undefined' | 'string' | 'binary' | 'stream'; interface RpcTypedData { string?: string | null; @@ -497,7 +466,7 @@ declare module '@azure/functions-core' { httpOnly?: RpcNullableBool | null; - sameSite?: RpcHttpCookie.SameSite | null; + sameSite?: RpcHttpCookieSameSite | null; maxAge?: RpcNullableDouble | null; } @@ -524,13 +493,6 @@ declare module '@azure/functions-core' { nanos?: number | null; } - namespace RpcHttpCookie { - enum SameSite { - None = 0, - Lax = 1, - Strict = 2, - ExplicitNone = 3, - } - } + type RpcHttpCookieSameSite = 'none' | 'lax' | 'strict' | 'explicitNone'; // #endregion rpc types }