diff --git a/.github/workflows/publish-pre-release.yml b/.github/workflows/publish-pre-release.yml new file mode 100644 index 00000000..c7eb5e41 --- /dev/null +++ b/.github/workflows/publish-pre-release.yml @@ -0,0 +1,58 @@ +name: Publish pre-release + +on: + workflow_dispatch: + +jobs: + publish-release: + runs-on: ubuntu-latest + if: github.repository_owner == 'ballerina-platform' + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: 11 + - name: Build with Gradle + env: + packageUser: ${{ github.actor }} + packagePAT: ${{ secrets.GITHUB_TOKEN }} + run: | + git config --global user.name ${{ secrets.BALLERINA_BOT_USERNAME }} + git config --global user.email ${{ secrets.BALLERINA_BOT_EMAIL }} + ./gradlew build -x check -x test + - name: Set version env variable + run: echo "VERSION=$((grep -w 'version' | cut -d= -f2) < gradle.properties)" >> $GITHUB_ENV + - name: Pre release dependency version update + env: + GITHUB_TOKEN: ${{ secrets.BALLERINA_BOT_TOKEN }} + run: | + echo "Version: ${VERSION}" + git checkout -b release-${VERSION} + sed -i 's/ballerinaLangVersion=\(.*\)-SNAPSHOT/ballerinaLangVersion=\1/g' gradle.properties + sed -i 's/ballerinaLangVersion=\(.*\)-[0-9]\{8\}-[0-9]\{6\}-.*$/ballerinaLangVersion=\1/g' gradle.properties + sed -i 's/stdlib\(.*\)=\(.*\)-SNAPSHOT/stdlib\1=\2/g' gradle.properties + sed -i 's/stdlib\(.*\)=\(.*\)-[0-9]\{8\}-[0-9]\{6\}-.*$/stdlib\1=\2/g' gradle.properties + sed -i 's/observe\(.*\)=\(.*\)-SNAPSHOT/observe\1=\2/g' gradle.properties + sed -i 's/observe\(.*\)=\(.*\)-[0-9]\{8\}-[0-9]\{6\}-.*$/observe\1=\2/g' gradle.properties + git add gradle.properties + git commit -m "Move dependencies to stable version" || echo "No changes to commit" + - name: Publish artifact + env: + GITHUB_TOKEN: ${{ secrets.BALLERINA_BOT_TOKEN }} + BALLERINA_CENTRAL_ACCESS_TOKEN: ${{ secrets.BALLERINA_CENTRAL_ACCESS_TOKEN }} + packageUser: ${{ secrets.BALLERINA_BOT_USERNAME }} + packagePAT: ${{ secrets.BALLERINA_BOT_TOKEN }} + publishUser: ${{ secrets.BALLERINA_BOT_USERNAME }} + publishPAT: ${{ secrets.BALLERINA_BOT_TOKEN }} + run: | + ./gradlew clean release -Prelease.useAutomaticVersion=true + ./gradlew -Pversion=${VERSION} publish -x test -PpublishToCentral=true + - name: GitHub Release and Release Sync PR + env: + GITHUB_TOKEN: ${{ secrets.BALLERINA_BOT_TOKEN }} + run: | + gh release create v$VERSION --title "module-ballerinax-azure.functions-v$VERSION" + gh pr create --title "[Automated] Sync master after $VERSION release" --body "Sync master after $VERSION release" diff --git a/.gitignore b/.gitignore index e9a4896f..572028bf 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,5 @@ target .ballerina .idea *.iml + +compiler-plugin-tests/src/test/resources/handlers/.vscode/ diff --git a/README.md b/README.md index a6b9f32e..f0bc504d 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ import ballerinax/azure_functions as af; // HTTP request/response with no authentication @af:Function public isolated function hello(@af:HTTPTrigger { authLevel: "anonymous" } string payload) - returns @af:HTTPOutput string|error { + returns @af:HttpOutput string|error { return "Hello, " + payload + "!"; } @@ -39,7 +39,7 @@ public isolated function hello(@af:HTTPTrigger { authLevel: "anonymous" } string public isolated function fromHttpToQueue(af:Context ctx, @af:HTTPTrigger af:HTTPRequest req, @af:QueueOutput { queueName: "queue1" } af:StringOutputBinding msg) - returns @af:HTTPOutput af:HTTPBinding { + returns @af:HttpOutput af:HTTPBinding { msg.value = req.body; return { statusCode: 200, payload: "Request: " + req.toString() }; } @@ -68,7 +68,7 @@ public isolated function fromBlobToQueue(af:Context ctx, @af:Function public isolated function httpTriggerBlobInput(@af:HTTPTrigger af:HTTPRequest req, @af:BlobInput { path: "bpath1/{Query.name}" } byte[]? blobIn) - returns @af:HTTPOutput string { + returns @af:HttpOutput string { int length = 0; if blobIn is byte[] { length = blobIn.length(); @@ -81,7 +81,7 @@ public isolated function httpTriggerBlobInput(@af:HTTPTrigger af:HTTPRequest req @af:Function public isolated function httpTriggerBlobOutput(@af:HTTPTrigger af:HTTPRequest req, @af:BlobOutput { path: "bpath1/{Query.name}" } af:StringOutputBinding bb) - returns @af:HTTPOutput string|error { + returns @af:HttpOutput string|error { bb.value = req.body; return "Blob: " + req.query["name"].toString() + " Content: " + bb?.value.toString(); @@ -91,7 +91,7 @@ public isolated function httpTriggerBlobOutput(@af:HTTPTrigger af:HTTPRequest re @af:Function public isolated function httpTriggerBlobOutput2(@af:HTTPTrigger af:HTTPRequest req, @af:BlobOutput { path: "bpath1/{Query.name}" } af:BytesOutputBinding bb) - returns @af:HTTPOutput string|error { + returns @af:HttpOutput string|error { bb.value = [65, 66, 67, 97, 98]; return "Blob: " + req.query["name"].toString() + " Content: " + bb?.value.toString(); @@ -102,7 +102,7 @@ public isolated function httpTriggerBlobOutput2(@af:HTTPTrigger af:HTTPRequest r public isolated function sendSMS(@af:HTTPTrigger af:HTTPRequest req, @af:TwilioSmsOutput { fromNumber: "+12069845840" } af:TwilioSmsOutputBinding tb) - returns @af:HTTPOutput string { + returns @af:HttpOutput string { tb.to = req.query["to"].toString(); tb.body = req.body.toString(); return "Message - to: " + tb?.to.toString() + " body: " + tb?.body.toString(); @@ -138,7 +138,7 @@ public isolated function httpTriggerCosmosDBInput1( @af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c1", id: "{Query.id}", partitionKey: "{Query.country}" } json dbReq) - returns @af:HTTPOutput string|error { + returns @af:HttpOutput string|error { return dbReq.toString(); } @@ -148,7 +148,7 @@ public isolated function httpTriggerCosmosDBInput2( @af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c1", id: "{Query.id}", partitionKey: "{Query.country}" } Person? dbReq) - returns @af:HTTPOutput string|error { + returns @af:HttpOutput string|error { return dbReq.toString(); } @@ -159,14 +159,14 @@ public isolated function httpTriggerCosmosDBInput3( databaseName: "db1", collectionName: "c1", sqlQuery: "select * from c1 where c1.country = {country}" } Person[] dbReq) - returns @af:HTTPOutput string|error { + returns @af:HttpOutput string|error { return dbReq.toString(); } // HTTP request to write records to CosmosDB @af:Function public isolated function httpTriggerCosmosDBOutput1( - @af:HTTPTrigger af:HTTPRequest httpReq, @af:HTTPOutput af:HTTPBinding hb) + @af:HTTPTrigger af:HTTPRequest httpReq, @af:HttpOutput af:HTTPBinding hb) returns @af:CosmosDBOutput { connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c1" } json { json entry = { id: uuid:createType1AsString(), name: "Saman", country: "Sri Lanka" }; @@ -177,7 +177,7 @@ public isolated function httpTriggerCosmosDBOutput1( @af:Function public isolated function httpTriggerCosmosDBOutput2( @af:HTTPTrigger af:HTTPRequest httpReq, - @af:HTTPOutput af:HTTPBinding hb) + @af:HttpOutput af:HTTPBinding hb) returns @af:CosmosDBOutput { connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c1" } json { diff --git a/ballerina-tests/Ballerina.toml b/ballerina-tests/Ballerina.toml index 781cbce5..1645dbc2 100644 --- a/ballerina-tests/Ballerina.toml +++ b/ballerina-tests/Ballerina.toml @@ -1,4 +1,9 @@ [package] org = "ballerinax" name = "azure_functions_tests" -version = "2.1.1" +version = "3.0.0-alpha.1" + +[[dependency]] +org = "ballerinax" +name = "azure_functions" +version = "3.0.0-alpha.1" diff --git a/ballerina-tests/build.gradle b/ballerina-tests/build.gradle index d8045708..a1e3030b 100644 --- a/ballerina-tests/build.gradle +++ b/ballerina-tests/build.gradle @@ -22,14 +22,14 @@ import org.apache.tools.ant.taskdefs.condition.Os description = 'Ballerinax - Azure Functions Tests' def packageName = "azure_functions" -def packageOrg = "ballerinax" //TODO change +def packageOrg = "ballerinax" def moduleName = "tests" def tomlVersion = stripBallerinaExtensionVersion("${project.version}") def ballerinaTomlFilePlaceHolder = new File("${project.rootDir}/build-config/resources/BallerinaTest.toml") def ballerinaTomlFile = new File("$project.projectDir/Ballerina.toml") def ballerinaDist = "${project.rootDir}/target/ballerina-runtime" def distributionBinPath = "${ballerinaDist}/bin" -def testCoverageParam = "--code-coverage --includes=*" +def testCoverageParam = "--test-report --code-coverage --coverage-format=xml --includes=io.ballerina.stdlib.azure.functions.*:ballerinax.azure_functions" def stripBallerinaExtensionVersion(String extVersion) { if (extVersion.matches(project.ext.timestampedVersionRegex)) { diff --git a/ballerina-tests/main.bal b/ballerina-tests/main.bal deleted file mode 100644 index a372656d..00000000 --- a/ballerina-tests/main.bal +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) 2020 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -// -// WSO2 Inc. licenses this file to you under the Apache License, -// Version 2.0 (the "License"); you may not use this file except -// in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -import ballerina/uuid; -import ballerinax/azure_functions as af; - -// HTTP request/response with no authentication -@af:Function -public isolated function hello(@af:HTTPTrigger { authLevel: "anonymous" } string payload) - returns @af:HTTPOutput string|error { - return "Hello, " + payload + "!"; -} - -// HTTP request to add data to a queue -@af:Function -public isolated function fromHttpToQueue(af:Context ctx, - @af:HTTPTrigger {} af:HTTPRequest req, - @af:QueueOutput { queueName: "queue1" } af:StringOutputBinding msg) - returns @af:HTTPOutput af:HTTPBinding { - msg.value = req.body; - return { statusCode: 200, payload: "Request: " + req.toString() }; -} - -// A message put to a queue is copied to another queue -@af:Function -public isolated function fromQueueToQueue(af:Context ctx, - @af:QueueTrigger { queueName: "queue2" } string inMsg, - @af:QueueOutput { queueName: "queue3" } af:StringOutputBinding outMsg) { - ctx.log("In Message: " + inMsg); - ctx.log("Metadata: " + ctx.metadata.toString()); - outMsg.value = inMsg; -} - -// // A blob added to a container is copied to a queue -@af:Function -public isolated function fromBlobToQueue(af:Context ctx, - @af:BlobTrigger { path: "bpath1/{name}" } byte[] blobIn, - @af:BindingName { } string name, - @af:QueueOutput { queueName: "queue3" } af:StringOutputBinding outMsg) - returns error? { - outMsg.value = "Name: " + name + " Content: " + blobIn.toString(); -} - -// // HTTP request to read a blob value -@af:Function -public isolated function httpTriggerBlobInput(@af:HTTPTrigger { } af:HTTPRequest req, - @af:BlobInput { path: "bpath1/{Query.name}" } byte[]? blobIn) - returns @af:HTTPOutput string { - int length = 0; - if blobIn is byte[] { - length = blobIn.length(); - } - return "Blob: " + req.query["name"].toString() + " Length: " + - length.toString() + " Content: " + blobIn.toString(); -} - -// // HTTP request to add a new blob -@af:Function -public isolated function httpTriggerBlobOutput(@af:HTTPTrigger { } af:HTTPRequest req, - @af:BlobOutput { path: "bpath1/{Query.name}" } af:StringOutputBinding bb) - returns @af:HTTPOutput string|error { - bb.value = req.body; - return "Blob: " + req.query["name"].toString() + " Content: " + - bb?.value.toString(); -} - -// // Sending an SMS -@af:Function -public isolated function sendSMS(@af:HTTPTrigger { } af:HTTPRequest req, - @af:TwilioSmsOutput { fromNumber: "+12069845840" } - af:TwilioSmsOutputBinding tb) - returns @af:HTTPOutput string { - tb.to = req.query["to"].toString(); - tb.body = req.body.toString(); - return "Message - to: " + tb?.to.toString() + " body: " + tb?.body.toString(); -} - -public type Person record { - string id; - string name; - string country; -}; - -// // CosmosDB record trigger -@af:Function -public isolated function cosmosDBToQueue1(@af:CosmosDBTrigger { - connectionStringSetting: "CosmosDBConnection", databaseName: "db1", - collectionName: "c1" } Person[] req, - @af:QueueOutput { queueName: "queue3" } af:StringOutputBinding outMsg) { - outMsg.value = req.toString(); -} - -@af:Function -public isolated function cosmosDBToQueue2(@af:CosmosDBTrigger { - connectionStringSetting: "CosmosDBConnection", databaseName: "db1", - collectionName: "c2" } json req, - @af:QueueOutput { queueName: "queue3" } af:StringOutputBinding outMsg) { - outMsg.value = req.toString(); -} - -// // HTTP request to read CosmosDB records -@af:Function -public isolated function httpTriggerCosmosDBInput1( - @af:HTTPTrigger { } af:HTTPRequest httpReq, - @af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1", - id: "{Query.id}", partitionKey: "{Query.country}" } json dbReq) - returns @af:HTTPOutput string|error { - return dbReq.toString(); -} - -@af:Function -public isolated function httpTriggerCosmosDBInput2( - @af:HTTPTrigger { } af:HTTPRequest httpReq, - @af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1", - id: "{Query.id}", partitionKey: "{Query.country}" } Person? dbReq) - returns @af:HTTPOutput string|error { - return dbReq.toString(); -} - -@af:Function -public isolated function httpTriggerCosmosDBInput3( - @af:HTTPTrigger { route: "c1/{country}" } af:HTTPRequest httpReq, - @af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1", - sqlQuery: "select * from c1 where c1.country = {country}" } - Person[] dbReq) - returns @af:HTTPOutput string|error { - return dbReq.toString(); -} - -// // HTTP request to write records to CosmosDB -@af:Function -public isolated function httpTriggerCosmosDBOutput1( - @af:HTTPTrigger { } af:HTTPRequest httpReq, @af:HTTPOutput af:HTTPBinding hb) - returns @af:CosmosDBOutput { connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1" } json { - json entry = { id: uuid:createType1AsString(), name: "Saman", country: "Sri Lanka" }; - hb.payload = "Adding entry: " + entry.toString(); - return entry; -} - -@af:Function -public isolated function httpTriggerCosmosDBOutput2( - @af:HTTPTrigger { } af:HTTPRequest httpReq, - @af:HTTPOutput af:HTTPBinding hb) - returns @af:CosmosDBOutput { - connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1" } json { - json entry = [{ id: uuid:createType1AsString(), name: "John Doe A", country: "USA" }, - { id: uuid:createType1AsString(), name: "John Doe B", country: "USA" }]; - hb.payload = "Adding entries: " + entry.toString(); - return entry; -} - -@af:Function -public isolated function httpTriggerCosmosDBOutput3( - @af:HTTPTrigger { } af:HTTPRequest httpReq) - returns @af:CosmosDBOutput { - connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1" } Person[] { - Person[] persons = []; - persons.push({id: uuid:createType1AsString(), name: "Jack", country: "UK"}); - persons.push({id: uuid:createType1AsString(), name: "Will", country: "UK"}); - return persons; -} - -// // A timer function which is executed every 10 seconds. -@af:Function -public isolated function queuePopulationTimer( - @af:TimerTrigger { schedule: "*/10 * * * * *" } json triggerInfo, - @af:QueueOutput { queueName: "queue4" } af:StringOutputBinding msg) { - msg.value = triggerInfo.toString(); -} diff --git a/ballerina-tests/tests/main.bal b/ballerina-tests/tests/main.bal new file mode 100644 index 00000000..4a6809ca --- /dev/null +++ b/ballerina-tests/tests/main.bal @@ -0,0 +1,438 @@ +import ballerinax/azure_functions as af; +import ballerina/http; + +public type DBEntry record { + string id; +}; + +public type Person record { + string name; + int age; +}; + +public type RateLimitHeaders record {| + int Content\-Length; + string Content\-Type; +|}; + +public type NoHeaderVal record {| + int Content\-Length; + string Content\-Type; + string Content\-Type1; +|}; + +listener af:HttpListener ep1 = new (); + +service /hello\- on ep1 { + + resource function post hello\-query() returns string|error { + return "Hello from the hello-query"; + } +} + +listener af:HttpListener ep2 = new (); + +@http:ServiceConfig { + treatNilableAsOptional: false +} +service /httpHeader on ep2 { + resource function post nonTreatNilAsOpt\-Nil\-noHeaderTest(@http:Header string? hoste) returns string? { + return hoste; + } + + resource function post nonTreatNilAsOpt\-nonNil\-noHeaderTest(@http:Header string hoste) returns string { + return hoste; + + } + + resource function post nonTreatNilAsOpt\-nonNil\-HeaderTest(@http:Header string hos) returns string { + return hos; + + } + + resource function post nonTreatNilAsOpt\-Nil\-HeaderTest(@http:Header string? hos) returns string? { + return hos; + + } +} + +listener af:HttpListener ep3 = new (); + +service /httpHeader on ep3 { + resource function post retrFromAnnotField(@http:Header {name: "Content-Type"} string contentType) returns string { + + return contentType; + } + + resource function post retrFromParam(@http:Header string Host) returns string { + + return Host; + + } + + resource function post retrSingleVal(@http:Header {name: "Content-Length"} int contentLength) returns int { + + return contentLength + 10; + + } + + resource function post retrArrVal(@http:Header {name: "Content-Length"} int[] contentLength) returns int { + + return contentLength[0] + 15; + + } + + resource function post retrArrValStr(@http:Header string[] test) returns string { + return test[0]; + + } + + resource function post retrAsRecord(@http:Header RateLimitHeaders rateLimiters) returns int { + return rateLimiters.Content\-Length + 100; + + } + + resource function post retrNilable(@http:Header string? Host) returns string? { + return Host; + + } + + resource function post treatNilAsOpt\-nonNil\-noHeaderTest(@http:Header string hoste) returns string { + return hoste; + + } + + resource function post treatNilAsOpt\-nonNil\-HeaderTest(@http:Header string hos) returns string { + return hos; + + } + + resource function post retrAsRecordNoField(@http:Header NoHeaderVal noHeaderVal) returns int { + return noHeaderVal.Content\-Length + 100; + + } + + resource function post treatNilAsOpt\-Nil\-noHeaderTest(@http:Header string? hoste) returns string? { + return hoste; + + } + + resource function post treatNilAsOpt\-Nil\-HeaderTest(@http:Header string? hos) returns string? { + return hos; + + } +} +listener af:HttpListener ep = new (); + +service /hello on ep { + + resource function default all() returns @af:HttpOutput string { + return "Hello from all"; + } + + resource function post optional/out(@http:Payload string greeting) returns string { + return "Hello from optional output binding"; + } + + resource function post optional/payload(@http:Payload string? greeting) returns string { + if (greeting is string) { + return "Hello, the payload found " + greeting; + } + return "Hello, the payload wasn't set but all good ;)"; + } + + resource function post .(@http:Payload string greeting) returns @af:HttpOutput string { + return "Hello from . path "; + } + resource function post httpResTest1(@http:Payload string greeting) returns @af:HttpOutput http:Unauthorized { + http:Unauthorized unauth = { + body: "Helloworld.....", + mediaType: "application/account+json", + headers: { + "Location": "/myServer/084230" + } + }; + return unauth; + } + + resource function post httpResTest2(@http:Payload string greeting) returns @af:HttpOutput http:Ok { + http:Ok ok = {body: "Helloworld....."}; + return ok; + } + resource function post httpResTest3(@http:Payload string greeting) returns @af:HttpOutput http:InternalServerError { + http:InternalServerError err = { + body: "Helloworld.....", + headers: { + "Content-Type": "application/json+id", + "Location": "/myServer/084230" + } + }; + return err; + } + resource function post httpResTest4(@http:Payload string greeting) returns @af:HttpOutput http:InternalServerError { + http:InternalServerError err = {}; + return err; + } + + resource function post foo(@http:Payload string greeting) returns @af:HttpOutput string { + return "Hello from foo path " + greeting; + } + + resource function post foo/[string bar](@http:Payload string greeting) returns @af:HttpOutput string { + return "Hello from foo param " + bar; + } + + resource function post foo/bar(@http:Payload string greeting) returns @af:HttpOutput string { + return "Hello from foo bar res"; + } + + resource function post db(@http:Payload string greeting, @af:CosmosDBInput { + connectionStringSetting: "CosmosDBConnection", + databaseName: "db1", + collectionName: "c2", + sqlQuery: "SELECT * FROM Items" + } DBEntry[] input1) returns @af:HttpOutput string|error { + return "Hello " + greeting + input1[0].id; + } + + resource function post payload/jsonToRecord(@http:Payload Person greeting) returns @af:HttpOutput string|error { + return "Hello from json to record " + greeting.name; + } + + resource function post payload/jsonToJson(@http:Payload json greeting) returns @af:HttpOutput string|error { + string name = check greeting.name; + return "Hello from json to json " + name; + } + + resource function post payload/xmlToXml(@http:Payload xml greeting) returns @af:HttpOutput string|error { + return greeting.toJsonString(); + } + + resource function post payload/textToString(@http:Payload string greeting) returns @af:HttpOutput string|error { + return greeting; + } + + resource function post payload/textToByte(@http:Payload byte[] greeting) returns @af:HttpOutput string|error { + return string:fromBytes(greeting); + } + + resource function post payload/octaToByte(@http:Payload byte[] greeting) returns @af:HttpOutput string|error { + return string:fromBytes(greeting); + } + + resource function get err/empty/payload(@http:Payload string greeting) returns @af:HttpOutput string { + return "Hello from get empty payload"; + } + + resource function post err/invalid/payload(@http:Payload string greeting) returns @af:HttpOutput string { + return "Hello from get invalid payload " + greeting; + } + + resource function get httpAccessorTest() returns @af:HttpOutput string { + return "Hello from all"; + } + + resource function put httpAccessorTest() returns @af:HttpOutput string { + return "Hello from all"; + } + + resource function patch httpAccessorTest() returns @af:HttpOutput string { + return "Hello from all"; + } + + resource function delete httpAccessorTest() returns @af:HttpOutput string { + return "Hello from all"; + } + + resource function head httpAccessorTest() returns @af:HttpOutput string { + return "Hello from all"; + } + + resource function options httpAccessorTest() returns @af:HttpOutput string { + return "Hello from all"; + } + + resource function post httpResTest5() returns http:StatusCodeResponse { + http:InternalServerError err = {}; + return err; + } + + resource function post nonHttpResTest1() returns string { + string s1 = "alpha"; + return s1; + } + + resource function post nonHttpResTest2() returns xml { + xml x1 = xml `The Lost World`; + return x1; + } + + resource function post nonHttpResTest3() returns byte[] { + byte[] b1 = base64 `yPHaytRgJPg+QjjylUHakEwz1fWPx/wXCW41JSmqYW8=`; + return b1; + + } + + resource function post nonHttpResTest4() returns int { + int i1 = 100; + return i1; + } + + resource function post nonHttpResTest6() returns decimal { + decimal d1 = 100; + return d1; + } + + resource function post nonHttpResTest7() returns boolean { + boolean bo1 = true; + return bo1; + } + + resource function post nonHttpResTest8() returns map { + map mj1 = {"a": {"b": 12, "c": "helloworld"}}; + return mj1; + + } + + resource function post nonHttpResTest9() returns table> { + + table> t = table [ + {"a": {"b": 12, "c": "helloworld"}}, + {"b": 1100} + ]; + + return t; + } + + resource function post nonHttpResTest10() returns map[] { + + map[] mjarr1 = [{"a": {"b": 12, "c": "helloworld"}}, {"b": 12}]; + + return mjarr1; + } + + resource function post nonHttpResTest11() returns table>[] { + table>[] tarr = [ + table [ + {"a": {"b": 12, "c": "helloworld"}}, + {"b": 12} + ], + table [ + {"a": {"b": 14, "c": "helloworld"}}, + {"b": 100} + ] + ]; + return tarr; + } + + resource function post nonReturnTest1() { + + } + + resource function get blobInput(@http:Payload string greeting, string name, @af:BlobInput {path: "bpath1/{Query.name}"} byte[]? blobIn) returns string|error { + if blobIn is byte[] { + string content = check string:fromBytes(blobIn); + return "Blob from " + name + ", content is " + content; + } else { + return "Blob from " + name + " not found"; + } + } + + resource function post query(string name, @http:Payload string greeting) returns @af:HttpOutput string|error { + return "Hello from the query " + greeting + " " + name; + } + + resource function get query/optional(string? name) returns string|error { + if (name is string) { + return "Hello from the optional query " + name; + } else { + return "Query not found but all good ;)"; + } + } + + resource function get query/bool(boolean name) returns string|error { + return "Hello from the bool query " + name.toString(); + } + + resource function get query/floatt(float name) returns string|error { + return "Hello from the float query " + name.toString(); + } + + resource function get query/arr(string[] name) returns string|error { + string out = ""; + foreach string i in name { + out += i + " "; + } + return "Hello from the arr query " + out; + } + + resource function get query/arrOrNil(string[]|() name) returns string|error { + if (name is string[]) { + string out = ""; + foreach string i in name { + out += i + " "; + } + return "Hello from the arr or nil query " + out; + } else { + return "Query arr not found but all good ;)"; + } + } +} + +@af:QueueTrigger { + queueName: "queue2" +} +service "queue" on new af:QueueListener() { + remote function onMessage(string inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + return "helloo " + inMsg; + } +} + +@af:CosmosDBTrigger {connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c2"} +listener af:CosmosDBListener cosmosEp = new (); + +service "cosmos" on cosmosEp { + remote function onUpdated(DBEntry[] inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + string id = inMsg[0].id; + return "helloo " + id; + } +} + +@af:TimerTrigger {schedule: "*/10 * * * * *"} +listener af:TimerListener timerListener = new af:TimerListener(); + +service "timer" on timerListener { + remote function onTrigger(af:TimerMetadata inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + return "helloo " + inMsg.IsPastDue.toString(); + } +} + +@af:QueueTrigger { + queueName: "queue4" +} + +listener af:QueueListener queueListener1 = new af:QueueListener(); + +service "queue-input" on queueListener1 { + remote function onMessage(string inMsg, @af:CosmosDBInput { + connectionStringSetting: "CosmosDBConnection", + databaseName: "db1", + collectionName: "c2", + sqlQuery: "SELECT * FROM Items" + } DBEntry[] input1) returns @af:QueueOutput {queueName: "queue3"} string|error { + return "helloo " + inMsg + " " + input1[0].id; + } +} + +@af:BlobTrigger { + path: "bpath1/{name}" +} +listener af:BlobListener blobListener = new af:BlobListener(); + +service "blob" on blobListener { + remote function onUpdated(byte[] blobIn, @af:BindingName {} string name) returns @af:BlobOutput { + path: "bpath1/newBlob" + } byte[]|error { + return blobIn; + } +} diff --git a/ballerina-tests/tests/resources/base-dot.json b/ballerina-tests/tests/resources/base-dot.json new file mode 100644 index 00000000..2d77addf --- /dev/null +++ b/ballerina-tests/tests/resources/base-dot.json @@ -0,0 +1,108 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/hello" + ], + "X-WAWS-Unencoded-URL": [ + "/hello" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/hello", + "X-WAWS-Unencoded-URL": "/hello" + }, + "sys": { + "MethodName": "post-hello", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/resources/blob-trigger.json b/ballerina-tests/tests/resources/blob-trigger.json new file mode 100644 index 00000000..75a124f3 --- /dev/null +++ b/ballerina-tests/tests/resources/blob-trigger.json @@ -0,0 +1,43 @@ +{ + "Data": { + "blobIn": "aGVsbG8gZnJvbSBieXRlCg==" + }, + "Metadata": { + "Uri": "\"https:\/\/baldevgroup84df.blob.core.windows.net\/bpath1\/hello.txt\"", + "Properties": { + "CacheControl": null, + "ContentDisposition": null, + "ContentEncoding": null, + "ContentLanguage": null, + "Length": 16, + "ContentMD5": "vNUQNie6YzklPqNxnmy97g==", + "ContentType": "text/plain", + "ETag": "\"0x8DA6E28262505DD\"", + "Created": "2022-07-25T10:26:34+00:00", + "LastModified": "2022-07-25T10:26:34+00:00", + "BlobType": 2, + "LeaseStatus": 2, + "LeaseState": 1, + "LeaseDuration": 0, + "PageBlobSequenceNumber": null, + "AppendBlobCommittedBlockCount": null, + "IsServerEncrypted": true, + "EncryptionScope": null, + "IsIncrementalCopy": false, + "StandardBlobTier": 0, + "RehydrationStatus": null, + "PremiumPageBlobTier": null, + "BlobTierInferred": false, + "BlobTierLastModifiedTime": null, + "DeletedTime": null, + "RemainingDaysBeforePermanentDelete": null + }, + "Metadata": {}, + "name": "\"hello.txt\"", + "sys": { + "MethodName": "blob", + "UtcNow": "2022-07-25T10:26:43.0352723Z", + "RandGuid": "30d01e72-94e7-4d4f-906a-2ce51939bfcc" + } + } +} diff --git a/ballerina-tests/tests/resources/cosmos-db-arr.json b/ballerina-tests/tests/resources/cosmos-db-arr.json new file mode 100644 index 00000000..815c452c --- /dev/null +++ b/ballerina-tests/tests/resources/cosmos-db-arr.json @@ -0,0 +1,109 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/db", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "a492fc81-584d-4c6b-96bd-73e64dfae778" + ], + "CLIENT-IP": [ + "10.0.32.12:51102" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.130.212:17220" + ], + "X-Original-URL": [ + "/hello/db" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/db" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + }, + "input1": "[{\"id\":\"hello1\",\"_rid\":\"zlIsAKxe8VCBhB4AAAAAAA==\",\"_self\":\"dbs\/zlIsAA==\/colls\/zlIsAKxe8VA=\/docs\/zlIsAKxe8VCBhB4AAAAAAA==\/\",\"_etag\":\"\\\"3d00aaf8-0000-0700-0000-625412270000\\\"\",\"_attachments\":\"attachments\/\",\"_ts\":1649676839},{\"id\":\"ssss\",\"_rid\":\"zlIsAKxe8VCChB4AAAAAAA==\",\"_self\":\"dbs\/zlIsAA==\/colls\/zlIsAKxe8VA=\/docs\/zlIsAKxe8VCChB4AAAAAAA==\/\",\"_etag\":\"\\\"3e00ed1c-0000-0700-0000-625412970000\\\"\",\"_attachments\":\"attachments\/\",\"_ts\":1649676951},{\"id\":\"hello2\",\"_rid\":\"zlIsAKxe8VCDhB4AAAAAAA==\",\"_self\":\"dbs\/zlIsAA==\/colls\/zlIsAKxe8VA=\/docs\/zlIsAKxe8VCDhB4AAAAAAA==\/\",\"_etag\":\"\\\"3e00c262-0000-0700-0000-625413330000\\\"\",\"_attachments\":\"attachments\/\",\"_ts\":1649677107}]" + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "a492fc81-584d-4c6b-96bd-73e64dfae778", + "CLIENT-IP": "10.0.32.12:51102", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.130.212:17220", + "X-Original-URL": "/hello/db", + "X-WAWS-Unencoded-URL": "/hello/db", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "post-hello-db", + "UtcNow": "2022-06-13T12:19:46.7381431Z", + "RandGuid": "c1e78f43-0004-4fc3-b605-371335fa8c6b" + } + } +} diff --git a/ballerina-tests/tests/resources/cosmos-db.json b/ballerina-tests/tests/resources/cosmos-db.json new file mode 100644 index 00000000..3920acd2 --- /dev/null +++ b/ballerina-tests/tests/resources/cosmos-db.json @@ -0,0 +1,117 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://sl-update-1-rc.azurewebsites.net/hello/hi?id=11", + "Method": "POST", + "Query": { + "id": "11" + }, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "sl-update-1-rc.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "51c48e88-d5fb-447a-adf4-1c144dfe3c66" + ], + "CLIENT-IP": [ + "10.0.32.14:45249" + ], + "X-SITE-DEPLOYMENT-ID": [ + "sl-update-1-rc" + ], + "WAS-DEFAULT-HOSTNAME": [ + "sl-update-1-rc.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.131.153:31932" + ], + "X-Original-URL": [ + "/hello/hi?id=11" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/hi?id=11" + ], + "DISGUISED-HOST": [ + "sl-update-1-rc.azurewebsites.net" + ] + }, + "Params": { + "RemainingPath": "hi" + }, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + }, + "input": "\"{\\\"id\\\":\\\"11\\\",\\\"_rid\\\":\\\"P89cAMobTCgBAAAAAAAAAA==\\\",\\\"_self\\\":\\\"dbs\/P89cAA==\/colls\/P89cAMobTCg=\/docs\/P89cAMobTCgBAAAAAAAAAA==\/\\\",\\\"_ts\\\":1652717163,\\\"_etag\\\":\\\"\\\\\\\"0501238d-0000-0700-0000-6282766b0000\\\\\\\"\\\"}\"" + }, + "Metadata": { + "id": "\"11\"", + "RemainingPath": "\"hi\"", + "Query": { + "id": "11" + }, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "sl-update-1-rc.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "51c48e88-d5fb-447a-adf4-1c144dfe3c66", + "CLIENT-IP": "10.0.32.14:45249", + "X-SITE-DEPLOYMENT-ID": "sl-update-1-rc", + "WAS-DEFAULT-HOSTNAME": "sl-update-1-rc.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.131.153:31932", + "X-Original-URL": "/hello/hi?id=11", + "X-WAWS-Unencoded-URL": "/hello/hi?id=11", + "DISGUISED-HOST": "sl-update-1-rc.azurewebsites.net" + }, + "sys": { + "MethodName": "hello", + "UtcNow": "2022-05-17T08:30:37.1181668Z", + "RandGuid": "e134c648-4722-4ef5-a889-6a60830cb2d8" + } + } +} diff --git a/ballerina-tests/tests/resources/default.json b/ballerina-tests/tests/resources/default.json new file mode 100644 index 00000000..fb801b6a --- /dev/null +++ b/ballerina-tests/tests/resources/default.json @@ -0,0 +1,107 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/all", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/hello/all" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/all" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ] + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/hello/all", + "X-WAWS-Unencoded-URL": "/hello/all" + }, + "sys": { + "MethodName": "default-hello-all", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/resources/error-invalid-payload.json b/ballerina-tests/tests/resources/error-invalid-payload.json new file mode 100644 index 00000000..9fdc9626 --- /dev/null +++ b/ballerina-tests/tests/resources/error-invalid-payload.json @@ -0,0 +1,116 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/payload/octaToByte", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Content-Length": [ + "20" + ], + "Content-Type": [ + "application/octet-stream" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "4464b495-cbb0-4398-b79f-9b626afc54af" + ], + "X-ARR-LOG-ID": [ + "03f45b02-ca0c-44a4-8fbd-1a916dc44743" + ], + "CLIENT-IP": [ + "10.0.32.9:31863" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.183:8622" + ], + "X-Original-URL": [ + "/hello/payload/octaToByte" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/payload/octaToByte" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "aGVsbG8gZnJvbSBieXRlIGFycgo=" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Content-Length": "20", + "Content-Type": "application/octet-stream", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "4464b495-cbb0-4398-b79f-9b626afc54af", + "X-ARR-LOG-ID": "03f45b02-ca0c-44a4-8fbd-1a916dc44743", + "CLIENT-IP": "10.0.32.9:31863", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.183:8622", + "X-Original-URL": "/hello/payload/octaToByte", + "X-WAWS-Unencoded-URL": "/hello/payload/octaToByte", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "post-hello-err-invalid-payload", + "UtcNow": "2022-06-21T09:16:39.7549127Z", + "RandGuid": "4d6607a9-6f7f-47ab-b604-9d38b6d60166" + } + } +} diff --git a/ballerina-tests/tests/resources/error-missing-payload.json b/ballerina-tests/tests/resources/error-missing-payload.json new file mode 100644 index 00000000..f252a245 --- /dev/null +++ b/ballerina-tests/tests/resources/error-missing-payload.json @@ -0,0 +1,99 @@ +{ + "Data": { + "httpPayload": { + "Url": "http://localhost:7071/hello/err/empty/payload", + "Method": "GET", + "Query": {}, + "Headers": { + "Cache-Control": [ + "max-age=0" + ], + "Connection": [ + "keep-alive" + ], + "Accept": [ + "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Accept-Language": [ + "en-US,en;q=0.9" + ], + "Cookie": [ + "_ga=GA1.1.720190479.1641539348; _hjSessionUser_865786=eyJpZCI6IjhjNjRiYjkwLTA0NzYtNTc5MS1hZWNiLTRjN2VhZTM4OWM5NCIsImNyZWF0ZWQiOjE2NDE1MzkzNDg4NTAsImV4aXN0aW5nIjp0cnVlfQ==; Idea-2474b141=7a691445-10e4-435d-b306-2b36a77b1d2e; Webstorm-fe5cf5e6=379eafe5-e706-45c1-92e8-6e424ab655f0; cookie_accepted=1" + ], + "Host": [ + "localhost:7071" + ], + "User-Agent": [ + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" + ], + "Upgrade-Insecure-Requests": [ + "1" + ], + "sec-ch-ua": [ + "\".Not\/A)Brand\";v=\"99\", \"Google Chrome\";v=\"103\", \"Chromium\";v=\"103\"" + ], + "sec-ch-ua-mobile": [ + "?0" + ], + "sec-ch-ua-platform": [ + "\"Linux\"" + ], + "Sec-Fetch-Site": [ + "none" + ], + "Sec-Fetch-Mode": [ + "navigate" + ], + "Sec-Fetch-User": [ + "?1" + ], + "Sec-Fetch-Dest": [ + "document" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ] + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Cache-Control": "max-age=0", + "Connection": "keep-alive", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "en-US,en;q=0.9", + "Cookie": "_ga=GA1.1.720190479.1641539348; _hjSessionUser_865786=eyJpZCI6IjhjNjRiYjkwLTA0NzYtNTc5MS1hZWNiLTRjN2VhZTM4OWM5NCIsImNyZWF0ZWQiOjE2NDE1MzkzNDg4NTAsImV4aXN0aW5nIjp0cnVlfQ==; Idea-2474b141=7a691445-10e4-435d-b306-2b36a77b1d2e; Webstorm-fe5cf5e6=379eafe5-e706-45c1-92e8-6e424ab655f0; cookie_accepted=1", + "Host": "localhost:7071", + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36", + "Upgrade-Insecure-Requests": "1", + "sec-ch-ua": "\".Not\/A)Brand\";v=\"99\", \"Google Chrome\";v=\"103\", \"Chromium\";v=\"103\"", + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": "\"Linux\"", + "Sec-Fetch-Site": "none", + "Sec-Fetch-Mode": "navigate", + "Sec-Fetch-User": "?1", + "Sec-Fetch-Dest": "document" + }, + "sys": { + "MethodName": "get-hello-err-empty-payload", + "UtcNow": "2022-08-04T16:06:50.5393863Z", + "RandGuid": "0243c7ea-084a-4413-bd70-3cee25cbbd3c" + } + } +} diff --git a/ballerina-tests/tests/resources/escape-seq.json b/ballerina-tests/tests/resources/escape-seq.json new file mode 100644 index 00000000..66ea5990 --- /dev/null +++ b/ballerina-tests/tests/resources/escape-seq.json @@ -0,0 +1,108 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello-/hello-query", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/hello-/hello-query" + ], + "X-WAWS-Unencoded-URL": [ + "/hello-/hello-query" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/hello-/hello-query", + "X-WAWS-Unencoded-URL": "/hello-/hello-query" + }, + "sys": { + "MethodName": "post-hello--hello-query", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/resources/http-optional-out.json b/ballerina-tests/tests/resources/http-optional-out.json new file mode 100644 index 00000000..c16bd550 --- /dev/null +++ b/ballerina-tests/tests/resources/http-optional-out.json @@ -0,0 +1,108 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/optional/out", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/hello/optional/out" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/optional/out" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/hello/optional/out", + "X-WAWS-Unencoded-URL": "/hello/optional/out" + }, + "sys": { + "MethodName": "post-hello-optional-out", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/resources/http-optional-with-payload.json b/ballerina-tests/tests/resources/http-optional-with-payload.json new file mode 100644 index 00000000..e6051881 --- /dev/null +++ b/ballerina-tests/tests/resources/http-optional-with-payload.json @@ -0,0 +1,108 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/optional/payload", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/hello/optional/payload" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/optional/payload" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/hello/optional/payload", + "X-WAWS-Unencoded-URL": "/hello/optional/payload" + }, + "sys": { + "MethodName": "post-hello-optional-payload", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/resources/http-optional-without-payload.json b/ballerina-tests/tests/resources/http-optional-without-payload.json new file mode 100644 index 00000000..dc75d58f --- /dev/null +++ b/ballerina-tests/tests/resources/http-optional-without-payload.json @@ -0,0 +1,107 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/optional/payload", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/hello/optional/payload" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/optional/payload" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ] + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/hello/optional/payload", + "X-WAWS-Unencoded-URL": "/hello/optional/payload" + }, + "sys": { + "MethodName": "post-hello-optional-payload", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/resources/http-query-blob-input.json b/ballerina-tests/tests/resources/http-query-blob-input.json new file mode 100644 index 00000000..a2726a73 --- /dev/null +++ b/ballerina-tests/tests/resources/http-query-blob-input.json @@ -0,0 +1,122 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/blobInput?name=hello.txt", + "Method": "GET", + "Query": { + "name": "hello.txt" + }, + "Headers": { + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "text/plain" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "4c33f9fa-9126-4f46-a34a-e328a2b5d192" + ], + "X-ARR-LOG-ID": [ + "4dd64a38-fed1-42d2-b765-269065bd8a4f" + ], + "CLIENT-IP": [ + "10.0.32.12:47555" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.76:48146" + ], + "X-Original-URL": [ + "/hello/blobInput?name=hello.txt" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/blobInput?name=hello.txt" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + }, + "blobIn": "\"hello from byte\\n\"" + }, + "Metadata": { + "name": "\"hello.txt\"", + "Query": { + "name": "hello.txt" + }, + "Headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Content-Length": "4", + "Content-Type": "text/plain", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "4c33f9fa-9126-4f46-a34a-e328a2b5d192", + "X-ARR-LOG-ID": "4dd64a38-fed1-42d2-b765-269065bd8a4f", + "CLIENT-IP": "10.0.32.12:47555", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.76:48146", + "X-Original-URL": "/hello/blobInput?name=hello.txt", + "X-WAWS-Unencoded-URL": "/hello/blobInput?name=hello.txt", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "get-hello-blobInput", + "UtcNow": "2022-08-15T07:52:01.8861913Z", + "RandGuid": "fa58f25f-74af-40e7-83a0-029a4331e9a7" + } + } +} diff --git a/ballerina-tests/tests/resources/http-query-blob-optional-input.json b/ballerina-tests/tests/resources/http-query-blob-optional-input.json new file mode 100644 index 00000000..9497c807 --- /dev/null +++ b/ballerina-tests/tests/resources/http-query-blob-optional-input.json @@ -0,0 +1,122 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/blobInput?name=hello1.txt", + "Method": "GET", + "Query": { + "name": "hello1.txt" + }, + "Headers": { + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "text/plain" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "01ebc672-cde0-4cc4-a5df-77de30196d8d" + ], + "X-ARR-LOG-ID": [ + "27b8e1d3-8468-4c53-a28c-7f84874488d3" + ], + "CLIENT-IP": [ + "10.0.32.17:43005" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.76:48828" + ], + "X-Original-URL": [ + "/hello/blobInput?name=hello1.txt" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/blobInput?name=hello1.txt" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + }, + "blobIn": "null" + }, + "Metadata": { + "name": "\"hello1.txt\"", + "Query": { + "name": "hello1.txt" + }, + "Headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Content-Length": "4", + "Content-Type": "text/plain", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "01ebc672-cde0-4cc4-a5df-77de30196d8d", + "X-ARR-LOG-ID": "27b8e1d3-8468-4c53-a28c-7f84874488d3", + "CLIENT-IP": "10.0.32.17:43005", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.76:48828", + "X-Original-URL": "/hello/blobInput?name=hello1.txt", + "X-WAWS-Unencoded-URL": "/hello/blobInput?name=hello1.txt", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "get-hello-blobInput", + "UtcNow": "2022-08-15T08:50:15.0529418Z", + "RandGuid": "8b11d3f8-ed35-4cbb-aeda-deeea3ef07c2" + } + } +} diff --git a/ballerina-tests/tests/resources/httpAccessorTest.json b/ballerina-tests/tests/resources/httpAccessorTest.json new file mode 100644 index 00000000..a0ab5a6c --- /dev/null +++ b/ballerina-tests/tests/resources/httpAccessorTest.json @@ -0,0 +1,107 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/httpAccessorTest", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/hello/httpAccessorTest" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/httpAccessorTest" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ] + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/hello/httpAccessorTest", + "X-WAWS-Unencoded-URL": "/hello/httpAccessorTest" + }, + "sys": { + "MethodName": "ACCESSOR_NAME-hello-httpAccessorTest", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/resources/httpHeaderTest.json b/ballerina-tests/tests/resources/httpHeaderTest.json new file mode 100644 index 00000000..7992b0b8 --- /dev/null +++ b/ballerina-tests/tests/resources/httpHeaderTest.json @@ -0,0 +1,120 @@ +{ + "Data":{ + "httpPayload":{ + "Url":"https://az-func-http-test.azurewebsites.net/httpHeader/FUNC_NAME", + "Method":"POST", + "Query":{ + + }, + "Headers":{ + "Content-Length":[ + "5" + ], + "Content-Type":[ + "text/plain" + ], + "Host":[ + "az-func-http-test.azurewebsites.net" + ], + "Max-Forwards":[ + "10" + ], + "User-Agent":[ + "ballerina" + ], + "test":[ + "12, 13, 14" + ], + "hos":[ + "" + ], + "X-ARR-LOG-ID":[ + "77ef8e37-520e-417b-a972-30746b719b60" + ], + "CLIENT-IP":[ + "45.121.88.92:53880" + ], + "DISGUISED-HOST":[ + "az-func-http-test.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID":[ + "az-func-http-test" + ], + "WAS-DEFAULT-HOSTNAME":[ + "az-func-http-test.azurewebsites.net" + ], + "X-Forwarded-Proto":[ + "https" + ], + "X-AppService-Proto":[ + "https" + ], + "X-ARR-SSL":[ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion":[ + "1.2" + ], + "X-Forwarded-For":[ + "45.121.88.92:53880" + ], + "X-Original-URL":[ + "/httpHeader/FUNC_NAME" + ], + "X-WAWS-Unencoded-URL":[ + "/httpHeader/FUNC_NAME" + ] + }, + "Params":{ + + }, + "Identities":[ + { + "AuthenticationType":null, + "IsAuthenticated":false, + "Actor":null, + "BootstrapContext":null, + "Claims":[ + + ], + "Label":null, + "Name":null, + "NameClaimType":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType":"http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body":"httpHeader" + } + }, + "Metadata":{ + "Query":{ + + }, + "Headers":{ + "Content-Length":"5", + "Content-Type":"text/plain", + "Host":"az-func-http-test.azurewebsites.net", + "Max-Forwards":"10", + "User-Agent":"ballerina", + "test":"12, 13, 14", + "hos": "", + "X-ARR-LOG-ID":"77ef8e37-520e-417b-a972-30746b719b60", + "CLIENT-IP":"45.121.88.92:53880", + "DISGUISED-HOST":"az-func-http-test.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID":"az-func-http-test", + "WAS-DEFAULT-HOSTNAME":"az-func-http-test.azurewebsites.net", + "X-Forwarded-Proto":"https", + "X-AppService-Proto":"https", + "X-ARR-SSL":"2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion":"1.2", + "X-Forwarded-For":"45.121.88.92:53880", + "X-Original-URL":"/httpHeader/FUNC_NAME", + "X-WAWS-Unencoded-URL":"/httpHeader/FUNC_NAME" + }, + "sys":{ + "MethodName":"post-httpHeader-FUNC_NAME", + "UtcNow":"2022-09-01T10:12:54.2952774Z", + "RandGuid":"f891f95b-cc04-4e8c-b440-24b8da192b28" + } + } + } diff --git a/ballerina-tests/tests/resources/httpResTest1.json b/ballerina-tests/tests/resources/httpResTest1.json new file mode 100644 index 00000000..40f86b23 --- /dev/null +++ b/ballerina-tests/tests/resources/httpResTest1.json @@ -0,0 +1,108 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/httpResTest1", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/hello/httpResTest1" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/httpResTest1" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/hello/httpResTest1", + "X-WAWS-Unencoded-URL": "/hello/httpResTest1" + }, + "sys": { + "MethodName": "post-hello-httpResTest1", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/resources/httpResTest2.json b/ballerina-tests/tests/resources/httpResTest2.json new file mode 100644 index 00000000..28c4373f --- /dev/null +++ b/ballerina-tests/tests/resources/httpResTest2.json @@ -0,0 +1,108 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/httpResTest2", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/hello/httpResTest2" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/httpResTest2" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/hello/httpResTest2", + "X-WAWS-Unencoded-URL": "/hello/httpResTest2" + }, + "sys": { + "MethodName": "post-hello-httpResTest2", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/resources/httpResTest3.json b/ballerina-tests/tests/resources/httpResTest3.json new file mode 100644 index 00000000..31e7c14d --- /dev/null +++ b/ballerina-tests/tests/resources/httpResTest3.json @@ -0,0 +1,108 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/httpResTest3", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/hello/httpResTest3" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/httpResTest3" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/hello/httpResTest3", + "X-WAWS-Unencoded-URL": "/hello/httpResTest3" + }, + "sys": { + "MethodName": "post-hello-httpResTest3", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/resources/httpResTest4.json b/ballerina-tests/tests/resources/httpResTest4.json new file mode 100644 index 00000000..d85447a3 --- /dev/null +++ b/ballerina-tests/tests/resources/httpResTest4.json @@ -0,0 +1,108 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/httpResTest4", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/hello/httpResTest4" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/httpResTest4" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/hello/httpResTest4", + "X-WAWS-Unencoded-URL": "/hello/httpResTest4" + }, + "sys": { + "MethodName": "post-hello-httpResTest4", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/resources/local-res-path.json b/ballerina-tests/tests/resources/local-res-path.json new file mode 100644 index 00000000..918cc420 --- /dev/null +++ b/ballerina-tests/tests/resources/local-res-path.json @@ -0,0 +1,99 @@ +{ + "Data": { + "httpPayload": { + "Url": "http://localhost:7071/hello/foo", + "Method": "GET", + "Query": {}, + "Headers": { + "Cache-Control": [ + "max-age=0" + ], + "Connection": [ + "keep-alive" + ], + "Accept": [ + "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Accept-Language": [ + "en-US,en;q=0.9" + ], + "Cookie": [ + "_ga=GA1.1.720190479.1641539348; _hjSessionUser_865786=eyJpZCI6IjhjNjRiYjkwLTA0NzYtNTc5MS1hZWNiLTRjN2VhZTM4OWM5NCIsImNyZWF0ZWQiOjE2NDE1MzkzNDg4NTAsImV4aXN0aW5nIjp0cnVlfQ==; Idea-2474b141=7a691445-10e4-435d-b306-2b36a77b1d2e; Webstorm-fe5cf5e6=379eafe5-e706-45c1-92e8-6e424ab655f0; cookie_accepted=1" + ], + "Host": [ + "localhost:7071" + ], + "User-Agent": [ + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" + ], + "Upgrade-Insecure-Requests": [ + "1" + ], + "sec-ch-ua": [ + "\".Not\/A)Brand\";v=\"99\", \"Google Chrome\";v=\"103\", \"Chromium\";v=\"103\"" + ], + "sec-ch-ua-mobile": [ + "?0" + ], + "sec-ch-ua-platform": [ + "\"Linux\"" + ], + "Sec-Fetch-Site": [ + "none" + ], + "Sec-Fetch-Mode": [ + "navigate" + ], + "Sec-Fetch-User": [ + "?1" + ], + "Sec-Fetch-Dest": [ + "document" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ] + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Cache-Control": "max-age=0", + "Connection": "keep-alive", + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "en-US,en;q=0.9", + "Cookie": "_ga=GA1.1.720190479.1641539348; _hjSessionUser_865786=eyJpZCI6IjhjNjRiYjkwLTA0NzYtNTc5MS1hZWNiLTRjN2VhZTM4OWM5NCIsImNyZWF0ZWQiOjE2NDE1MzkzNDg4NTAsImV4aXN0aW5nIjp0cnVlfQ==; Idea-2474b141=7a691445-10e4-435d-b306-2b36a77b1d2e; Webstorm-fe5cf5e6=379eafe5-e706-45c1-92e8-6e424ab655f0; cookie_accepted=1", + "Host": "localhost:7071", + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36", + "Upgrade-Insecure-Requests": "1", + "sec-ch-ua": "\".Not\/A)Brand\";v=\"99\", \"Google Chrome\";v=\"103\", \"Chromium\";v=\"103\"", + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": "\"Linux\"", + "Sec-Fetch-Site": "none", + "Sec-Fetch-Mode": "navigate", + "Sec-Fetch-User": "?1", + "Sec-Fetch-Dest": "document" + }, + "sys": { + "MethodName": "get-hello-foo", + "UtcNow": "2022-08-01T06:13:05.6335269Z", + "RandGuid": "eba6cb26-507a-40b1-a800-781964722f00" + } + } +} diff --git a/ballerina-tests/tests/resources/multi-path-param.json b/ballerina-tests/tests/resources/multi-path-param.json new file mode 100644 index 00000000..c64893f4 --- /dev/null +++ b/ballerina-tests/tests/resources/multi-path-param.json @@ -0,0 +1,112 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-svc-impl.azurewebsites.net/hello/foo/one/bar/two", + "Method": "POST", + "Query": { + }, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-svc-impl.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "df5cfa56-ac43-4671-8836-07537852bdf6" + ], + "CLIENT-IP": [ + "10.0.32.6:45851" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-svc-impl" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-svc-impl.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.134.89:51660" + ], + "X-Original-URL": [ + "/hello/foo/bar?test=hello" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/foo/bar?test=hello" + ], + "DISGUISED-HOST": [ + "bal-svc-impl.azurewebsites.net" + ] + }, + "Params": { + "RemainingPath": "foo/one/bar/two" + }, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": { + }, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-svc-impl.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "df5cfa56-ac43-4671-8836-07537852bdf6", + "CLIENT-IP": "10.0.32.6:45851", + "X-SITE-DEPLOYMENT-ID": "bal-svc-impl", + "WAS-DEFAULT-HOSTNAME": "bal-svc-impl.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.134.89:51660", + "X-Original-URL": "/hello/foo/bar?test=hello", + "X-WAWS-Unencoded-URL": "/hello/foo/bar?test=hello", + "DISGUISED-HOST": "bal-svc-impl.azurewebsites.net" + }, + "sys": { + "MethodName": "hello", + "UtcNow": "2022-04-29T10:51:55.458828Z", + "RandGuid": "c4747555-c815-4569-95ed-5d76f3691a98" + } + } +} diff --git a/ballerina-tests/tests/resources/multi-res-query.json b/ballerina-tests/tests/resources/multi-res-query.json new file mode 100644 index 00000000..4079638e --- /dev/null +++ b/ballerina-tests/tests/resources/multi-res-query.json @@ -0,0 +1,114 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-svc-impl.azurewebsites.net/hello/foo?name=hello", + "Method": "POST", + "Query": { + "name": "hello" + }, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-svc-impl.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "df5cfa56-ac43-4671-8836-07537852bdf6" + ], + "CLIENT-IP": [ + "10.0.32.6:45851" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-svc-impl" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-svc-impl.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.134.89:51660" + ], + "X-Original-URL": [ + "/hello/foo/bar?test=hello" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/foo/bar?test=hello" + ], + "DISGUISED-HOST": [ + "bal-svc-impl.azurewebsites.net" + ] + }, + "Params": { + "RemainingPath": "hello/foo" + }, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": { + "test": "hello" + }, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-svc-impl.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "df5cfa56-ac43-4671-8836-07537852bdf6", + "CLIENT-IP": "10.0.32.6:45851", + "X-SITE-DEPLOYMENT-ID": "bal-svc-impl", + "WAS-DEFAULT-HOSTNAME": "bal-svc-impl.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.134.89:51660", + "X-Original-URL": "/hello/foo/bar?test=hello", + "X-WAWS-Unencoded-URL": "/hello/foo/bar?test=hello", + "DISGUISED-HOST": "bal-svc-impl.azurewebsites.net" + }, + "sys": { + "MethodName": "hello", + "UtcNow": "2022-04-29T10:51:55.458828Z", + "RandGuid": "c4747555-c815-4569-95ed-5d76f3691a98" + } + } +} diff --git a/ballerina-tests/tests/resources/multi-res.json b/ballerina-tests/tests/resources/multi-res.json new file mode 100644 index 00000000..ff5b64c6 --- /dev/null +++ b/ballerina-tests/tests/resources/multi-res.json @@ -0,0 +1,112 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-svc-impl.azurewebsites.net/hello/foo/bar?test=hello", + "Method": "POST", + "Query": { + }, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-svc-impl.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "df5cfa56-ac43-4671-8836-07537852bdf6" + ], + "CLIENT-IP": [ + "10.0.32.6:45851" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-svc-impl" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-svc-impl.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.134.89:51660" + ], + "X-Original-URL": [ + "/hello/foo/bar?test=hello" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/foo/bar?test=hello" + ], + "DISGUISED-HOST": [ + "bal-svc-impl.azurewebsites.net" + ] + }, + "Params": { + "RemainingPath": "foo/bar" + }, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": { + }, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-svc-impl.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "df5cfa56-ac43-4671-8836-07537852bdf6", + "CLIENT-IP": "10.0.32.6:45851", + "X-SITE-DEPLOYMENT-ID": "bal-svc-impl", + "WAS-DEFAULT-HOSTNAME": "bal-svc-impl.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.134.89:51660", + "X-Original-URL": "/hello/foo/bar?test=hello", + "X-WAWS-Unencoded-URL": "/hello/foo/bar?test=hello", + "DISGUISED-HOST": "bal-svc-impl.azurewebsites.net" + }, + "sys": { + "MethodName": "hello", + "UtcNow": "2022-04-29T10:51:55.458828Z", + "RandGuid": "c4747555-c815-4569-95ed-5d76f3691a98" + } + } +} diff --git a/ballerina-tests/tests/resources/nonHttpResTest.json b/ballerina-tests/tests/resources/nonHttpResTest.json new file mode 100644 index 00000000..965b8e65 --- /dev/null +++ b/ballerina-tests/tests/resources/nonHttpResTest.json @@ -0,0 +1,108 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/FUNC_NAME", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/hello/FUNC_NAME" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/FUNC_NAME" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/hello/FUNC_NAME", + "X-WAWS-Unencoded-URL": "/hello/FUNC_NAME" + }, + "sys": { + "MethodName": "post-hello-FUNC_NAME", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/resources/nonReturnTest1.json b/ballerina-tests/tests/resources/nonReturnTest1.json new file mode 100644 index 00000000..317a2f81 --- /dev/null +++ b/ballerina-tests/tests/resources/nonReturnTest1.json @@ -0,0 +1,108 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/nonReturnTest1", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "10" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "28d97039-ef3e-4e6f-948b-680f7ff166f7" + ], + "CLIENT-IP": [ + "112.134.128.105:41856" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41856" + ], + "X-Original-URL": [ + "/hello/nonReturnTest1" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/nonReturnTest1" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "10", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "28d97039-ef3e-4e6f-948b-680f7ff166f7", + "CLIENT-IP": "112.134.128.105:41856", + "DISGUISED-HOST": "bal-dev.azurewebsites.net", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41856", + "X-Original-URL": "/hello/nonReturnTest1", + "X-WAWS-Unencoded-URL": "/hello/nonReturnTest1" + }, + "sys": { + "MethodName": "post-hello-nonReturnTest1", + "UtcNow": "2022-06-10T07:10:30.1722785Z", + "RandGuid": "19f5a752-e046-4f7f-964f-e53207baed7b" + } + } +} diff --git a/ballerina-tests/tests/resources/payload-json-json.json b/ballerina-tests/tests/resources/payload-json-json.json new file mode 100644 index 00000000..6f51b603 --- /dev/null +++ b/ballerina-tests/tests/resources/payload-json-json.json @@ -0,0 +1,118 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Content-Length": [ + "41" + ], + "Content-Type": [ + "application/json" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "39884e46-dbbd-4396-a921-d24cd2003063" + ], + "X-ARR-LOG-ID": [ + "0320ea36-d38d-476d-a3d2-61cb5b113763" + ], + "CLIENT-IP": [ + "10.0.32.18:48308" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.131.214:19414" + ], + "X-Original-URL": [ + "/hello" + ], + "X-WAWS-Unencoded-URL": [ + "/hello" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "{\n \"name\" : \"Anjana\",\n \"age\" : 12\n}" + } + }, + "Metadata": { + "name": "\"Anjana\"", + "age": "\"12\"", + "Query": {}, + "Headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Content-Length": "41", + "Content-Type": "application/json", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "39884e46-dbbd-4396-a921-d24cd2003063", + "X-ARR-LOG-ID": "0320ea36-d38d-476d-a3d2-61cb5b113763", + "CLIENT-IP": "10.0.32.18:48308", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.131.214:19414", + "X-Original-URL": "/hello", + "X-WAWS-Unencoded-URL": "/hello", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "post-hello-payload-jsonToJson", + "UtcNow": "2022-06-20T07:50:50.4482488Z", + "RandGuid": "3e4ea15e-30cf-408b-8e72-58409d33e9c4" + } + } +} diff --git a/ballerina-tests/tests/resources/payload-json-record.json b/ballerina-tests/tests/resources/payload-json-record.json new file mode 100644 index 00000000..c7bc678d --- /dev/null +++ b/ballerina-tests/tests/resources/payload-json-record.json @@ -0,0 +1,118 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Content-Length": [ + "41" + ], + "Content-Type": [ + "application/json" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "39884e46-dbbd-4396-a921-d24cd2003063" + ], + "X-ARR-LOG-ID": [ + "0320ea36-d38d-476d-a3d2-61cb5b113763" + ], + "CLIENT-IP": [ + "10.0.32.18:48308" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.131.214:19414" + ], + "X-Original-URL": [ + "/hello" + ], + "X-WAWS-Unencoded-URL": [ + "/hello" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "{\n \"name\" : \"Anjana\",\n \"age\" : 12\n}" + } + }, + "Metadata": { + "name": "\"Anjana\"", + "age": "\"12\"", + "Query": {}, + "Headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Content-Length": "41", + "Content-Type": "application/json", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "39884e46-dbbd-4396-a921-d24cd2003063", + "X-ARR-LOG-ID": "0320ea36-d38d-476d-a3d2-61cb5b113763", + "CLIENT-IP": "10.0.32.18:48308", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.131.214:19414", + "X-Original-URL": "/hello", + "X-WAWS-Unencoded-URL": "/hello", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "post-hello-payload-jsonToRecord", + "UtcNow": "2022-06-20T07:50:50.4482488Z", + "RandGuid": "3e4ea15e-30cf-408b-8e72-58409d33e9c4" + } + } +} diff --git a/ballerina-tests/tests/resources/payload-octa-byte.json b/ballerina-tests/tests/resources/payload-octa-byte.json new file mode 100644 index 00000000..d4de06dc --- /dev/null +++ b/ballerina-tests/tests/resources/payload-octa-byte.json @@ -0,0 +1,116 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/payload/octaToByte", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Content-Length": [ + "20" + ], + "Content-Type": [ + "application/octet-stream" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "4464b495-cbb0-4398-b79f-9b626afc54af" + ], + "X-ARR-LOG-ID": [ + "03f45b02-ca0c-44a4-8fbd-1a916dc44743" + ], + "CLIENT-IP": [ + "10.0.32.9:31863" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.183:8622" + ], + "X-Original-URL": [ + "/hello/payload/octaToByte" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/payload/octaToByte" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "aGVsbG8gZnJvbSBieXRlIGFycgo=" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Content-Length": "20", + "Content-Type": "application/octet-stream", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "4464b495-cbb0-4398-b79f-9b626afc54af", + "X-ARR-LOG-ID": "03f45b02-ca0c-44a4-8fbd-1a916dc44743", + "CLIENT-IP": "10.0.32.9:31863", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.183:8622", + "X-Original-URL": "/hello/payload/octaToByte", + "X-WAWS-Unencoded-URL": "/hello/payload/octaToByte", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "post-hello-payload-octaToByte", + "UtcNow": "2022-06-21T09:16:39.7549127Z", + "RandGuid": "4d6607a9-6f7f-47ab-b604-9d38b6d60166" + } + } +} diff --git a/ballerina-tests/tests/resources/payload-text-byte.json b/ballerina-tests/tests/resources/payload-text-byte.json new file mode 100644 index 00000000..0353da2a --- /dev/null +++ b/ballerina-tests/tests/resources/payload-text-byte.json @@ -0,0 +1,116 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/payload/textToByte", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Content-Length": [ + "16" + ], + "Content-Type": [ + "text/plain" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "30ab1809-31c6-4289-bdf1-211af03494e6" + ], + "X-ARR-LOG-ID": [ + "583960d3-f15e-40ba-8c6e-f36ef5f9b04d" + ], + "CLIENT-IP": [ + "10.0.32.17:56250" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.183:7912" + ], + "X-Original-URL": [ + "/hello/payload/textToByte" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/payload/textToByte" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "hello from byte\n" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Content-Length": "16", + "Content-Type": "text/plain", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "30ab1809-31c6-4289-bdf1-211af03494e6", + "X-ARR-LOG-ID": "583960d3-f15e-40ba-8c6e-f36ef5f9b04d", + "CLIENT-IP": "10.0.32.17:56250", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.183:7912", + "X-Original-URL": "/hello/payload/textToByte", + "X-WAWS-Unencoded-URL": "/hello/payload/textToByte", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "post-hello-payload-textToByte", + "UtcNow": "2022-06-21T09:03:30.9844689Z", + "RandGuid": "1a881943-cf07-4ead-b539-d86c5040e2b7" + } + } +} diff --git a/ballerina-tests/tests/resources/payload-text-string.json b/ballerina-tests/tests/resources/payload-text-string.json new file mode 100644 index 00000000..c807f601 --- /dev/null +++ b/ballerina-tests/tests/resources/payload-text-string.json @@ -0,0 +1,116 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/payload/textToString", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Content-Length": [ + "16" + ], + "Content-Type": [ + "text/plain" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "0a6f2d81-c33b-46eb-8de5-fa3f89dbd102" + ], + "X-ARR-LOG-ID": [ + "b726530b-e6cf-45f4-a33d-61a6dc9b50ff" + ], + "CLIENT-IP": [ + "10.0.32.6:44171" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.183:7868" + ], + "X-Original-URL": [ + "/hello/payload/textToString" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/payload/textToString" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "hello from byte\n" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Content-Length": "16", + "Content-Type": "text/plain", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "0a6f2d81-c33b-46eb-8de5-fa3f89dbd102", + "X-ARR-LOG-ID": "b726530b-e6cf-45f4-a33d-61a6dc9b50ff", + "CLIENT-IP": "10.0.32.6:44171", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.183:7868", + "X-Original-URL": "/hello/payload/textToString", + "X-WAWS-Unencoded-URL": "/hello/payload/textToString", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "post-hello-payload-textToString", + "UtcNow": "2022-06-21T08:19:49.9190374Z", + "RandGuid": "b079ac9b-37d8-4037-a4fe-2c4a367ea4bd" + } + } +} diff --git a/ballerina-tests/tests/resources/payload-xml-xml.json b/ballerina-tests/tests/resources/payload-xml-xml.json new file mode 100644 index 00000000..deb7c8d1 --- /dev/null +++ b/ballerina-tests/tests/resources/payload-xml-xml.json @@ -0,0 +1,116 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/payload/xmlToXml", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Content-Length": [ + "92" + ], + "Content-Type": [ + "application/xml" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "35be09d4-fc8d-45c5-ba43-1cea2e71d92d" + ], + "X-ARR-LOG-ID": [ + "138a364a-acfc-47b1-a28d-8d6cdadd15ed" + ], + "CLIENT-IP": [ + "10.0.32.13:26380" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.131.47:2686" + ], + "X-Original-URL": [ + "/hello/payload/xmlToXml" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/payload/xmlToXml" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "\n\n Anjana<\/name>\n 12<\/age>\n<\/root>" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Content-Length": "92", + "Content-Type": "application/xml", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "35be09d4-fc8d-45c5-ba43-1cea2e71d92d", + "X-ARR-LOG-ID": "138a364a-acfc-47b1-a28d-8d6cdadd15ed", + "CLIENT-IP": "10.0.32.13:26380", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.131.47:2686", + "X-Original-URL": "/hello/payload/xmlToXml", + "X-WAWS-Unencoded-URL": "/hello/payload/xmlToXml", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "post-hello-payload-xmlToXml", + "UtcNow": "2022-06-20T14:58:03.9297621Z", + "RandGuid": "2e7871d4-c404-49ad-ae44-e148f33be742" + } + } +} diff --git a/ballerina-tests/tests/resources/query-arr-no-payload.json b/ballerina-tests/tests/resources/query-arr-no-payload.json new file mode 100644 index 00000000..48a73ea6 --- /dev/null +++ b/ballerina-tests/tests/resources/query-arr-no-payload.json @@ -0,0 +1,113 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-svc-impl.azurewebsites.net/hello", + "Method": "GET", + "Query": { + "name" : ["Jack 1", "Jack 2"] + }, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-svc-impl.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "df5cfa56-ac43-4671-8836-07537852bdf6" + ], + "CLIENT-IP": [ + "10.0.32.6:45851" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-svc-impl" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-svc-impl.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.134.89:51660" + ], + "X-Original-URL": [ + "/hello/foo/bar?test=hello" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/foo/bar?test=hello" + ], + "DISGUISED-HOST": [ + "bal-svc-impl.azurewebsites.net" + ] + }, + "Params": { + "RemainingPath": null + }, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": { + }, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-svc-impl.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "df5cfa56-ac43-4671-8836-07537852bdf6", + "CLIENT-IP": "10.0.32.6:45851", + "X-SITE-DEPLOYMENT-ID": "bal-svc-impl", + "WAS-DEFAULT-HOSTNAME": "bal-svc-impl.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.134.89:51660", + "X-Original-URL": "/hello/foo/bar?test=hello", + "X-WAWS-Unencoded-URL": "/hello/foo/bar?test=hello", + "DISGUISED-HOST": "bal-svc-impl.azurewebsites.net" + }, + "sys": { + "MethodName": "hello", + "UtcNow": "2022-04-29T10:51:55.458828Z", + "RandGuid": "c4747555-c815-4569-95ed-5d76f3691a98" + } + } +} diff --git a/ballerina-tests/tests/resources/query-arr-optional-with.json b/ballerina-tests/tests/resources/query-arr-optional-with.json new file mode 100644 index 00000000..b714ac93 --- /dev/null +++ b/ballerina-tests/tests/resources/query-arr-optional-with.json @@ -0,0 +1,64 @@ +{ + "Data": { + "httpPayload": { + "Url": "http://localhost:7071/hello/query/arrOrNil?name=red&name=green", + "Method": "GET", + "Query": { + "name": "red,green" + }, + "Headers": { + "Connection": [ + "keep-alive" + ], + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Host": [ + "localhost:7071" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "5de49357-5322-41f2-9550-8d85df57c66b" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ] + } + }, + "Metadata": { + "name": "\"green\"", + "Query": { + "name": "green" + }, + "Headers": { + "Connection": "keep-alive", + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Host": "localhost:7071", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "5de49357-5322-41f2-9550-8d85df57c66b" + }, + "sys": { + "MethodName": "get-hello-query-arrOrNil", + "UtcNow": "2022-08-16T10:37:07.6777821Z", + "RandGuid": "3ae73282-ec8d-4f0e-8e9e-4f3e0602b175" + } + } +} diff --git a/ballerina-tests/tests/resources/query-arr-optional-without.json b/ballerina-tests/tests/resources/query-arr-optional-without.json new file mode 100644 index 00000000..ce25880e --- /dev/null +++ b/ballerina-tests/tests/resources/query-arr-optional-without.json @@ -0,0 +1,59 @@ +{ + "Data": { + "httpPayload": { + "Url": "http://localhost:7071/hello/query/arrOrNil", + "Method": "GET", + "Query": {}, + "Headers": { + "Connection": [ + "keep-alive" + ], + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Host": [ + "localhost:7071" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "49b7bbcb-bd4f-4f2c-a897-ce35236acdfe" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ] + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Connection": "keep-alive", + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Host": "localhost:7071", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "49b7bbcb-bd4f-4f2c-a897-ce35236acdfe" + }, + "sys": { + "MethodName": "get-hello-query-arrOrNil", + "UtcNow": "2022-08-16T10:38:59.2405064Z", + "RandGuid": "5de1fdb9-ed9e-43a1-80ca-57e596a2b146" + } + } +} diff --git a/ballerina-tests/tests/resources/query-arr.json b/ballerina-tests/tests/resources/query-arr.json new file mode 100644 index 00000000..cd2ad2f8 --- /dev/null +++ b/ballerina-tests/tests/resources/query-arr.json @@ -0,0 +1,64 @@ +{ + "Data": { + "httpPayload": { + "Url": "http://localhost:7071/hello/query/arr?name=red&name=green", + "Method": "GET", + "Query": { + "name": "red,green" + }, + "Headers": { + "Connection": [ + "keep-alive" + ], + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Host": [ + "localhost:7071" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "5de49357-5322-41f2-9550-8d85df57c66b" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ] + } + }, + "Metadata": { + "name": "\"green\"", + "Query": { + "name": "green" + }, + "Headers": { + "Connection": "keep-alive", + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Host": "localhost:7071", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "5de49357-5322-41f2-9550-8d85df57c66b" + }, + "sys": { + "MethodName": "get-hello-query-arr", + "UtcNow": "2022-08-16T10:37:07.6777821Z", + "RandGuid": "3ae73282-ec8d-4f0e-8e9e-4f3e0602b175" + } + } +} diff --git a/ballerina-tests/tests/resources/query-bool.json b/ballerina-tests/tests/resources/query-bool.json new file mode 100644 index 00000000..b06feaec --- /dev/null +++ b/ballerina-tests/tests/resources/query-bool.json @@ -0,0 +1,64 @@ +{ + "Data": { + "httpPayload": { + "Url": "http://localhost:7071/hello/query/bool?name=false", + "Method": "GET", + "Query": { + "name": "false" + }, + "Headers": { + "Connection": [ + "keep-alive" + ], + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Host": [ + "localhost:7071" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "1854bfc5-0e04-4793-ac51-b9dba41d0272" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ] + } + }, + "Metadata": { + "name": "\"false\"", + "Query": { + "name": "false" + }, + "Headers": { + "Connection": "keep-alive", + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Host": "localhost:7071", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "1854bfc5-0e04-4793-ac51-b9dba41d0272" + }, + "sys": { + "MethodName": "get-hello-query-bool", + "UtcNow": "2022-08-16T10:26:19.8474115Z", + "RandGuid": "74449761-f557-450c-b969-a48b5647dcf1" + } + } +} diff --git a/ballerina-tests/tests/resources/query-float.json b/ballerina-tests/tests/resources/query-float.json new file mode 100644 index 00000000..1f48a9c5 --- /dev/null +++ b/ballerina-tests/tests/resources/query-float.json @@ -0,0 +1,64 @@ +{ + "Data": { + "httpPayload": { + "Url": "http://localhost:7071/hello/floatt/bool?name=10.5", + "Method": "GET", + "Query": { + "name": "10.5" + }, + "Headers": { + "Connection": [ + "keep-alive" + ], + "Accept": [ + "*/*" + ], + "Accept-Encoding": [ + "gzip, deflate, br" + ], + "Host": [ + "localhost:7071" + ], + "User-Agent": [ + "PostmanRuntime/7.26.8" + ], + "Postman-Token": [ + "0af627a1-73fe-4990-865d-6e438249ae98" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ] + } + }, + "Metadata": { + "name": "\"10.5\"", + "Query": { + "name": "10.5" + }, + "Headers": { + "Connection": "keep-alive", + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate, br", + "Host": "localhost:7071", + "User-Agent": "PostmanRuntime/7.26.8", + "Postman-Token": "0af627a1-73fe-4990-865d-6e438249ae98" + }, + "sys": { + "MethodName": "get-hello-query-floatt", + "UtcNow": "2022-08-16T10:28:47.6485592Z", + "RandGuid": "e31b37f3-08fe-4268-aabb-ff055227f24d" + } + } +} diff --git a/ballerina-tests/tests/resources/query-no-payload.json b/ballerina-tests/tests/resources/query-no-payload.json new file mode 100644 index 00000000..49f2f518 --- /dev/null +++ b/ballerina-tests/tests/resources/query-no-payload.json @@ -0,0 +1,113 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-svc-impl.azurewebsites.net/hello", + "Method": "GET", + "Query": { + "name" : "Jack" + }, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-svc-impl.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "df5cfa56-ac43-4671-8836-07537852bdf6" + ], + "CLIENT-IP": [ + "10.0.32.6:45851" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-svc-impl" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-svc-impl.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.134.89:51660" + ], + "X-Original-URL": [ + "/hello/foo/bar?test=hello" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/foo/bar?test=hello" + ], + "DISGUISED-HOST": [ + "bal-svc-impl.azurewebsites.net" + ] + }, + "Params": { + "RemainingPath": null + }, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": { + }, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-svc-impl.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "df5cfa56-ac43-4671-8836-07537852bdf6", + "CLIENT-IP": "10.0.32.6:45851", + "X-SITE-DEPLOYMENT-ID": "bal-svc-impl", + "WAS-DEFAULT-HOSTNAME": "bal-svc-impl.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.134.89:51660", + "X-Original-URL": "/hello/foo/bar?test=hello", + "X-WAWS-Unencoded-URL": "/hello/foo/bar?test=hello", + "DISGUISED-HOST": "bal-svc-impl.azurewebsites.net" + }, + "sys": { + "MethodName": "hello", + "UtcNow": "2022-04-29T10:51:55.458828Z", + "RandGuid": "c4747555-c815-4569-95ed-5d76f3691a98" + } + } +} diff --git a/ballerina-tests/tests/resources/query-optional-with.json b/ballerina-tests/tests/resources/query-optional-with.json new file mode 100644 index 00000000..607d036b --- /dev/null +++ b/ballerina-tests/tests/resources/query-optional-with.json @@ -0,0 +1,113 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/query/optional?name=test1", + "Method": "GET", + "Query": { + "name": "test1" + }, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "072319b5-49e5-4c56-859c-4fcc1a714811" + ], + "CLIENT-IP": [ + "10.0.32.4:29256" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.130.212:18792" + ], + "X-Original-URL": [ + "/hello/query/optional?name=test1" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/query/optional?name=test1" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "name": "\"test1\"", + "Query": { + "name": "test1" + }, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "072319b5-49e5-4c56-859c-4fcc1a714811", + "CLIENT-IP": "10.0.32.4:29256", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.130.212:18792", + "X-Original-URL": "/hello/query/optional?name=test1", + "X-WAWS-Unencoded-URL": "/hello/query/optional?name=test1", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "get-hello-query-optional", + "UtcNow": "2022-06-13T10:12:25.6088199Z", + "RandGuid": "80274c51-3807-49ae-bfbf-44c5b74fa4e9" + } + } +} diff --git a/ballerina-tests/tests/resources/query-optional-without.json b/ballerina-tests/tests/resources/query-optional-without.json new file mode 100644 index 00000000..a04a256b --- /dev/null +++ b/ballerina-tests/tests/resources/query-optional-without.json @@ -0,0 +1,111 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/query/optional", + "Method": "GET", + "Query": { + }, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "072319b5-49e5-4c56-859c-4fcc1a714811" + ], + "CLIENT-IP": [ + "10.0.32.4:29256" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.130.212:18792" + ], + "X-Original-URL": [ + "/hello/query/optional" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/query/optional" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "name": "\"test1\"", + "Query": { + }, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "072319b5-49e5-4c56-859c-4fcc1a714811", + "CLIENT-IP": "10.0.32.4:29256", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.130.212:18792", + "X-Original-URL": "/hello/query/optional", + "X-WAWS-Unencoded-URL": "/hello/query/optional", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "get-hello-query-optional", + "UtcNow": "2022-06-13T10:12:25.6088199Z", + "RandGuid": "80274c51-3807-49ae-bfbf-44c5b74fa4e9" + } + } +} diff --git a/ballerina-tests/tests/resources/query-param.json b/ballerina-tests/tests/resources/query-param.json new file mode 100644 index 00000000..1cec095b --- /dev/null +++ b/ballerina-tests/tests/resources/query-param.json @@ -0,0 +1,113 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/query?name=test1", + "Method": "POST", + "Query": { + "name": "test1" + }, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "072319b5-49e5-4c56-859c-4fcc1a714811" + ], + "CLIENT-IP": [ + "10.0.32.4:29256" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.130.212:18792" + ], + "X-Original-URL": [ + "/hello/query?name=test1" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/query?name=test1" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "name": "\"test1\"", + "Query": { + "name": "test1" + }, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "072319b5-49e5-4c56-859c-4fcc1a714811", + "CLIENT-IP": "10.0.32.4:29256", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.130.212:18792", + "X-Original-URL": "/hello/query?name=test1", + "X-WAWS-Unencoded-URL": "/hello/query?name=test1", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "post-hello-query", + "UtcNow": "2022-06-13T10:12:25.6088199Z", + "RandGuid": "80274c51-3807-49ae-bfbf-44c5b74fa4e9" + } + } +} diff --git a/ballerina-tests/tests/resources/queue-input.json b/ballerina-tests/tests/resources/queue-input.json new file mode 100644 index 00000000..c3e41eeb --- /dev/null +++ b/ballerina-tests/tests/resources/queue-input.json @@ -0,0 +1,19 @@ +{ + "Data": { + "inMsg": "\"qqeeewwww\"", + "input1": "[{\"id\":\"hello1\",\"_rid\":\"zlIsAKxe8VCBhB4AAAAAAA==\",\"_self\":\"dbs\/zlIsAA==\/colls\/zlIsAKxe8VA=\/docs\/zlIsAKxe8VCBhB4AAAAAAA==\/\",\"_etag\":\"\\\"3d00aaf8-0000-0700-0000-625412270000\\\"\",\"_attachments\":\"attachments\/\",\"_ts\":1649676839},{\"id\":\"ssss\",\"_rid\":\"zlIsAKxe8VCChB4AAAAAAA==\",\"_self\":\"dbs\/zlIsAA==\/colls\/zlIsAKxe8VA=\/docs\/zlIsAKxe8VCChB4AAAAAAA==\/\",\"_etag\":\"\\\"3e00ed1c-0000-0700-0000-625412970000\\\"\",\"_attachments\":\"attachments\/\",\"_ts\":1649676951},{\"id\":\"hello2\",\"_rid\":\"zlIsAKxe8VCDhB4AAAAAAA==\",\"_self\":\"dbs\/zlIsAA==\/colls\/zlIsAKxe8VA=\/docs\/zlIsAKxe8VCDhB4AAAAAAA==\/\",\"_etag\":\"\\\"3e00c262-0000-0700-0000-625413330000\\\"\",\"_attachments\":\"attachments\/\",\"_ts\":1649677107},{\"id\":\"01ecf794-9b0a-132e-8eb4-4019891a13ad\",\"name\":\"Jack\",\"country\":\"Sri Lanka\",\"_rid\":\"zlIsAKxe8VCEhB4AAAAAAA==\",\"_self\":\"dbs\/zlIsAA==\/colls\/zlIsAKxe8VA=\/docs\/zlIsAKxe8VCEhB4AAAAAAA==\/\",\"_etag\":\"\\\"1f0554aa-0000-0700-0000-62bc269a0000\\\"\",\"_attachments\":\"attachments\/\",\"_ts\":1656497818},{\"id\":\"replace_with_new_document_id\",\"name\":\"Anjana\",\"_rid\":\"zlIsAKxe8VCFhB4AAAAAAA==\",\"_self\":\"dbs\/zlIsAA==\/colls\/zlIsAKxe8VA=\/docs\/zlIsAKxe8VCFhB4AAAAAAA==\/\",\"_etag\":\"\\\"1f05eac6-0000-0700-0000-62bc3e700000\\\"\",\"_attachments\":\"attachments\/\",\"_ts\":1656503920},{\"id\":\"tessstt\",\"_rid\":\"zlIsAKxe8VCGhB4AAAAAAA==\",\"_self\":\"dbs\/zlIsAA==\/colls\/zlIsAKxe8VA=\/docs\/zlIsAKxe8VCGhB4AAAAAAA==\/\",\"_etag\":\"\\\"1f0568ca-0000-0700-0000-62bc41500000\\\"\",\"_attachments\":\"attachments\/\",\"_ts\":1656504656},{\"id\":\"ehee\",\"_rid\":\"zlIsAKxe8VCHhB4AAAAAAA==\",\"_self\":\"dbs\/zlIsAA==\/colls\/zlIsAKxe8VA=\/docs\/zlIsAKxe8VCHhB4AAAAAAA==\/\",\"_etag\":\"\\\"1f0507d0-0000-0700-0000-62bc45ca0000\\\"\",\"_attachments\":\"attachments\/\",\"_ts\":1656505802},{\"id\":\"qqme\",\"_rid\":\"zlIsAKxe8VCIhB4AAAAAAA==\",\"_self\":\"dbs\/zlIsAA==\/colls\/zlIsAKxe8VA=\/docs\/zlIsAKxe8VCIhB4AAAAAAA==\/\",\"_etag\":\"\\\"0d00f5cb-0000-0700-0000-62be88f40000\\\"\",\"_attachments\":\"attachments\/\",\"_ts\":1656654068}]" + }, + "Metadata": { + "DequeueCount": "1", + "ExpirationTime": "2022-07-14T04:40:05+00:00", + "Id": "\"71d4bded-1113-4cd2-9cc2-8886f3fffea7\"", + "InsertionTime": "2022-07-07T04:40:05+00:00", + "NextVisibleTime": "2022-07-07T04:50:25+00:00", + "PopReceipt": "\"AgAAAAMAAAAAAAAA64VxEr2R2AE=\"", + "sys": { + "MethodName": "queue-input", + "UtcNow": "2022-07-07T04:40:25.4502012Z", + "RandGuid": "a5beb30f-4f4d-4853-99b3-56aa2966d897" + } + } +} diff --git a/ballerina-tests/tests/resources/queue-string.json b/ballerina-tests/tests/resources/queue-string.json new file mode 100644 index 00000000..e925ea26 --- /dev/null +++ b/ballerina-tests/tests/resources/queue-string.json @@ -0,0 +1,18 @@ +{ + "Data": { + "inMsg": "\"aaaaa\"" + }, + "Metadata": { + "DequeueCount": "1", + "ExpirationTime": "2022-06-20T06:00:06+00:00", + "Id": "\"a0004923-f050-417a-9742-6d7c7b984134\"", + "InsertionTime": "2022-06-13T06:00:06+00:00", + "NextVisibleTime": "2022-06-13T06:10:18+00:00", + "PopReceipt": "\"AgAAAAMAAAAAAAAA8d5gQex+2AE=\"", + "sys": { + "MethodName": "queue", + "UtcNow": "2022-06-13T06:00:18.1974545Z", + "RandGuid": "d9ba2785-ee1a-4260-a83b-f57cb54b969e" + } + } +} diff --git a/ballerina-tests/tests/resources/res-path-conflict-param.json b/ballerina-tests/tests/resources/res-path-conflict-param.json new file mode 100644 index 00000000..b9d26415 --- /dev/null +++ b/ballerina-tests/tests/resources/res-path-conflict-param.json @@ -0,0 +1,111 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/foo/meow", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "17355b71-874c-4cea-ac49-226eaffc9423" + ], + "CLIENT-IP": [ + "10.0.32.7:33881" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:42408" + ], + "X-Original-URL": [ + "/hello/foo/meow" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/foo/meow" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": { + "bar": "meow" + }, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "bar": "\"meow\"", + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "17355b71-874c-4cea-ac49-226eaffc9423", + "CLIENT-IP": "10.0.32.7:33881", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:42408", + "X-Original-URL": "/hello/foo/meow", + "X-WAWS-Unencoded-URL": "/hello/foo/meow", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "post-hello-foo-bar-1", + "UtcNow": "2022-06-10T08:23:28.1520104Z", + "RandGuid": "6d6d581c-3dce-4907-8638-c1f18a6e0d64" + } + } +} diff --git a/ballerina-tests/tests/resources/res-path-param.json b/ballerina-tests/tests/resources/res-path-param.json new file mode 100644 index 00000000..d148318a --- /dev/null +++ b/ballerina-tests/tests/resources/res-path-param.json @@ -0,0 +1,108 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/foo/bar", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "aedb1fdc-e89c-4740-aa5f-40ed87792703" + ], + "CLIENT-IP": [ + "10.0.32.6:54697" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:42010" + ], + "X-Original-URL": [ + "/hello/foo/bar" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/foo/bar" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "aedb1fdc-e89c-4740-aa5f-40ed87792703", + "CLIENT-IP": "10.0.32.6:54697", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:42010", + "X-Original-URL": "/hello/foo/bar", + "X-WAWS-Unencoded-URL": "/hello/foo/bar", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "post-hello-foo-bar-2", + "UtcNow": "2022-06-10T07:57:46.8453883Z", + "RandGuid": "0f4737ff-5b49-4e1d-9639-e51aaca81bc6" + } + } +} diff --git a/ballerina-tests/tests/resources/res-path.json b/ballerina-tests/tests/resources/res-path.json new file mode 100644 index 00000000..27c7db85 --- /dev/null +++ b/ballerina-tests/tests/resources/res-path.json @@ -0,0 +1,108 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-dev.azurewebsites.net/hello/foo", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-dev.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "1d35ad4a-0f3e-4be3-838b-c2983d0283f9" + ], + "CLIENT-IP": [ + "10.0.32.17:60066" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-dev" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-dev.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.128.105:41478" + ], + "X-Original-URL": [ + "/hello/foo" + ], + "X-WAWS-Unencoded-URL": [ + "/hello/foo" + ], + "DISGUISED-HOST": [ + "bal-dev.azurewebsites.net" + ] + }, + "Params": {}, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-dev.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "1d35ad4a-0f3e-4be3-838b-c2983d0283f9", + "CLIENT-IP": "10.0.32.17:60066", + "X-SITE-DEPLOYMENT-ID": "bal-dev", + "WAS-DEFAULT-HOSTNAME": "bal-dev.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.128.105:41478", + "X-Original-URL": "/hello/foo", + "X-WAWS-Unencoded-URL": "/hello/foo", + "DISGUISED-HOST": "bal-dev.azurewebsites.net" + }, + "sys": { + "MethodName": "post-hello-foo", + "UtcNow": "2022-06-10T08:29:04.8772396Z", + "RandGuid": "a0799c47-3216-47cf-9814-b50c05104c08" + } + } +} diff --git a/ballerina-tests/tests/request.json b/ballerina-tests/tests/resources/simple.json similarity index 88% rename from ballerina-tests/tests/request.json rename to ballerina-tests/tests/resources/simple.json index facc0207..91f655c2 100644 --- a/ballerina-tests/tests/request.json +++ b/ballerina-tests/tests/resources/simple.json @@ -1,7 +1,7 @@ { "Data": { - "payload": { - "Url": "https://functions1778.azurewebsites.net/api/hello", + "httpPayload": { + "Url": "https://functions1778.azurewebsites.net/hello", "Method": "POST", "Query": {}, "Headers": { @@ -12,12 +12,12 @@ "Host": ["functions1778.azurewebsites.net"], "Max-Forwards": ["9"], "User-Agent": ["curl/7.71.1"], - "X-WAWS-Unencoded-URL": ["/api/hello"], + "X-WAWS-Unencoded-URL": ["/hello"], "CLIENT-IP": ["10.0.128.35:48692"], "X-ARR-LOG-ID": ["b1d1b77a-689a-41a0-8e6e-aeb9563c7c41"], "X-SITE-DEPLOYMENT-ID": ["functions1778"], "WAS-DEFAULT-HOSTNAME": ["functions1778.azurewebsites.net"], - "X-Original-URL": ["/api/hello"], + "X-Original-URL": ["/hello"], "X-Forwarded-For": ["45.30.94.9:41710"], "X-ARR-SSL": ["2048|256|C=US, O=Microsoft Corporation, CN=Microsoft RSA TLS CA 01|CN=*.azurewebsites.net"], "X-Forwarded-Proto": ["https"], @@ -25,7 +25,9 @@ "X-Forwarded-TlsVersion": ["1.2"], "DISGUISED-HOST": ["functions1778.azurewebsites.net"] }, - "Params": {}, + "Params": { + "RemainingPath" : null + }, "Identities": [{ "AuthenticationType": null, "IsAuthenticated": false, @@ -50,12 +52,12 @@ "Host": "functions1778.azurewebsites.net", "Max-Forwards": "9", "User-Agent": "curl/7.71.1", - "X-WAWS-Unencoded-URL": "/api/hello", + "X-WAWS-Unencoded-URL": "/hello", "CLIENT-IP": "10.0.128.35:48692", "X-ARR-LOG-ID": "b1d1b77a-689a-41a0-8e6e-aeb9563c7c41", "X-SITE-DEPLOYMENT-ID": "functions1778", "WAS-DEFAULT-HOSTNAME": "functions1778.azurewebsites.net", - "X-Original-URL": "/api/hello", + "X-Original-URL": "/hello", "X-Forwarded-For": "45.30.94.9:41710", "X-ARR-SSL": "2048|256|C=US, O=Microsoft Corporation, CN=Microsoft RSA TLS CA 01|CN=*.azurewebsites.net", "X-Forwarded-Proto": "https", diff --git a/ballerina-tests/tests/resources/temp.json b/ballerina-tests/tests/resources/temp.json new file mode 100644 index 00000000..70e920b0 --- /dev/null +++ b/ballerina-tests/tests/resources/temp.json @@ -0,0 +1,110 @@ +{ + "Data": { + "httpPayload": { + "Url": "https://bal-svc-impl.azurewebsites.net/hello", + "Method": "POST", + "Query": {}, + "Headers": { + "Accept": [ + "*/*" + ], + "Content-Length": [ + "4" + ], + "Content-Type": [ + "application/x-www-form-urlencoded" + ], + "Host": [ + "bal-svc-impl.azurewebsites.net" + ], + "Max-Forwards": [ + "9" + ], + "User-Agent": [ + "curl/7.78.0" + ], + "X-ARR-LOG-ID": [ + "8a17b6d7-b17e-4edd-9fd4-025fe03e1859" + ], + "CLIENT-IP": [ + "10.0.32.13:54062" + ], + "X-SITE-DEPLOYMENT-ID": [ + "bal-svc-impl" + ], + "WAS-DEFAULT-HOSTNAME": [ + "bal-svc-impl.azurewebsites.net" + ], + "X-Forwarded-Proto": [ + "https" + ], + "X-AppService-Proto": [ + "https" + ], + "X-ARR-SSL": [ + "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US" + ], + "X-Forwarded-TlsVersion": [ + "1.2" + ], + "X-Forwarded-For": [ + "112.134.134.3:36070" + ], + "X-Original-URL": [ + "/hello" + ], + "X-WAWS-Unencoded-URL": [ + "/hello" + ], + "DISGUISED-HOST": [ + "bal-svc-impl.azurewebsites.net" + ] + }, + "Params": { + "RemainingPath": null + }, + "Identities": [ + { + "AuthenticationType": null, + "IsAuthenticated": false, + "Actor": null, + "BootstrapContext": null, + "Claims": [], + "Label": null, + "Name": null, + "NameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", + "RoleClaimType": "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" + } + ], + "Body": "Jack" + } + }, + "Metadata": { + "Query": {}, + "Headers": { + "Accept": "*/*", + "Content-Length": "4", + "Content-Type": "application/x-www-form-urlencoded", + "Host": "bal-svc-impl.azurewebsites.net", + "Max-Forwards": "9", + "User-Agent": "curl/7.78.0", + "X-ARR-LOG-ID": "8a17b6d7-b17e-4edd-9fd4-025fe03e1859", + "CLIENT-IP": "10.0.32.13:54062", + "X-SITE-DEPLOYMENT-ID": "bal-svc-impl", + "WAS-DEFAULT-HOSTNAME": "bal-svc-impl.azurewebsites.net", + "X-Forwarded-Proto": "https", + "X-AppService-Proto": "https", + "X-ARR-SSL": "2048|256|CN=Microsoft Azure TLS Issuing CA 01, O=Microsoft Corporation, C=US|CN=*.azurewebsites.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US", + "X-Forwarded-TlsVersion": "1.2", + "X-Forwarded-For": "112.134.134.3:36070", + "X-Original-URL": "/hello", + "X-WAWS-Unencoded-URL": "/hello", + "DISGUISED-HOST": "bal-svc-impl.azurewebsites.net" + }, + "sys": { + "MethodName": "hello", + "UtcNow": "2022-04-30T04:22:18.5062555Z", + "RandGuid": "ad4274d6-fbe3-435e-a07c-57266317c018" + } + } +} diff --git a/ballerina-tests/tests/resources/timer.json b/ballerina-tests/tests/resources/timer.json new file mode 100644 index 00000000..9be8b31d --- /dev/null +++ b/ballerina-tests/tests/resources/timer.json @@ -0,0 +1,18 @@ +{ + "Data": { + "inMsg": { + "Schedule": { + "AdjustForDST": true + }, + "ScheduleStatus": null, + "IsPastDue": false + } + }, + "Metadata": { + "sys": { + "MethodName": "timer", + "UtcNow": "2022-07-05T11:40:07.4850616Z", + "RandGuid": "9cd4c06c-fc8f-4b63-af94-56bc75c3f0cb" + } + } +} diff --git a/ballerina-tests/tests/resources/trigger-cosmos-base.json b/ballerina-tests/tests/resources/trigger-cosmos-base.json new file mode 100644 index 00000000..c5002035 --- /dev/null +++ b/ballerina-tests/tests/resources/trigger-cosmos-base.json @@ -0,0 +1,12 @@ +{ + "Data": { + "inMsg": "[{\"id\":\"ehee\",\"_rid\":\"zlIsAKxe8VCHhB4AAAAAAA==\",\"_self\":\"dbs\/zlIsAA==\/colls\/zlIsAKxe8VA=\/docs\/zlIsAKxe8VCHhB4AAAAAAA==\/\",\"_ts\":1656505802,\"_etag\":\"\\\"1f0507d0-0000-0700-0000-62bc45ca0000\\\"\",\"_lsn\":9}]" + }, + "Metadata": { + "sys": { + "MethodName": "cosmos", + "UtcNow": "2022-06-29T12:30:04.2341186Z", + "RandGuid": "5e14dca0-efb6-47e0-ae50-a4c994675dce" + } + } +} diff --git a/ballerina-tests/tests/test.bal b/ballerina-tests/tests/test.bal index d28bc8e5..108918a8 100644 --- a/ballerina-tests/tests/test.bal +++ b/ballerina-tests/tests/test.bal @@ -1,13 +1,999 @@ -import ballerina/test; -import ballerina/io; import ballerina/http; +import ballerina/io; +import ballerina/lang.value; +import ballerina/regex; +import ballerina/test; + +@test:Config {} +function retrFromAnnotField() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "retrFromAnnotField"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-retrFromAnnotField", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":"201", "headers":{"Content-Type":"text/plain"}, "body":"text/plain"}}, "Logs":[], "ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function retrFromParam() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "retrFromParam"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-retrFromParam", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":"201", "headers":{"Content-Type":"text/plain"}, "body":"az-func-http-test.azurewebsites.net"}}, "Logs":[], "ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function retrSingleVal() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "retrSingleVal"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-retrSingleVal", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":"201", "headers":{"Content-Type":"application/json"}, "body":15}}, "Logs":[], "ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function retrArrVal() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "retrArrVal"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-retrArrVal", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":"201", "headers":{"Content-Type":"application/json"}, "body":20}}, "Logs":[], "ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function retrArrValStr() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "retrArrValStr"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-retrArrValStr", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":"201", "headers":{"Content-Type":"text/plain"}, "body":"12"}}, "Logs":[], "ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function retrAsRecord() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "retrAsRecord"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-retrAsRecord", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":"201", "headers":{"Content-Type":"application/json"}, "body":105}}, "Logs":[], "ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function retrNilable() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "retrNilable"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-retrNilable", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":"201", "headers":{"Content-Type":"text/plain"}, "body":"az-func-http-test.azurewebsites.net"}}, "Logs":[], "ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nnonTreatNilAsOpt\-Nil\-noHeaderTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonTreatNilAsOpt-Nil-noHeaderTest"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-nonTreatNilAsOpt-Nil-noHeaderTest", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":400, "body":"no header value found for 'hoste'", "headers":{"Content-Type":"text/plain"}}}, "Logs":[], "ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function treatNilAsOpt\-nonNil\-noHeaderTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "treatNilAsOpt-nonNil-noHeaderTest"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-treatNilAsOpt-nonNil-noHeaderTest", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":400, "body":"no header value found for 'hoste'", "headers":{"Content-Type":"text/plain"}}}, "Logs":[], "ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function treatNilAsOpt\-nonNil\-HeaderTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "treatNilAsOpt-nonNil-HeaderTest"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-treatNilAsOpt-nonNil-HeaderTest", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":400, "body":"no header value found for 'hos'", "headers":{"Content-Type":"text/plain"}}}, "Logs":[], "ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function retrAsRecordNoField() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "retrAsRecordNoField"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-retrAsRecordNoField", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":400, "body":"no header value found for 'Content-Type1'", "headers":{"Content-Type":"text/plain"}}}, "Logs":[], "ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function treatNilAsOpt\-Nil\-noHeaderTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "treatNilAsOpt-Nil-noHeaderTest"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-treatNilAsOpt-Nil-noHeaderTest", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":"202"}},"Logs":[],"ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function treatNilAsOpt\-Nil\-HeaderTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "treatNilAsOpt-Nil-HeaderTest"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-treatNilAsOpt-Nil-HeaderTest", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":"202"}},"Logs":[],"ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonTreatNilAsOpt\-nonNil\-noHeaderTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonTreatNilAsOpt-nonNil-noHeaderTest"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-nonTreatNilAsOpt-nonNil-noHeaderTest", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":400, "body":"no header value found for 'hoste'", "headers":{"Content-Type":"text/plain"}}}, "Logs":[], "ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonTreatNilAsOpt\-nonNil\-HeaderTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonTreatNilAsOpt-nonNil-HeaderTest"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-nonTreatNilAsOpt-nonNil-HeaderTest", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":400, "body":"no header value found for 'hos'", "headers":{"Content-Type":"text/plain"}}}, "Logs":[], "ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonTreatNilAsOpt\-Nil\-HeaderTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpHeaderTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonTreatNilAsOpt-Nil-HeaderTest"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-httpHeader-nonTreatNilAsOpt-Nil-HeaderTest", readJson); + json expectedResp = {"Outputs":{"resp":{"statusCode":"202"}},"Logs":[],"ReturnValue":null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testEscapeSequences() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/escape-seq.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello--hello-query", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "Hello from the hello-query"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testDefault() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/default.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/default-hello-all", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "200", "headers": {"Content-Type": "text/plain"}, "body": "Hello from all"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function getHttpAccessorTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpAccessorTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(ACCESSOR_NAME)", "get"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/get-hello-httpAccessorTest", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "200", "headers": {"Content-Type": "text/plain"}, "body": "Hello from all"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function putHttpAccessorTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpAccessorTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(ACCESSOR_NAME)", "put"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/put-hello-httpAccessorTest", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "200", "headers": {"Content-Type": "text/plain"}, "body": "Hello from all"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function patchHttpAccessorTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpAccessorTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(ACCESSOR_NAME)", "patch"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/patch-hello-httpAccessorTest", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "200", "headers": {"Content-Type": "text/plain"}, "body": "Hello from all"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function deleteHttpAccessorTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpAccessorTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(ACCESSOR_NAME)", "delete"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/delete-hello-httpAccessorTest", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "200", "headers": {"Content-Type": "text/plain"}, "body": "Hello from all"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function headHttpAccessorTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpAccessorTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(ACCESSOR_NAME)", "head"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/head-hello-httpAccessorTest", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "200", "headers": {"Content-Type": "text/plain"}, "body": "Hello from all"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function optionsHttpAccessorTest() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpAccessorTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(ACCESSOR_NAME)", "options"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/options-hello-httpAccessorTest", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "200", "headers": {"Content-Type": "text/plain"}, "body": "Hello from all"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testBaseDot() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/base-dot.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "Hello from . path "}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function httpResTest1() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpResTest1.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-httpResTest1", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "401", + "body": "Helloworld.....", + "headers": {"Location": "/myServer/084230", "Content-Type": "application/account+json"} + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function httpResTest2() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpResTest2.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-httpResTest2", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "200", + "body": "Helloworld.....", + "headers": {"Content-Type": "application/json"} + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function httpResTest3() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpResTest3.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-httpResTest3", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "500", + "body": "Helloworld.....", + "headers": {"Content-Type": "application/json+id", "Location": "/myServer/084230"} + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function httpResTest4() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/httpResTest4.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-httpResTest4", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "500", + "headers": {"Content-Type": "application/json"} + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonHttpResTest1() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/nonHttpResTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonHttpResTest1"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-hello-nonHttpResTest1", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "201", + "body": "alpha", + "headers": {"Content-Type": "text/plain"} + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonHttpResTest2() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/nonHttpResTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonHttpResTest2"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-hello-nonHttpResTest2", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "application/xml"}, "body": "The Lost World"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonHttpResTest3() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/nonHttpResTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonHttpResTest3"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-hello-nonHttpResTest3", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "201", + "headers": {"Content-Type": "application/octet-stream"}, + "body": "yPHaytRgJPg+QjjylUHakEwz1fWPx/wXCW41JSmqYW8=" + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonHttpResTest4() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/nonHttpResTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonHttpResTest4"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-hello-nonHttpResTest4", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "application/json"}, "body": 100}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonHttpResTest6() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/nonHttpResTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonHttpResTest6"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-hello-nonHttpResTest6", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "application/json"}, "body": 100}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonHttpResTest7() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/nonHttpResTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonHttpResTest7"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-hello-nonHttpResTest7", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "application/json"}, "body": true}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonHttpResTest8() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/nonHttpResTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonHttpResTest8"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-hello-nonHttpResTest8", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "201", + "body": {"a": {"b": 12, "c": "helloworld"}}, + "headers": {"Content-Type": "application/json"} + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonHttpResTest9() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/nonHttpResTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonHttpResTest9"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-hello-nonHttpResTest9", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "201", + "body": [{"a": {"b": 12, "c": "helloworld"}}, {"b": 1100}], + "headers": {"Content-Type": "application/json"} + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonHttpResTest10() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/nonHttpResTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonHttpResTest10"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-hello-nonHttpResTest10", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "201", + "body": [{"a": {"b": 12, "c": "helloworld"}}, {"b": 12}], + "headers": {"Content-Type": "application/json"} + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonHttpResTest11() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/nonHttpResTest.json"; + string readString = check io:fileReadString(jsonFilePath); + string replacedString = regex:replaceAll(readString, "(FUNC_NAME)", "nonHttpResTest11"); + json readJson = check value:fromJsonString(replacedString); + json resp = check clientEndpoint->post("/post-hello-nonHttpResTest11", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "201", + "body": [[{"a": {"b": 12, "c": "helloworld"}}, {"b": 12}], [{"a": {"b": 14, "c": "helloworld"}}, {"b": 100}]], + "headers": {"Content-Type": "application/json"} + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function nonReturnTest1() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/nonReturnTest1.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-nonHttpResTest1", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "202" + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testSimpleResourcePath() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/res-path.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-foo", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "Hello from foo path Jack"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testSimpleMultiResourcePath() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/res-path-param.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-foo-bar-2", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "Hello from foo bar res"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testSimpleConflictingPathParam() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/res-path-conflict-param.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-foo-bar-1", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "Hello from foo param meow"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testSimpleMultiQueryPath() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/query-param.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-query", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "Hello from the query Jack test1"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testOptionalQueryWithQuery() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/query-optional-with.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/get-hello-query-optional", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "200", + "headers": { + "Content-Type": "text/plain" + }, + "body": "Hello from the optional query test1" + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testQueryBool() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/query-bool.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/get-hello-query-bool", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "200", + "headers": { + "Content-Type": "text/plain" + }, + "body": "Hello from the bool query false" + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testQueryFloatt() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/query-float.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/get-hello-query-floatt", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "200", + "headers": { + "Content-Type": "text/plain" + }, + "body": "Hello from the float query 10.5" + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testQueryArr() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/query-arr.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/get-hello-query-arr", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "200", + "headers": { + "Content-Type": "text/plain" + }, + "body": "Hello from the arr query red green " + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testQueryOptionalArrWithout() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/query-arr-optional-without.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/get-hello-query-arrOrNil", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "200", + "headers": { + "Content-Type": "text/plain" + }, + "body": "Query arr not found but all good ;)" + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testQueryOptionalArrWith() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/query-arr-optional-with.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/get-hello-query-arrOrNil", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "200", + "headers": { + "Content-Type": "text/plain" + }, + "body": "Hello from the arr or nil query red green " + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testOptionalQueryWithoutQuery() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/query-optional-without.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/get-hello-query-optional", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "200", + "headers": { + "Content-Type": "text/plain" + }, + "body": "Query not found but all good ;)" + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testSimpleQueue() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/queue-string.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/queue", readJson); + json expectedResp = {"Outputs": {"outMsg": "helloo aaaaa"}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testCosmosInputArr() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/cosmos-db-arr.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-db", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "Hello Jackhello1"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testJsonJsonPayload() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/payload-json-json.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-payload-jsonToJson", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "Hello from json to json Anjana"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testJsonRecordPayload() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/payload-json-record.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-payload-jsonToRecord", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "Hello from json to record Anjana"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testXmlPayload() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/payload-xml-xml.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-payload-xmlToXml", readJson); + string xmlPayload = "\"\\n Anjana<\\/name>\\n 12<\\/age>\\n<\\/root>\""; + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": xmlPayload}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testTextStringPayload() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/payload-text-string.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-payload-textToString", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "hello from byte\n"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testTextBytePayload() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/payload-text-byte.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-payload-textToByte", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "hello from byte\n"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testOctaBytePayload() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/payload-octa-byte.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-payload-octaToByte", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "hello from byte arr\n"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testCosmosTrigger() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/trigger-cosmos-base.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/cosmos", readJson); + json expectedResp = {"Outputs": {"outMsg": "helloo ehee"}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testTimerTrigger() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/timer.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/timer", readJson); + json expectedResp = {"Outputs": {"outMsg": "helloo false"}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testQueueInput() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/queue-input.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/queue-input", readJson); + json expectedResp = {"Outputs": {"outMsg": "helloo qqeeewwww hello1"}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +function replaceFuncName(string actual) { + +} + +@test:Config {} +function testOptionalOutputBinding() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/http-optional-out.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-optional-out", readJson); + json expectedResp = { + "Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "Hello from optional output binding"}}, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testErrorPayloadNotFound() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/error-missing-payload.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/get-hello-err-empty-payload", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": 400, + "body": "payload not found for the variable 'greeting'", + "headers": {"Content-Type": "text/plain"} + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testErrorInvalidPayload() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/error-invalid-payload.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-err-invalid-payload", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": 400, + "body": "incompatible type found: 'string", + "headers": {"Content-Type": "text/plain"} + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testOptionalPayloadWithPayload() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/http-optional-with-payload.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-optional-payload", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "Hello, the payload found Jack"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testOptionalPayloadWithoutPayload() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/http-optional-without-payload.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/post-hello-optional-payload", readJson); + json expectedResp = {"Outputs": {"resp": {"statusCode": "201", "headers": {"Content-Type": "text/plain"}, "body": "Hello, the payload wasn't set but all good ;)"}}, "Logs": [], "ReturnValue": null}; + test:assertEquals(resp, expectedResp); +} + +@test:Config {} +function testHttpBlobInput() returns error? { + final http:Client clientEndpoint = check new ("http://localhost:3000"); + string jsonFilePath = "./tests/resources/http-query-blob-input.json"; + json readJson = check io:fileReadJson(jsonFilePath); + json resp = check clientEndpoint->post("/get-hello-blobInput", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "200", + "headers": {"Content-Type": "text/plain"}, + "body": "Blob from hello.txt, content is hello from byte\n" + } + }, + "Logs": [], + "ReturnValue": null + }; + test:assertEquals(resp, expectedResp); +} -@test:Config { } -function testHelloWorld() returns error? { +@test:Config {} +function testHttpBlobInputOptional() returns error? { final http:Client clientEndpoint = check new ("http://localhost:3000"); - string jsonFilePath = "./tests/request.json"; + string jsonFilePath = "./tests/resources/http-query-blob-optional-input.json"; json readJson = check io:fileReadJson(jsonFilePath); - json resp = check clientEndpoint->post("/hello", readJson); - json expectedResp = {"Outputs":{},"Logs":[],"ReturnValue":"Hello, Jack!"}; + json resp = check clientEndpoint->post("/get-hello-blobInput", readJson); + json expectedResp = { + "Outputs": { + "resp": { + "statusCode": "200", + "headers": {"Content-Type": "text/plain"}, + "body": "Blob from hello1.txt not found" + } + }, + "Logs": [], + "ReturnValue": null + }; test:assertEquals(resp, expectedResp); } diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 5681a91f..44c7ab8e 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,4 +1,13 @@ [package] org = "ballerinax" name = "azure_functions" -version = "2.1.1" +version = "3.0.0-alpha.1" + +[[platform.java11.dependency]] +path = "../native/build/libs/azure_functions-native-3.0.0-alpha.1.jar" + +#[[platform.java11.dependency]] +#path = "./lib/http-native-@stdlib.httpnative.version@.jar" + +[[platform.java11.dependency]] +path = "./lib/mime-native-2.4.0.jar" diff --git a/ballerina/CompilerPlugin.toml b/ballerina/CompilerPlugin.toml index 2485a917..f2c21aba 100644 --- a/ballerina/CompilerPlugin.toml +++ b/ballerina/CompilerPlugin.toml @@ -1,6 +1,6 @@ [plugin] id = "azure-functions" -class = "org.ballerinax.azurefunctions.generator.AzureCompilerPlugin" +class = "org.ballerinax.azurefunctions.AzureCompilerPlugin" [[dependency]] -path = "../compiler-plugin/build/libs/azure_functions-compiler-plugin-2.1.1-SNAPSHOT.jar" +path = "../compiler-plugin/build/libs/azure_functions-compiler-plugin-3.0.0-alpha.1.jar" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index b713807e..defa38f6 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -29,6 +29,14 @@ dependencies = [ {org = "ballerina", name = "time"} ] +[[package]] +org = "ballerina" +name = "constraint" +version = "1.0.0" +dependencies = [ + {org = "ballerina", name = "jballerina.java"} +] + [[package]] org = "ballerina" name = "crypto" @@ -58,6 +66,7 @@ version = "2.4.0" dependencies = [ {org = "ballerina", name = "auth"}, {org = "ballerina", name = "cache"}, + {org = "ballerina", name = "constraint"}, {org = "ballerina", name = "crypto"}, {org = "ballerina", name = "file"}, {org = "ballerina", name = "io"}, @@ -94,6 +103,9 @@ dependencies = [ org = "ballerina" name = "jballerina.java" version = "0.0.0" +modules = [ + {org = "ballerina", packageName = "jballerina.java", moduleName = "jballerina.java"} +] [[package]] org = "ballerina" @@ -127,20 +139,6 @@ dependencies = [ {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.__internal"} ] -modules = [ - {org = "ballerina", packageName = "lang.array", moduleName = "lang.array"} -] - -[[package]] -org = "ballerina" -name = "lang.boolean" -version = "0.0.0" -dependencies = [ - {org = "ballerina", name = "jballerina.java"} -] -modules = [ - {org = "ballerina", packageName = "lang.boolean", moduleName = "lang.boolean"} -] [[package]] org = "ballerina" @@ -181,9 +179,6 @@ version = "0.0.0" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] -modules = [ - {org = "ballerina", packageName = "lang.string", moduleName = "lang.string"} -] [[package]] org = "ballerina" @@ -196,7 +191,7 @@ dependencies = [ [[package]] org = "ballerina" name = "log" -version = "2.4.0" +version = "2.4.1" dependencies = [ {org = "ballerina", name = "io"}, {org = "ballerina", name = "jballerina.java"}, @@ -283,13 +278,11 @@ dependencies = [ [[package]] org = "ballerinax" name = "azure_functions" -version = "2.1.1" +version = "3.0.0-alpha.1" dependencies = [ {org = "ballerina", name = "http"}, - {org = "ballerina", name = "lang.array"}, - {org = "ballerina", name = "lang.boolean"}, + {org = "ballerina", name = "jballerina.java"}, {org = "ballerina", name = "lang.int"}, - {org = "ballerina", name = "lang.string"}, {org = "ballerina", name = "os"} ] modules = [ diff --git a/ballerina/Module.md b/ballerina/Module.md index 61420596..acfc19ec 100644 --- a/ballerina/Module.md +++ b/ballerina/Module.md @@ -20,7 +20,7 @@ import ballerinax/azure_functions as af; // HTTP request/response with no authentication @af:Function public isolated function hello(@af:HTTPTrigger { authLevel: "anonymous" } string payload) - returns @af:HTTPOutput string|error { + returns @af:HttpOutput string|error { return "Hello, " + payload + "!"; } @@ -29,7 +29,7 @@ public isolated function hello(@af:HTTPTrigger { authLevel: "anonymous" } string public isolated function fromHttpToQueue(af:Context ctx, @af:HTTPTrigger {} af:HTTPRequest req, @af:QueueOutput { queueName: "queue1" } af:StringOutputBinding msg) - returns @af:HTTPOutput af:HTTPBinding { + returns @af:HttpOutput af:HTTPBinding { msg.value = req.body; return { statusCode: 200, payload: "Request: " + req.toString() }; } @@ -58,7 +58,7 @@ public isolated function fromBlobToQueue(af:Context ctx, @af:Function public isolated function httpTriggerBlobInput(@af:HTTPTrigger { } af:HTTPRequest req, @af:BlobInput { path: "bpath1/{Query.name}" } byte[]? blobIn) - returns @af:HTTPOutput string { + returns @af:HttpOutput string { int length = 0; if blobIn is byte[] { length = blobIn.length(); @@ -71,7 +71,7 @@ public isolated function httpTriggerBlobInput(@af:HTTPTrigger { } af:HTTPRequest @af:Function public isolated function httpTriggerBlobOutput(@af:HTTPTrigger { } af:HTTPRequest req, @af:BlobOutput { path: "bpath1/{Query.name}" } af:StringOutputBinding bb) - returns @af:HTTPOutput string|error { + returns @af:HttpOutput string|error { bb.value = req.body; return "Blob: " + req.query["name"].toString() + " Content: " + bb?.value.toString(); @@ -82,7 +82,7 @@ public isolated function httpTriggerBlobOutput(@af:HTTPTrigger { } af:HTTPReques public isolated function sendSMS(@af:HTTPTrigger { } af:HTTPRequest req, @af:TwilioSmsOutput { fromNumber: "+12069845840" } af:TwilioSmsOutputBinding tb) - returns @af:HTTPOutput string { + returns @af:HttpOutput string { tb.to = req.query["to"].toString(); tb.body = req.body.toString(); return "Message - to: " + tb?.to.toString() + " body: " + tb?.body.toString(); @@ -118,7 +118,7 @@ public isolated function httpTriggerCosmosDBInput1( @af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c1", id: "{Query.id}", partitionKey: "{Query.country}" } json dbReq) - returns @af:HTTPOutput string|error { + returns @af:HttpOutput string|error { return dbReq.toString(); } @@ -128,7 +128,7 @@ public isolated function httpTriggerCosmosDBInput2( @af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c1", id: "{Query.id}", partitionKey: "{Query.country}" } Person? dbReq) - returns @af:HTTPOutput string|error { + returns @af:HttpOutput string|error { return dbReq.toString(); } @@ -139,14 +139,14 @@ public isolated function httpTriggerCosmosDBInput3( databaseName: "db1", collectionName: "c1", sqlQuery: "select * from c1 where c1.country = {country}" } Person[] dbReq) - returns @af:HTTPOutput string|error { + returns @af:HttpOutput string|error { return dbReq.toString(); } // HTTP request to write records to CosmosDB @af:Function public isolated function httpTriggerCosmosDBOutput1( - @af:HTTPTrigger { } af:HTTPRequest httpReq, @af:HTTPOutput af:HTTPBinding hb) + @af:HTTPTrigger { } af:HTTPRequest httpReq, @af:HttpOutput af:HTTPBinding hb) returns @af:CosmosDBOutput { connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c1" } json { json entry = { id: uuid:createType1AsString(), name: "Saman", country: "Sri Lanka" }; @@ -157,7 +157,7 @@ public isolated function httpTriggerCosmosDBOutput1( @af:Function public isolated function httpTriggerCosmosDBOutput2( @af:HTTPTrigger { } af:HTTPRequest httpReq, - @af:HTTPOutput af:HTTPBinding hb) + @af:HttpOutput af:HTTPBinding hb) returns @af:CosmosDBOutput { connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c1" } json { diff --git a/ballerina/annotation.bal b/ballerina/annotation.bal index bca3d928..a4b4ee5b 100644 --- a/ballerina/annotation.bal +++ b/ballerina/annotation.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2020 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2022 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except @@ -14,25 +14,36 @@ // specific language governing permissions and limitations // under the License. -# @azurefunctions:Function annotation. -public const annotation Function on function; +public const annotation FunctionConfiguration Function on function; + +public type FunctionConfiguration record {| + string name; +|}; public type AUTH_LEVEL "anonymous"|"function"|"admin"; +public const annotation HTTPTriggerConfiguration HttpTrigger on source listener, service; # HTTPTrigger annotation configuration. # # + authLevel - The authentication level of the function -# + route - The route template public type HTTPTriggerConfiguration record {| - AUTH_LEVEL authLevel?; - string route?; + AUTH_LEVEL authLevel = "anonymous"; +|}; + +public annotation Payload on parameter, return; + +# Defines the Header resource signature parameter. +# +# + name - Specifies the name of the required header +public type HttpHeader record {| + string name?; |}; -# @azurefunctions:HTTPTrigger annotation. -public const annotation HTTPTriggerConfiguration HTTPTrigger on parameter; +# The annotation which is used to define the Header resource signature parameter. +public annotation HttpHeader Header on parameter; -# @azurefunctions:HTTPOutput annotation -public const annotation HTTPOutput on parameter, return; +# @azurefunctions:HttpOutput annotation +public const annotation HttpOutput on parameter, return; # Queue annotation configuration. # @@ -47,7 +58,7 @@ public type QueueConfiguration record {| public const annotation QueueConfiguration QueueOutput on parameter, return; # @azurefunctions:QueueOutput annotation. -public const annotation QueueConfiguration QueueTrigger on parameter; +public const annotation QueueConfiguration QueueTrigger on source listener, service; # TimerTrigger annotation configuration. # @@ -59,7 +70,7 @@ public type TimerTriggerConfiguration record {| |}; # @azurefunctions:TimerTrigger annotation. -public const annotation TimerTriggerConfiguration TimerTrigger on parameter; +public const annotation TimerTriggerConfiguration TimerTrigger on source listener, service; # Blob annotation configuration. # @@ -71,13 +82,13 @@ public type BlobConfiguration record {| |}; # @azurefunctions:BlobTrigger annotation. -public const annotation BlobConfiguration BlobTrigger on parameter; +public const annotation BlobConfiguration BlobTrigger on source listener, service; # @azurefunctions:BlobInput annotation. public const annotation BlobConfiguration BlobInput on parameter; # @azurefunctions:BlobOutput annotation. -public const annotation BlobConfiguration BlobOutput on parameter; +public const annotation BlobConfiguration BlobOutput on return; # CosmosDB trigger annotation configuration. # @@ -119,7 +130,7 @@ public type CosmosDBTriggerConfiguration record {| |}; # @azurefunctions:CosmosDBTrigger annotation. -public const annotation CosmosDBTriggerConfiguration CosmosDBTrigger on parameter; +public const annotation CosmosDBTriggerConfiguration CosmosDBTrigger on source listener, service; # CosmosDB input annotation configuration. # @@ -171,15 +182,18 @@ public const annotation CosmosDBOutputConfiguration CosmosDBOutput on return; # # + accountSidSetting - The app setting which holds the Twilio Account Sid # + authTokenSetting - The app setting which holds the Twilio authentication token -# + fromNumber - The phone number the SMS is sent from +# + from - The phone number the SMS is sent from +# + to - The phone number the SMS is sent to public type TwilioSmsConfiguration record {| string accountSidSetting = "AzureWebJobsTwilioAccountSid"; string authTokenSetting = "AzureWebJobsTwilioAuthToken"; - string fromNumber; + string 'from; + string to; + |}; # @azurefunctions:TwilioSmsOutput annotation. -public const annotation TwilioSmsConfiguration TwilioSmsOutput on parameter; +public const annotation TwilioSmsConfiguration TwilioSmsOutput on return; # BindingName annotation configuration. # diff --git a/ballerina/blob_listener.bal b/ballerina/blob_listener.bal new file mode 100644 index 00000000..4eeaacfb --- /dev/null +++ b/ballerina/blob_listener.bal @@ -0,0 +1,41 @@ +// Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +public class BlobListener { + DispatcherService? httpService; + + public isolated function init() returns error? { + self.httpService = (); + } + + public function attach(BlobService svc, string[]|string? name = ()) returns error? { + AzureRemoteAdapter adaptor = new(svc); + self.httpService = new (adaptor, "onUpdated"); + check httpListener.attach(self.httpService, name); + } + + public isolated function detach(BlobService svc) returns error? { + } + + public function 'start() returns error? { + check httpListener.'start(); + } + + public isolated function gracefulStop() returns error? { + } + + public isolated function immediateStop() returns error? { + } +} diff --git a/ballerina/build.gradle b/ballerina/build.gradle index a0316ac0..7a51e798 100644 --- a/ballerina/build.gradle +++ b/ballerina/build.gradle @@ -64,23 +64,37 @@ ballerina { packageOrganization = packageOrg module = packageName langVersion = ballerinaLangVersion - platform = "any" } configurations { externalJars } +dependencies { + externalJars(group: 'io.ballerina.stdlib', name: 'http-native', version: "${stdlibHttpVersion}") { + transitive = false + } + externalJars(group: 'io.ballerina.stdlib', name: 'mime-native', version: "${stdlibMimeVersion}") { + transitive = false + } +} task updateTomlFiles { doLast { def newBallerinaToml = ballerinaTomlFilePlaceHolder.text.replace("@project.version@", project.version) newBallerinaToml = newBallerinaToml.replace("@toml.version@", tomlVersion) - ballerinaTomlFile.text = newBallerinaToml def newCompilerPluginToml = compilerPluginTomlFilePlaceHolder.text.replace("@project.version@", project.version) compilerPluginTomlFile.text = newCompilerPluginToml + +// def stdlibDependentHttpNativeVersion = project.stdlibHttpVersion +// newBallerinaToml = newBallerinaToml.replace("@stdlib.httpnative.version@", stdlibDependentHttpNativeVersion) + + def stdlibDependentMimeNativeVersion = project.stdlibMimeVersion + newBallerinaToml = newBallerinaToml.replace("@stdlib.mimenative.version@", stdlibDependentMimeNativeVersion) + + ballerinaTomlFile.text = newBallerinaToml } } @@ -120,9 +134,11 @@ publishing { updateTomlFiles.dependsOn copyStdlibs build.dependsOn "generatePomFileForMavenPublication" +build.dependsOn ":${packageName}-native:build" build.dependsOn ":${packageName}-compiler-plugin:build" build.finalizedBy ":${packageName}-compiler-plugin-tests:build" build.finalizedBy ":${packageName}-ballerina-tests:build" +test.dependsOn ":${packageName}-native:build" test.dependsOn ":${packageName}-compiler-plugin:build" test.finalizedBy ":${packageName}-compiler-plugin-tests:build" test.finalizedBy ":${packageName}-ballerina-tests:build" diff --git a/ballerina/code.bal b/ballerina/code.bal deleted file mode 100644 index 0278413d..00000000 --- a/ballerina/code.bal +++ /dev/null @@ -1,639 +0,0 @@ -// Copyright (c) 2021 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -// -// WSO2 Inc. licenses this file to you under the Apache License, -// Version 2.0 (the "License"); you may not use this file except -// in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -import ballerina/http; -import ballerina/os; -import ballerina/lang.'int as ints; -import ballerina/lang.'array as arrays; -import ballerina/lang.'string as strings; -import ballerina/lang.'boolean as booleans; - -# HTTP binding data. -# -# + statusCode - The HTTP response status code -# + payload - The HTTP response payload -public type HTTPBinding record { - int statusCode = 200; - string payload?; -}; - -# String output binding data. -# -# + value - The string value -public type StringOutputBinding record { - string value?; -}; - -# Byte array output binding data. -# -# + value - The byte[] value -public type BytesOutputBinding record { - byte[] value?; -}; - -# Twilion SMS output binding data. -# -# + to - The SMS recipient phone number -# + body - The message body -public type TwilioSmsOutputBinding record { - string to?; - string body?; -}; - -# HTTP request binding data. -# -# + url - The request URL -# + method - The request HTTP method -# + query - The request query parameter map -# + headers - The request HTTP header map -# + params - The request parameters -# + identities - The request identities -# + body - The request body -public type HTTPRequest record { - string url; - string method; - map query; - map headers; - map params; - json[] identities; - string body; -}; - -# INTERNAL stucture - the request handler parameter data. -# -# + request - The HTTP request -# + response - The HTTP response -# + pure - The flag to mention if it's a pure HTTP request -# + result - The result JSON -public type HandlerParams record { - http:Request request; - http:Response response; - boolean pure = false; - json result = { Outputs: {}, Logs: [] }; -}; - -# The request context holder. -# -# + metadata - The context metadata -public class Context { - - HandlerParams hparams; - - public json metadata; - - public isolated function init(HandlerParams hparams, boolean populateMetadata) returns error? { - self.hparams = hparams; - if populateMetadata { - self.metadata = check getMetadata(self.hparams); - } else { - self.metadata = {}; - } - } - - # Enters to function invocation logs. - # - # + msg - The log message - public isolated function log(string msg) { - log(self.hparams, msg); - } - -} - -# INTERNAL usage - Enters to function invocation logs. -# -# + hparams - The handler parameters -# + msg - The log message -public isolated function log(HandlerParams hparams, string msg) { - json[] logs = checkpanic hparams.result.Logs; - logs.push(msg); -} - -# INTERNAL usage - Checks if request tracing is enabled. -# -# + return - The request tracing flag -public isolated function isRequestTrace() returns boolean { - string? value = os:getEnv("BALLERINA_AZURE_FUNCTIONS_REQUEST_TRACE"); - if value is string { - var flag = booleans:fromString(value); - if flag is boolean { - return flag; - } else { - return false; - } - } else { - return false; - } -} - -public isolated function logError(HandlerParams hparams, error err) { - log(hparams, "ERROR: " + err.toString()); -} - -public isolated function logRequest(HandlerParams hparams, http:Request request) { - var payload = request.getTextPayload(); - string val = payload is error ? payload.toString() : payload.toString(); - log(hparams, "REQUEST: " + val); -} - -# Function handler type. -type FunctionHandler (function (HandlerParams) returns error?); - -@untainted public listener http:Listener hl = new(check ints:fromString(os:getEnv("FUNCTIONS_CUSTOMHANDLER_PORT"))); - -public isolated function handleFunctionResposne(error? err, HandlerParams hparams) { - http:Request request = hparams.request; - http:Response response = hparams.response; - if err is error { - logError(hparams, err); - logRequest(hparams, request); - response.setJsonPayload(<@untainted> hparams.result); - } else { - if !hparams.pure { - if isRequestTrace() { - logRequest(hparams, request); - } - response.setJsonPayload(<@untainted> hparams.result); - } - } -} - -# INTERNAL usage - extracts the metadata. -# -# + hparams - The handler parameters -# + return - The metadata JSON -public isolated function getMetadata(HandlerParams hparams) returns json|error { - json payload = check <@untainted> hparams.request.getJsonPayload(); - json metadata = check payload.Metadata; - return metadata; -} - -# INTERNAL usage - creates function context. -# -# + hparams - The handler parameters -# + populateMetadata - The flag to populate metadata -# + return - The function context -public isolated function createContext(HandlerParams hparams, boolean populateMetadata) returns Context|error { - return new Context(hparams, populateMetadata); -} - -# INTERNAL usage - Sets the HTTP output. -# -# + params - The handler parameters -# + name - The parameter name -# + binding - The binding data -# + return - An error in failure -public isolated function setHTTPOutput(HandlerParams params, string name, HTTPBinding binding) returns error? { - string? payload = binding?.payload; - if (payload is string) { - json content = params.result; - json outputs = check content.Outputs; - map bvals = { }; - bvals[name] = { statusCode: binding.statusCode, body: payload }; - _ = check outputs.mergeJson(bvals); - } -} - -# INTERNAL usage - Sets the string output. -# -# + params - The handler parameters -# + name - The parameter name -# + binding - The binding data -# + return - An error in failure -public isolated function setStringOutput(HandlerParams params, string name, StringOutputBinding binding) returns error? { - string? value = binding?.value; - if (value is string) { - json content = params.result; - json outputs = check content.Outputs; - map bvals = { }; - bvals[name] = value; - _ = check outputs.mergeJson(bvals); - } -} - -# INTERNAL usage - Sets the Blob output. -# -# + params - The handler parameters -# + name - The parameter name -# + binding - The binding data -# + return - An error in failure -public isolated function setBlobOutput(HandlerParams params, string name, any binding) returns error? { - string? value = (); - if binding is BytesOutputBinding { - byte[]? bytes = binding?.value; - if bytes is byte[] { - value = bytes.toBase64(); - } - } else if binding is StringOutputBinding { - string? text = binding?.value; - if text is string { - value = text.toBytes().toBase64(); - } - } - if value is string { - json content = params.result; - json outputs = check content.Outputs; - map bvals = { }; - bvals[name] = value; - _ = check outputs.mergeJson(bvals); - } -} - -# INTERNAL usage - Sets the Twilio output. -# -# + params - The handler parameters -# + name - The parameter name -# + binding - The binding data -# + return - An error in failure -public isolated function setTwilioSmsOutput(HandlerParams params, string name, TwilioSmsOutputBinding binding) returns error? { - string? to = binding?.to; - string? body = binding?.body; - if to is string && body is string { - json content = params.result; - json outputs = check content.Outputs; - map bvals = { }; - bvals[name] = { body, to }; - _ = check outputs.mergeJson(bvals); - } -} - -# INTERNAL usage - Sets the pure HTTP output. -# -# + params - The handler parameters -# + binding - The binding data -# + return - An error in failure -public isolated function setPureHTTPOutput(HandlerParams params, HTTPBinding binding) returns error? { - string? payload = binding?.payload; - if payload is string { - params.response.statusCode = binding.statusCode; - params.response.setTextPayload(payload); - } - params.pure = true; -} - -# INTERNAL usage - Sets the pure string output. -# -# + params - The handler parameters -# + value - The value -# + return - An error in failure -public isolated function setPureStringOutput(HandlerParams params, string value) returns error? { - params.response.setTextPayload(value); - params.pure = true; -} - -# INTERNAL usage - Returns the HTTP request data. -# -# + params - The handler parameters -# + return - The HTTP request -public isolated function getHTTPRequestFromParams(HandlerParams params) returns http:Request|error { - return params.request; -} - -# INTERNAL usage - Returns the string payload from the HTTP request. -# -# + params - The handler parameters -# + return - The string payload -public isolated function getStringFromHTTPReq(HandlerParams params) returns string|error { - return check <@untainted> params.request.getTextPayload(); -} - -# INTERNAL usage - Returns a parsed JSON value. -# -# + input - The escaped JSON value -# + return - The parsed JSON value -isolated function parseJson(string input) returns json|error { - json x = check input.fromJsonString(); - return x; -} - -# INTERNAL usage - Returns a json value from metadata. -# -# + params - The handler parameters -# + name - The metadata entry name -# + return - The metadata entry value -public isolated function getJsonFromMetadata(HandlerParams params, string name) returns json|error { - map metadata = > check getMetadata(params); - return parseJson(metadata[name].toString()); -} - -# INTERNAL usage - Returns a string value from metadata. -# -# + params - The handler parameters -# + name - The metadata entry name -# + return - The metadata entry value -public isolated function getStringFromMetadata(HandlerParams params, string name) returns string|error { - json result = check getJsonFromMetadata(params, name); - return result.toString(); -} - -# INTERNAL usage - Returns the JSON payload from the HTTP request. -# -# + params - The handler parameters -# + return - The JSON payload -public isolated function getJsonFromHTTPReq(HandlerParams params) returns json|error { - return check <@untainted> params.request.getJsonPayload(); -} - -# INTERNAL usage - Returns the binary payload from the HTTP request. -# -# + params - The handler parameters -# + return - The binary payload -public isolated function getBinaryFromHTTPReq(HandlerParams params) returns byte[]|error { - return check <@untainted> params.request.getBinaryPayload(); -} - -# INTERNAL usage - Returns the string value from input data. -# -# + params - The handler parameters -# + name - The input data entry name -# + return - The string value -public isolated function getStringFromInputData(HandlerParams params, string name) returns string|error { - json payload = check getJsonFromHTTPReq(params); - map data = > check payload.Data; - return data[name].toString(); -} - -# INTERNAL usage - Returns the JSON string value from input data. -# -# + params - The handler parameters -# + name - The input data entry name -# + return - The string value -public isolated function getJsonStringFromInputData(HandlerParams params, string name) returns string|error { - return (check getJsonFromInputData(params, name)).toString(); -} - -# INTERNAL usage - Returns the optional string value from input data. -# -# + params - The handler parameters -# + name - The input data entry name -# + return - The optional string value -public isolated function getOptionalStringFromInputData(HandlerParams params, string name) returns string?|error { - json payload = check getJsonFromHTTPReq(params); - map data = > check payload.Data; - json result = data[name]; - if result == () { - return (); - } - return result.toString(); -} - -# INTERNAL usage - Returns the binary value from input data. -# -# + params - The handler parameters -# + name - The input data entry name -# + return - The binary value -public isolated function getBytesFromInputData(HandlerParams params, string name) returns byte[]|error { - string data = check getStringFromInputData(params, name); - return arrays:fromBase64(data.toString()); -} - -# INTERNAL usage - Returns the optional binary value from input data. -# -# + params - The handler parameters -# + name - The input data entry name -# + return - The optional string value -public isolated function getOptionalBytesFromInputData(HandlerParams params, string name) returns byte[]?|error { - string? data = check getOptionalStringFromInputData(params, name); - if data == () { - return (); - } else { - return arrays:fromBase64(data.toString()); - } -} - -# INTERNAL usage - Returns the string value converted from input binary data. -# -# + params - The handler parameters -# + name - The input data entry name -# + return - The string value -public isolated function getStringConvertedBytesFromInputData(HandlerParams params, string name) returns string|error { - string data = check getStringFromInputData(params, name); - var result = arrays:fromBase64(data.toString()); - if result is error { - return result; - } else { - return check strings:fromBytes(result); - } -} - -# INTERNAL usage - Returns the optional string value converted from input binary data. -# -# + params - The handler parameters -# + name - The input data entry name -# + return - The optional binary value -public isolated function getOptionalStringConvertedBytesFromInputData(HandlerParams params, string name) returns string?|error { - string? data = check getOptionalStringFromInputData(params, name); - if data == () { - return (); - } else { - var result = arrays:fromBase64(data.toString()); - if result is error { - return result; - } else { - return check strings:fromBytes(result); - } - } -} - -# INTERNAL usage - Returns the HTTP body value from input data. -# -# + params - The handler parameters -# + name - The input data entry name -# + return - The HTTP body -public isolated function getBodyFromHTTPInputData(HandlerParams params, string name) returns string|error { - HTTPRequest req = check getHTTPRequestFromInputData(params, name); - return req.body; -} - -# INTERNAL usage - Extracts HTTP headers from the JSON value. -# -# + headers - The headers JSON -# + return - The headers map -isolated function extractHTTPHeaders(json headers) returns map { - map headerMap = > headers; - map result = {}; - foreach var key in headerMap.keys() { - json[] values = headerMap[key]; - string[] headerVals = values.map(isolated function (json j) returns string { return j.toString(); } ); - result[key] = headerVals; - } - return result; -} - -# INTERNAL usage - Extracts string map from the JSON value. -# -# + params - The params JSON -# + return - The string map -isolated function extractStringMap(json params) returns map { - map paramMap = > params; - map result = {}; - foreach var key in paramMap.keys() { - result[key] = paramMap[key].toString(); - } - return result; -} - -# INTERNAL usage - Populates the HTTP request structure from an input data entry. -# -# + params - The handler parameters -# + name - The input data entry name -# + return - The HTTP request -public isolated function getHTTPRequestFromInputData(HandlerParams params, string name) returns HTTPRequest|error { - json payload = check getJsonFromHTTPReq(params); - map data = > check payload.Data; - json hreq = data[name]; - var urlVal = hreq.Url; - string url = urlVal is error ? urlVal.toString() : urlVal.toString(); - var methodVal = hreq.Method; - string method = methodVal is error ? methodVal.toString() : methodVal.toString(); - map headers = extractHTTPHeaders(check hreq.Headers); - map hparams = extractStringMap(check hreq.Params); - json qx = check hreq.Query; - map query = extractStringMap(check parseJson(qx.toString())); - json idx = check hreq.Identities; - json identitiesTemp = check parseJson(idx.toString()); - json[] identities = identitiesTemp; - var bodyVal = hreq.Body; - string body = bodyVal is error ? bodyVal.toString() : bodyVal.toString(); - HTTPRequest req = { url: url, method: method, query: query, headers: headers, - params: hparams, identities: identities, body: body }; - return req; -} - -# INTERNAL usage - Returns the JSON value from input data. -# -# + params - The handler parameters -# + name - The input data entry name -# + return - The JSON value -public isolated function getJsonFromInputData(HandlerParams params, string name) returns json|error { - return parseJson(check getStringFromInputData(params, name)); -} - -# INTERNAL usage - JSON parse the string value available from "getJsonStringFromInputData". -# -# + params - The handler parameters -# + name - The input data entry name -# + return - The JSON value -public isolated function getParsedJsonFromJsonStringFromInputData(HandlerParams params, string name) returns json|error { - return parseJson(check getJsonStringFromInputData(params, name)); -} - -# INTERNAL usage - Returns a converted Ballerina value from input data. -# -# + params - The handler parameters -# + name - The input data entry name -# + recordType - The record type descriptor -# + return - The JSON value -public isolated function getBallerinaValueFromInputData(HandlerParams params, string name, - typedesc recordType) returns anydata|error { - var result = getJsonFromInputData(params, name); - if result is error { - return result; - } else { - return result.cloneWithType(recordType); - } -} - -# INTERNAL usage - Returns the optional converted Ballerina value from "getParsedJsonFromJsonStringFromInputData". -# -# + params - The handler parameters -# + name - The input data entry name -# + recordType - The record type descriptor -# + return - The JSON value -public isolated function getOptionalBallerinaValueFromInputData(HandlerParams params, string name, - typedesc recordType) returns anydata?|error { - var result = getParsedJsonFromJsonStringFromInputData(params, name); - if result is error { - return result; - } else if result == () { - return (); - } else { - return result.cloneWithType(recordType); - } -} - -# INTERNAL usage - Sets the string return value. -# -# + params - The handler parameters -# + value - The string return value -# + return - An error in failure -public isolated function setStringReturn(HandlerParams params, string value) returns error? { - json content = params.result; - _ = check content.mergeJson({ ReturnValue: value }); -} - -# INTERNAL usage - Sets the JSON return value. -# -# + params - The handler parameters -# + value - The JSON return value -# + return - An error in failure -public isolated function setJsonReturn(HandlerParams params, json value) returns error? { - json content = params.result; - _ = check content.mergeJson({ ReturnValue: value }); -} - -# INTERNAL usage - Sets the CosmosDS JSON return value. -# -# + params - The handler parameters -# + value - The JSON return value -# + partitionKey - The partition key -# + return - An error in failure -public isolated function setCosmosDBJsonReturn(HandlerParams params, json value, string partitionKey) returns error? { - json content = params.result; - if partitionKey.length() > 0 { - if value is json[] { - json[] valArray = value; - foreach json valEntry in valArray { - _ = check valEntry.mergeJson({ pk: partitionKey }); - } - } else { - _ = check value.mergeJson({ pk: partitionKey }); - } - } - _ = check content.mergeJson({ ReturnValue: value }); -} - -# INTERNAL usage - Converts a Ballerina value to a JSON and set the return value. -# -# + params - The handler parameters -# + value - The value -# + return - An error in failure -public isolated function setBallerinaValueAsJsonReturn(HandlerParams params, anydata value) returns error? { - check setJsonReturn(params, check value.cloneWithType(json)); -} - -# INTERNAL usage - Converts a CosmosDS Ballerina value to a JSON and set the return value. -# -# + params - The handler parameters -# + value - The value -# + partitionKey - The partition key -# + return - An error in failure -public isolated function setCosmosDBBallerinaValueAsJsonReturn(HandlerParams params, anydata value, - string partitionKey) returns error? { - check setCosmosDBJsonReturn(params, check value.cloneWithType(json), partitionKey); -} - -# INTERNAL usage - Sets the HTTP binding return value. -# -# + params - The handler parameters -# + binding - The HTTP binding return value -# + return - An error in failure -public isolated function setHTTPReturn(HandlerParams params, HTTPBinding binding) returns error? { - string? payload = binding?.payload; - if (payload is string) { - json content = params.result; - _ = check content.mergeJson({ ReturnValue: { statusCode: binding.statusCode, body: payload } }); - } -} diff --git a/ballerina/cosmos_listener.bal b/ballerina/cosmos_listener.bal new file mode 100644 index 00000000..bcce0f6a --- /dev/null +++ b/ballerina/cosmos_listener.bal @@ -0,0 +1,41 @@ +// Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +public class CosmosDBListener { + DispatcherService? httpService; + + public isolated function init() returns error? { + self.httpService = (); + } + + public function attach(CosmosService svc, string[]|string? name = ()) returns error? { + AzureRemoteAdapter adaptor = new(svc); + self.httpService = new (adaptor, "onUpdated"); + check httpListener.attach(self.httpService, name); + } + + public isolated function detach(CosmosService svc) returns error? { + } + + public function 'start() returns error? { + check httpListener.'start(); + } + + public isolated function gracefulStop() returns error? { + } + + public isolated function immediateStop() returns error? { + } +} diff --git a/ballerina/dispatcher_service.bal b/ballerina/dispatcher_service.bal new file mode 100644 index 00000000..26957514 --- /dev/null +++ b/ballerina/dispatcher_service.bal @@ -0,0 +1,39 @@ +// Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import ballerina/http; + +isolated service class DispatcherService { + *http:Service; + + private final AzureRemoteAdapter adaptor; + private final string remoteMethodName; + + isolated function init(AzureRemoteAdapter adaptor, string remoteMethodName) { + self.adaptor = adaptor; + self.remoteMethodName = remoteMethodName; + } + + isolated resource function post .(http:Caller caller, http:Request request) returns error? { + http:Response response = new; + json platformPayload = check request.getJsonPayload(); + + map callRegisterMethod = check self.adaptor.callRemoteFunction(>platformPayload, self.remoteMethodName); + + response.setJsonPayload({Outputs: callRegisterMethod.toJson(), Logs: [], ReturnValue: null}); + check caller->respond(response); + } +} diff --git a/compiler-plugin-tests/src/test/resources/validations/submodule/main.bal b/ballerina/errors.bal similarity index 61% rename from compiler-plugin-tests/src/test/resources/validations/submodule/main.bal rename to ballerina/errors.bal index 7e002fb5..b9779d38 100644 --- a/compiler-plugin-tests/src/test/resources/validations/submodule/main.bal +++ b/ballerina/errors.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2021 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2022 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except @@ -14,14 +14,12 @@ // specific language governing permissions and limitations // under the License. -import ballerinax/azure_functions as af; -import submodule.mod1; +public type Error distinct error; -// HTTP request/response with no authentication -@af:Function -public isolated function hello(@af:HTTPTrigger { authLevel: "anonymous" } string payload) - returns @af:HTTPOutput string|error { - return "Hello, " + payload + "!"; -} +public type FunctionNotFoundError distinct Error; +public type PayloadNotFoundError distinct Error; +public type InvalidPayloadError distinct Error; + +public type HeaderNotFoundError distinct Error; diff --git a/ballerina/http_listener.bal b/ballerina/http_listener.bal new file mode 100644 index 00000000..2091e8ff --- /dev/null +++ b/ballerina/http_listener.bal @@ -0,0 +1,51 @@ +// Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//TODO See if unused methods are required for a listener declaration +public class HttpListener { + ResourceService[] httpServices; + + public isolated function init() returns error? { + self.httpServices = []; + } + + public function attach(HttpService svc, string[]|string? name = ()) returns error? { + HttpToAzureAdaptor adaptor = new(svc); + string[] resourcePaths = adaptor.getAzureFunctionNames(); + foreach string resourcePath in resourcePaths{ + ResourceService httpService = new (adaptor); + check httpListener.attach(httpService, resourcePath); + } + } + + public isolated function detach(HttpService svc) returns error? { + } + + public function 'start() returns error? { + check httpListener.'start(); + } + + public isolated function gracefulStop() returns error? { + } + + public isolated function immediateStop() returns error? { + } +} +public type HttpService distinct service object { + +}; + + diff --git a/ballerina/http_service.bal b/ballerina/http_service.bal new file mode 100644 index 00000000..7f1c03b3 --- /dev/null +++ b/ballerina/http_service.bal @@ -0,0 +1,48 @@ +// Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import ballerina/http; + +isolated service class ResourceService { + *http:Service; + + private final HttpToAzureAdaptor adaptor; + + isolated function init(HttpToAzureAdaptor adaptor) { + self.adaptor = adaptor; + } + + isolated resource function post .(http:Caller caller, http:Request request) returns error? { + http:Response response = new; + json message = check request.getJsonPayload(); + Payload payload = check message.cloneWithType(Payload); + string functionName = payload.Metadata.sys.MethodName; + map|error callRegisterMethod = self.adaptor.callNativeMethod(payload.Data, functionName); + response.setJsonPayload(getResponsePayload(callRegisterMethod)); + check caller->respond(response); + } +} + + +isolated function getResponsePayload (map|error nativeResponse) returns json { + if (nativeResponse is PayloadNotFoundError || nativeResponse is InvalidPayloadError || nativeResponse is HeaderNotFoundError) { + return {"Outputs": {"resp": {"statusCode": 400, "body": nativeResponse.message(),"headers": {"Content-Type": "text/plain"}}}, "Logs": [], "ReturnValue": null}; + } else if (nativeResponse is error) { + return {"Outputs": {"resp": {"statusCode": 500}}, "Logs": [], "ReturnValue": null}; + } else { + return {Outputs: nativeResponse.toJson(), Logs: [], ReturnValue: null}; + } +} diff --git a/compiler-plugin-tests/src/test/resources/validations/submodule/modules/mod1/mod1.bal b/ballerina/init.bal similarity index 66% rename from compiler-plugin-tests/src/test/resources/validations/submodule/modules/mod1/mod1.bal rename to ballerina/init.bal index d515e39e..8d87a491 100644 --- a/compiler-plugin-tests/src/test/resources/validations/submodule/modules/mod1/mod1.bal +++ b/ballerina/init.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2021 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2022 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. // // WSO2 Inc. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except @@ -13,10 +13,13 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -import ballerinax/azure_functions as af; -@af:Function -public isolated function hello(@af:HTTPTrigger { authLevel: "anonymous" } string payload) - returns @af:HTTPOutput string|error { - return "Hello, " + payload + "!"; +import ballerina/jballerina.java; + +isolated function init() { + setModule(); } + +isolated function setModule() = @java:Method { + 'class: "io.ballerina.stdlib.azure.functions.ModuleUtils" +} external; diff --git a/ballerina/natives.bal b/ballerina/natives.bal new file mode 100644 index 00000000..b7667e89 --- /dev/null +++ b/ballerina/natives.bal @@ -0,0 +1,52 @@ +// Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +import ballerina/jballerina.java; + +isolated class HttpToAzureAdaptor { + isolated function init(HttpService 'service) { + externInit(self, 'service); + } + + isolated function getAzureFunctionNames() returns string[] = @java:Method { + 'class: "io.ballerina.stdlib.azure.functions.NativeHttpToAzureAdaptor" + } external; + + isolated function callNativeMethod(map body, string functionName) returns map|error = + @java:Method { + 'class: "io.ballerina.stdlib.azure.functions.NativeHttpToAzureAdaptor" + } external; +} + +isolated function externInit(HttpToAzureAdaptor adaptor, HttpService serviceObj) = @java:Method { + 'class: "io.ballerina.stdlib.azure.functions.NativeHttpToAzureAdaptor" +} external; + + + +isolated class AzureRemoteAdapter { + isolated function init(RemoteService 'service) { + externRemoteInit(self, 'service); + } + + isolated function callRemoteFunction(map body, string functionName) returns map|error = + @java:Method { + 'class: "io.ballerina.stdlib.azure.functions.NativeRemoteAdapter" + } external; +} + +isolated function externRemoteInit(AzureRemoteAdapter adaptor, RemoteService serviceObj) = @java:Method { + 'class: "io.ballerina.stdlib.azure.functions.NativeRemoteAdapter" +} external; diff --git a/ballerina/queue_listener.bal b/ballerina/queue_listener.bal new file mode 100644 index 00000000..4055ca6e --- /dev/null +++ b/ballerina/queue_listener.bal @@ -0,0 +1,41 @@ +// Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +public class QueueListener { + DispatcherService? httpService; + + public isolated function init() returns error? { + self.httpService = (); + } + + public function attach(QueueService svc, string[]|string? name = ()) returns error? { + AzureRemoteAdapter adaptor = new(svc); + self.httpService = new (adaptor, "onMessage"); + check httpListener.attach(self.httpService, name); + } + + public isolated function detach(QueueService svc) returns error? { + } + + public function 'start() returns error? { + check httpListener.'start(); + } + + public isolated function gracefulStop() returns error? { + } + + public isolated function immediateStop() returns error? { + } +} diff --git a/ballerina/records.bal b/ballerina/records.bal new file mode 100644 index 00000000..88dacaff --- /dev/null +++ b/ballerina/records.bal @@ -0,0 +1,72 @@ +// Copyright (c) 2022 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +# Represents details about the Timer trigger event +# +# + Schedule - Schedule the timer is being executed on +# + ScheduleStatus - Status of the Schedule +# + IsPastDue - Weather the timer is past its due time +public type TimerMetadata record { + TimerSchedule Schedule; + anydata ScheduleStatus?; + boolean IsPastDue; +}; + +# Represents the details about timer schedule +# +# + AdjustForDST - shows weather time is adjusted for DST +public type TimerSchedule record { + boolean AdjustForDST; +}; + +type Payload record { + map Data; + Metadata Metadata; +}; + +type Metadata record { + map Query; + map Headers; + Sys sys; +}; + +type Sys record { + string MethodName; + string UtcNow; + string RandGuid; +}; + +type HttpPayload record { + string Url; + string Method; + map Query; + map Headers; + map Params; + Identity[] Identities; + anydata? Body?; +}; + +type Identity record { +}; + +# Twilion SMS output binding data. +# +# + to - The SMS recipient phone number +# + body - The message body +public type TwilioSmsOutputBinding record { + string to?; + string body?; +}; diff --git a/ballerina/service_types.bal b/ballerina/service_types.bal new file mode 100644 index 00000000..fe91f82c --- /dev/null +++ b/ballerina/service_types.bal @@ -0,0 +1,46 @@ +// Copyright (c) 2022 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +import ballerina/http; +import ballerina/os; +import ballerina/lang.'int as ints; + +//TODO rename file and docs +http:Listener httpListener = check new (check ints:fromString(os:getEnv("FUNCTIONS_CUSTOMHANDLER_PORT"))); + +public type RemoteService QueueService|CosmosService|TimerService|BlobService; + + +public type QueueService distinct service object { + // remote function onMessage(anydata payload) returns anydata|error?; +}; + + +public type CosmosService distinct service object { + // remote function onUpdated(anydata payload) returns anydata|error?; +}; + + +public type TimerService distinct service object { + // remote function onTrigger(anydata payload) returns anydata|error?; +}; + + +public type BlobService distinct service object { + // remote function onTrigger(anydata payload) returns anydata|error?; +}; + + diff --git a/ballerina/timer_listener.bal b/ballerina/timer_listener.bal new file mode 100644 index 00000000..5842bdfc --- /dev/null +++ b/ballerina/timer_listener.bal @@ -0,0 +1,41 @@ +// Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you under the Apache License, +// Version 2.0 (the "License"); you may not use this file except +// in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +public class TimerListener { + DispatcherService? httpService; + + public isolated function init() returns error? { + self.httpService = (); + } + + public function attach(TimerService svc, string[]|string? name = ()) returns error? { + AzureRemoteAdapter adaptor = new(svc); + self.httpService = new (adaptor, "onTrigger"); + check httpListener.attach(self.httpService, name); + } + + public isolated function detach(TimerService svc) returns error? { + } + + public function 'start() returns error? { + check httpListener.'start(); + } + + public isolated function gracefulStop() returns error? { + } + + public isolated function immediateStop() returns error? { + } +} diff --git a/build-config/resources/Ballerina.toml b/build-config/resources/Ballerina.toml index a36361c7..d25a1946 100644 --- a/build-config/resources/Ballerina.toml +++ b/build-config/resources/Ballerina.toml @@ -2,3 +2,12 @@ org = "ballerinax" name = "azure_functions" version = "@toml.version@" + +[[platform.java11.dependency]] +path = "../native/build/libs/azure_functions-native-@project.version@.jar" + +#[[platform.java11.dependency]] +#path = "./lib/http-native-@stdlib.httpnative.version@.jar" + +[[platform.java11.dependency]] +path = "./lib/mime-native-@stdlib.mimenative.version@.jar" diff --git a/build-config/resources/BallerinaTest.toml b/build-config/resources/BallerinaTest.toml index 72d040e2..72a1eb02 100644 --- a/build-config/resources/BallerinaTest.toml +++ b/build-config/resources/BallerinaTest.toml @@ -2,3 +2,8 @@ org = "ballerinax" name = "azure_functions_tests" version = "@toml.version@" + +[[dependency]] +org = "ballerinax" +name = "azure_functions" +version = "3.0.0-alpha.1" diff --git a/build-config/resources/CompilerPlugin.toml b/build-config/resources/CompilerPlugin.toml index 1c27583f..ec4888ad 100644 --- a/build-config/resources/CompilerPlugin.toml +++ b/build-config/resources/CompilerPlugin.toml @@ -1,6 +1,6 @@ [plugin] id = "azure-functions" -class = "org.ballerinax.azurefunctions.generator.AzureCompilerPlugin" +class = "org.ballerinax.azurefunctions.AzureCompilerPlugin" [[dependency]] path = "../compiler-plugin/build/libs/azure_functions-compiler-plugin-@project.version@.jar" diff --git a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/HandlerTest.java b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/HandlerTest.java deleted file mode 100644 index 86c429e6..00000000 --- a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/HandlerTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.test; - -import com.google.gson.JsonObject; -import io.ballerina.projects.CodeGeneratorResult; -import io.ballerina.projects.DiagnosticResult; -import io.ballerina.projects.Document; -import io.ballerina.projects.DocumentId; -import io.ballerina.projects.Module; -import io.ballerina.projects.Package; -import io.ballerina.projects.PackageCompilation; -import io.ballerina.projects.directory.BuildProject; -import org.ballerinax.azurefunctions.generator.test.utils.ParserTestUtils; -import org.testng.Assert; -import org.testng.annotations.Test; - -import java.nio.file.Path; -import java.nio.file.Paths; - -/** - * Test case for checking generated source of handler. - */ -public class HandlerTest { - protected static final Path RESOURCE_DIRECTORY = Paths.get("src/test/resources/handlers/"); - @Test - public void testGeneratedHandlerSource() { - try { - BuildProject project = BuildProject.load(RESOURCE_DIRECTORY.resolve("code")); - CodeGeneratorResult codeGeneratorResult = project.currentPackage().runCodeGeneratorPlugins(); - Package updatedPackage = codeGeneratorResult.updatedPackage().orElseThrow(); - PackageCompilation compilation = updatedPackage.getCompilation(); - DiagnosticResult diagnosticResult = compilation.diagnosticResult(); - Assert.assertFalse(diagnosticResult.hasErrors()); - Module module = project.currentPackage().getDefaultModule(); - Assert.assertEquals(module.documentIds().size(), 2); - for (DocumentId documentId : module.documentIds()) { - Document document = module.document(documentId); - if ("main.bal".equals(document.name())) { - continue; - } - - JsonObject assertJson = - ParserTestUtils.readAssertFile(RESOURCE_DIRECTORY.resolve("generated").resolve("generated" + - ".json")); - - // Validate the tree against the assertion file - ParserTestUtils.assertNode(document.syntaxTree().rootNode().internalNode(), assertJson); - } - } catch (Exception e) { - Assert.fail(e.getMessage()); - } - } -} diff --git a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/ProjectValidationTests.java b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/ProjectValidationTests.java deleted file mode 100644 index 69df834d..00000000 --- a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/ProjectValidationTests.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.test; - -import io.ballerina.projects.DiagnosticResult; -import io.ballerina.projects.PackageCompilation; -import io.ballerina.projects.directory.BuildProject; -import io.ballerina.projects.directory.SingleFileProject; -import io.ballerina.tools.diagnostics.Diagnostic; -import org.testng.Assert; -import org.testng.annotations.Test; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Iterator; - -/** - * Contains the project related validations of azure functions. - * - * @since 2.0.0 - */ -public class ProjectValidationTests { - - protected static final Path RESOURCE_DIRECTORY = Paths.get("src/test/resources/validations/"); - - @Test - public void mainFunctionTest() { - BuildProject project = BuildProject.load(RESOURCE_DIRECTORY.resolve("main")); - PackageCompilation compilation = project.currentPackage().getCompilation(); - DiagnosticResult diagnosticResult = compilation.diagnosticResult(); - Assert.assertEquals(diagnosticResult.errorCount(), 1); - Diagnostic diagnostic = diagnosticResult.errors().iterator().next(); - Assert.assertEquals(diagnostic.message(), "main function is not allowed in azure functions"); - } - - @Test - public void submoduleTest() { - BuildProject project = BuildProject.load(RESOURCE_DIRECTORY.resolve("submodule")); - PackageCompilation compilation = project.currentPackage().getCompilation(); - DiagnosticResult diagnosticResult = compilation.diagnosticResult(); - Assert.assertEquals(diagnosticResult.errorCount(), 2); - Iterator iterator = diagnosticResult.errors().iterator(); - Diagnostic unusedModuleDiag = iterator.next(); - Assert.assertEquals(unusedModuleDiag.message(), "unused module prefix 'mod1'"); - Diagnostic submoduleDiag = iterator.next(); - Assert.assertEquals(submoduleDiag.message(), "azure functions is not allowed inside sub modules"); - } - - @Test - public void singleFileTest() { - SingleFileProject project = SingleFileProject.load(RESOURCE_DIRECTORY.resolve("single-file").resolve( - "functions.bal")); - PackageCompilation compilation = project.currentPackage().getCompilation(); - DiagnosticResult diagnosticResult = compilation.diagnosticResult(); - Assert.assertEquals(diagnosticResult.errorCount(), 1); - Iterator iterator = diagnosticResult.errors().iterator(); - Diagnostic unusedModuleDiag = iterator.next(); - Assert.assertEquals(unusedModuleDiag.message(), "azure functions are only allowed in ballerina" + - " projects"); - } -} diff --git a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/DeploymentTest.java b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/DeploymentTest.java similarity index 59% rename from compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/DeploymentTest.java rename to compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/DeploymentTest.java index 8985734a..752508a5 100644 --- a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/DeploymentTest.java +++ b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/DeploymentTest.java @@ -15,20 +15,16 @@ * specific language governing permissions and limitations * under the License. */ -package org.ballerinax.azurefunctions.generator.test; +package org.ballerinax.azurefunctions.test; -import org.ballerinax.azurefunctions.generator.test.utils.ProcessOutput; -import org.ballerinax.azurefunctions.generator.test.utils.TestUtils; +import org.ballerinax.azurefunctions.test.utils.ProcessOutput; +import org.ballerinax.azurefunctions.test.utils.TestUtils; import org.testng.Assert; import org.testng.annotations.Test; -import java.net.URI; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.HashMap; /** * Azure functions deployment test. @@ -39,26 +35,20 @@ public class DeploymentTest { @Test public void testAzureFunctionsDeploymentProject() throws Exception { - Path depedenciesToml = SOURCE_DIR.resolve("deployment").resolve("Dependencies.toml"); + Path handlers = SOURCE_DIR.resolve("handlers"); + Path depedenciesToml = handlers.resolve("Dependencies.toml"); Files.deleteIfExists(depedenciesToml); - ProcessOutput processOutput = TestUtils.compileBallerinaProject(SOURCE_DIR.resolve("deployment")); + ProcessOutput processOutput = TestUtils.compileBallerinaProject(handlers); Assert.assertEquals(processOutput.getExitCode(), 0); Assert.assertTrue(processOutput.getStdOutput().contains("@azure_functions")); // check if the executable jar and the host.json files are in the generated zip file - Path zipFilePath = SOURCE_DIR.resolve("deployment").resolve("target").resolve("bin").resolve("azure-functions" + - ".zip"); + Path zipFilePath = handlers.resolve("target").resolve("azure_functions"); Assert.assertTrue(Files.exists(zipFilePath)); - URI uri = URI.create("jar:file:" + zipFilePath.toUri().getPath()); - FileSystem zipfs = FileSystems.newFileSystem(uri, new HashMap<>()); - try { - Path jarFile = zipfs.getPath("/deployment.jar"); - Path hostJson = zipfs.getPath("/host.json"); - Assert.assertTrue(Files.exists(jarFile)); - Assert.assertTrue(Files.exists(hostJson)); - } finally { - zipfs.close(); - } + + Assert.assertTrue(Files.exists(zipFilePath.resolve("azure_functions_tests.jar"))); + Assert.assertTrue(Files.exists(zipFilePath.resolve("host.json"))); + Files.deleteIfExists(depedenciesToml); } } diff --git a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/FunctionArtifactTest.java b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/FunctionArtifactTest.java new file mode 100644 index 00000000..11935380 --- /dev/null +++ b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/FunctionArtifactTest.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.test; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import io.ballerina.projects.CodeModifierResult; +import io.ballerina.projects.DiagnosticResult; +import io.ballerina.projects.Package; +import io.ballerina.projects.PackageCompilation; +import io.ballerina.projects.directory.BuildProject; +import org.ballerinax.azurefunctions.AzureFunctionServiceExtractor; +import org.ballerinax.azurefunctions.FunctionContext; +import org.ballerinax.azurefunctions.service.Binding; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Test cases to generated function.json in different cases. + * + * @since 2201.3.0 + */ +public class FunctionArtifactTest { + + public static final Path RESOURCE_DIRECTORY = Paths.get("src/test/resources/handlers/"); + + private JsonParser jsonParser = new JsonParser(); + private Map generatedFunctions = new HashMap<>(); + + @BeforeClass + public void compileSample() { + BuildProject project = BuildProject.load(RESOURCE_DIRECTORY); + CodeModifierResult codeModifierResult = project.currentPackage().runCodeModifierPlugins(); + Package updatedPackage = codeModifierResult.updatedPackage().orElseThrow(); + PackageCompilation compilation = updatedPackage.getCompilation(); + + AzureFunctionServiceExtractor azureFunctionServiceExtractor = + new AzureFunctionServiceExtractor(updatedPackage); + List functionContexts = azureFunctionServiceExtractor.extractFunctions(); + + for (FunctionContext ctx : functionContexts) { + JsonObject functions = new JsonObject(); + JsonArray bindings = new JsonArray(); + List bindingList = ctx.getBindingList(); + for (Binding binding : bindingList) { + bindings.add(binding.getJsonObject()); + } + functions.add("bindings", bindings); + generatedFunctions.put(ctx.getFunctionName(), functions); + } + + DiagnosticResult diagnosticResult = compilation.diagnosticResult(); + Assert.assertFalse(diagnosticResult.hasErrors()); + Assert.assertEquals(generatedFunctions.size(), 24); + } + + @Test + public void testOptionalHttp() { + JsonObject httpHello = generatedFunctions.get("post-hello-optional"); + String str = + "{\"bindings\":[{\"type\":\"httpTrigger\",\"authLevel\":\"anonymous\",\"methods\":[\"post\"]," + + "\"direction\":\"in\",\"name\":\"httpPayload\",\"route\":\"hello/optional\"}," + + "{\"type\":\"http\",\"direction\":\"out\",\"name\":\"resp\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(httpHello, parse); + } + + @Test + public void testHttpTriggerInlineListener() { + JsonObject httpHello = generatedFunctions.get("post-helo-hello-query"); + String str = + "{\"bindings\":[{\"type\":\"httpTrigger\",\"authLevel\":\"anonymous\",\"methods\":[\"post\"]," + + "\"direction\":\"in\",\"name\":\"httpPayload\",\"route\":\"helo/hello-query\"}," + + "{\"type\":\"http\",\"direction\":\"out\",\"name\":\"resp\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(httpHello, parse); + } + + @Test + public void testHttpHello() { + JsonObject httpHello = generatedFunctions.get("post-hello"); + String str = + "{\"bindings\":[{\"type\":\"httpTrigger\",\"authLevel\":\"anonymous\",\"methods\":[\"post\"]," + + "\"direction\":\"in\",\"name\":\"httpPayload\",\"route\":\"hello\"}," + + "{\"type\":\"http\",\"direction\":\"out\",\"name\":\"resp\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(httpHello, parse); + } + + @Test + public void testHttpDefault() { + JsonObject httpHello = generatedFunctions.get("default-hello-all"); + String str = "{\"bindings\":[{\"type\":\"httpTrigger\",\"authLevel\":\"anonymous\",\"methods\":[\"DELETE\"," + + "\"GET\",\"HEAD\",\"OPTIONS\",\"POST\",\"PUT\"],\"direction\":\"in\",\"name\":\"httpPayload\"," + + "\"route\":\"hello/all\"},{\"type\":\"http\",\"direction\":\"out\",\"name\":\"resp\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(httpHello, parse); + } + + @Test + public void testHttpHelloFoo() { + JsonObject actual = generatedFunctions.get("post-hello-foo"); + String str = + "{\"bindings\":[{\"type\":\"httpTrigger\",\"authLevel\":\"anonymous\",\"methods\":[\"post\"]," + + "\"direction\":\"in\",\"name\":\"httpPayload\",\"route\":\"hello/foo\"},{\"type\":\"http\"," + + "\"direction\":\"out\",\"name\":\"resp\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + + @Test + public void testHttpHelloFooParam() { + JsonObject actual = generatedFunctions.get("post-hello-foo-bar-1"); + String str = + "{\"bindings\":[{\"type\":\"httpTrigger\",\"authLevel\":\"anonymous\",\"methods\":[\"post\"]," + + "\"direction\":\"in\",\"name\":\"httpPayload\",\"route\":\"hello/foo/{bar}\"}," + + "{\"type\":\"http\",\"direction\":\"out\",\"name\":\"resp\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + + @Test + public void testHttpHelloFooConflictPathParam() { + JsonObject actual = generatedFunctions.get("post-hello-foo-bar-2"); + String str = + "{\"bindings\":[{\"type\":\"httpTrigger\",\"authLevel\":\"anonymous\",\"methods\":[\"post\"]," + + "\"direction\":\"in\",\"name\":\"httpPayload\",\"route\":\"hello/foo/bar\"},{\"type\":" + + "\"http\",\"direction\":\"out\",\"name\":\"resp\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + + @Test + public void testQueueTrigger() { + JsonObject actual = generatedFunctions.get("queue"); + String str = + "{\"bindings\":[{\"type\":\"queueTrigger\",\"connection\":\"AzureWebJobsStorage\"," + + "\"queueName\":\"queue2\",\"direction\":\"in\",\"name\":\"inMsg\"},{\"type\":\"queue\"," + + "\"connection\":\"AzureWebJobsStorage\",\"queueName\":\"queue3\",\"direction\":\"out\"," + + "\"name\":\"outMsg\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + + @Test + public void testQueueTriggerInlineListener() { + JsonObject actual = generatedFunctions.get("queue1"); + String str = + "{\"bindings\":[{\"type\":\"queueTrigger\",\"connection\":\"AzureWebJobsStorage\"," + + "\"queueName\":\"queue21\",\"direction\":\"in\",\"name\":\"inMsg\"},{\"type\":\"queue\"," + + "\"connection\":\"AzureWebJobsStorage\",\"queueName\":\"queue3\",\"direction\":\"out\"," + + "\"name\":\"outMsg\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + + @Test + public void testCosmosTrigger() { + JsonObject actual = generatedFunctions.get("cosmos"); + String str = + "{\"bindings\":[{\"type\":\"cosmosDBTrigger\",\"connectionStringSetting\":\"CosmosDBConnection\"," + + "\"databaseName\":\"db1\",\"collectionName\":\"c2\",\"name\":\"inMsg\",\"direction\":\"in\"," + + "\"createLeaseCollectionIfNotExists\":true,\"leasesCollectionThroughput\":400}," + + "{\"type\":\"queue\",\"connection\":\"AzureWebJobsStorage\",\"queueName\":\"queue3\"," + + "\"direction\":\"out\",\"name\":\"outMsg\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + + @Test + public void testCosmosTriggerInlineListener() { + JsonObject actual = generatedFunctions.get("cosmos1"); + String str = + "{\"bindings\":[{\"type\":\"cosmosDBTrigger\",\"connectionStringSetting\":\"CosmosDBConnection\"," + + "\"databaseName\":\"db1\",\"collectionName\":\"c2\",\"name\":\"inMsg\",\"direction\":\"in\"," + + "\"createLeaseCollectionIfNotExists\":true,\"leasesCollectionThroughput\":400}," + + "{\"type\":\"queue\",\"connection\":\"AzureWebJobsStorage\",\"queueName\":\"queue3\"," + + "\"direction\":\"out\",\"name\":\"outMsg\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + + @Test + public void testTimerTrigger() { + JsonObject actual = generatedFunctions.get("timer"); + String str = "{\"bindings\":[{\"type\":\"timerTrigger\",\"schedule\":\"*/10 * * * * *\"," + + "\"runOnStartup\":true,\"direction\":\"in\",\"name\":\"inMsg\"},{\"type\":\"queue\",\"connection\":" + + "\"AzureWebJobsStorage\",\"queueName\":\"queue3\",\"direction\":\"out\",\"name\":\"outMsg\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + + @Test + public void testTimerTriggerInlineListener() { + JsonObject actual = generatedFunctions.get("timer1"); + String str = "{\"bindings\":[{\"type\":\"timerTrigger\",\"schedule\":\"*/10 * * * * *\"," + + "\"runOnStartup\":true,\"direction\":\"in\",\"name\":\"inMsg\"},{\"type\":\"queue\",\"connection\":" + + "\"AzureWebJobsStorage\",\"queueName\":\"queue3\",\"direction\":\"out\",\"name\":\"outMsg\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + + @Test + public void testBlobTrigger() { + JsonObject actual = generatedFunctions.get("blob"); + String str = "{\"bindings\":[{\"type\":\"blobTrigger\",\"name\":\"blobIn\",\"direction\":\"in\"," + + "\"path\":\"bpath1/{name}\",\"connection\":\"AzureWebJobsStorage\"},{\"type\":\"blob\"," + + "\"direction\":\"out\",\"name\":\"outMsg\",\"path\":\"bpath1/newBlob\"," + + "\"connection\":\"AzureWebJobsStorage\",\"dataType\":\"string\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + + @Test + public void testBlobTriggerInlineListener() { + JsonObject actual = generatedFunctions.get("blob1"); + String str = "{\"bindings\":[{\"type\":\"blobTrigger\",\"name\":\"blobIn\",\"direction\":\"in\"," + + "\"path\":\"bpath1/{name}\",\"connection\":\"AzureWebJobsStorage\"},{\"type\":\"blob\"," + + "\"direction\":\"out\",\"name\":\"outMsg\",\"path\":\"bpath1/newBlob\"," + + "\"connection\":\"AzureWebJobsStorage\",\"dataType\":\"string\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(actual, parse); + } + + @Test + public void testEscapeSequence() { + JsonObject httpHello = generatedFunctions.get("post-hello--hello-query"); + String str = + "{\"bindings\":[{\"type\":\"httpTrigger\",\"authLevel\":\"anonymous\",\"methods\":[\"post\"]," + + "\"direction\":\"in\",\"name\":\"httpPayload\",\"route\":\"hello-/hello-query\"}," + + "{\"type\":\"http\",\"direction\":\"out\",\"name\":\"resp\"}]}"; + JsonElement parse = jsonParser.parse(str); + Assert.assertEquals(httpHello, parse); + } +} diff --git a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/ProjectValidationTests.java b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/ProjectValidationTests.java new file mode 100644 index 00000000..ba855b4d --- /dev/null +++ b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/ProjectValidationTests.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.test; + +import io.ballerina.projects.DiagnosticResult; +import io.ballerina.projects.PackageCompilation; +import io.ballerina.projects.directory.BuildProject; +import io.ballerina.tools.diagnostics.Diagnostic; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.nio.file.Path; +import java.nio.file.Paths; + + +/** + * Contains the project related validations of azure functions. + * + * @since 2.0.0 + */ +public class ProjectValidationTests { + + protected static final Path RESOURCE_DIRECTORY = Paths.get("src/test/resources/validations/"); + + @Test + public void headerAnnotationTest() { + BuildProject project = BuildProject.load(RESOURCE_DIRECTORY.resolve("http-header-annotation")); + PackageCompilation compilation = project.currentPackage().getCompilation(); + DiagnosticResult diagnosticResult = compilation.diagnosticResult(); + Object [] diagnostics = diagnosticResult.errors().toArray(); + Assert.assertEquals(diagnosticResult.errorCount(), 13); + String diagnosticMessage0 = "invalid annotation type on param 'a'"; + String diagnosticMessage1 = "invalid union type of header param 'xRate': one of the 'string','int','float'," + + "'decimal','boolean' types, an array of the above types or a record which consists of the above " + + "types can only be union with '()'. Eg: string|() or string[]|()"; + String diagnosticMessage2 = "invalid type of header param 'abc': One of the following types is expected: " + + "'string','int','float','decimal','boolean', an array of the above types or a record which consists " + + "of the above types"; + String diagnosticMessage3 = "invalid union type of header param 'abc': one of the 'string','int','float'," + + "'decimal','boolean' types, an array of the above types or a record which consists of the above types " + + "can only be union with '()'. Eg: string|() or string[]|()"; + String diagnosticMessage4 = "invalid union type of header param 'abc': one of the 'string','int','float'," + + "'decimal','boolean' types, an array of the above types or a record which consists of the above " + + "types can only be union with '()'. Eg: string|() or string[]|()"; + String diagnosticMessage5 = "rest fields are not allowed for header binding records. " + + "Use 'http:Headers' type to access all headers"; + String diagnosticMessage6 = "rest fields are not allowed for header binding records. " + + "Use 'http:Headers' type to access all headers"; + String diagnosticMessage7 = "invalid type of header param 'abc': One of the following types is expected: " + + "'string','int','float','decimal','boolean', an array of the above types or a record which " + + "consists of the above types"; + String diagnosticMessage8 = "invalid multiple resource parameter annotations for 'abc'"; + String diagnosticMessage9 = "invalid type of header param 'abc': One of the following types is expected: " + + "'string','int','float','decimal','boolean', an array of the above types or a record which " + + "consists of the above types"; + String diagnosticMessage10 = "invalid union type of header param 'abc': one of the 'string','int','float'," + + "'decimal','boolean' types, an array of the above types or a record which consists of the " + + "above types can only be union with '()'. Eg: string|() or string[]|()"; + String diagnosticMessage11 = "invalid type of header param 'abc': One of the following types is expected: " + + "'string','int','float','decimal','boolean', an array of the above types or a record which " + + "consists of the above types"; + String diagnosticMessage12 = "invalid union type of header param 'abc': one of the 'string','int','float'," + + "'decimal','boolean' types, an array of the above types or a record which consists of " + + "the above types can only be union with '()'. Eg: string|() or string[]|()"; + Assert.assertEquals(((Diagnostic) diagnostics[0]).diagnosticInfo().messageFormat(), diagnosticMessage0); + Assert.assertEquals(((Diagnostic) diagnostics[1]).diagnosticInfo().messageFormat(), diagnosticMessage1); + Assert.assertEquals(((Diagnostic) diagnostics[2]).diagnosticInfo().messageFormat(), diagnosticMessage2); + Assert.assertEquals(((Diagnostic) diagnostics[3]).diagnosticInfo().messageFormat(), diagnosticMessage3); + Assert.assertEquals(((Diagnostic) diagnostics[4]).diagnosticInfo().messageFormat(), diagnosticMessage4); + Assert.assertEquals(((Diagnostic) diagnostics[5]).diagnosticInfo().messageFormat(), diagnosticMessage5); + Assert.assertEquals(((Diagnostic) diagnostics[6]).diagnosticInfo().messageFormat(), diagnosticMessage6); + Assert.assertEquals(((Diagnostic) diagnostics[7]).diagnosticInfo().messageFormat(), diagnosticMessage7); + Assert.assertEquals(((Diagnostic) diagnostics[8]).diagnosticInfo().messageFormat(), diagnosticMessage8); + Assert.assertEquals(((Diagnostic) diagnostics[9]).diagnosticInfo().messageFormat(), diagnosticMessage9); + Assert.assertEquals(((Diagnostic) diagnostics[10]).diagnosticInfo().messageFormat(), diagnosticMessage10); + Assert.assertEquals(((Diagnostic) diagnostics[11]).diagnosticInfo().messageFormat(), diagnosticMessage11); + Assert.assertEquals(((Diagnostic) diagnostics[12]).diagnosticInfo().messageFormat(), diagnosticMessage12); + } + + @Test + public void httpServiceConfigTest() { + BuildProject project = BuildProject.load(RESOURCE_DIRECTORY.resolve("http-service-config")); + PackageCompilation compilation = project.currentPackage().getCompilation(); + DiagnosticResult diagnosticResult = compilation.diagnosticResult(); + Object[] diagnostics = diagnosticResult.warnings().toArray(); + Assert.assertEquals(diagnosticResult.warningCount(), 2); + String diagnosticMessage = "'treatNilableAsOptional' is the only @http:serviceConfig " + + "field supported by Azure Function at the moment"; + Assert.assertEquals(((Diagnostic) diagnostics[0]).diagnosticInfo().messageFormat(), diagnosticMessage); + Assert.assertEquals(((Diagnostic) diagnostics[1]).diagnosticInfo().messageFormat(), diagnosticMessage); + } +} diff --git a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/ParserTestConstants.java b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/ParserTestConstants.java similarity index 95% rename from compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/ParserTestConstants.java rename to compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/ParserTestConstants.java index cf621291..228a87be 100644 --- a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/ParserTestConstants.java +++ b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/ParserTestConstants.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.ballerinax.azurefunctions.generator.test.utils; +package org.ballerinax.azurefunctions.test.utils; /** * Constants related to the parser. diff --git a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/ParserTestUtils.java b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/ParserTestUtils.java similarity index 98% rename from compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/ParserTestUtils.java rename to compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/ParserTestUtils.java index 8e824622..4c8c0861 100644 --- a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/ParserTestUtils.java +++ b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/ParserTestUtils.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.ballerinax.azurefunctions.generator.test.utils; +package org.ballerinax.azurefunctions.test.utils; import com.google.gson.Gson; import com.google.gson.JsonArray; @@ -45,15 +45,15 @@ import java.util.Collection; import static io.ballerina.compiler.internal.syntax.SyntaxUtils.isSTNodePresent; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.CHILDREN_FIELD; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.DIAGNOSTICS_FIELD; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.HAS_DIAGNOSTICS; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.INVALID_NODE_FIELD; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.IS_MISSING_FIELD; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.KIND_FIELD; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.LEADING_MINUTIAE; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.TRAILING_MINUTIAE; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.VALUE_FIELD; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.CHILDREN_FIELD; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.DIAGNOSTICS_FIELD; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.HAS_DIAGNOSTICS; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.INVALID_NODE_FIELD; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.IS_MISSING_FIELD; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.KIND_FIELD; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.LEADING_MINUTIAE; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.TRAILING_MINUTIAE; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.VALUE_FIELD; /** * Convenient methods for testing the parser. diff --git a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/ProcessOutput.java b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/ProcessOutput.java similarity index 96% rename from compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/ProcessOutput.java rename to compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/ProcessOutput.java index ad47ac86..602f9256 100644 --- a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/ProcessOutput.java +++ b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/ProcessOutput.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.ballerinax.azurefunctions.generator.test.utils; +package org.ballerinax.azurefunctions.test.utils; /** * Represents a Java process output. diff --git a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/SyntaxTreeJSONGenerator.java b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/SyntaxTreeJSONGenerator.java similarity index 88% rename from compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/SyntaxTreeJSONGenerator.java rename to compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/SyntaxTreeJSONGenerator.java index 13367ccf..9f0008c7 100644 --- a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/SyntaxTreeJSONGenerator.java +++ b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/SyntaxTreeJSONGenerator.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.ballerinax.azurefunctions.generator.test.utils; +package org.ballerinax.azurefunctions.test.utils; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -41,15 +41,15 @@ import java.nio.file.Paths; import java.util.Collection; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.CHILDREN_FIELD; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.DIAGNOSTICS_FIELD; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.HAS_DIAGNOSTICS; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.INVALID_NODE_FIELD; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.IS_MISSING_FIELD; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.KIND_FIELD; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.LEADING_MINUTIAE; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.TRAILING_MINUTIAE; -import static org.ballerinax.azurefunctions.generator.test.utils.ParserTestConstants.VALUE_FIELD; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.CHILDREN_FIELD; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.DIAGNOSTICS_FIELD; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.HAS_DIAGNOSTICS; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.INVALID_NODE_FIELD; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.IS_MISSING_FIELD; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.KIND_FIELD; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.LEADING_MINUTIAE; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.TRAILING_MINUTIAE; +import static org.ballerinax.azurefunctions.test.utils.ParserTestConstants.VALUE_FIELD; /** * Generates a JSON that represents the structure of the syntax tree. This JSON diff --git a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/TestUtils.java b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/TestUtils.java similarity index 98% rename from compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/TestUtils.java rename to compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/TestUtils.java index 4b12596c..d83c1fa5 100644 --- a/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/generator/test/utils/TestUtils.java +++ b/compiler-plugin-tests/src/test/java/org/ballerinax/azurefunctions/test/utils/TestUtils.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.ballerinax.azurefunctions.generator.test.utils; +package org.ballerinax.azurefunctions.test.utils; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; diff --git a/compiler-plugin-tests/src/test/resources/deployment/Ballerina.toml b/compiler-plugin-tests/src/test/resources/deployment/Ballerina.toml deleted file mode 100644 index cd92fa2b..00000000 --- a/compiler-plugin-tests/src/test/resources/deployment/Ballerina.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -org = "anjana" -name = "deployment" -version = "0.1.0" - -[build-options] -observabilityIncluded = true diff --git a/compiler-plugin-tests/src/test/resources/deployment/functions.bal b/compiler-plugin-tests/src/test/resources/deployment/functions.bal deleted file mode 100644 index 98892b78..00000000 --- a/compiler-plugin-tests/src/test/resources/deployment/functions.bal +++ /dev/null @@ -1,195 +0,0 @@ -import ballerina/uuid; -import ballerinax/azure_functions as af; - -// HTTP request/response with no authentication -@af:Function -public isolated function hello(@af:HTTPTrigger { authLevel: "anonymous" } string payload) - returns @af:HTTPOutput string|error { - return "Hello, " + payload + "!"; -} - -// HTTP request to add data to a queue -@af:Function -public isolated function fromHttpToQueue(af:Context ctx, - @af:HTTPTrigger af:HTTPRequest req, - @af:QueueOutput { queueName: "queue1" } af:StringOutputBinding msg) - returns @af:HTTPOutput af:HTTPBinding { - msg.value = req.body; - return { statusCode: 200, payload: "Request: " + req.toString() }; -} - -// A message put to a queue is copied to another queue -@af:Function -public isolated function fromQueueToQueue(af:Context ctx, - @af:QueueTrigger { queueName: "queue2" } string inMsg, - @af:QueueOutput { queueName: "queue3" } af:StringOutputBinding outMsg) { - ctx.log("In Message: " + inMsg); - ctx.log("Metadata: " + ctx.metadata.toString()); - outMsg.value = inMsg; -} - -// A blob added to a container is copied to a queue -@af:Function -public isolated function fromBlobToQueue(af:Context ctx, - @af:BlobTrigger { path: "bpath1/{name}" } byte[] blobIn, - @af:BindingName string name, - @af:QueueOutput { queueName: "queue3" } af:StringOutputBinding outMsg) - returns error? { - outMsg.value = "Name: " + name + " Content: " + blobIn.toString(); -} - -// HTTP request to read a blob value -@af:Function -public isolated function httpTriggerBlobInput(@af:HTTPTrigger af:HTTPRequest req, - @af:BlobInput { path: "bpath1/{Query.name}" } byte[]? blobIn) - returns @af:HTTPOutput string { - int length = 0; - if blobIn is byte[] { - length = blobIn.length(); - } - return "Blob: " + req.query["name"].toString() + " Length: " + - length.toString() + " Content: " + blobIn.toString(); -} - -// HTTP request to read a blob value input string -@af:Function -public isolated function httpTriggerBlobInputStr(@af:HTTPTrigger af:HTTPRequest req, - @af:BlobInput { path: "bpath1/{Query.name}" } string? strIn) - returns @af:HTTPOutput string { - string str = ""; - if strIn is string { - str = strIn; - } - return "Blob: " + req.query["name"].toString() + " Length: " + - strIn.toString() + " Content: " + str; -} - -// HTTP request to add a new blob -@af:Function -public isolated function httpTriggerBlobOutput(@af:HTTPTrigger af:HTTPRequest req, - @af:BlobOutput { path: "bpath1/{Query.name}" } af:StringOutputBinding bb) - returns @af:HTTPOutput string|error { - bb.value = req.body; - return "Blob: " + req.query["name"].toString() + " Content: " + - bb?.value.toString(); -} - -// HTTP request to add a new blob -@af:Function -public isolated function httpTriggerBlobOutput2(@af:HTTPTrigger af:HTTPRequest req, - @af:BlobOutput { path: "bpath1/{Query.name}" } af:BytesOutputBinding bb) - returns @af:HTTPOutput string|error { - bb.value = [65, 66, 67, 97, 98]; - return "Blob: " + req.query["name"].toString() + " Content: " + - bb?.value.toString(); -} - -// Sending an SMS -@af:Function -public isolated function sendSMS(@af:HTTPTrigger af:HTTPRequest req, - @af:TwilioSmsOutput { fromNumber: "+12069845840" } - af:TwilioSmsOutputBinding tb) - returns @af:HTTPOutput string { - tb.to = req.query["to"].toString(); - tb.body = req.body.toString(); - return "Message - to: " + tb?.to.toString() + " body: " + tb?.body.toString(); -} - -public type Person record { - string id; - string name; - string country; -}; - -// CosmosDB record trigger -@af:Function -public isolated function cosmosDBToQueue1(@af:CosmosDBTrigger { - connectionStringSetting: "CosmosDBConnection", databaseName: "db1", - collectionName: "c1" } Person[] req, - @af:QueueOutput { queueName: "queue3" } af:StringOutputBinding outMsg) { - outMsg.value = req.toString(); -} - -@af:Function -public isolated function cosmosDBToQueue2(@af:CosmosDBTrigger { - connectionStringSetting: "CosmosDBConnection", databaseName: "db1", - collectionName: "c2" } json req, - @af:QueueOutput { queueName: "queue3" } af:StringOutputBinding outMsg) { - outMsg.value = req.toString(); -} - -// HTTP request to read CosmosDB records -@af:Function -public isolated function httpTriggerCosmosDBInput1( - @af:HTTPTrigger af:HTTPRequest httpReq, - @af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1", - id: "{Query.id}", partitionKey: "{Query.country}" } json dbReq) - returns @af:HTTPOutput string|error { - return dbReq.toString(); -} - -@af:Function -public isolated function httpTriggerCosmosDBInput2( - @af:HTTPTrigger af:HTTPRequest httpReq, - @af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1", - id: "{Query.id}", partitionKey: "{Query.country}" } Person? dbReq) - returns @af:HTTPOutput string|error { - return dbReq.toString(); -} - -@af:Function -public isolated function httpTriggerCosmosDBInput3( - @af:HTTPTrigger { route: "c1/{country}" } af:HTTPRequest httpReq, - @af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1", - sqlQuery: "select * from c1 where c1.country = {country}" } - Person[] dbReq) - returns @af:HTTPOutput string|error { - return dbReq.toString(); -} - -// HTTP request to write records to CosmosDB -@af:Function -public isolated function httpTriggerCosmosDBOutput1( - @af:HTTPTrigger af:HTTPRequest httpReq, @af:HTTPOutput af:HTTPBinding hb) - returns @af:CosmosDBOutput { connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1" } json { - json entry = { id: uuid:createType1AsString(), name: "Saman", country: "Sri Lanka" }; - hb.payload = "Adding entry: " + entry.toString(); - return entry; -} - -@af:Function -public isolated function httpTriggerCosmosDBOutput2( - @af:HTTPTrigger af:HTTPRequest httpReq, - @af:HTTPOutput af:HTTPBinding hb) - returns @af:CosmosDBOutput { - connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1" } json { - json entry = [{ id: uuid:createType1AsString(), name: "John Doe A", country: "USA" }, - { id: uuid:createType1AsString(), name: "John Doe B", country: "USA" }]; - hb.payload = "Adding entries: " + entry.toString(); - return entry; -} - -@af:Function -public isolated function httpTriggerCosmosDBOutput3( - @af:HTTPTrigger af:HTTPRequest httpReq) - returns @af:CosmosDBOutput { - connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1" } Person[] { - Person[] persons = []; - persons.push({id: uuid:createType1AsString(), name: "Jack", country: "UK"}); - persons.push({id: uuid:createType1AsString(), name: "Will", country: "UK"}); - return persons; -} - -// A timer function which is executed every 10 seconds. -@af:Function -public isolated function queuePopulationTimer( - @af:TimerTrigger { schedule: "*/10 * * * * *" } json triggerInfo, - @af:QueueOutput { queueName: "queue4" } af:StringOutputBinding msg) { - msg.value = triggerInfo.toString(); -} diff --git a/compiler-plugin-tests/src/test/resources/handlers/Ballerina.toml b/compiler-plugin-tests/src/test/resources/handlers/Ballerina.toml new file mode 100644 index 00000000..2758f261 --- /dev/null +++ b/compiler-plugin-tests/src/test/resources/handlers/Ballerina.toml @@ -0,0 +1,9 @@ +[package] +org = "ballerinax" +name = "azure_functions_tests" +version = "3.0.0" + +[[dependency]] +org = "ballerinax" +name = "azure_functions" +version = "3.0.0-alpha.1" diff --git a/compiler-plugin-tests/src/test/resources/handlers/code/Ballerina.toml b/compiler-plugin-tests/src/test/resources/handlers/code/Ballerina.toml deleted file mode 100644 index 4e552d98..00000000 --- a/compiler-plugin-tests/src/test/resources/handlers/code/Ballerina.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -org = "anjana" -name = "proj" -version = "0.1.0" - -[build-options] -observabilityIncluded = true \ No newline at end of file diff --git a/compiler-plugin-tests/src/test/resources/handlers/code/main.bal b/compiler-plugin-tests/src/test/resources/handlers/code/main.bal deleted file mode 100644 index a372656d..00000000 --- a/compiler-plugin-tests/src/test/resources/handlers/code/main.bal +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) 2020 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -// -// WSO2 Inc. licenses this file to you under the Apache License, -// Version 2.0 (the "License"); you may not use this file except -// in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -import ballerina/uuid; -import ballerinax/azure_functions as af; - -// HTTP request/response with no authentication -@af:Function -public isolated function hello(@af:HTTPTrigger { authLevel: "anonymous" } string payload) - returns @af:HTTPOutput string|error { - return "Hello, " + payload + "!"; -} - -// HTTP request to add data to a queue -@af:Function -public isolated function fromHttpToQueue(af:Context ctx, - @af:HTTPTrigger {} af:HTTPRequest req, - @af:QueueOutput { queueName: "queue1" } af:StringOutputBinding msg) - returns @af:HTTPOutput af:HTTPBinding { - msg.value = req.body; - return { statusCode: 200, payload: "Request: " + req.toString() }; -} - -// A message put to a queue is copied to another queue -@af:Function -public isolated function fromQueueToQueue(af:Context ctx, - @af:QueueTrigger { queueName: "queue2" } string inMsg, - @af:QueueOutput { queueName: "queue3" } af:StringOutputBinding outMsg) { - ctx.log("In Message: " + inMsg); - ctx.log("Metadata: " + ctx.metadata.toString()); - outMsg.value = inMsg; -} - -// // A blob added to a container is copied to a queue -@af:Function -public isolated function fromBlobToQueue(af:Context ctx, - @af:BlobTrigger { path: "bpath1/{name}" } byte[] blobIn, - @af:BindingName { } string name, - @af:QueueOutput { queueName: "queue3" } af:StringOutputBinding outMsg) - returns error? { - outMsg.value = "Name: " + name + " Content: " + blobIn.toString(); -} - -// // HTTP request to read a blob value -@af:Function -public isolated function httpTriggerBlobInput(@af:HTTPTrigger { } af:HTTPRequest req, - @af:BlobInput { path: "bpath1/{Query.name}" } byte[]? blobIn) - returns @af:HTTPOutput string { - int length = 0; - if blobIn is byte[] { - length = blobIn.length(); - } - return "Blob: " + req.query["name"].toString() + " Length: " + - length.toString() + " Content: " + blobIn.toString(); -} - -// // HTTP request to add a new blob -@af:Function -public isolated function httpTriggerBlobOutput(@af:HTTPTrigger { } af:HTTPRequest req, - @af:BlobOutput { path: "bpath1/{Query.name}" } af:StringOutputBinding bb) - returns @af:HTTPOutput string|error { - bb.value = req.body; - return "Blob: " + req.query["name"].toString() + " Content: " + - bb?.value.toString(); -} - -// // Sending an SMS -@af:Function -public isolated function sendSMS(@af:HTTPTrigger { } af:HTTPRequest req, - @af:TwilioSmsOutput { fromNumber: "+12069845840" } - af:TwilioSmsOutputBinding tb) - returns @af:HTTPOutput string { - tb.to = req.query["to"].toString(); - tb.body = req.body.toString(); - return "Message - to: " + tb?.to.toString() + " body: " + tb?.body.toString(); -} - -public type Person record { - string id; - string name; - string country; -}; - -// // CosmosDB record trigger -@af:Function -public isolated function cosmosDBToQueue1(@af:CosmosDBTrigger { - connectionStringSetting: "CosmosDBConnection", databaseName: "db1", - collectionName: "c1" } Person[] req, - @af:QueueOutput { queueName: "queue3" } af:StringOutputBinding outMsg) { - outMsg.value = req.toString(); -} - -@af:Function -public isolated function cosmosDBToQueue2(@af:CosmosDBTrigger { - connectionStringSetting: "CosmosDBConnection", databaseName: "db1", - collectionName: "c2" } json req, - @af:QueueOutput { queueName: "queue3" } af:StringOutputBinding outMsg) { - outMsg.value = req.toString(); -} - -// // HTTP request to read CosmosDB records -@af:Function -public isolated function httpTriggerCosmosDBInput1( - @af:HTTPTrigger { } af:HTTPRequest httpReq, - @af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1", - id: "{Query.id}", partitionKey: "{Query.country}" } json dbReq) - returns @af:HTTPOutput string|error { - return dbReq.toString(); -} - -@af:Function -public isolated function httpTriggerCosmosDBInput2( - @af:HTTPTrigger { } af:HTTPRequest httpReq, - @af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1", - id: "{Query.id}", partitionKey: "{Query.country}" } Person? dbReq) - returns @af:HTTPOutput string|error { - return dbReq.toString(); -} - -@af:Function -public isolated function httpTriggerCosmosDBInput3( - @af:HTTPTrigger { route: "c1/{country}" } af:HTTPRequest httpReq, - @af:CosmosDBInput { connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1", - sqlQuery: "select * from c1 where c1.country = {country}" } - Person[] dbReq) - returns @af:HTTPOutput string|error { - return dbReq.toString(); -} - -// // HTTP request to write records to CosmosDB -@af:Function -public isolated function httpTriggerCosmosDBOutput1( - @af:HTTPTrigger { } af:HTTPRequest httpReq, @af:HTTPOutput af:HTTPBinding hb) - returns @af:CosmosDBOutput { connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1" } json { - json entry = { id: uuid:createType1AsString(), name: "Saman", country: "Sri Lanka" }; - hb.payload = "Adding entry: " + entry.toString(); - return entry; -} - -@af:Function -public isolated function httpTriggerCosmosDBOutput2( - @af:HTTPTrigger { } af:HTTPRequest httpReq, - @af:HTTPOutput af:HTTPBinding hb) - returns @af:CosmosDBOutput { - connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1" } json { - json entry = [{ id: uuid:createType1AsString(), name: "John Doe A", country: "USA" }, - { id: uuid:createType1AsString(), name: "John Doe B", country: "USA" }]; - hb.payload = "Adding entries: " + entry.toString(); - return entry; -} - -@af:Function -public isolated function httpTriggerCosmosDBOutput3( - @af:HTTPTrigger { } af:HTTPRequest httpReq) - returns @af:CosmosDBOutput { - connectionStringSetting: "CosmosDBConnection", - databaseName: "db1", collectionName: "c1" } Person[] { - Person[] persons = []; - persons.push({id: uuid:createType1AsString(), name: "Jack", country: "UK"}); - persons.push({id: uuid:createType1AsString(), name: "Will", country: "UK"}); - return persons; -} - -// // A timer function which is executed every 10 seconds. -@af:Function -public isolated function queuePopulationTimer( - @af:TimerTrigger { schedule: "*/10 * * * * *" } json triggerInfo, - @af:QueueOutput { queueName: "queue4" } af:StringOutputBinding msg) { - msg.value = triggerInfo.toString(); -} diff --git a/compiler-plugin-tests/src/test/resources/handlers/generated/generated.bal b/compiler-plugin-tests/src/test/resources/handlers/generated/generated.bal deleted file mode 100644 index 2a33cd11..00000000 --- a/compiler-plugin-tests/src/test/resources/handlers/generated/generated.bal +++ /dev/null @@ -1,82 +0,0 @@ -import ballerinax/azure_functions as af; -import ballerina/http; -public listener http:Listener __testListener=af:hl ;type PersonOptionalGenerated Person? ;type PersonArrayGenerated Person[] ;service http:Service / on __testListener {isolated resource function 'default hello (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.helloHandler(params),params);check caller->respond(response);}public isolated function helloHandler (af:HandlerParams params)returns error? { -string v1=check hello(check af:getBodyFromHTTPInputData(params,"payload")); -_=check af:setStringReturn(params,v1); -}isolated resource function 'default fromHttpToQueue (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.fromHttpToQueueHandler(params),params);check caller->respond(response);}public isolated function fromHttpToQueueHandler (af:HandlerParams params)returns error? { -af:StringOutputBinding v1={}; -af:HTTPBinding v2=fromHttpToQueue(check af:createContext(params,true),check af:getHTTPRequestFromInputData(params,"req"),v1); -_=check af:setStringOutput(params,"msg",v1); -_=check af:setHTTPReturn(params,v2); -}isolated resource function 'default fromQueueToQueue (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.fromQueueToQueueHandler(params),params);check caller->respond(response);}public isolated function fromQueueToQueueHandler (af:HandlerParams params)returns error? { -af:StringOutputBinding v1={}; -_=fromQueueToQueue(check af:createContext(params,true),check af:getJsonStringFromInputData(params,"inMsg"),v1); -_=check af:setStringOutput(params,"outMsg",v1); -}isolated resource function 'default fromBlobToQueue (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.fromBlobToQueueHandler(params),params);check caller->respond(response);}public isolated function fromBlobToQueueHandler (af:HandlerParams params)returns error? { -af:StringOutputBinding v1={}; -_=check fromBlobToQueue(check af:createContext(params,true),check af:getBytesFromInputData(params,"blobIn"),check af:getStringFromMetadata(params,"name"),v1); -_=check af:setStringOutput(params,"outMsg",v1); -}isolated resource function 'default httpTriggerBlobInput (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.httpTriggerBlobInputHandler(params),params);check caller->respond(response);}public isolated function httpTriggerBlobInputHandler (af:HandlerParams params)returns error? { -string v1=httpTriggerBlobInput(check af:getHTTPRequestFromInputData(params,"req"),check af:getOptionalBytesFromInputData(params,"blobIn")); -_=check af:setStringReturn(params,v1); -}isolated resource function 'default httpTriggerBlobOutput (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.httpTriggerBlobOutputHandler(params),params);check caller->respond(response);}public isolated function httpTriggerBlobOutputHandler (af:HandlerParams params)returns error? { -af:StringOutputBinding v1={}; -string v2=check httpTriggerBlobOutput(check af:getHTTPRequestFromInputData(params,"req"),v1); -_=check af:setBlobOutput(params,"bb",v1); -_=check af:setStringReturn(params,v2); -}isolated resource function 'default sendSMS (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.sendSMSHandler(params),params);check caller->respond(response);}public isolated function sendSMSHandler (af:HandlerParams params)returns error? { -af:TwilioSmsOutputBinding v1={}; -string v2=sendSMS(check af:getHTTPRequestFromInputData(params,"req"),v1); -_=check af:setTwilioSmsOutput(params,"tb",v1); -_=check af:setStringReturn(params,v2); -}isolated resource function 'default cosmosDBToQueue1 (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.cosmosDBToQueue1Handler(params),params);check caller->respond(response);}public isolated function cosmosDBToQueue1Handler (af:HandlerParams params)returns error? { -af:StringOutputBinding v1={}; -_=cosmosDBToQueue1(check af:getBallerinaValueFromInputData(params,"req",PersonArrayGenerated),v1); -_=check af:setStringOutput(params,"outMsg",v1); -}isolated resource function 'default cosmosDBToQueue2 (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.cosmosDBToQueue2Handler(params),params);check caller->respond(response);}public isolated function cosmosDBToQueue2Handler (af:HandlerParams params)returns error? { -af:StringOutputBinding v1={}; -_=cosmosDBToQueue2(check af:getJsonFromInputData(params,"req"),v1); -_=check af:setStringOutput(params,"outMsg",v1); -}isolated resource function 'default httpTriggerCosmosDBInput1 (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.httpTriggerCosmosDBInput1Handler(params),params);check caller->respond(response);}public isolated function httpTriggerCosmosDBInput1Handler (af:HandlerParams params)returns error? { -string v1=check httpTriggerCosmosDBInput1(check af:getHTTPRequestFromInputData(params,"httpReq"),check af:getParsedJsonFromJsonStringFromInputData(params,"dbReq")); -_=check af:setStringReturn(params,v1); -}isolated resource function 'default httpTriggerCosmosDBInput2 (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.httpTriggerCosmosDBInput2Handler(params),params);check caller->respond(response);}public isolated function httpTriggerCosmosDBInput2Handler (af:HandlerParams params)returns error? { -string v1=check httpTriggerCosmosDBInput2(check af:getHTTPRequestFromInputData(params,"httpReq"),check af:getOptionalBallerinaValueFromInputData(params,"dbReq",PersonOptionalGenerated)); -_=check af:setStringReturn(params,v1); -}isolated resource function 'default httpTriggerCosmosDBInput3 (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.httpTriggerCosmosDBInput3Handler(params),params);check caller->respond(response);}public isolated function httpTriggerCosmosDBInput3Handler (af:HandlerParams params)returns error? { -string v1=check httpTriggerCosmosDBInput3(check af:getHTTPRequestFromInputData(params,"httpReq"),< Person[] >check af:getBallerinaValueFromInputData(params,"dbReq",PersonArrayGenerated)); -_=check af:setStringReturn(params,v1); -}isolated resource function 'default httpTriggerCosmosDBOutput1 (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.httpTriggerCosmosDBOutput1Handler(params),params);check caller->respond(response);}public isolated function httpTriggerCosmosDBOutput1Handler (af:HandlerParams params)returns error? { -af:HTTPBinding v1={}; -json v2=httpTriggerCosmosDBOutput1(check af:getHTTPRequestFromInputData(params,"httpReq"),v1); -_=check af:setHTTPOutput(params,"hb",v1); -_=check af:setJsonReturn(params,v2); -}isolated resource function 'default httpTriggerCosmosDBOutput2 (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.httpTriggerCosmosDBOutput2Handler(params),params);check caller->respond(response);}public isolated function httpTriggerCosmosDBOutput2Handler (af:HandlerParams params)returns error? { -af:HTTPBinding v1={}; -json v2=httpTriggerCosmosDBOutput2(check af:getHTTPRequestFromInputData(params,"httpReq"),v1); -_=check af:setHTTPOutput(params,"hb",v1); -_=check af:setJsonReturn(params,v2); -}isolated resource function 'default httpTriggerCosmosDBOutput3 (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.httpTriggerCosmosDBOutput3Handler(params),params);check caller->respond(response);}public isolated function httpTriggerCosmosDBOutput3Handler (af:HandlerParams params)returns error? { -Person[] v1=httpTriggerCosmosDBOutput3(check af:getHTTPRequestFromInputData(params,"httpReq")); -_=check af:setBallerinaValueAsJsonReturn(params,v1); -}isolated resource function 'default queuePopulationTimer (http:Caller caller,http:Request request)returns error? { -http:Response response =new;af:HandlerParams params ={request,response};af:handleFunctionResposne(trap self.queuePopulationTimerHandler(params),params);check caller->respond(response);}public isolated function queuePopulationTimerHandler (af:HandlerParams params)returns error? { -af:StringOutputBinding v1={}; -_=queuePopulationTimer(check af:getJsonFromInputData(params,"triggerInfo"),v1); -_=check af:setStringOutput(params,"msg",v1); -}} diff --git a/compiler-plugin-tests/src/test/resources/handlers/generated/generated.json b/compiler-plugin-tests/src/test/resources/handlers/generated/generated.json deleted file mode 100644 index fc4ff2f7..00000000 --- a/compiler-plugin-tests/src/test/resources/handlers/generated/generated.json +++ /dev/null @@ -1,18777 +0,0 @@ -{ - "kind": "MODULE_PART", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "IMPORT_DECLARATION", - "children": [ - { - "kind": "IMPORT_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IMPORT_ORG_NAME", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "ballerinax" - }, - { - "kind": "SLASH_TOKEN" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "azure_functions", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IMPORT_PREFIX", - "children": [ - { - "kind": "AS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "IMPORT_DECLARATION", - "children": [ - { - "kind": "IMPORT_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IMPORT_ORG_NAME", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "ballerina" - }, - { - "kind": "SLASH_TOKEN" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LISTENER_DECLARATION", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LISTENER_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Listener", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "__testListener" - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "hl", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "TYPE_DEFINITION", - "children": [ - { - "kind": "TYPE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "PersonOptionalGenerated", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "Person" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "TYPE_DEFINITION", - "children": [ - { - "kind": "TYPE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "PersonArrayGenerated", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ARRAY_TYPE_DESC", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "Person" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "ARRAY_DIMENSION", - "children": [ - { - "kind": "OPEN_BRACKET_TOKEN" - }, - { - "kind": "CLOSE_BRACKET_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "SERVICE_DECLARATION", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "SERVICE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Service", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SLASH_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "ON_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "__testListener", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "hello", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "helloHandler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "helloHandler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "STRING_TYPE_DESC", - "children": [ - { - "kind": "STRING_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "hello" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getBodyFromHTTPInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "payload" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setStringReturn" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "fromHttpToQueue", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "fromHttpToQueueHandler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "fromHttpToQueueHandler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "StringOutputBinding", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HTTPBinding", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v2" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "fromHttpToQueue" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "createContext" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "BOOLEAN_LITERAL", - "children": [ - { - "kind": "TRUE_KEYWORD" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getHTTPRequestFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "req" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setStringOutput" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "msg" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setHTTPReturn" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v2" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "fromQueueToQueue", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "fromQueueToQueueHandler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "fromQueueToQueueHandler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "StringOutputBinding", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "fromQueueToQueue" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "createContext" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "BOOLEAN_LITERAL", - "children": [ - { - "kind": "TRUE_KEYWORD" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getJsonStringFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "inMsg" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setStringOutput" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "outMsg" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "fromBlobToQueue", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "fromBlobToQueueHandler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "fromBlobToQueueHandler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "StringOutputBinding", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "fromBlobToQueue" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "createContext" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "BOOLEAN_LITERAL", - "children": [ - { - "kind": "TRUE_KEYWORD" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getBytesFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "blobIn" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getStringFromMetadata" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "name" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setStringOutput" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "outMsg" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerBlobInput", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerBlobInputHandler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerBlobInputHandler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "STRING_TYPE_DESC", - "children": [ - { - "kind": "STRING_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerBlobInput" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getHTTPRequestFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "req" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getOptionalBytesFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "blobIn" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setStringReturn" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerBlobOutput", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerBlobOutputHandler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerBlobOutputHandler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "StringOutputBinding", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "STRING_TYPE_DESC", - "children": [ - { - "kind": "STRING_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v2" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerBlobOutput" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getHTTPRequestFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "req" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setBlobOutput" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "bb" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setStringReturn" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v2" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "sendSMS", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "sendSMSHandler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "sendSMSHandler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "TwilioSmsOutputBinding", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "STRING_TYPE_DESC", - "children": [ - { - "kind": "STRING_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v2" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "sendSMS" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getHTTPRequestFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "req" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setTwilioSmsOutput" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "tb" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setStringReturn" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v2" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "cosmosDBToQueue1", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "cosmosDBToQueue1Handler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "cosmosDBToQueue1Handler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "StringOutputBinding", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "cosmosDBToQueue1" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TYPE_CAST_EXPRESSION", - "children": [ - { - "kind": "LT_TOKEN" - }, - { - "kind": "TYPE_CAST_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "ARRAY_TYPE_DESC", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "Person" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "ARRAY_DIMENSION", - "children": [ - { - "kind": "OPEN_BRACKET_TOKEN" - }, - { - "kind": "CLOSE_BRACKET_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "GT_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getBallerinaValueFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "req" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "PersonArrayGenerated" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setStringOutput" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "outMsg" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "cosmosDBToQueue2", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "cosmosDBToQueue2Handler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "cosmosDBToQueue2Handler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "StringOutputBinding", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "cosmosDBToQueue2" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getJsonFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "req" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setStringOutput" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "outMsg" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBInput1", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBInput1Handler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBInput1Handler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "STRING_TYPE_DESC", - "children": [ - { - "kind": "STRING_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBInput1" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getHTTPRequestFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "httpReq" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getParsedJsonFromJsonStringFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "dbReq" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setStringReturn" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBInput2", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBInput2Handler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBInput2Handler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "STRING_TYPE_DESC", - "children": [ - { - "kind": "STRING_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBInput2" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getHTTPRequestFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "httpReq" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TYPE_CAST_EXPRESSION", - "children": [ - { - "kind": "LT_TOKEN" - }, - { - "kind": "TYPE_CAST_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "Person" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "GT_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getOptionalBallerinaValueFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "dbReq" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "PersonOptionalGenerated" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setStringReturn" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBInput3", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBInput3Handler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBInput3Handler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "STRING_TYPE_DESC", - "children": [ - { - "kind": "STRING_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBInput3" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getHTTPRequestFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "httpReq" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TYPE_CAST_EXPRESSION", - "children": [ - { - "kind": "LT_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "TYPE_CAST_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "ARRAY_TYPE_DESC", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "Person" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "ARRAY_DIMENSION", - "children": [ - { - "kind": "OPEN_BRACKET_TOKEN" - }, - { - "kind": "CLOSE_BRACKET_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "GT_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getBallerinaValueFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "dbReq" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "PersonArrayGenerated" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setStringReturn" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBOutput1", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBOutput1Handler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBOutput1Handler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HTTPBinding", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "JSON_TYPE_DESC", - "children": [ - { - "kind": "JSON_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v2" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBOutput1" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getHTTPRequestFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "httpReq" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setHTTPOutput" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "hb" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setJsonReturn" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v2" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBOutput2", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBOutput2Handler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBOutput2Handler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HTTPBinding", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "JSON_TYPE_DESC", - "children": [ - { - "kind": "JSON_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v2" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBOutput2" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getHTTPRequestFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "httpReq" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setHTTPOutput" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "hb" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setJsonReturn" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v2" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBOutput3", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBOutput3Handler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBOutput3Handler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "ARRAY_TYPE_DESC", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "Person" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "ARRAY_DIMENSION", - "children": [ - { - "kind": "OPEN_BRACKET_TOKEN" - }, - { - "kind": "CLOSE_BRACKET_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "httpTriggerCosmosDBOutput3" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getHTTPRequestFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "httpReq" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setBallerinaValueAsJsonReturn" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "RESOURCE_ACCESSOR_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RESOURCE_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "\u0027default", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "queuePopulationTimer", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Caller", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Request", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "http" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "Response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "IMPLICIT_NEW_EXPRESSION", - "children": [ - { - "kind": "NEW_KEYWORD" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "request" - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "SPECIFIC_FIELD", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "CALL_STATEMENT", - "children": [ - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "handleFunctionResposne" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "TRAP_EXPRESSION", - "children": [ - { - "kind": "TRAP_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "METHOD_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "self" - } - ] - }, - { - "kind": "DOT_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "queuePopulationTimerHandler" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "CHECK_ACTION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "REMOTE_METHOD_CALL_ACTION", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "caller" - } - ] - }, - { - "kind": "RIGHT_ARROW_TOKEN" - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "respond" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "response" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN" - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - }, - { - "kind": "OBJECT_METHOD_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [ - { - "kind": "PUBLIC_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "ISOLATED_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "queuePopulationTimerHandler", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "REQUIRED_PARAM", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "HandlerParams", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - }, - { - "kind": "RETURN_TYPE_DESCRIPTOR", - "children": [ - { - "kind": "RETURNS_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "OPTIONAL_TYPE_DESC", - "children": [ - { - "kind": "ERROR_TYPE_DESC", - "children": [ - { - "kind": "ERROR_KEYWORD" - } - ] - }, - { - "kind": "QUESTION_MARK_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "StringOutputBinding", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "MAPPING_CONSTRUCTOR", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "queuePopulationTimer" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "getJsonFromInputData" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "triggerInfo" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "WILDCARD_BINDING_PATTERN", - "children": [ - { - "kind": "UNDERSCORE_KEYWORD" - } - ] - }, - { - "kind": "EQUAL_TOKEN" - }, - { - "kind": "CHECK_EXPRESSION", - "children": [ - { - "kind": "CHECK_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "FUNCTION_CALL", - "children": [ - { - "kind": "QUALIFIED_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "af" - }, - { - "kind": "COLON_TOKEN" - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "setStringOutput" - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "params" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "STRING_LITERAL", - "children": [ - { - "kind": "STRING_LITERAL_TOKEN", - "value": "msg" - } - ] - } - ] - }, - { - "kind": "COMMA_TOKEN" - }, - { - "kind": "POSITIONAL_ARG", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "v1" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "EOF_TOKEN" - } - ] -} diff --git a/compiler-plugin-tests/src/test/resources/handlers/main.bal b/compiler-plugin-tests/src/test/resources/handlers/main.bal new file mode 100644 index 00000000..804920e0 --- /dev/null +++ b/compiler-plugin-tests/src/test/resources/handlers/main.bal @@ -0,0 +1,172 @@ +import ballerinax/azure_functions as af; +import ballerina/http; + +listener af:HttpListener ep = new (); + +public type DBEntry record { + string id; +}; + +public type Person record { + string name; + int age; +}; + +listener af:HttpListener ep1 = new (); + +service /hello\- on ep1 { + + resource function post hello\-query() returns string|error { + return "Hello from the hello-query"; + } +} + +service /helo on new af:HttpListener() { + + resource function post hello\-query() returns string|error { + return "Hello from the hello-query"; + } +} + +// @af:HTTPTest +service /hello on ep { + resource function default all() returns @af:HttpOutput string { + return "Hello from all "; + } + + resource function post optional(@http:Payload string greeting) returns string { + return "Hello from optional output bindin"; + } + + resource function post .(@http:Payload string greeting) returns @af:HttpOutput string { + return "Hello from . path "; + } + + resource function post foo(@http:Payload string greeting) returns @af:HttpOutput string { + return "Hello from foo path " + greeting; + } + + resource function post foo/[string bar](@http:Payload string greeting) returns @af:HttpOutput string { + return "Hello from foo param " + bar; + } + + resource function post foo/bar(@http:Payload string greeting) returns @af:HttpOutput string { + return "Hello from foo bar res"; + } + + resource function post query(string name, @http:Payload string greeting) returns @af:HttpOutput string|error { + return "Hello from the query " + greeting + " " + name; + } + + resource function post db(@http:Payload string greeting, @af:CosmosDBInput { + connectionStringSetting: "CosmosDBConnection",databaseName: "db1", + collectionName: "c2", sqlQuery: "SELECT * FROM Items"} DBEntry[] input1) returns @af:HttpOutput string|error { + return "Hello " + greeting + input1[0].id; + } + + resource function post payload/jsonToRecord (@http:Payload Person greeting) returns @af:HttpOutput string|error { + return "Hello from json to record " + greeting.name; + } + + resource function post payload/jsonToJson (@http:Payload json greeting) returns @af:HttpOutput string|error { + string name = check greeting.name; + return "Hello from json to json "+ name; + } + + resource function post payload/xmlToXml (@http:Payload xml greeting) returns @af:HttpOutput string|error { + return greeting.toJsonString(); + } + + resource function post payload/textToString (@http:Payload string greeting) returns @af:HttpOutput string|error { + return greeting; + } + + resource function post payload/textToByte (@http:Payload byte[] greeting) returns @af:HttpOutput string|error { + return string:fromBytes(greeting); + } + + resource function post payload/octaToByte (@http:Payload byte[] greeting) returns @af:HttpOutput string|error { + return string:fromBytes(greeting); + } +} + +@af:QueueTrigger { + queueName: "queue2" +} +listener af:QueueListener queueListener = new af:QueueListener(); + +service "queue" on queueListener { + remote function onMessage (string inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + return "helloo "+ inMsg; + } +} + + +@af:QueueTrigger { + queueName: "queue21" +} +service "queue1" on new af:QueueListener() { + remote function onMessage (string inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + return "helloo "+ inMsg; + } +} + + +@af:CosmosDBTrigger {connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c2"} +listener af:CosmosDBListener cosmosEp = new (); + +service "cosmos" on cosmosEp { + remote function onUpdated (DBEntry[] inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + string id = inMsg[0].id; + return "helloo "+ id; + } +} + + +@af:CosmosDBTrigger {connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c2"} +service "cosmos1" on new af:CosmosDBListener() { + remote function onUpdated (DBEntry[] inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + string id = inMsg[0].id; + return "helloo "+ id; + } +} + + +@af:TimerTrigger { schedule: "*/10 * * * * *" } +listener af:TimerListener timerListener = new af:TimerListener(); +service "timer" on timerListener { + remote function onTrigger (af:TimerMetadata inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + return "helloo "+ inMsg.IsPastDue.toString(); + } +} + + +@af:TimerTrigger { schedule: "*/10 * * * * *" } +service "timer1" on new af:TimerListener() { + remote function onTrigger (af:TimerMetadata inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + return "helloo "+ inMsg.IsPastDue.toString(); + } +} + +@af:BlobTrigger { + path: "bpath1/{name}" +} +listener af:BlobListener blobListener = new af:BlobListener(); + +service "blob" on blobListener { + remote function onUpdated (byte[] blobIn, @af:BindingName { } string name) returns @af:BlobOutput { + path: "bpath1/newBlob" } byte[]|error { + return blobIn; + } +} + +@af:BlobTrigger { + path: "bpath1/{name}" +} + +service "blob1" on new af:BlobListener() { + remote function onUpdated (byte[] blobIn, @af:BindingName { } string name) returns @af:BlobOutput { + path: "bpath1/newBlob" } byte[]|error { + return blobIn; + } +} diff --git a/compiler-plugin-tests/src/test/resources/testng.xml b/compiler-plugin-tests/src/test/resources/testng.xml index 7c9f97a4..140520f9 100644 --- a/compiler-plugin-tests/src/test/resources/testng.xml +++ b/compiler-plugin-tests/src/test/resources/testng.xml @@ -1,6 +1,6 @@ + + + + + diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureCodeGeneratedTask.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureCodeGeneratedTask.java new file mode 100644 index 00000000..6b558096 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureCodeGeneratedTask.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import io.ballerina.projects.plugins.CompilerLifecycleEventContext; +import io.ballerina.projects.plugins.CompilerLifecycleTask; +import org.ballerinax.azurefunctions.service.Binding; + +import java.io.IOException; +import java.io.PrintStream; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * Contains the code generation part of the azure functions. + * + * @since 2.0.0 + */ +public class AzureCodeGeneratedTask implements CompilerLifecycleTask { + + private static final PrintStream OUT = System.out; + + @Override + public void perform(CompilerLifecycleEventContext compilerLifecycleEventContext) { + + AzureFunctionServiceExtractor azureFunctionServiceExtractor = + new AzureFunctionServiceExtractor(compilerLifecycleEventContext.currentPackage()); + List functionContexts = azureFunctionServiceExtractor.extractFunctions(); + Map generatedFunctions = new HashMap<>(); + + for (FunctionContext ctx : functionContexts) { + JsonObject functions = new JsonObject(); + JsonArray bindings = new JsonArray(); + List bindingList = ctx.getBindingList(); + for (Binding binding : bindingList) { + bindings.add(binding.getJsonObject()); + } + functions.add("bindings", bindings); + generatedFunctions.put(ctx.getFunctionName(), functions); + } + + OUT.println("\t@azure_functions:Function: " + String.join(", ", generatedFunctions.keySet())); + Optional generatedArtifactPath = compilerLifecycleEventContext.getGeneratedArtifactPath(); + generatedArtifactPath.ifPresent(path -> { + try { + this.generateFunctionsArtifact(generatedFunctions, path); + } catch (IOException e) { + String msg = "Error generating Azure Functions: " + e.getMessage(); + OUT.println(msg); + throw new RuntimeException(msg, e); + } + OUT.println("\n\tExecute the below command to deploy the function locally:"); + OUT.println( + "\tfunc start --script-root " + Constants.ARTIFACT_PATH + " --java"); + OUT.println("\n\tExecute the below command to deploy Ballerina Azure Functions:"); + Path parent = path.getParent(); + if (parent != null) { + OUT.println( + "\tfunc azure functionapp publish --script-root " + + Constants.ARTIFACT_PATH + " \n\n"); + } + }); + } + + private void generateFunctionsArtifact(Map functions, Path binaryPath) + throws IOException { + new FunctionsArtifact(functions, binaryPath).generate(); + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureCodeModifier.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureCodeModifier.java new file mode 100644 index 00000000..19800c39 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureCodeModifier.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.ballerinax.azurefunctions; + +import io.ballerina.projects.plugins.CodeModifier; +import io.ballerina.projects.plugins.CodeModifierContext; + +/** + * {@code AzureCodeModifier} handles required code-modification for Azure Function Services. + */ +public class AzureCodeModifier extends CodeModifier { + @Override + public void init(CodeModifierContext codeModifierContext) { + codeModifierContext.addSourceModifierTask(new FunctionUpdaterTask()); + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureCompilerPlugin.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureCompilerPlugin.java similarity index 85% rename from compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureCompilerPlugin.java rename to compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureCompilerPlugin.java index 4433b976..cbe29443 100644 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureCompilerPlugin.java +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureCompilerPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -15,7 +15,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.ballerinax.azurefunctions.generator; +package org.ballerinax.azurefunctions; import io.ballerina.projects.plugins.CompilerPlugin; import io.ballerina.projects.plugins.CompilerPluginContext; @@ -29,7 +29,7 @@ public class AzureCompilerPlugin extends CompilerPlugin { @Override public void init(CompilerPluginContext pluginContext) { pluginContext.addCodeAnalyzer(new AzureFunctionsCodeAnalyzer()); - pluginContext.addCodeGenerator(new AzureCodeGenerator()); + pluginContext.addCodeModifier(new AzureCodeModifier()); pluginContext.addCompilerLifecycleListener(new AzureLifecycleListener()); } } diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureDiagnosticCodes.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureDiagnosticCodes.java new file mode 100644 index 00000000..290a5540 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureDiagnosticCodes.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.ballerinax.azurefunctions; + +import io.ballerina.tools.diagnostics.DiagnosticSeverity; + +import static io.ballerina.tools.diagnostics.DiagnosticSeverity.ERROR; +import static io.ballerina.tools.diagnostics.DiagnosticSeverity.WARNING; + +/** + * {@code DiagnosticCodes} is used to hold diagnostic codes. + */ +public enum AzureDiagnosticCodes { + AF_001("AF_001", "invalid annotation type on param '%s'", ERROR), + AF_002("AF_002", "invalid resource parameter '%s'", ERROR), + AF_003("AF_003", "invalid type of header param '%s': One of the following types is expected: " + + "'string','int','float','decimal','boolean', an array of the above types or a record which consists of " + + "the above types", ERROR), + AF_004("AF_004", "invalid union type of header param '%s': one of the 'string','int','float'," + + "'decimal','boolean' types, an array of the above types or a record which consists of the above types can" + + " only be union with '()'. Eg: string|() or string[]|()", ERROR), + AF_005("AF_005", "invalid intersection type : '%s'. Only readonly type is allowed", ERROR), + AF_006("AF_006", "rest fields are not allowed for header binding records. Use 'http:Headers' type to access " + + "all headers", ERROR), + AF_007("AF_007", "invalid multiple resource parameter annotations for '%s'", ERROR), + AF_008("AF_008", "'treatNilableAsOptional' is the only @http:serviceConfig field supported by Azure " + + "Function at the moment", WARNING); + + private final String code; + private final String message; + private final DiagnosticSeverity severity; + + AzureDiagnosticCodes(String code, String message, DiagnosticSeverity severity) { + this.code = code; + this.message = message; + this.severity = severity; + } + + public String getCode() { + return code; + } + + public String getMessage() { + return message; + } + + public DiagnosticSeverity getSeverity() { + return severity; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionModifier.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionModifier.java new file mode 100644 index 00000000..04f56a8f --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionModifier.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions; + +import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.api.symbols.TypeDescKind; +import io.ballerina.compiler.api.symbols.TypeReferenceTypeSymbol; +import io.ballerina.compiler.api.symbols.TypeSymbol; +import io.ballerina.compiler.api.symbols.UnionTypeSymbol; +import io.ballerina.compiler.syntax.tree.AbstractNodeFactory; +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import io.ballerina.compiler.syntax.tree.BasicLiteralNode; +import io.ballerina.compiler.syntax.tree.ExpressionNode; +import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.ImportDeclarationNode; +import io.ballerina.compiler.syntax.tree.ImportOrgNameNode; +import io.ballerina.compiler.syntax.tree.ImportPrefixNode; +import io.ballerina.compiler.syntax.tree.LiteralValueToken; +import io.ballerina.compiler.syntax.tree.MappingConstructorExpressionNode; +import io.ballerina.compiler.syntax.tree.MappingFieldNode; +import io.ballerina.compiler.syntax.tree.MetadataNode; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NodeFactory; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.QualifiedNameReferenceNode; +import io.ballerina.compiler.syntax.tree.SeparatedNodeList; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import io.ballerina.compiler.syntax.tree.SyntaxKind; +import io.ballerina.compiler.syntax.tree.TreeModifier; + +import java.util.Optional; + +/** + * Responsible for generating annotations for each function. + * + * @since 2.0.0 + */ +public class AzureFunctionModifier extends TreeModifier { + + private SemanticModel semanticModel; + private String modulePrefix; + + public AzureFunctionModifier(SemanticModel semanticModel) { + super(); + this.semanticModel = semanticModel; + this.modulePrefix = Constants.AZURE_FUNCTIONS_MODULE_NAME; + } + + @Override + public ImportDeclarationNode transform(ImportDeclarationNode importDeclarationNode) { + Optional importOrgNameNode = importDeclarationNode.orgName(); + if (importOrgNameNode.isEmpty()) { + return importDeclarationNode; + } + if (!Constants.AZURE_FUNCTIONS_PACKAGE_ORG.equals(importOrgNameNode.get().orgName().text())) { + return importDeclarationNode; + } + SeparatedNodeList identifierTokens = importDeclarationNode.moduleName(); + if (identifierTokens.size() != 1) { + return importDeclarationNode; + } + if (!Constants.AZURE_FUNCTIONS_MODULE_NAME.equals(identifierTokens.get(0).text())) { + return importDeclarationNode; + } + + Optional prefix = importDeclarationNode.prefix(); + if (prefix.isEmpty()) { + this.modulePrefix = Constants.AZURE_FUNCTIONS_MODULE_NAME; + return importDeclarationNode; + } + this.modulePrefix = prefix.get().prefix().text(); + return importDeclarationNode; + } + + @Override + public ServiceDeclarationNode transform(ServiceDeclarationNode serviceDeclarationNode) { + String servicePath = Util.resourcePathToString(serviceDeclarationNode.absoluteResourcePath()); + ExpressionNode listenerExpressionNode = serviceDeclarationNode.expressions().get(0); + Optional listenerSymbol = semanticModel.typeOf(listenerExpressionNode); + if (listenerSymbol.isEmpty()) { + return super.transform(serviceDeclarationNode); + } + TypeReferenceTypeSymbol typeRefSymbol; + if (TypeDescKind.UNION == listenerSymbol.get().typeKind()) { + UnionTypeSymbol union = (UnionTypeSymbol) listenerSymbol.get(); + typeRefSymbol = (TypeReferenceTypeSymbol) union.memberTypeDescriptors().get(0); + + } else { + typeRefSymbol = (TypeReferenceTypeSymbol) listenerSymbol.get(); + } + Optional name = typeRefSymbol.definition().getName(); + if (name.isEmpty()) { + return super.transform(serviceDeclarationNode); + } + NodeList members = serviceDeclarationNode.members(); + if (!Constants.AZURE_HTTP_LISTENER.equals(name.get())) { + return super.transform(serviceDeclarationNode); + } + AzureFunctionNameGenerator nameGen = new AzureFunctionNameGenerator(serviceDeclarationNode); + NodeList newMembersList = NodeFactory.createNodeList(); + for (Node node : members) { + Optional modifiedMember = getModifiedMember(node, servicePath, nameGen); + if (modifiedMember.isEmpty()) { + newMembersList = newMembersList.add(node); + } else { + newMembersList = newMembersList.add(modifiedMember.get()); + } + } + return new ServiceDeclarationNode.ServiceDeclarationNodeModifier(serviceDeclarationNode) + .withMembers(newMembersList).apply(); + } + + public Optional getModifiedMember(Node node, String servicePath, AzureFunctionNameGenerator nameGen) { + if (SyntaxKind.RESOURCE_ACCESSOR_DEFINITION != node.kind()) { + return Optional.empty(); + } + FunctionDefinitionNode functionDefinitionNode = (FunctionDefinitionNode) node; + String uniqueFunctionName = nameGen.getUniqueFunctionName(servicePath, functionDefinitionNode); + Optional metadata = functionDefinitionNode.metadata(); + NodeList existingAnnotations = NodeFactory.createNodeList(); + MetadataNode metadataNode; + if (metadata.isPresent()) { + metadataNode = metadata.get(); + existingAnnotations = metadataNode.annotations(); + } else { + metadataNode = NodeFactory.createMetadataNode(null, existingAnnotations); + } + + //Create and add annotation + NodeList modifiedAnnotations = + existingAnnotations.add(createFunctionAnnotation(uniqueFunctionName)); + MetadataNode modifiedMetadata = + new MetadataNode.MetadataNodeModifier(metadataNode).withAnnotations(modifiedAnnotations).apply(); + FunctionDefinitionNode updatedFunctionNode = + new FunctionDefinitionNode.FunctionDefinitionNodeModifier(functionDefinitionNode) + .withMetadata(modifiedMetadata).apply(); + return Optional.of(updatedFunctionNode); + } + + public AnnotationNode createFunctionAnnotation(String functionName) { + QualifiedNameReferenceNode azureFunctionAnnotRef = + NodeFactory.createQualifiedNameReferenceNode(NodeFactory.createIdentifierToken(modulePrefix), + NodeFactory.createToken(SyntaxKind.COLON_TOKEN), + NodeFactory.createIdentifierToken(Constants.FUNCTION_ANNOTATION)); + LiteralValueToken literalValueToken = + NodeFactory.createLiteralValueToken(SyntaxKind.STRING_LITERAL_TOKEN, "\"" + functionName + + "\"", NodeFactory.createEmptyMinutiaeList(), AbstractNodeFactory + .createEmptyMinutiaeList()); + BasicLiteralNode basicLiteralNode = + NodeFactory.createBasicLiteralNode(SyntaxKind.STRING_LITERAL, literalValueToken); + SpecificFieldNode name = NodeFactory.createSpecificFieldNode(null, NodeFactory.createIdentifierToken("name"), + NodeFactory.createToken(SyntaxKind.COLON_TOKEN), basicLiteralNode); + SeparatedNodeList updatedFields = NodeFactory.createSeparatedNodeList(name); + MappingConstructorExpressionNode annotationValue = + NodeFactory.createMappingConstructorExpressionNode( + NodeFactory.createToken(SyntaxKind.OPEN_BRACE_TOKEN), updatedFields, + NodeFactory.createToken(SyntaxKind.CLOSE_BRACE_TOKEN)); + return NodeFactory.createAnnotationNode(NodeFactory.createToken(SyntaxKind.AT_TOKEN), azureFunctionAnnotRef, + annotationValue); + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionNameGenerator.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionNameGenerator.java new file mode 100644 index 00000000..799474ef --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionNameGenerator.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions; + +import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.ResourcePathParameterNode; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import io.ballerina.compiler.syntax.tree.SyntaxKind; +import io.ballerina.compiler.syntax.tree.Token; + +import java.util.ArrayList; +import java.util.List; + +/** + * Responsible for generating Azure function name for each resource function. + * + * @since 2.0.0 + */ +public class AzureFunctionNameGenerator { + + private List functionNames = new ArrayList<>(); + private List generatedNames = new ArrayList<>(); + + public AzureFunctionNameGenerator(ServiceDeclarationNode serviceDeclarationNode) { + NodeList members = serviceDeclarationNode.members(); + String servicePath = Util.resourcePathToString(serviceDeclarationNode.absoluteResourcePath()); + for (Node node : members) { + if (SyntaxKind.RESOURCE_ACCESSOR_DEFINITION != node.kind()) { + continue; + } + FunctionDefinitionNode functionDefinitionNode = (FunctionDefinitionNode) node; + String functionName = getFunctionName(servicePath, functionDefinitionNode); + this.functionNames.add(functionName); + } + } + + private String getFunctionName(String servicePath, FunctionDefinitionNode functionDefinitionNode) { + String method = functionDefinitionNode.functionName().text(); + StringBuilder resourcePath = new StringBuilder(); + servicePath = servicePath.replace("\\", ""); + resourcePath.append(servicePath); + for (Node pathBlock : functionDefinitionNode.relativeResourcePath()) { + if (pathBlock.kind() == SyntaxKind.IDENTIFIER_TOKEN) { + String specialCharReplacedPathBlock = (((IdentifierToken) pathBlock).text()).replace("\\", ""); + resourcePath.append("/").append(specialCharReplacedPathBlock); + } else if (pathBlock.kind() == SyntaxKind.RESOURCE_PATH_SEGMENT_PARAM) { + Token token = ((ResourcePathParameterNode) pathBlock).paramName().get(); + resourcePath.append("/").append(token.text()); + } + } + return getEncodedAzureFunctionName(resourcePath.toString(), servicePath, method); + } + //TODO move slashs, dashes to consts + private String getEncodedAzureFunctionName(String resourcePath, String servicePath, String method) { + String functionName = resourcePath.replace("/", "-"); + if (servicePath.equals("")) { + return method + functionName; + } + return method + "-" + functionName; + } + + public String getUniqueFunctionName(String servicePath, FunctionDefinitionNode functionDefinitionNode) { + String functionName = getFunctionName(servicePath, functionDefinitionNode); + functionName = generateUniqueName(functionName, 0); + generatedNames.add(functionName); + return functionName; + } + + private String generateUniqueName(String initialName, int index) { + String newName; + if (index == 0) { + newName = initialName; + } else { + newName = initialName + "-" + index; + } + + if (!isDuplicateName(newName)) { + return newName; + } + return generateUniqueName(initialName, index + 1); + } + + private boolean isDuplicateName(String initialName) { + int count = 0; + for (String functionName : this.functionNames) { + if (functionName.equals(initialName)) { + count++; + } + } + return generatedNames.contains(initialName) || count > 1; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionExtractor.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionServiceExtractor.java similarity index 74% rename from compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionExtractor.java rename to compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionServiceExtractor.java index 128371a2..6b23da39 100644 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionExtractor.java +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionServiceExtractor.java @@ -15,9 +15,9 @@ * specific language governing permissions and limitations * under the License. */ -package org.ballerinax.azurefunctions.generator; +package org.ballerinax.azurefunctions; -import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; +import io.ballerina.compiler.api.SemanticModel; import io.ballerina.compiler.syntax.tree.Node; import io.ballerina.projects.Document; import io.ballerina.projects.DocumentId; @@ -32,23 +32,24 @@ * * @since 2.0.0 */ -public class AzureFunctionExtractor { +public class AzureFunctionServiceExtractor { private final Package currentPackage; - public AzureFunctionExtractor(Package currentPackage) { + public AzureFunctionServiceExtractor(Package currentPackage) { this.currentPackage = currentPackage; } - public List extractFunctions() { + public List extractFunctions() { Module module = this.currentPackage.getDefaultModule(); - List moduleFunctions = new ArrayList<>(); + List moduleFunctions = new ArrayList<>(); for (DocumentId documentId : module.documentIds()) { Document document = module.document(documentId); Node node = document.syntaxTree().rootNode(); - AzureFunctionVisitor azureFunctionVisitor = new AzureFunctionVisitor(); + SemanticModel semanticModel = module.getCompilation().getSemanticModel(); + AzureFunctionServiceVisitor azureFunctionVisitor = new AzureFunctionServiceVisitor(semanticModel); node.accept(azureFunctionVisitor); - moduleFunctions.addAll(azureFunctionVisitor.getFunctions()); + moduleFunctions.addAll(azureFunctionVisitor.getFunctionContexts()); } return moduleFunctions; } diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionServiceVisitor.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionServiceVisitor.java new file mode 100644 index 00000000..691b5a4a --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionServiceVisitor.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions; + +import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.syntax.tree.NodeVisitor; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import org.ballerinax.azurefunctions.service.ServiceHandler; +import org.ballerinax.azurefunctions.service.TriggerBinding; + +import java.util.ArrayList; +import java.util.List; +/** + * Visitor for extracting Azure functions from a ballerina document. + * + * @since 2.0.0 + */ +public class AzureFunctionServiceVisitor extends NodeVisitor { + + private List functionContexts; + private SemanticModel semanticModel; + + public AzureFunctionServiceVisitor(SemanticModel semanticModel) { + this.functionContexts = new ArrayList<>(); + this.semanticModel = semanticModel; + } + + @Override + public void visit(ServiceDeclarationNode serviceDeclarationNode) { + TriggerBinding builder = ServiceHandler.getBuilder(serviceDeclarationNode, semanticModel); + List contexts = builder.getBindings(); + functionContexts.addAll(contexts); + } + + public List getFunctionContexts() { + return functionContexts; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionsCodeAnalyzer.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionsCodeAnalyzer.java similarity index 67% rename from compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionsCodeAnalyzer.java rename to compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionsCodeAnalyzer.java index 50454506..1b41b934 100644 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionsCodeAnalyzer.java +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureFunctionsCodeAnalyzer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -15,11 +15,12 @@ * specific language governing permissions and limitations * under the License. */ -package org.ballerinax.azurefunctions.generator; +package org.ballerinax.azurefunctions; +import io.ballerina.compiler.syntax.tree.SyntaxKind; import io.ballerina.projects.plugins.CodeAnalysisContext; import io.ballerina.projects.plugins.CodeAnalyzer; -import org.ballerinax.azurefunctions.generator.validators.AzureFunctionsCodeAnalyzerTask; +import org.ballerinax.azurefunctions.validators.AzureFunctionsCodeAnalyzerTask; /** * Contains the code analyzers for azure functions. @@ -29,7 +30,7 @@ public class AzureFunctionsCodeAnalyzer extends CodeAnalyzer { @Override - public void init(CodeAnalysisContext codeAnalysisContext) { - codeAnalysisContext.addCompilationAnalysisTask(new AzureFunctionsCodeAnalyzerTask()); + public void init(CodeAnalysisContext codeAnalysisCtx) { + codeAnalysisCtx.addSyntaxNodeAnalysisTask(new AzureFunctionsCodeAnalyzerTask(), SyntaxKind.SERVICE_DECLARATION); } } diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureLifecycleListener.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureLifecycleListener.java similarity index 95% rename from compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureLifecycleListener.java rename to compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureLifecycleListener.java index 9d05710e..6e8a0bdc 100644 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureLifecycleListener.java +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/AzureLifecycleListener.java @@ -15,7 +15,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.ballerinax.azurefunctions.generator; +package org.ballerinax.azurefunctions; import io.ballerina.projects.plugins.CompilerLifecycleContext; import io.ballerina.projects.plugins.CompilerLifecycleListener; diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/Constants.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/Constants.java new file mode 100644 index 00000000..6093b57e --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/Constants.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions; + + /** + * Constants for Azure Functions. + */ +public class Constants { + + public static final String AZURE_FUNCTIONS_MODULE_NAME = "azure_functions"; + public static final String COLON = ":"; + + public static final String HTTP = "http"; + public static final String HEADER_ANNOTATION_TYPE = "HttpHeader"; + public static final String AZURE_FUNCTIONS_PACKAGE_ORG = "ballerinax"; + public static final String CHARSET = "UTF-8"; + + public static final String ANNOTATION_HTTP_TRIGGER = "HttpTrigger"; + public static final String ANNOTATION_QUEUE_TRIGGER = "QueueTrigger"; + public static final String ANNOTATION_COSMOS_TRIGGER = "CosmosDBTrigger"; + public static final String ANNOTATION_TIMER_TRIGGER = "TimerTrigger"; + public static final String ANNOTATION_BLOB_TRIGGER = "BlobTrigger"; + + public static final String AZURE_HTTP_LISTENER = "HttpListener"; + public static final String AZURE_QUEUE_LISTENER = "QueueListener"; + public static final String AZURE_COSMOS_LISTENER = "CosmosDBListener"; + public static final String AZURE_TIMER_LISTENER = "TimerListener"; + public static final String AZURE_BLOB_LISTENER = "BlobListener"; + + public static final String COSMOS_INPUT_BINDING = "CosmosDBInput"; + public static final String BLOB_INPUT_BINDING = "BlobInput"; + + public static final String QUEUE_OUTPUT_BINDING = "QueueOutput"; + public static final String HTTP_OUTPUT_BINDING = "HttpOutput"; + public static final String COSMOS_OUTPUT_BINDING = "CosmosDBOutput"; + public static final String TWILIO_OUTPUT_BINDING = "TwilioSmsOutput"; + public static final String BLOB_OUTPUT_BINDING = "BlobOutput"; + + public static final String DIRECTION_IN = "in"; + public static final String DIRECTION_OUT = "out"; + + public static final String RETURN_VAR_NAME = "outMsg"; + + public static final String FUNCTION_DIRECTORY = "azure_functions"; + + public static final String ARTIFACT_PATH = "target/" + FUNCTION_DIRECTORY; + + public static final String SETTINGS_LOCAL_FILE_NAME = "local.settings.json"; + public static final String EXTENSIONS_FILE_NAME = "extensions.json"; + public static final String SETTINGS_FILE_NAME = "settings.json"; + public static final String TASKS_FILE_NAME = "tasks.json"; + + public static final String FUNCTION_ANNOTATION = "Function"; + public static final String SERVICE_CONFIG_ANNOTATION = "ServiceConfig"; + public static final String TREAT_NILABLE_AS_OPTIONAL = "treatNilableAsOptional"; + + } diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/FunctionContext.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/FunctionContext.java new file mode 100644 index 00000000..0c1b31fc --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/FunctionContext.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions; + +import org.ballerinax.azurefunctions.service.Binding; + +import java.util.List; + +/** + * Represents a the function.json structure. + * + * @since 2.0.0 + */ +public class FunctionContext { + private String functionName; + private List bindingList; + + public FunctionContext(String functionName, List bindingList) { + this.functionName = functionName; + this.bindingList = bindingList; + } + + public String getFunctionName() { + return functionName; + } + + public List getBindingList() { + return bindingList; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/FunctionUpdaterTask.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/FunctionUpdaterTask.java new file mode 100644 index 00000000..966e2238 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/FunctionUpdaterTask.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions; + +import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.syntax.tree.ModulePartNode; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.SyntaxTree; +import io.ballerina.projects.Document; +import io.ballerina.projects.DocumentId; +import io.ballerina.projects.Module; +import io.ballerina.projects.ModuleId; +import io.ballerina.projects.plugins.ModifierTask; +import io.ballerina.projects.plugins.SourceModifierContext; +import io.ballerina.tools.diagnostics.DiagnosticSeverity; + +/** + * {@code FunctionUpdaterTask} modifies the source by adding required meta-info for the azure function service + * declarations. + */ +public class FunctionUpdaterTask implements ModifierTask { + + @Override + public void modify(SourceModifierContext context) { + boolean erroneousCompilation = context.compilation().diagnosticResult() + .diagnostics().stream() + .anyMatch(d -> DiagnosticSeverity.ERROR.equals(d.diagnosticInfo().severity())); + // if the compilation already contains any error, do not proceed + if (erroneousCompilation) { + return; + } + + Module module = context.currentPackage().getDefaultModule(); + SemanticModel semanticModel = module.getCompilation().getSemanticModel(); + for (DocumentId documentId : module.documentIds()) { + Document document = module.document(documentId); + ModulePartNode rootNode = document.syntaxTree().rootNode(); + AzureFunctionModifier azureFunctionVisitor = new AzureFunctionModifier(semanticModel); + Node newNode = rootNode.apply(azureFunctionVisitor); + SyntaxTree updatedSyntaxTree = document.syntaxTree().modifyWith(newNode); + context.modifySourceFile(updatedSyntaxTree.textDocument(), documentId); + } + + // for test files + for (ModuleId modId : context.currentPackage().moduleIds()) { + Module currentModule = context.currentPackage().module(modId); + for (DocumentId docId : currentModule.testDocumentIds()) { + Document document = module.document(docId); + ModulePartNode rootNode = document.syntaxTree().rootNode(); + AzureFunctionModifier azureFunctionVisitor = new AzureFunctionModifier(semanticModel); + Node newNode = rootNode.apply(azureFunctionVisitor); + SyntaxTree updatedSyntaxTree = document.syntaxTree().modifyWith(newNode); + context.modifyTestSourceFile(updatedSyntaxTree.textDocument(), docId); + } + } + + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/FunctionsArtifact.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/FunctionsArtifact.java new file mode 100644 index 00000000..d77a6771 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/FunctionsArtifact.java @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; +import org.ballerinax.azurefunctions.tooling.Extensions; +import org.ballerinax.azurefunctions.tooling.LocalSettings; +import org.ballerinax.azurefunctions.tooling.Settings; +import org.ballerinax.azurefunctions.tooling.Tasks; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.nio.file.StandardOpenOption; +import java.util.Comparator; +import java.util.Map; +import java.util.Optional; + +/** + * Represents the output artifact (.zip) generated for Azure Functions. + */ +public class FunctionsArtifact { + + private static final String HOST_JSON_NAME = "host.json"; + private static final String FUNCTION_JSON_NAME = "function.json"; + + private static final String VSCODE_DIRECTORY = ".vscode"; + private static final String GITIGNORE = ".gitignore"; + + private Map functions; + + private Path binaryPath; + + private JsonObject hostJson; + + private Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + public FunctionsArtifact(Map functions, Path binaryPath) throws IOException { + this.functions = functions; + this.binaryPath = binaryPath; + this.generateHostJson(); + } + + public Map getFunctions() { + return functions; + } + + private JsonObject readExistingHostJson() throws IOException { + File file = new File(HOST_JSON_NAME); + if (file.exists()) { + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(new FileInputStream(file), Constants.CHARSET))) { + JsonParser parser = new JsonParser(); + return parser.parse(reader).getAsJsonObject(); + } + } else { + return null; + } + } + + private void generateHostJson() throws IOException { + this.hostJson = readExistingHostJson(); + if (this.hostJson == null) { + this.hostJson = new JsonObject(); + } + this.hostJson.add("version", new JsonPrimitive("2.0")); + JsonObject extensions = new JsonObject(); + JsonObject http = new JsonObject(); + http.addProperty("routePrefix", ""); + extensions.add("http", http); + this.hostJson.add("extensions", extensions); + JsonObject httpWorker = new JsonObject(); + this.hostJson.add("customHandler", httpWorker); + JsonObject httpWorkerDesc = new JsonObject(); + httpWorker.add("description", httpWorkerDesc); + httpWorkerDesc.add("defaultExecutablePath", new JsonPrimitive("java")); + Path fileName = this.binaryPath.getFileName(); + if (fileName != null) { + httpWorkerDesc.add("defaultWorkerPath", new JsonPrimitive(fileName.toString())); + } + JsonArray workerArgs = new JsonArray(); + workerArgs.add("-jar"); + httpWorkerDesc.add("arguments", workerArgs); + httpWorker.add("enableForwardingHttpRequest", new JsonPrimitive(false)); + JsonObject extensionBundle = new JsonObject(); + this.hostJson.add("extensionBundle", extensionBundle); + extensionBundle.add("id", new JsonPrimitive("Microsoft.Azure.Functions.ExtensionBundle")); + extensionBundle.add("version", new JsonPrimitive("[3.*, 4.0.0)")); + } + + private InputStream jtos(Object element) { + try { + return new ByteArrayInputStream(this.gson.toJson(element).getBytes(Constants.CHARSET)); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException(e); + } + } + + public void generate() throws IOException { + // if an earlier generated file is there, delete it, or else + // this will merge content to the earlier artifact + if (this.binaryPath == null) { + return; + } + Path parent = this.binaryPath.toAbsolutePath().getParent(); + if (parent == null) { + return; + } + Path targetDir = parent.getParent(); + if (targetDir == null) { + return; + } + + Path projectDir = targetDir.getParent(); + if (projectDir == null) { + return; + } + generateVsCodeConfigs(projectDir); + + Path functionsDir = targetDir.resolve(Constants.FUNCTION_DIRECTORY); + Optional cachedLocalSettings = cacheLocalSettings(functionsDir); + deleteDirectory(functionsDir); + Files.createDirectories(functionsDir); + Files.copy(this.binaryPath, functionsDir.resolve(this.binaryPath.getFileName()), + StandardCopyOption.REPLACE_EXISTING); + Files.copy(this.jtos(this.hostJson), functionsDir.resolve(HOST_JSON_NAME), + StandardCopyOption.REPLACE_EXISTING); + if (cachedLocalSettings.isEmpty()) { + generateLocalSettings(functionsDir); + } else { + String localSettings = cachedLocalSettings.get(); + ByteArrayInputStream inStream = + new ByteArrayInputStream(localSettings.getBytes(StandardCharsets.UTF_8)); + Files.copy(inStream, functionsDir.resolve(Constants.SETTINGS_LOCAL_FILE_NAME), + StandardCopyOption.REPLACE_EXISTING); + } + for (Map.Entry entry : this.functions.entrySet()) { + Path functionDir = functionsDir.resolve(entry.getKey()); + Files.createDirectories(functionDir); + Files.copy(this.jtos(entry.getValue()), functionDir.resolve(FUNCTION_JSON_NAME), + StandardCopyOption.REPLACE_EXISTING); + } + } + + private void deleteDirectory(Path azureFunctionsDir) throws IOException { + if (azureFunctionsDir.toFile().exists()) { + Files.walk(azureFunctionsDir) + .sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .forEach(File::delete); + } + } + + private void generateLocalSettings(Path azureFunctionsDir) throws IOException { + Files.copy(jtos(new LocalSettings()), azureFunctionsDir.resolve(Constants.SETTINGS_LOCAL_FILE_NAME), + StandardCopyOption.REPLACE_EXISTING); + } + + private Optional cacheLocalSettings(Path azureFunctionsDir) throws IOException { + Path localSettingsPath = azureFunctionsDir.resolve(Constants.SETTINGS_LOCAL_FILE_NAME); + if (localSettingsPath.toFile().exists()) { + return Optional.of(Files.readString(localSettingsPath)); + } + return Optional.empty(); + } + + private void generateVsCodeConfigs(Path projectDir) throws IOException { + Path vsCodeDir = projectDir.resolve(VSCODE_DIRECTORY); + Files.createDirectories(vsCodeDir); + Files.copy(jtos(new Extensions()), vsCodeDir.resolve(Constants.EXTENSIONS_FILE_NAME), + StandardCopyOption.REPLACE_EXISTING); + Files.copy(jtos(new Settings()), vsCodeDir.resolve(Constants.SETTINGS_FILE_NAME), + StandardCopyOption.REPLACE_EXISTING); + Files.copy(jtos(new Tasks()), vsCodeDir.resolve(Constants.TASKS_FILE_NAME), + StandardCopyOption.REPLACE_EXISTING); + + addToGitIgnore(projectDir); + } + + private void addToGitIgnore(Path projectDir) throws IOException { + Path gitIgnore = projectDir.resolve(GITIGNORE); + if (!Files.exists(gitIgnore)) { + return; + } + String gitIgnoreContent = Files.readString(gitIgnore); + if (gitIgnoreContent.contains(VSCODE_DIRECTORY)) { + return; + } + + Files.write(gitIgnore, VSCODE_DIRECTORY.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND); + } +} + diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/Util.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/Util.java new file mode 100644 index 00000000..ff9091b5 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/Util.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions; + +import io.ballerina.compiler.api.symbols.Symbol; +import io.ballerina.compiler.syntax.tree.BasicLiteralNode; +import io.ballerina.compiler.syntax.tree.ExpressionNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.ModulePartNode; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.NonTerminalNode; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import io.ballerina.compiler.syntax.tree.SyntaxKind; +import io.ballerina.compiler.syntax.tree.SyntaxTree; +import io.ballerina.compiler.syntax.tree.Token; +import io.ballerina.projects.plugins.SyntaxNodeAnalysisContext; +import io.ballerina.tools.diagnostics.DiagnosticFactory; +import io.ballerina.tools.diagnostics.DiagnosticInfo; +import io.ballerina.tools.diagnostics.DiagnosticProperty; +import io.ballerina.tools.diagnostics.Location; +import io.ballerina.tools.text.LineRange; +import io.ballerina.tools.text.TextDocument; +import io.ballerina.tools.text.TextRange; + +import java.util.List; +import java.util.Optional; + +/** + * Contains the utilities required for the compiler extension. + * + * @since 2.0.0 + */ +public class Util { + + public static Optional extractValueFromAnnotationField(SpecificFieldNode fieldNode) { + Optional expressionNode = fieldNode.valueExpr(); + if (expressionNode.isEmpty()) { + return Optional.empty(); + } + ExpressionNode expressionNode1 = expressionNode.get(); + if (expressionNode1.kind() == SyntaxKind.STRING_LITERAL) { + String text1 = ((BasicLiteralNode) expressionNode1).literalToken().text(); + return Optional.of(text1.substring(1, text1.length() - 1)); + } else if (expressionNode1.kind() == SyntaxKind.DECIMAL_INTEGER_LITERAL_TOKEN) { + String text1 = ((BasicLiteralNode) expressionNode1).literalToken().text(); + return Optional.of(text1); + } + return Optional.empty(); + } + + /** + * Find node of this symbol. + * + * @param symbol {@link Symbol} + * @return {@link NonTerminalNode} + */ + public static NonTerminalNode findNode(ServiceDeclarationNode serviceDeclarationNode, Symbol symbol) { + if (symbol.getLocation().isEmpty()) { + return null; + } + SyntaxTree syntaxTree = serviceDeclarationNode.syntaxTree(); + TextDocument textDocument = syntaxTree.textDocument(); + LineRange symbolRange = symbol.getLocation().get().lineRange(); + int start = textDocument.textPositionFrom(symbolRange.startLine()); + int end = textDocument.textPositionFrom(symbolRange.endLine()); + return ((ModulePartNode) syntaxTree.rootNode()).findNode(TextRange.from(start, end - start), true); + } + + public static String resourcePathToString(NodeList nodes) { + StringBuilder out = new StringBuilder(); + for (Node node : nodes) { + if (node.kind() == SyntaxKind.STRING_LITERAL) { + String value = ((BasicLiteralNode) node).literalToken().text(); + out.append(value, 1, value.length() - 1); + } else if (node.kind() == SyntaxKind.SLASH_TOKEN) { + Token token = (Token) node; + out.append(token.text()); + } else if (node.kind() == SyntaxKind.IDENTIFIER_TOKEN) { + out.append(((IdentifierToken) node).text()); + } + } + String finalPath = out.toString(); + if (finalPath.startsWith("/")) { + return finalPath.substring(1); + } + return finalPath; + } + + public static void updateDiagnostic(SyntaxNodeAnalysisContext ctx, Location location, + AzureDiagnosticCodes httpDiagnosticCodes) { + DiagnosticInfo diagnosticInfo = getDiagnosticInfo(httpDiagnosticCodes); + ctx.reportDiagnostic(DiagnosticFactory.createDiagnostic(diagnosticInfo, location)); + } + + public static void updateDiagnostic(SyntaxNodeAnalysisContext ctx, Location location, + AzureDiagnosticCodes azureDiagnosticCodes, Object... argName) { + DiagnosticInfo diagnosticInfo = getDiagnosticInfo(azureDiagnosticCodes, argName); + ctx.reportDiagnostic(DiagnosticFactory.createDiagnostic(diagnosticInfo, location)); + } + + public static void updateDiagnostic(SyntaxNodeAnalysisContext ctx, Location location, + AzureDiagnosticCodes azureDiagnosticCodes, + List> diagnosticProperties, String argName) { + DiagnosticInfo diagnosticInfo = getDiagnosticInfo(azureDiagnosticCodes, argName); + ctx.reportDiagnostic(DiagnosticFactory.createDiagnostic(diagnosticInfo, location, diagnosticProperties)); + } + + public static DiagnosticInfo getDiagnosticInfo(AzureDiagnosticCodes diagnostic, Object... args) { + return new DiagnosticInfo(diagnostic.getCode(), String.format(diagnostic.getMessage(), args), + diagnostic.getSeverity()); + } + +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureCodeGeneratedTask.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureCodeGeneratedTask.java deleted file mode 100644 index 80b58b1e..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureCodeGeneratedTask.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import com.google.gson.reflect.TypeToken; -import io.ballerina.projects.plugins.CompilerLifecycleEventContext; -import io.ballerina.projects.plugins.CompilerLifecycleTask; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.PrintStream; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Map; -import java.util.Optional; - -/** - * Contains the code generation part of the azure functions. - * - * @since 2.0.0 - */ -public class AzureCodeGeneratedTask implements CompilerLifecycleTask { - - private static final PrintStream OUT = System.out; - - @Override - public void perform(CompilerLifecycleEventContext compilerLifecycleEventContext) { - Path azfJson = compilerLifecycleEventContext.currentPackage().project().targetDir().resolve("azf.json"); - Gson gson = new Gson(); - try (FileReader file = new FileReader(azfJson.toAbsolutePath().toString(), - StandardCharsets.UTF_8)) { - Type map = new TypeToken>() { - }.getType(); - Map generatedFunctions = gson.fromJson(file, map); - file.close(); - Files.deleteIfExists(azfJson); - if (generatedFunctions.isEmpty()) { - // no azure functions, nothing else to do - return; - } - OUT.println("\t@azure_functions:Function: " + String.join(", ", generatedFunctions.keySet())); - Optional generatedArtifactPath = compilerLifecycleEventContext.getGeneratedArtifactPath(); - generatedArtifactPath.ifPresent(path -> { - try { - this.generateFunctionsArtifact(generatedFunctions, path); - } catch (IOException e) { - String msg = "Error generating Azure Functions: " + e.getMessage(); - OUT.println(msg); - throw new RuntimeException(msg, e); - } - OUT.println("\n\tExecute the below command to deploy Ballerina Azure Functions:"); - Path parent = path.getParent(); - if (parent != null) { - OUT.println( - "\taz functionapp deployment source config-zip -g -n " + - " --src " + parent.toString() + File.separator + - Constants.AZURE_FUNCS_OUTPUT_ZIP_FILENAME + "\n\n"); - } - }); - } catch (IOException e) { - OUT.println("Internal error occurred. Unable to read target/azf.json " + e.getMessage()); - } - } - - private void generateFunctionsArtifact(Map functions, Path binaryPath) - throws IOException { - new FunctionsArtifact(functions, binaryPath).generate(Constants.AZURE_FUNCS_OUTPUT_ZIP_FILENAME); - } -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureCodegenTask.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureCodegenTask.java deleted file mode 100644 index bba02eb7..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureCodegenTask.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - -import com.google.gson.Gson; -import com.google.gson.JsonObject; -import io.ballerina.compiler.api.SemanticModel; -import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; -import io.ballerina.compiler.syntax.tree.ModulePartNode; -import io.ballerina.compiler.syntax.tree.TypeDefinitionNode; -import io.ballerina.projects.Module; -import io.ballerina.projects.Package; -import io.ballerina.projects.plugins.GeneratorTask; -import io.ballerina.projects.plugins.SourceGeneratorContext; -import io.ballerina.tools.diagnostics.DiagnosticFactory; -import io.ballerina.tools.diagnostics.DiagnosticInfo; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import io.ballerina.tools.diagnostics.Location; -import io.ballerina.tools.text.LinePosition; -import io.ballerina.tools.text.LineRange; -import io.ballerina.tools.text.TextDocument; -import io.ballerina.tools.text.TextDocuments; -import io.ballerina.tools.text.TextRange; - -import java.io.FileWriter; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * An {@code AnalysisTask} that is triggered for Cloud.toml validation. - * - * @since 1.0.0 - */ -public class AzureCodegenTask implements GeneratorTask { - - @Override - public void generate(SourceGeneratorContext sourceGeneratorContext) { - Package currentPackage = sourceGeneratorContext.currentPackage(); - AzureFunctionExtractor azureFunctionExtractor = new AzureFunctionExtractor(currentPackage); - List extractedFunctions = azureFunctionExtractor.extractFunctions(); - Module module = currentPackage.getDefaultModule(); - SemanticModel semanticModel = sourceGeneratorContext.compilation().getSemanticModel(module.moduleId()); - Map typeDefinitions = new HashMap<>(); - FunctionHandlerGenerator functionGenerator = new FunctionHandlerGenerator(semanticModel, typeDefinitions); - Map generatedFunctions = new LinkedHashMap<>(); - List contextList = new ArrayList<>(); - for (FunctionDefinitionNode function : extractedFunctions) { - try { - FunctionDeploymentContext context = functionGenerator.generateHandlerFunction(function); - contextList.add(context); - generatedFunctions.put(function.functionName().text(), context.getFunctionDefinition()); - } catch (AzureFunctionsException e) { - sourceGeneratorContext.reportDiagnostic(e.getDiagnostic()); - } - } - try { - writeObjectToJson(sourceGeneratorContext.currentPackage().project().targetDir(), generatedFunctions); - } catch (IOException e) { - DiagnosticInfo diagnosticInfo = new DiagnosticInfo("azf-001", "azf.json creation failed " - + e.getMessage(), DiagnosticSeverity.ERROR); - sourceGeneratorContext.reportDiagnostic(DiagnosticFactory.createDiagnostic(diagnosticInfo, - new NullLocation())); - return; - } - if (generatedFunctions.isEmpty()) { - // no azure functions, nothing else to do - return; - } - TextDocument textDocument = generateHandlerDocument(typeDefinitions, contextList); - sourceGeneratorContext.addSourceFile(textDocument, Constants.AZ_FUNCTION_PREFIX, module.moduleId()); - } - - private TextDocument generateHandlerDocument(Map typeDefinitions, - List ctx) { - ModulePartNode modulePartNode = - GeneratorUtil.createModulePartNode(ctx, typeDefinitions); - return TextDocuments.from(modulePartNode.toSourceCode()); - } - - private void writeObjectToJson(Path targetPath, Map ctxMap) - throws IOException { - Gson gson = new Gson(); - Path jsonPath = targetPath.resolve("azf.json"); - Files.deleteIfExists(jsonPath); - Path targetDir = jsonPath.getParent(); - if (targetDir == null) { - return; - } - if (!Files.exists(targetDir)) { - Files.createDirectories(targetDir); - } - Files.createFile(jsonPath); - try (FileWriter r = new FileWriter(jsonPath.toAbsolutePath().toString(), StandardCharsets.UTF_8)) { - gson.toJson(ctxMap, r); - } - } -} - -/** - * Represents Null Location in a ballerina document. - * - * @since 2.0.0 - */ -class NullLocation implements Location { - - @Override - public LineRange lineRange() { - LinePosition from = LinePosition.from(0, 0); - return LineRange.from("", from, from); - } - - @Override - public TextRange textRange() { - return TextRange.from(0, 0); - } -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionDiagnostics.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionDiagnostics.java deleted file mode 100644 index 88eb0dce..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionDiagnostics.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - -import io.ballerina.tools.diagnostics.Diagnostic; -import io.ballerina.tools.diagnostics.DiagnosticInfo; -import io.ballerina.tools.diagnostics.DiagnosticProperty; -import io.ballerina.tools.diagnostics.Location; - -import java.util.List; - -/** - * This util class use for creating Azure Function diagnostic. - */ -public class AzureFunctionDiagnostics extends Diagnostic { - - private Location location; - private DiagnosticInfo diagnosticInfo; - private String message; - - public AzureFunctionDiagnostics(Location location, DiagnosticInfo diagnosticInfo, String message) { - this.location = location; - this.diagnosticInfo = diagnosticInfo; - this.message = message; - } - - @Override - public Location location() { - return this.location; - } - - @Override - public DiagnosticInfo diagnosticInfo() { - return this.diagnosticInfo; - } - - @Override - public String message() { - return this.message; - } - - @Override - public List> properties() { - return null; - } -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionVisitor.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionVisitor.java deleted file mode 100644 index 28425c29..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionVisitor.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; -import io.ballerina.compiler.syntax.tree.ImportDeclarationNode; -import io.ballerina.compiler.syntax.tree.MetadataNode; -import io.ballerina.compiler.syntax.tree.ModulePartNode; -import io.ballerina.compiler.syntax.tree.NodeVisitor; -import io.ballerina.compiler.syntax.tree.QualifiedNameReferenceNode; -import io.ballerina.compiler.syntax.tree.SyntaxKind; - -import java.util.ArrayList; -import java.util.List; - -/** - * Visitor for extracting Azure functions from a ballerina document. - * - * @since 2.0.0 - */ -public class AzureFunctionVisitor extends NodeVisitor { - - private final List functions; - private String moduleName; - - public AzureFunctionVisitor() { - this.functions = new ArrayList<>(); - } - - @Override - public void visit(ModulePartNode modulePartNode) { - super.visit(modulePartNode); - } - - @Override - public void visit(ImportDeclarationNode importDeclarationNode) { - if (importDeclarationNode.orgName().isEmpty()) { - return; - } - String orgName = importDeclarationNode.orgName().get().orgName().text(); - if (!Constants.AZURE_FUNCTIONS_PACKAGE_ORG.equals(orgName)) { - return; - } - if (importDeclarationNode.moduleName().size() != 1) { - return; - } - String moduleName = importDeclarationNode.moduleName().get(0).text(); - if (Constants.AZURE_FUNCTIONS_MODULE_NAME.equals(moduleName)) { - this.moduleName = moduleName; - } - if (importDeclarationNode.prefix().isEmpty()) { - return; - } - this.moduleName = importDeclarationNode.prefix().get().prefix().text(); - } - - @Override - public void visit(FunctionDefinitionNode functionDefinitionNode) { - if (this.moduleName == null) { - return; - } - if (functionDefinitionNode.metadata().isEmpty()) { - return; - } - - MetadataNode metadataNode = functionDefinitionNode.metadata().get(); - for (AnnotationNode annotation : metadataNode.annotations()) { - if (annotation.annotReference().kind() != SyntaxKind.QUALIFIED_NAME_REFERENCE) { - continue; - } - QualifiedNameReferenceNode qualifiedNameReferenceNode = - (QualifiedNameReferenceNode) annotation.annotReference(); - String modulePrefix = qualifiedNameReferenceNode.modulePrefix().text(); - String identifier = qualifiedNameReferenceNode.identifier().text(); - if (modulePrefix.equals(this.moduleName) && Constants.AWS_FUNCTION_TYPE.equals(identifier)) { - functions.add(functionDefinitionNode); - } - } - } - - public List getFunctions() { - return functions; - } -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionsException.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionsException.java deleted file mode 100644 index a32ce082..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionsException.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - -import io.ballerina.tools.diagnostics.Diagnostic; - -/** - * Represents Azure functions compiler extension errors. - */ -public class AzureFunctionsException extends Exception { - - private static final long serialVersionUID = -6540373040546296073L; - private transient Diagnostic diagnostic; - - public AzureFunctionsException(Diagnostic diagnostic) { - super(diagnostic.message()); - this.diagnostic = diagnostic; - } - - public AzureFunctionsException(Diagnostic diagnostic, Throwable cause) { - super(diagnostic.message(), cause); - } - - public Diagnostic getDiagnostic() { - return diagnostic; - } -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionsExtensionProvider.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionsExtensionProvider.java deleted file mode 100644 index 4e559397..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureFunctionsExtensionProvider.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - -import org.ballerinalang.annotation.JavaSPIService; -import org.ballerinalang.spi.SystemPackageRepositoryProvider; -import org.wso2.ballerinalang.compiler.packaging.repo.JarRepo; -import org.wso2.ballerinalang.compiler.packaging.repo.Repo; - -/** - * This represents the Ballerina AzureFunctions extension package repository provider. - */ -@JavaSPIService("org.ballerinalang.spi.SystemPackageRepositoryProvider") -public class AzureFunctionsExtensionProvider implements SystemPackageRepositoryProvider { - - @SuppressWarnings("rawtypes") - @Override - public Repo loadRepository() { - return new JarRepo(SystemPackageRepositoryProvider.getClassUri(this)); - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/Constants.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/Constants.java deleted file mode 100644 index 7f6ec089..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/Constants.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - - /** - * Constants for Azure Functions. - */ -public class Constants { - - public static final String MAIN_FUNC_NAME = "main"; - public static final String AZURE_FUNCTIONS_MODULE_NAME = "azure_functions"; - public static final String BALLERINA_ORG = "ballerina"; - public static final String REQUEST_PARAMS_TYPE = "HandlerParams"; - public static final String REQUEST_PARAMS_NAME = "params"; - public static final String HTTP_CALLER_PARAMS_NAME = "caller"; - public static final String HTTP_REQUEST_PARAMS_NAME = "request"; - public static final String AZURE_FUNCTIONS_PACKAGE_ORG = "ballerinax"; - public static final String AZURE_FUNCTIONS_CONTEXT_NAME = "Context"; - public static final String AZURE_FUNCS_OUTPUT_ZIP_FILENAME = "azure-functions.zip"; - public static final String FUNCTION_BINDINGS_NAME = "bindings"; - public static final String CHARSET = "UTF-8"; - public static final String DEFAULT_STORAGE_CONNECTION_NAME = "AzureWebJobsStorage"; - public static final String DEFAULT_TWILIO_ACCOUNT_SID_SETTING = "AzureWebJobsTwilioAccountSid"; - public static final String DEFAULT_TWILIO_AUTH_TOKEN_SETTING = "AzureWebJobsTwilioAuthToken"; - public static final boolean DEFAULT_TIMER_TRIGGER_RUNONSTARTUP = true; - public static final boolean DEFAULT_COSMOS_DB_CREATELEASECOLLECTIONIFNOTEXISTS = true; - public static final String PARAMS = "params"; - public static final String AF_IMPORT_ALIAS = "af"; - public static final String HTTP_IMPORT = "http"; - public static final String AWS_FUNCTION_TYPE = "Function"; - public static final String AZ_FUNCTION_PREFIX = "az-func"; - } diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/FunctionDeploymentContext.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/FunctionDeploymentContext.java deleted file mode 100644 index 598101f7..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/FunctionDeploymentContext.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; - -import java.util.ArrayList; -import java.util.List; - -/** - * Represents the Azure functions context. - */ -public class FunctionDeploymentContext { - - private static final String VAR_PREFIX = "v"; - private List parameterHandlers = new ArrayList<>(); - private ReturnHandler returnHandler; - private JsonObject functionDefinition; - private FunctionDefinitionNode sourceFunction; - private FunctionDefinitionNode function; - private int varCounter = 0; - private boolean isolatedFunction = false; - - public FunctionDeploymentContext() { - this.setFunctionDefinition(new JsonObject()); - this.getFunctionDefinition().add(Constants.FUNCTION_BINDINGS_NAME, new JsonArray()); - } - - public String getNextVarName() { - return VAR_PREFIX + (++varCounter); - } - - public List getParameterHandlers() { - return parameterHandlers; - } - - public void setParameterHandlers(List parameterHandlers) { - this.parameterHandlers = parameterHandlers; - } - - public ReturnHandler getReturnHandler() { - return returnHandler; - } - - public void setReturnHandler(ReturnHandler returnHandler) { - this.returnHandler = returnHandler; - } - - public JsonObject getFunctionDefinition() { - return functionDefinition; - } - - public void setFunctionDefinition(JsonObject functionDefinition) { - this.functionDefinition = functionDefinition; - } - - public FunctionDefinitionNode getSourceFunction() { - return sourceFunction; - } - - public void setSourceFunction(FunctionDefinitionNode sourceFunction) { - this.sourceFunction = sourceFunction; - } - - public FunctionDefinitionNode getFunction() { - return function; - } - - public void setFunction(FunctionDefinitionNode function) { - this.function = function; - } - - public boolean isIsolatedFunction() { - return isolatedFunction; - } - - public void setIsolatedFunction(boolean isolatedFunction) { - this.isolatedFunction = isolatedFunction; - } -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/FunctionHandlerGenerator.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/FunctionHandlerGenerator.java deleted file mode 100644 index 2b328ea9..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/FunctionHandlerGenerator.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - -import io.ballerina.compiler.api.SemanticModel; -import io.ballerina.compiler.api.symbols.FunctionSymbol; -import io.ballerina.compiler.api.symbols.FunctionTypeSymbol; -import io.ballerina.compiler.api.symbols.TypeDescKind; -import io.ballerina.compiler.api.symbols.TypeSymbol; -import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.ParameterNode; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.TypeDefinitionNode; -import io.ballerina.compiler.syntax.tree.TypeDescriptorNode; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -/** - * Responsible for generating intermediate handler functions for each azure function. - * - * @since 2.0.0 - */ -public class FunctionHandlerGenerator { - - private final SemanticModel semanticModel; - private final Map typeDefinitions; - - public FunctionHandlerGenerator(SemanticModel semanticModel, - Map generatedTypeDefinitions) { - this.semanticModel = semanticModel; - this.typeDefinitions = generatedTypeDefinitions; - } - - public FunctionDeploymentContext generateHandlerFunction(FunctionDefinitionNode sourceFunc) - throws AzureFunctionsException { - FunctionDeploymentContext ctx = this.createFuncDeplContext(sourceFunc); - List positionalArgumentNodes = new ArrayList<>(); - for (ParameterHandler ph : ctx.getParameterHandlers()) { - positionalArgumentNodes.add(NodeFactory.createPositionalArgumentNode(ph.invocationProcess())); - } - TypeDescriptorNode originalFunctionTypeDesc = - GeneratorUtil.getCheckedReturnTypeDescOfOriginalFunction(ctx.getSourceFunction()); - - boolean isCheckRequired = GeneratorUtil.isCheckingRequiredForOriginalFunction(ctx.getSourceFunction()); - String returnName = GeneratorUtil.addFunctionCallStatement(originalFunctionTypeDesc, ctx, - GeneratorUtil.createFunctionInvocationNode(sourceFunc.functionName().text(), - positionalArgumentNodes.toArray(new PositionalArgumentNode[0])), isCheckRequired); - - for (ParameterHandler ph : ctx.getParameterHandlers()) { - ph.postInvocationProcess(); - } - ReturnHandler returnHandler = ctx.getReturnHandler(); - if (returnHandler != null) { - returnHandler.postInvocationProcess(GeneratorUtil.createVariableRef(returnName)); - } - return ctx; - } - - private FunctionDeploymentContext createFuncDeplContext(FunctionDefinitionNode sourceFunc) - throws AzureFunctionsException { - FunctionDeploymentContext ctx = new FunctionDeploymentContext(); - ctx.setSourceFunction(sourceFunc); - ctx.setIsolatedFunction(GeneratorUtil.isIsolatedFunction(sourceFunc)); - ctx.setFunction(GeneratorUtil.createHandlerFunction(ctx)); - - for (ParameterNode parameter : sourceFunc.functionSignature().parameters()) { - ctx.getParameterHandlers() - .add(HandlerFactory.createParameterHandler(parameter, semanticModel, typeDefinitions)); - } - - for (ParameterHandler ph : ctx.getParameterHandlers()) { - ph.init(ctx); - } - FunctionTypeSymbol functionTypeSymbol = - ((FunctionSymbol) semanticModel.symbol(sourceFunc.functionName()).orElseThrow()).typeDescriptor(); - - Optional returnSymbolOptional = functionTypeSymbol.returnTypeDescriptor(); - if (returnSymbolOptional.isPresent() && !(returnSymbolOptional.get().typeKind() == TypeDescKind.NIL)) { - ctx.setReturnHandler(HandlerFactory.createReturnHandler(returnSymbolOptional.get(), - sourceFunc.functionSignature().returnTypeDesc().orElseThrow())); - if (ctx.getReturnHandler() != null) { - ctx.getReturnHandler().init(ctx); - } - } - return ctx; - } -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/FunctionsArtifact.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/FunctionsArtifact.java deleted file mode 100644 index 17336280..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/FunctionsArtifact.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonPrimitive; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; -import java.util.HashMap; -import java.util.Map; - -/** - * Represents the output artifact (.zip) generated for Azure Functions. - */ -public class FunctionsArtifact { - - private static final String HOST_JSON_NAME = "host.json"; - - private static final String FUNCTION_JSON_NAME = "function.json"; - - private Map functions; - - private Path binaryPath; - - private JsonObject hostJson; - - private Gson gson = new GsonBuilder().setPrettyPrinting().create(); - - public FunctionsArtifact(Map functions, Path binaryPath) throws IOException { - this.functions = functions; - this.binaryPath = binaryPath; - this.generateHostJson(); - } - - public Map getFunctions() { - return functions; - } - - public Path getBinaryPath() { - return binaryPath; - } - - private JsonObject readExistingHostJson() throws IOException { - File file = new File(HOST_JSON_NAME); - if (file.exists()) { - try (BufferedReader reader = new BufferedReader( - new InputStreamReader(new FileInputStream(file), Constants.CHARSET))) { - JsonParser parser = new JsonParser(); - return parser.parse(reader).getAsJsonObject(); - } - } else { - return null; - } - } - - private void generateHostJson() throws IOException { - this.hostJson = readExistingHostJson(); - if (this.hostJson == null) { - this.hostJson = new JsonObject(); - } - this.hostJson.add("version", new JsonPrimitive("2.0")); - JsonObject httpWorker = new JsonObject(); - this.hostJson.add("customHandler", httpWorker); - JsonObject httpWorkerDesc = new JsonObject(); - httpWorker.add("description", httpWorkerDesc); - httpWorkerDesc.add("defaultExecutablePath", new JsonPrimitive("java")); - Path fileName = this.binaryPath.getFileName(); - if (fileName != null) { - httpWorkerDesc.add("defaultWorkerPath", new JsonPrimitive(fileName.toString())); - } - JsonArray workerArgs = new JsonArray(); - workerArgs.add("-jar"); - httpWorkerDesc.add("arguments", workerArgs); - httpWorker.add("enableForwardingHttpRequest", new JsonPrimitive(false)); - JsonObject extensionBundle = new JsonObject(); - this.hostJson.add("extensionBundle", extensionBundle); - extensionBundle.add("id", new JsonPrimitive("Microsoft.Azure.Functions.ExtensionBundle")); - extensionBundle.add("version", new JsonPrimitive("[2.*, 3.0.0)")); - } - - private InputStream jtos(JsonElement element) { - try { - return new ByteArrayInputStream(this.gson.toJson(element).getBytes(Constants.CHARSET)); - } catch (UnsupportedEncodingException e) { - throw new IllegalStateException(e); - } - } - - public void generate(String outputFileName) throws IOException { - // if an earlier generated file is there, delete it, or else - // this will merge content to the earlier artifact - Files.deleteIfExists(Paths.get(outputFileName)); - Map env = new HashMap<>(); - env.put("create", "true"); - if (this.binaryPath == null) { - return; - } - Path parent = this.binaryPath.toAbsolutePath().getParent(); - if (parent == null) { - return; - } - URI uri = URI.create("jar:file:" + parent.resolve(outputFileName).toUri().getPath()); - try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) { - Files.copy(this.binaryPath, zipfs.getPath("/" + this.binaryPath.getFileName()), - StandardCopyOption.REPLACE_EXISTING); - Files.copy(this.jtos(this.hostJson), zipfs.getPath("/" + HOST_JSON_NAME), - StandardCopyOption.REPLACE_EXISTING); - for (Map.Entry entry : this.functions.entrySet()) { - Path functionDir = zipfs.getPath("/" + entry.getKey()); - Files.createDirectory(functionDir); - Files.copy(this.jtos(entry.getValue()), functionDir.resolve(FUNCTION_JSON_NAME), - StandardCopyOption.REPLACE_EXISTING); - } - } - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/GeneratorUtil.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/GeneratorUtil.java deleted file mode 100644 index 800b837f..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/GeneratorUtil.java +++ /dev/null @@ -1,931 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; -import io.ballerina.compiler.api.ModuleID; -import io.ballerina.compiler.api.symbols.AnnotationSymbol; -import io.ballerina.compiler.api.symbols.ArrayTypeSymbol; -import io.ballerina.compiler.api.symbols.ModuleSymbol; -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.api.symbols.TypeDescKind; -import io.ballerina.compiler.api.symbols.TypeSymbol; -import io.ballerina.compiler.api.symbols.UnionTypeSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ArrayTypeDescriptorNode; -import io.ballerina.compiler.syntax.tree.AssignmentStatementNode; -import io.ballerina.compiler.syntax.tree.BasicLiteralNode; -import io.ballerina.compiler.syntax.tree.CaptureBindingPatternNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.ExpressionStatementNode; -import io.ballerina.compiler.syntax.tree.FunctionArgumentNode; -import io.ballerina.compiler.syntax.tree.FunctionBodyBlockNode; -import io.ballerina.compiler.syntax.tree.FunctionCallExpressionNode; -import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; -import io.ballerina.compiler.syntax.tree.FunctionSignatureNode; -import io.ballerina.compiler.syntax.tree.IdentifierToken; -import io.ballerina.compiler.syntax.tree.ImplicitNewExpressionNode; -import io.ballerina.compiler.syntax.tree.ImportDeclarationNode; -import io.ballerina.compiler.syntax.tree.ListenerDeclarationNode; -import io.ballerina.compiler.syntax.tree.MappingConstructorExpressionNode; -import io.ballerina.compiler.syntax.tree.MappingFieldNode; -import io.ballerina.compiler.syntax.tree.MinutiaeList; -import io.ballerina.compiler.syntax.tree.ModuleMemberDeclarationNode; -import io.ballerina.compiler.syntax.tree.ModulePartNode; -import io.ballerina.compiler.syntax.tree.NilTypeDescriptorNode; -import io.ballerina.compiler.syntax.tree.Node; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.NodeList; -import io.ballerina.compiler.syntax.tree.OptionalTypeDescriptorNode; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.QualifiedNameReferenceNode; -import io.ballerina.compiler.syntax.tree.RemoteMethodCallActionNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.compiler.syntax.tree.ReturnTypeDescriptorNode; -import io.ballerina.compiler.syntax.tree.SeparatedNodeList; -import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; -import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode; -import io.ballerina.compiler.syntax.tree.SpecificFieldNode; -import io.ballerina.compiler.syntax.tree.StatementNode; -import io.ballerina.compiler.syntax.tree.SyntaxKind; -import io.ballerina.compiler.syntax.tree.Token; -import io.ballerina.compiler.syntax.tree.TrapExpressionNode; -import io.ballerina.compiler.syntax.tree.TypeDefinitionNode; -import io.ballerina.compiler.syntax.tree.TypeDescriptorNode; -import io.ballerina.compiler.syntax.tree.TypedBindingPatternNode; -import io.ballerina.compiler.syntax.tree.UnionTypeDescriptorNode; -import io.ballerina.compiler.syntax.tree.VariableDeclarationNode; -import io.ballerina.compiler.syntax.tree.WildcardBindingPatternNode; -import io.ballerina.tools.diagnostics.Diagnostic; -import io.ballerina.tools.diagnostics.DiagnosticInfo; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import io.ballerina.tools.diagnostics.Location; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -/** - * Utility functions for Azure Functions. - * - * @since 2.0.0 - */ -public class GeneratorUtil { - - /** - * Generates boilerplate Handler function for a specific azure function. - * - * @param ctx function context - * @return boilerplate handler function - */ - public static FunctionDefinitionNode createHandlerFunction(FunctionDeploymentContext ctx) { - String baseName = ctx.getSourceFunction().functionName().text(); - QualifiedNameReferenceNode azHandlerParamsType = - NodeFactory - .createQualifiedNameReferenceNode(NodeFactory.createIdentifierToken(Constants.AF_IMPORT_ALIAS), - NodeFactory.createToken(SyntaxKind.COLON_TOKEN), NodeFactory - .createIdentifierToken("HandlerParams", NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace())); - RequiredParameterNode requiredParameterNode = - NodeFactory.createRequiredParameterNode(NodeFactory.createEmptyNodeList(), azHandlerParamsType, - NodeFactory.createIdentifierToken(Constants.REQUEST_PARAMS_NAME)); - OptionalTypeDescriptorNode optionalErrorTypeDescriptorNode = - NodeFactory.createOptionalTypeDescriptorNode( - NodeFactory.createParameterizedTypeDescriptorNode(SyntaxKind.ERROR_TYPE_DESC, - NodeFactory.createToken(SyntaxKind.ERROR_KEYWORD), null), - NodeFactory.createToken(SyntaxKind.QUESTION_MARK_TOKEN, NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace())); - - ReturnTypeDescriptorNode returnTypeDescriptorNode = - NodeFactory.createReturnTypeDescriptorNode(NodeFactory - .createToken(SyntaxKind.RETURNS_KEYWORD, NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace()), - NodeFactory.createEmptyNodeList(), optionalErrorTypeDescriptorNode); - FunctionSignatureNode functionSignatureNode = - NodeFactory.createFunctionSignatureNode(NodeFactory.createToken(SyntaxKind.OPEN_PAREN_TOKEN), - NodeFactory.createSeparatedNodeList(requiredParameterNode), - NodeFactory.createToken(SyntaxKind.CLOSE_PAREN_TOKEN), returnTypeDescriptorNode); - - FunctionBodyBlockNode emptyFunctionBodyNode = - NodeFactory.createFunctionBodyBlockNode( - NodeFactory.createToken(SyntaxKind.OPEN_BRACE_TOKEN, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithNewline()), null, - NodeFactory.createEmptyNodeList(), NodeFactory.createToken(SyntaxKind.CLOSE_BRACE_TOKEN)); - - List qualifierList = new ArrayList<>(); - Token publicToken = NodeFactory.createToken(SyntaxKind.PUBLIC_KEYWORD, - NodeFactory.createEmptyMinutiaeList(), generateMinutiaeListWithWhitespace()); - qualifierList.add(publicToken); - - if (ctx.isIsolatedFunction()) { - Token isolatedToken = NodeFactory.createToken(SyntaxKind.ISOLATED_KEYWORD, - NodeFactory.createEmptyMinutiaeList(), generateMinutiaeListWithWhitespace()); - qualifierList.add(isolatedToken); - } - - return NodeFactory.createFunctionDefinitionNode( - SyntaxKind.FUNCTION_DEFINITION, null, NodeFactory.createNodeList(qualifierList), - NodeFactory.createToken(SyntaxKind.FUNCTION_KEYWORD, NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace()), NodeFactory.createIdentifierToken(baseName + - "Handler", NodeFactory.createEmptyMinutiaeList(), generateMinutiaeListWithWhitespace()), - NodeFactory.createEmptyNodeList(), functionSignatureNode, emptyFunctionBodyNode); - } - - public static FunctionDefinitionNode createResourceFunction(FunctionDeploymentContext ctx) { - //TODO change isolated - String baseName = ctx.getSourceFunction().functionName().text(); - QualifiedNameReferenceNode httpCallerType = - NodeFactory.createQualifiedNameReferenceNode(NodeFactory.createIdentifierToken(Constants.HTTP_IMPORT), - NodeFactory.createToken(SyntaxKind.COLON_TOKEN), - NodeFactory.createIdentifierToken("Caller", NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace())); - RequiredParameterNode callerParamNode = - NodeFactory.createRequiredParameterNode(NodeFactory.createEmptyNodeList(), httpCallerType, - NodeFactory.createIdentifierToken(Constants.HTTP_CALLER_PARAMS_NAME)); - - QualifiedNameReferenceNode httpRequestType = - NodeFactory.createQualifiedNameReferenceNode(NodeFactory.createIdentifierToken(Constants.HTTP_IMPORT), - NodeFactory.createToken(SyntaxKind.COLON_TOKEN), - NodeFactory.createIdentifierToken("Request", NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace())); - RequiredParameterNode requestParamNode = - NodeFactory.createRequiredParameterNode(NodeFactory.createEmptyNodeList(), httpRequestType, - NodeFactory.createIdentifierToken(Constants.HTTP_REQUEST_PARAMS_NAME)); - - OptionalTypeDescriptorNode optionalErrorTypeDescriptorNode = - NodeFactory.createOptionalTypeDescriptorNode( - NodeFactory.createParameterizedTypeDescriptorNode(SyntaxKind.ERROR_TYPE_DESC, - NodeFactory.createToken(SyntaxKind.ERROR_KEYWORD), null), - NodeFactory.createToken(SyntaxKind.QUESTION_MARK_TOKEN, NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace())); - - ReturnTypeDescriptorNode returnTypeDescriptorNode = - NodeFactory.createReturnTypeDescriptorNode(NodeFactory - .createToken(SyntaxKind.RETURNS_KEYWORD, NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace()), - NodeFactory.createEmptyNodeList(), optionalErrorTypeDescriptorNode); - FunctionSignatureNode functionSignatureNode = - NodeFactory.createFunctionSignatureNode(NodeFactory.createToken(SyntaxKind.OPEN_PAREN_TOKEN), - NodeFactory.createSeparatedNodeList(callerParamNode, - NodeFactory.createToken(SyntaxKind.COMMA_TOKEN), requestParamNode), - NodeFactory.createToken(SyntaxKind.CLOSE_PAREN_TOKEN), returnTypeDescriptorNode); - - QualifiedNameReferenceNode httpResponseType = - NodeFactory.createQualifiedNameReferenceNode(NodeFactory.createIdentifierToken(Constants.HTTP_IMPORT), - NodeFactory.createToken(SyntaxKind.COLON_TOKEN), - NodeFactory.createIdentifierToken("Response", NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace())); - - CaptureBindingPatternNode response = - NodeFactory.createCaptureBindingPatternNode( - NodeFactory.createIdentifierToken("response", NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace())); - - TypedBindingPatternNode responseTypeBindingNode = - NodeFactory.createTypedBindingPatternNode(httpResponseType, response); - - ImplicitNewExpressionNode implicitNewExpressionNode = - NodeFactory.createImplicitNewExpressionNode(NodeFactory.createToken(SyntaxKind.NEW_KEYWORD), null); - - VariableDeclarationNode responseDeclNode = - NodeFactory.createVariableDeclarationNode(NodeFactory.createEmptyNodeList(), null, - responseTypeBindingNode, NodeFactory.createToken(SyntaxKind.EQUAL_TOKEN), - implicitNewExpressionNode, - NodeFactory.createToken(SyntaxKind.SEMICOLON_TOKEN)); - - QualifiedNameReferenceNode afHandlerParamType = - NodeFactory - .createQualifiedNameReferenceNode(NodeFactory.createIdentifierToken(Constants.AF_IMPORT_ALIAS), - NodeFactory.createToken(SyntaxKind.COLON_TOKEN), - NodeFactory.createIdentifierToken(Constants.REQUEST_PARAMS_TYPE, - NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace())); - - CaptureBindingPatternNode params = - NodeFactory.createCaptureBindingPatternNode( - NodeFactory.createIdentifierToken(Constants.REQUEST_PARAMS_NAME, - NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace())); - - TypedBindingPatternNode paramsTypeBindingNode = - NodeFactory.createTypedBindingPatternNode(afHandlerParamType, params); - - SpecificFieldNode requestParam = - NodeFactory.createSpecificFieldNode(null, NodeFactory.createIdentifierToken("request"), null, null); - - SpecificFieldNode responseParam = - NodeFactory.createSpecificFieldNode(null, NodeFactory.createIdentifierToken("response"), null, null); - - MappingConstructorExpressionNode argList = - NodeFactory.createMappingConstructorExpressionNode(NodeFactory.createToken(SyntaxKind.OPEN_BRACE_TOKEN), - NodeFactory - .createSeparatedNodeList(requestParam, NodeFactory.createToken(SyntaxKind.COMMA_TOKEN), - responseParam), NodeFactory.createToken(SyntaxKind.CLOSE_BRACE_TOKEN)); - - VariableDeclarationNode paramDeclNode = - NodeFactory.createVariableDeclarationNode(NodeFactory.createEmptyNodeList(), null, - paramsTypeBindingNode, NodeFactory.createToken(SyntaxKind.EQUAL_TOKEN), argList, - NodeFactory.createToken(SyntaxKind.SEMICOLON_TOKEN)); - - PositionalArgumentNode paramsArg = NodeFactory.createPositionalArgumentNode( - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken(Constants.PARAMS))); - TrapExpressionNode trappedHandlerCall = NodeFactory.createTrapExpressionNode(SyntaxKind.TRAP_EXPRESSION, - NodeFactory.createToken(SyntaxKind.TRAP_KEYWORD, - NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithWhitespace()), createMethodInvocationNode( - baseName + "Handler", paramsArg)); - PositionalArgumentNode handlerArg = NodeFactory.createPositionalArgumentNode(trappedHandlerCall); - - ExpressionStatementNode expressionStatementNode = - NodeFactory.createExpressionStatementNode(SyntaxKind.CALL_STATEMENT, createAfFunctionInvocationNode( - "handleFunctionResposne", false, handlerArg, paramsArg), - NodeFactory.createToken(SyntaxKind.SEMICOLON_TOKEN)); - - SimpleNameReferenceNode caller = - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken("caller")); - SimpleNameReferenceNode respond = - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken("respond")); - SimpleNameReferenceNode responseVar = - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken("response")); - RemoteMethodCallActionNode remoteMethodCallActionNode = NodeFactory - .createRemoteMethodCallActionNode(caller, NodeFactory.createToken(SyntaxKind.RIGHT_ARROW_TOKEN), - respond, NodeFactory.createToken(SyntaxKind.OPEN_PAREN_TOKEN), - NodeFactory.createSeparatedNodeList(NodeFactory.createPositionalArgumentNode(responseVar)), - NodeFactory.createToken(SyntaxKind.CLOSE_PAREN_TOKEN)); - ExpressionStatementNode checkedResponseExpr = - NodeFactory.createExpressionStatementNode(SyntaxKind.ACTION_STATEMENT, - NodeFactory.createCheckExpressionNode(SyntaxKind.CHECK_ACTION, - NodeFactory.createToken(SyntaxKind.CHECK_KEYWORD, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil - .generateMinutiaeListWithWhitespace()), remoteMethodCallActionNode), - NodeFactory.createToken(SyntaxKind.SEMICOLON_TOKEN)); - - FunctionBodyBlockNode functionBodyNode = - NodeFactory.createFunctionBodyBlockNode( - NodeFactory.createToken(SyntaxKind.OPEN_BRACE_TOKEN, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithNewline()), null, - NodeFactory.createNodeList(responseDeclNode, paramDeclNode, expressionStatementNode, - checkedResponseExpr), - NodeFactory.createToken(SyntaxKind.CLOSE_BRACE_TOKEN)); - - NodeList relativeResPath = NodeFactory - .createNodeList(NodeFactory.createIdentifierToken(baseName, NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace())); - - List qualifierList = new ArrayList<>(); - if (ctx.isIsolatedFunction()) { - Token isolatedToken = NodeFactory.createToken(SyntaxKind.ISOLATED_KEYWORD, - NodeFactory.createEmptyMinutiaeList(), generateMinutiaeListWithWhitespace()); - qualifierList.add(isolatedToken); - } - - Token resToken = NodeFactory.createToken(SyntaxKind.RESOURCE_KEYWORD, - NodeFactory.createEmptyMinutiaeList(), generateMinutiaeListWithWhitespace()); - qualifierList.add(resToken); - - return NodeFactory.createFunctionDefinitionNode( - SyntaxKind.FUNCTION_DEFINITION, null, NodeFactory.createNodeList(qualifierList), - NodeFactory.createToken(SyntaxKind.FUNCTION_KEYWORD, NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace()), NodeFactory - .createIdentifierToken("'default", NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace()), relativeResPath, functionSignatureNode, - functionBodyNode); - } - - /** - * Generates top level ballerina document node with imports, typedesc, main method and handler functions. - * - * @param functionDeploymentContexts list of contexts containing original and generated function information - * @param generatedTypeDefinitions type descriptors that needs to be generated - * @return module part node - */ - public static ModulePartNode createModulePartNode(Collection functionDeploymentContexts, - Map generatedTypeDefinitions) { - - ImportDeclarationNode afImport = - NodeFactory.createImportDeclarationNode(NodeFactory.createToken(SyntaxKind.IMPORT_KEYWORD, - NodeFactory.createEmptyMinutiaeList(), GeneratorUtil.generateMinutiaeListWithWhitespace()), - NodeFactory.createImportOrgNameNode( - NodeFactory.createIdentifierToken(Constants.AZURE_FUNCTIONS_PACKAGE_ORG), - NodeFactory.createToken(SyntaxKind.SLASH_TOKEN)), - NodeFactory.createSeparatedNodeList( - NodeFactory.createIdentifierToken(Constants.AZURE_FUNCTIONS_MODULE_NAME)), - NodeFactory.createImportPrefixNode(NodeFactory.createToken(SyntaxKind.AS_KEYWORD, - GeneratorUtil.generateMinutiaeListWithWhitespace(), - GeneratorUtil.generateMinutiaeListWithWhitespace()), - NodeFactory.createIdentifierToken(Constants.AF_IMPORT_ALIAS)), - NodeFactory.createToken(SyntaxKind.SEMICOLON_TOKEN, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithNewline())); - - ImportDeclarationNode httpImport = - NodeFactory.createImportDeclarationNode(NodeFactory.createToken(SyntaxKind.IMPORT_KEYWORD, - NodeFactory.createEmptyMinutiaeList(), GeneratorUtil.generateMinutiaeListWithWhitespace()), - NodeFactory.createImportOrgNameNode(NodeFactory.createIdentifierToken(Constants.BALLERINA_ORG), - NodeFactory.createToken(SyntaxKind.SLASH_TOKEN)), - NodeFactory.createSeparatedNodeList(NodeFactory.createIdentifierToken("http")), - null, NodeFactory.createToken(SyntaxKind.SEMICOLON_TOKEN, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithNewline())); - List memberDeclarationNodeList = new ArrayList<>(); - QualifiedNameReferenceNode httpListener = - NodeFactory.createQualifiedNameReferenceNode(NodeFactory.createIdentifierToken("http"), - NodeFactory.createToken(SyntaxKind.COLON_TOKEN), - NodeFactory.createIdentifierToken("Listener", NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace())); - QualifiedNameReferenceNode listenerRef = - NodeFactory - .createQualifiedNameReferenceNode(NodeFactory.createIdentifierToken(Constants.AF_IMPORT_ALIAS), - NodeFactory.createToken(SyntaxKind.COLON_TOKEN), - NodeFactory.createIdentifierToken("hl", NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace())); - - ListenerDeclarationNode listener = - NodeFactory.createListenerDeclarationNode(null, NodeFactory.createToken(SyntaxKind.PUBLIC_KEYWORD, - NodeFactory.createEmptyMinutiaeList(), GeneratorUtil.generateMinutiaeListWithWhitespace()), - NodeFactory.createToken(SyntaxKind.LISTENER_KEYWORD, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithWhitespace()), httpListener, - NodeFactory.createIdentifierToken( - "__testListener"), NodeFactory.createToken(SyntaxKind.EQUAL_TOKEN), listenerRef, - NodeFactory.createToken(SyntaxKind.SEMICOLON_TOKEN)); - memberDeclarationNodeList.add(listener); - - memberDeclarationNodeList.addAll(generatedTypeDefinitions.values()); - - QualifiedNameReferenceNode httpService = - NodeFactory.createQualifiedNameReferenceNode(NodeFactory.createIdentifierToken("http"), - NodeFactory.createToken(SyntaxKind.COLON_TOKEN), - NodeFactory.createIdentifierToken("Service", NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace())); - - NodeList absResPathList = NodeFactory.createNodeList(NodeFactory.createToken(SyntaxKind.SLASH_TOKEN)); - - SeparatedNodeList listenerReff = NodeFactory.createSeparatedNodeList(NodeFactory - .createSimpleNameReferenceNode( - NodeFactory.createIdentifierToken("__testListener", NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace()))); - - List resourceFunctions = new ArrayList<>(); - for (FunctionDeploymentContext context : functionDeploymentContexts) { - resourceFunctions.add(createResourceFunction(context)); - resourceFunctions.add(context.getFunction()); - } - - ServiceDeclarationNode serviceDeclarationNode = - NodeFactory.createServiceDeclarationNode(null, NodeFactory.createEmptyNodeList(), - NodeFactory.createToken(SyntaxKind.SERVICE_KEYWORD, NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace()), httpService, absResPathList, - NodeFactory.createToken(SyntaxKind.ON_KEYWORD, generateMinutiaeListWithWhitespace(), - generateMinutiaeListWithWhitespace()), listenerReff, - NodeFactory.createToken(SyntaxKind.OPEN_BRACE_TOKEN), - NodeFactory.createNodeList(resourceFunctions), - NodeFactory.createToken(SyntaxKind.CLOSE_BRACE_TOKEN)); - - memberDeclarationNodeList.add(serviceDeclarationNode); - - NodeList nodeList = NodeFactory.createNodeList(memberDeclarationNodeList); - Token eofToken = NodeFactory.createToken(SyntaxKind.EOF_TOKEN, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithNewline()); - return NodeFactory.createModulePartNode(NodeFactory.createNodeList(afImport, httpImport), nodeList, eofToken); - } - - public static MinutiaeList generateMinutiaeListWithWhitespace() { - return NodeFactory.createMinutiaeList(NodeFactory.createWhitespaceMinutiae(" ")); - } - - public static MinutiaeList generateMinutiaeListWithNewline() { - return NodeFactory.createMinutiaeList(NodeFactory.createWhitespaceMinutiae("\n")); - } - - public static boolean isContextType(ParameterSymbol symbol) { - Optional module = symbol.typeDescriptor().getModule(); - if (module.isEmpty()) { - return false; - } - ModuleID id = module.get().id(); - if (!(id.orgName().equals(Constants.AZURE_FUNCTIONS_PACKAGE_ORG) && - id.moduleName().equals(Constants.AZURE_FUNCTIONS_MODULE_NAME))) { - return false; - } - Optional name = symbol.typeDescriptor().getName(); - if (name.isEmpty()) { - return false; - } - return name.get().equals(Constants.AZURE_FUNCTIONS_CONTEXT_NAME); - } - - public static void addFunctionBinding(FunctionDeploymentContext ctx, Map binding) { - if (binding == null) { - return; - } - JsonArray bindings = (JsonArray) ctx.getFunctionDefinition().get(Constants.FUNCTION_BINDINGS_NAME); - bindings.add(createBindingObject(binding)); - } - - public static JsonObject createBindingObject(Map binding) { - JsonObject obj = new JsonObject(); - for (Map.Entry entry : binding.entrySet()) { - obj.add(entry.getKey(), objectToJson(entry.getValue())); - } - return obj; - } - - public static JsonElement objectToJson(Object obj) { - if (obj instanceof String) { - return new JsonPrimitive((String) obj); - } else if (obj instanceof Number) { - return new JsonPrimitive((Number) obj); - } else if (obj instanceof Boolean) { - return new JsonPrimitive((Boolean) obj); - } else if (obj instanceof String[]) { - JsonArray array = new JsonArray(); - for (String item : (String[]) obj) { - array.add(item); - } - return array; - } else if (obj == null) { - return JsonNull.INSTANCE; - } else { - throw new IllegalStateException("Unsupported type to convert to JSON: " + obj.getClass()); - } - } - - //TODO remove when semantic api supports return type annotations - //https://github.com/ballerina-platform/ballerina-lang/issues/27225 - public static Optional extractAzureFunctionAnnotation(NodeList annons) { - for (AnnotationNode an : annons) { - Node node = an.annotReference(); - if (node.kind() == SyntaxKind.QUALIFIED_NAME_REFERENCE) { - QualifiedNameReferenceNode refNode = (QualifiedNameReferenceNode) node; - String text = refNode.modulePrefix().text(); - if (text.equals(Constants.AF_IMPORT_ALIAS) || text.equals(Constants.AZURE_FUNCTIONS_MODULE_NAME)) { - return Optional.of(an); - } - } - } - return Optional.empty(); - } - - public static Optional extractAzureFunctionAnnotation(List annotations) { - for (AnnotationSymbol annotationSymbol : annotations) { - Optional module = annotationSymbol.getModule(); - if (module.isEmpty()) { - return Optional.empty(); - } - ModuleID id = module.get().id(); - if (id.orgName().equals(Constants.AZURE_FUNCTIONS_PACKAGE_ORG) && - id.moduleName().equals(Constants.AZURE_FUNCTIONS_MODULE_NAME)) { - return Optional.of(annotationSymbol); - } - } - return Optional.empty(); - } - - public static boolean isAzurePkgType(ParameterSymbol variableSymbol, String name) { - Optional module = variableSymbol.typeDescriptor().getModule(); - if (module.isEmpty()) { - return false; - } - ModuleID id = module.get().id(); - if (!(id.orgName().equals(Constants.AZURE_FUNCTIONS_PACKAGE_ORG) && - id.moduleName().equals(Constants.AZURE_FUNCTIONS_MODULE_NAME))) { - return false; - } - Optional name1 = variableSymbol.typeDescriptor().getName(); - if (name1.isEmpty()) { - return false; - } - return name1.get().equals(name); - } - - public static boolean isStringType(ParameterSymbol variableSymbol) { - return variableSymbol.typeDescriptor().typeKind() == TypeDescKind.STRING; - } - - public static boolean isOptionalStringType(ParameterSymbol variableSymbol) { - if (variableSymbol.typeDescriptor().typeKind() == TypeDescKind.UNION) { - UnionTypeSymbol unionTypeSymbol = (UnionTypeSymbol) variableSymbol.typeDescriptor(); - for (TypeSymbol memberTypeDescriptor : unionTypeSymbol.memberTypeDescriptors()) { - if (memberTypeDescriptor.typeKind() == TypeDescKind.STRING) { - return true; - } - } - } - return false; - } - - public static boolean isOptionalByteArrayType(ParameterSymbol variableSymbol) { - if (variableSymbol.typeDescriptor().typeKind() == TypeDescKind.UNION) { - UnionTypeSymbol unionTypeSymbol = (UnionTypeSymbol) variableSymbol.typeDescriptor(); - for (TypeSymbol memberTypeDescriptor : unionTypeSymbol.memberTypeDescriptors()) { - if (memberTypeDescriptor.typeKind() == TypeDescKind.ARRAY) { - ArrayTypeSymbol arrayTypeDescriptor = (ArrayTypeSymbol) memberTypeDescriptor; - if (arrayTypeDescriptor.memberTypeDescriptor().typeKind() == TypeDescKind.BYTE) { - return true; - } - } - } - } - return false; - } - - public static boolean isByteArrayType(ParameterSymbol variableSymbol) { - if (variableSymbol.typeDescriptor().typeKind() == TypeDescKind.ARRAY) { - ArrayTypeSymbol arrayTypeDescriptor = (ArrayTypeSymbol) variableSymbol.typeDescriptor(); - return arrayTypeDescriptor.memberTypeDescriptor().typeKind() == TypeDescKind.BYTE; - } - return false; - } - - public static boolean isOptionalRecordType(ParameterSymbol variableSymbol) { - if (variableSymbol.typeDescriptor().typeKind() == TypeDescKind.UNION) { - UnionTypeSymbol unionTypeSymbol = (UnionTypeSymbol) variableSymbol.typeDescriptor(); - for (TypeSymbol memberTypeDescriptor : unionTypeSymbol.memberTypeDescriptors()) { - if (memberTypeDescriptor.typeKind() == TypeDescKind.TYPE_REFERENCE) { - return true; - } - } - } - return false; - } - - public static boolean isRecordArrayType(ParameterSymbol variableSymbol) { - return isRecordArrayType(variableSymbol.typeDescriptor()); - } - - public static boolean isRecordArrayType(TypeSymbol variableSymbol) { - if (variableSymbol.typeKind() == TypeDescKind.ARRAY) { - ArrayTypeSymbol arrayTypeSymbol = (ArrayTypeSymbol) variableSymbol; - return arrayTypeSymbol.memberTypeDescriptor().typeKind() == TypeDescKind.TYPE_REFERENCE; - } - return false; - } - - public static TypeDefinitionNode createArrayTypeDefinitionNode(ArrayTypeDescriptorNode arrayTypeDescriptorNode) { - String typeName = ((SimpleNameReferenceNode) arrayTypeDescriptorNode.memberTypeDesc()).name().text(); - return NodeFactory.createTypeDefinitionNode(null, null, NodeFactory.createToken(SyntaxKind.TYPE_KEYWORD, - NodeFactory.createEmptyMinutiaeList(), generateMinutiaeListWithWhitespace()), - NodeFactory.createIdentifierToken(typeName + "ArrayGenerated", NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace()), arrayTypeDescriptorNode, - NodeFactory.createToken(SyntaxKind.SEMICOLON_TOKEN)); - } - - public static TypeDefinitionNode createOptionalTypeDefinitionNode( - OptionalTypeDescriptorNode optionalTypeDescriptorNode) { - String typeName = ((SimpleNameReferenceNode) optionalTypeDescriptorNode.typeDescriptor()).name().text(); - return NodeFactory.createTypeDefinitionNode(null, null, NodeFactory.createToken(SyntaxKind.TYPE_KEYWORD, - NodeFactory.createEmptyMinutiaeList(), generateMinutiaeListWithWhitespace()), - NodeFactory.createIdentifierToken(typeName + "OptionalGenerated", NodeFactory.createEmptyMinutiaeList(), - generateMinutiaeListWithWhitespace()), - optionalTypeDescriptorNode, NodeFactory.createToken(SyntaxKind.SEMICOLON_TOKEN)); - } - - public static boolean isJsonType(ParameterSymbol variableSymbol) { - return variableSymbol.typeDescriptor().typeKind() == TypeDescKind.JSON; - } - - public static Map extractAnnotationKeyValues(AnnotationNode annotation) - throws AzureFunctionsException { - if (annotation.annotValue().isEmpty()) { - return Collections.emptyMap(); - } - MappingConstructorExpressionNode mappingConstructorExpressionNode = annotation.annotValue().get(); - Map annonMap = new HashMap<>(); - for (MappingFieldNode field : mappingConstructorExpressionNode.fields()) { - if (field.kind() != SyntaxKind.SPECIFIC_FIELD) { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(field.location(), "AZ0009", - "specific.field.required", DiagnosticSeverity.ERROR, "specific field expected for " + - "annotation field")); - } - SpecificFieldNode keyValue = (SpecificFieldNode) field; - Node node = keyValue.fieldName(); - if (node.kind() != SyntaxKind.IDENTIFIER_TOKEN) { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(field.location(), "AZ0010", - "identifier.token.expected", DiagnosticSeverity.ERROR, "identifier token expected for key")); - } - String key = ((IdentifierToken) node).text(); - if (keyValue.valueExpr().isEmpty()) { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(field.location(), "AZ0011", - "annotation.value.expected", DiagnosticSeverity.ERROR, "annotation value expected")); - } - ExpressionNode valueExpr = keyValue.valueExpr().get(); - if (valueExpr.kind() != SyntaxKind.STRING_LITERAL) { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(field.location(), "AZ0011", - "unsupported.annotation.value", DiagnosticSeverity.ERROR, - "unsupported annotation value " + valueExpr.kind())); - } - String value = ((BasicLiteralNode) valueExpr).literalToken().text(); - value = value.substring(1, value.length() - 1); - - annonMap.put(key, value); - } - return annonMap; - } - - public static TypeSymbol getMainParamType(TypeSymbol typeSymbol) { - if (typeSymbol.typeKind() == TypeDescKind.UNION) { - UnionTypeSymbol unionTypeSymbol = (UnionTypeSymbol) typeSymbol; - for (TypeSymbol memberTypeDescriptor : unionTypeSymbol.memberTypeDescriptors()) { - if (!(memberTypeDescriptor.typeKind() == TypeDescKind.ERROR || - memberTypeDescriptor.typeKind() == TypeDescKind.NIL)) { - return memberTypeDescriptor; - } - } - } - return typeSymbol; - } - - public static SimpleNameReferenceNode addAzurePkgRecordVarDef(FunctionDeploymentContext ctx, String type, - String name) { - QualifiedNameReferenceNode typeDesc = - NodeFactory - .createQualifiedNameReferenceNode(NodeFactory.createIdentifierToken(Constants.AF_IMPORT_ALIAS), - NodeFactory.createToken(SyntaxKind.COLON_TOKEN), - NodeFactory.createIdentifierToken(type)); - TypedBindingPatternNode typedBindingPatternNode = NodeFactory.createTypedBindingPatternNode(typeDesc, - NodeFactory.createCaptureBindingPatternNode(NodeFactory.createIdentifierToken(name, - generateMinutiaeListWithWhitespace(), NodeFactory.createEmptyMinutiaeList()))); - MappingConstructorExpressionNode emptyInit = - NodeFactory.createMappingConstructorExpressionNode(NodeFactory.createToken(SyntaxKind.OPEN_BRACE_TOKEN), - NodeFactory.createSeparatedNodeList(), NodeFactory.createToken(SyntaxKind.CLOSE_BRACE_TOKEN)); - VariableDeclarationNode variableDeclarationNode = NodeFactory - .createVariableDeclarationNode(NodeFactory.createEmptyNodeList(), null, typedBindingPatternNode, - NodeFactory.createToken(SyntaxKind.EQUAL_TOKEN), emptyInit, - NodeFactory.createToken(SyntaxKind.SEMICOLON_TOKEN, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithNewline())); - - FunctionDefinitionNode function = ctx.getFunction(); - ctx.setFunction(addStatementToFunctionBody(variableDeclarationNode, function)); - return NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken(name)); - } - - private static FunctionDefinitionNode addStatementToFunctionBody(StatementNode statementNode, - FunctionDefinitionNode function) { - FunctionBodyBlockNode functionBodyBlockNode = (FunctionBodyBlockNode) function.functionBody(); - NodeList newBodyStatements = functionBodyBlockNode.statements().add(statementNode); - FunctionBodyBlockNode newFunctionBodyBlock = - functionBodyBlockNode.modify().withStatements(newBodyStatements).apply(); - return function.modify().withFunctionBody(newFunctionBodyBlock).apply(); - } - - public static ExpressionNode createFunctionInvocationNode(String functionName, PositionalArgumentNode... args) { - SimpleNameReferenceNode simpleNameReferenceNode = - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken(functionName)); - SeparatedNodeList separatedNodeList = getFunctionParamList(args); - return NodeFactory.createFunctionCallExpressionNode(simpleNameReferenceNode, - NodeFactory.createToken(SyntaxKind.OPEN_PAREN_TOKEN), separatedNodeList, - NodeFactory.createToken(SyntaxKind.CLOSE_PAREN_TOKEN)); - } - - public static ExpressionNode createMethodInvocationNode(String functionName, PositionalArgumentNode... args) { - SimpleNameReferenceNode simpleNameReferenceNode = - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken(functionName)); - SimpleNameReferenceNode selfRef = - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken("self")); - SeparatedNodeList separatedNodeList = getFunctionParamList(args); - return NodeFactory.createMethodCallExpressionNode(selfRef, NodeFactory.createToken(SyntaxKind.DOT_TOKEN), - simpleNameReferenceNode, NodeFactory.createToken(SyntaxKind.OPEN_PAREN_TOKEN), separatedNodeList, - NodeFactory.createToken(SyntaxKind.CLOSE_PAREN_TOKEN)); - } - - public static ExpressionNode createAfFunctionInvocationNode(String functionName, - boolean checked, PositionalArgumentNode... args) { - QualifiedNameReferenceNode qualifiedNameReferenceNode = - NodeFactory - .createQualifiedNameReferenceNode(NodeFactory.createIdentifierToken(Constants.AF_IMPORT_ALIAS), - NodeFactory.createToken(SyntaxKind.COLON_TOKEN), - NodeFactory.createIdentifierToken(functionName)); - SeparatedNodeList separatedNodeList = getFunctionParamList(args); - - FunctionCallExpressionNode expression = - NodeFactory.createFunctionCallExpressionNode(qualifiedNameReferenceNode, - NodeFactory.createToken(SyntaxKind.OPEN_PAREN_TOKEN), separatedNodeList, - NodeFactory.createToken(SyntaxKind.CLOSE_PAREN_TOKEN)); - - if (checked) { - return NodeFactory.createCheckExpressionNode(SyntaxKind.CHECK_EXPRESSION, - NodeFactory.createToken(SyntaxKind.CHECK_KEYWORD, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithWhitespace()), - expression); - } - return expression; - } - - private static SeparatedNodeList getFunctionParamList(PositionalArgumentNode... args) { - List nodeList = new ArrayList<>(); - for (PositionalArgumentNode arg : args) { - nodeList.add(arg); - nodeList.add(NodeFactory.createToken(SyntaxKind.COMMA_TOKEN)); - } - if (args.length > 0) { - nodeList.remove(nodeList.size() - 1); - } - return NodeFactory.createSeparatedNodeList(nodeList); - } - - /** - * Calls internal function in Azure Functions module and adds into function body. - * - * @param ctx Function Deployment Context - * @param name name of the internal function needs to be called - * @param checked is checking required - * @param exprs parameter arguments - */ - public static void addAzurePkgFunctionCallStatement(FunctionDeploymentContext ctx, String name, - boolean checked, PositionalArgumentNode... exprs) { - NilTypeDescriptorNode nilTypeDescriptorNode = - NodeFactory.createNilTypeDescriptorNode(NodeFactory.createToken(SyntaxKind.OPEN_PAREN_TOKEN), - NodeFactory.createToken(SyntaxKind.CLOSE_PAREN_TOKEN, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithWhitespace())); - addFunctionCallStatement(nilTypeDescriptorNode, ctx, createAfFunctionInvocationNode(name, false, exprs), - checked); - } - - public static SimpleNameReferenceNode createVariableRef(String varName) { - return NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken(varName)); - } - - public static BasicLiteralNode createStringLiteral(String content) { - return NodeFactory - .createBasicLiteralNode(SyntaxKind.STRING_LITERAL, NodeFactory - .createLiteralValueToken(SyntaxKind.STRING_LITERAL_TOKEN, "\"" + content + "\"", - NodeFactory.createEmptyMinutiaeList(), - NodeFactory.createEmptyMinutiaeList())); - } - - /** - * Adds Function call statement to the function body. - * - * @param typeDescriptorNode type of the left hand side - * @param ctx Function Deployment Context - * @param inv expression of the right side - * @param checked is checking required for the expression - * @return variable name - */ - public static String addFunctionCallStatement(TypeDescriptorNode typeDescriptorNode, FunctionDeploymentContext ctx, - ExpressionNode inv, boolean checked) { - ExpressionNode expr; - if (checked) { - expr = NodeFactory.createCheckExpressionNode(SyntaxKind.CHECK_EXPRESSION, - NodeFactory.createToken(SyntaxKind.CHECK_KEYWORD, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithWhitespace()), inv); - } else { - expr = inv; - } - - if (typeDescriptorNode.kind() == SyntaxKind.NIL_TYPE_DESC) { - createWildcardAssignmentNode(ctx, expr); - return "_"; - } - if (typeDescriptorNode.kind() == SyntaxKind.OPTIONAL_TYPE_DESC) { - Node typeDescriptor = ((OptionalTypeDescriptorNode) typeDescriptorNode).typeDescriptor(); - if (typeDescriptor.kind() == SyntaxKind.ERROR_TYPE_DESC) { - createWildcardAssignmentNode(ctx, expr); - return "_"; - } - } - if (typeDescriptorNode.kind() == SyntaxKind.OPTIONAL_TYPE_DESC) { - createWildcardAssignmentNode(ctx, expr); - return "_"; - } - String varName = ctx.getNextVarName(); - CaptureBindingPatternNode captureBindingPatternNode = - NodeFactory.createCaptureBindingPatternNode(NodeFactory.createIdentifierToken(varName, - generateMinutiaeListWithWhitespace(), NodeFactory.createEmptyMinutiaeList())); - TypedBindingPatternNode typedBindingPatternNode = - NodeFactory.createTypedBindingPatternNode(typeDescriptorNode, captureBindingPatternNode); - VariableDeclarationNode variableDeclarationNode = NodeFactory - .createVariableDeclarationNode(NodeFactory.createEmptyNodeList(), null, typedBindingPatternNode, - NodeFactory.createToken(SyntaxKind.EQUAL_TOKEN), expr, - NodeFactory.createToken(SyntaxKind.SEMICOLON_TOKEN, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithNewline())); - ctx.setFunction(addStatementToFunctionBody(variableDeclarationNode, ctx.getFunction())); - return varName; - } - - private static void createWildcardAssignmentNode(FunctionDeploymentContext ctx, ExpressionNode expr) { - WildcardBindingPatternNode wildcardBindingPatternNode = NodeFactory - .createWildcardBindingPatternNode(NodeFactory.createToken(SyntaxKind.UNDERSCORE_KEYWORD)); - AssignmentStatementNode assignmentStatementNode = NodeFactory - .createAssignmentStatementNode(wildcardBindingPatternNode, - NodeFactory.createToken(SyntaxKind.EQUAL_TOKEN), expr, - NodeFactory.createToken(SyntaxKind.SEMICOLON_TOKEN, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithNewline())); - ctx.setFunction(addStatementToFunctionBody(assignmentStatementNode, ctx.getFunction())); - } - - /** - * Creates Azure Function Diagnostic object for unexpected syntax in ballerina documents. - * - * @param location location of the node - * @param code diagnostic code - * @param template diagnostic message template - * @param severity severity of the diagnostic - * @param message message if the diagnostic - * @return Azure Function diagnostic - */ - public static Diagnostic getAFDiagnostic(Location location, String code, - String template, DiagnosticSeverity severity, String message) { - DiagnosticInfo diagnosticInfo = new DiagnosticInfo(code, template, severity); - return new AzureFunctionDiagnostics(location, diagnosticInfo, message); - } - - public static TypeDescriptorNode getCheckedReturnTypeDescOfOriginalFunction(FunctionDefinitionNode functionNode) { - Optional returnTypeDescriptorNode = - functionNode.functionSignature().returnTypeDesc(); - if (returnTypeDescriptorNode.isEmpty()) { - return NodeFactory.createNilTypeDescriptorNode(NodeFactory.createToken(SyntaxKind.OPEN_PAREN_TOKEN), - NodeFactory.createToken(SyntaxKind.CLOSE_PAREN_TOKEN, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithWhitespace())); - } - Node returnType = returnTypeDescriptorNode.get().type(); - if (!(returnType instanceof TypeDescriptorNode)) { - return NodeFactory.createNilTypeDescriptorNode(NodeFactory.createToken(SyntaxKind.OPEN_PAREN_TOKEN), - NodeFactory.createToken(SyntaxKind.CLOSE_PAREN_TOKEN, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithWhitespace())); - } - - return getCheckedTypeDesc((TypeDescriptorNode) returnType); - } - - public static boolean isCheckingRequiredForOriginalFunction(FunctionDefinitionNode functionDefinitionNode) { - Optional returnTypeDescriptorNode = - functionDefinitionNode.functionSignature().returnTypeDesc(); - if (returnTypeDescriptorNode.isEmpty()) { - return false; - } - TypeDescriptorNode typeDescriptorNode = - (TypeDescriptorNode) returnTypeDescriptorNode.get().type(); - - if (typeDescriptorNode.kind() == SyntaxKind.UNION_TYPE_DESC) { - UnionTypeDescriptorNode unionTypeDescriptorNode = (UnionTypeDescriptorNode) typeDescriptorNode; - TypeDescriptorNode leftTypeDesc = unionTypeDescriptorNode.leftTypeDesc(); - if (leftTypeDesc.kind() == SyntaxKind.ERROR_TYPE_DESC) { - return true; - } - TypeDescriptorNode rightTypeDesc = unionTypeDescriptorNode.rightTypeDesc(); - return rightTypeDesc.kind() == SyntaxKind.ERROR_TYPE_DESC; - } - if (typeDescriptorNode.kind() == SyntaxKind.OPTIONAL_TYPE_DESC) { - OptionalTypeDescriptorNode optionalTypeDescriptorNode = (OptionalTypeDescriptorNode) typeDescriptorNode; - Node node = optionalTypeDescriptorNode.typeDescriptor(); - if (node.kind() == SyntaxKind.ERROR_TYPE_DESC) { - return true; - } - } - return typeDescriptorNode.kind() == SyntaxKind.ERROR_TYPE_DESC; - } - - public static TypeDescriptorNode getCheckedTypeDesc(TypeDescriptorNode typeDescriptorNode) { - if (typeDescriptorNode.kind() == SyntaxKind.UNION_TYPE_DESC) { - UnionTypeDescriptorNode unionTypeDescriptorNode = (UnionTypeDescriptorNode) typeDescriptorNode; - TypeDescriptorNode leftTypeDesc = getCheckedTypeDesc(unionTypeDescriptorNode.leftTypeDesc()); - if (leftTypeDesc.kind() != SyntaxKind.NIL_TYPE_DESC) { - return leftTypeDesc; - } - TypeDescriptorNode rightTypeDesc = getCheckedTypeDesc(unionTypeDescriptorNode.rightTypeDesc()); - if (rightTypeDesc.kind() != SyntaxKind.NIL_TYPE_DESC) { - return rightTypeDesc; - } - - return leftTypeDesc; - } - if (typeDescriptorNode.kind() == SyntaxKind.ERROR_TYPE_DESC) { - return NodeFactory.createNilTypeDescriptorNode(NodeFactory.createToken(SyntaxKind.OPEN_PAREN_TOKEN), - NodeFactory.createToken(SyntaxKind.CLOSE_PAREN_TOKEN, NodeFactory.createEmptyMinutiaeList(), - GeneratorUtil.generateMinutiaeListWithWhitespace())); - } - return typeDescriptorNode; - } - - public static boolean isIsolatedFunction(FunctionDefinitionNode functionDefinitionNode) { - NodeList tokens = functionDefinitionNode.qualifierList(); - for (Token token: tokens) { - if (token.kind() == SyntaxKind.ISOLATED_KEYWORD) { - return true; - } - } - return false; - } -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/HandlerFactory.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/HandlerFactory.java deleted file mode 100644 index b5f19142..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/HandlerFactory.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - -import io.ballerina.compiler.api.SemanticModel; -import io.ballerina.compiler.api.symbols.AnnotationSymbol; -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.api.symbols.Symbol; -import io.ballerina.compiler.api.symbols.SymbolKind; -import io.ballerina.compiler.api.symbols.TypeSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.Node; -import io.ballerina.compiler.syntax.tree.NodeList; -import io.ballerina.compiler.syntax.tree.ParameterNode; -import io.ballerina.compiler.syntax.tree.QualifiedNameReferenceNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.compiler.syntax.tree.ReturnTypeDescriptorNode; -import io.ballerina.compiler.syntax.tree.SyntaxKind; -import io.ballerina.compiler.syntax.tree.TypeDefinitionNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.handlers.blob.BlobInputParameterHandler; -import org.ballerinax.azurefunctions.generator.handlers.blob.BlobOutputParameterHandler; -import org.ballerinax.azurefunctions.generator.handlers.blob.BlobTriggerParameterHandler; -import org.ballerinax.azurefunctions.generator.handlers.context.ContextParameterHandler; -import org.ballerinax.azurefunctions.generator.handlers.cosmosdb.CosmosDBInputParameterHandler; -import org.ballerinax.azurefunctions.generator.handlers.cosmosdb.CosmosDBReturnHandler; -import org.ballerinax.azurefunctions.generator.handlers.cosmosdb.CosmosDBTriggerHandler; -import org.ballerinax.azurefunctions.generator.handlers.http.HTTPOutputParameterHandler; -import org.ballerinax.azurefunctions.generator.handlers.http.HTTPReturnHandler; -import org.ballerinax.azurefunctions.generator.handlers.http.HTTPTriggerParameterHandler; -import org.ballerinax.azurefunctions.generator.handlers.metadata.MetadataBindingParameterHandler; -import org.ballerinax.azurefunctions.generator.handlers.queue.QueueOutputParameterHandler; -import org.ballerinax.azurefunctions.generator.handlers.queue.QueueTriggerHandler; -import org.ballerinax.azurefunctions.generator.handlers.timer.TimerTriggerHandler; -import org.ballerinax.azurefunctions.generator.handlers.twilio.TwilioSmsOutputParameterHandler; - -import java.util.Map; -import java.util.Optional; - -/** - * Factory class to create parameter and return handlers. - */ -public class HandlerFactory { - - public static ParameterHandler createParameterHandler(ParameterNode param, SemanticModel semanticModel, - Map generatedTypeDefinitions) - throws AzureFunctionsException { - if (param.kind() != SyntaxKind.REQUIRED_PARAM) { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(param.location(), "AZ0004", - "required.param.supported", DiagnosticSeverity.ERROR, "only required params are supported")); - } - RequiredParameterNode requiredParameterNode = (RequiredParameterNode) param; - if (requiredParameterNode.paramName().isEmpty()) { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(param.location(), "AZ0005", - "required.param.name", DiagnosticSeverity.ERROR, "param name is required")); - } - Optional paramSymbol = semanticModel.symbol(requiredParameterNode.paramName().get()); - if (paramSymbol.isEmpty() || paramSymbol.get().kind() != SymbolKind.PARAMETER) { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(param.location(), "AZ0010", - "symbol.not.found", DiagnosticSeverity.ERROR, "parameter symbol not found")); - } - ParameterSymbol variableSymbol = (ParameterSymbol) paramSymbol.get(); - if (GeneratorUtil.isContextType(variableSymbol)) { - return new ContextParameterHandler(variableSymbol, requiredParameterNode); - } - - Optional annotationNode = - GeneratorUtil.extractAzureFunctionAnnotation(variableSymbol.annotations()); - if (annotationNode.isEmpty()) { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(requiredParameterNode.location(), "AZ0006", - "missing.required.annotation", DiagnosticSeverity.ERROR, "azure functions annotation is required")); - } - - String annotationName = annotationNode.get().getName().orElseThrow(); - switch (annotationName) { - case "HTTPOutput": - return new HTTPOutputParameterHandler(variableSymbol, requiredParameterNode); - case "HTTPTrigger": - return new HTTPTriggerParameterHandler(variableSymbol, requiredParameterNode); - case "QueueOutput": - return new QueueOutputParameterHandler(variableSymbol, requiredParameterNode); - case "QueueTrigger": - return new QueueTriggerHandler(variableSymbol, requiredParameterNode); - case "TimerTrigger": - return new TimerTriggerHandler(variableSymbol, requiredParameterNode); - case "BlobTrigger": - return new BlobTriggerParameterHandler(variableSymbol, requiredParameterNode); - case "BlobInput": - return new BlobInputParameterHandler(variableSymbol, requiredParameterNode); - case "BlobOutput": - return new BlobOutputParameterHandler(variableSymbol, requiredParameterNode); - case "TwilioSmsOutput": - return new TwilioSmsOutputParameterHandler(variableSymbol, requiredParameterNode); - case "BindingName": - return new MetadataBindingParameterHandler(variableSymbol, requiredParameterNode); - case "CosmosDBTrigger": - return new CosmosDBTriggerHandler(variableSymbol, requiredParameterNode, - generatedTypeDefinitions); - case "CosmosDBInput": - return new CosmosDBInputParameterHandler(variableSymbol, requiredParameterNode, - generatedTypeDefinitions); - default: - throw new AzureFunctionsException( - GeneratorUtil.getAFDiagnostic(annotationNode.get().getLocation().orElseThrow(), - "AZ0006", "unsupported.param.handler", DiagnosticSeverity.ERROR, - "param handler not found for the type: " + annotationName)); - } - } - - public static ReturnHandler createReturnHandler(TypeSymbol symbol, - ReturnTypeDescriptorNode returnTypeDescriptorNode) - throws AzureFunctionsException { - //TODO avoid using syntax tree and use semantic api instead when the its supported. - //https://github.com/ballerina-platform/ballerina-lang/issues/27225 - TypeSymbol retType = GeneratorUtil.getMainParamType(symbol); - NodeList annotations = returnTypeDescriptorNode.annotations(); - Optional azureAnnotations = GeneratorUtil.extractAzureFunctionAnnotation(annotations); - if (azureAnnotations.isEmpty()) { - return null; - } - Node annotReference = azureAnnotations.get().annotReference(); - if (annotReference.kind() != SyntaxKind.QUALIFIED_NAME_REFERENCE) { - throw new AzureFunctionsException( - GeneratorUtil.getAFDiagnostic(annotReference.location(), "AZ0002", "unexpected.node.type", - DiagnosticSeverity.ERROR, "unexpected node type")); - } - - String name = ((QualifiedNameReferenceNode) annotReference).identifier().text(); - if ("HTTPOutput".equals(name)) { - return new HTTPReturnHandler(retType, azureAnnotations.get()); - } else if ("CosmosDBOutput".equals(name)) { - return new CosmosDBReturnHandler(retType, azureAnnotations.get()); - } else { - throw new AzureFunctionsException( - GeneratorUtil.getAFDiagnostic(annotReference.location(), "AZ0001", "unsupported.return.handler", - DiagnosticSeverity.ERROR, "return handler not found for the type: " + symbol.signature())); - } - } -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/ParameterHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/ParameterHandler.java deleted file mode 100644 index 2e3337a9..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/ParameterHandler.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - -import io.ballerina.compiler.syntax.tree.ExpressionNode; - -/** - * Represents an Azure function parameter handler. - */ -public interface ParameterHandler { - - /** - * Initializes the {@link ParameterHandler}. This can be used for any initialization operations before - * the preInvocationProcess call is made. - * - * @param context The handler context - * @throws AzureFunctionsException thrown if an error occurs - */ - void init(FunctionDeploymentContext context) throws AzureFunctionsException; - - /** - * Called when generating the azure function invocation statement. This will be used for scenarios - * such as generating the parameter values for the function invocation by consuming the incoming HTTP - * data, which can be accessed using the context. After any required statement are generated, this must - * return an expression which is used for the parameter value of the azure function call. - * - * @return The expression which represents the parameter value - * @throws AzureFunctionsException thrown if an error occurs - */ - ExpressionNode invocationProcess() throws AzureFunctionsException; - - /** - * Called after the function call statement is generated. This can be used for scenarios like processing - * any output bindings, where we need to extra data from the parameter and populate the output JSON value - * that is referenced using the context instance. - */ - void postInvocationProcess() throws AzureFunctionsException; - - /** - * Retreives the binding type. - * - * @return The binding type - */ - BindingType getBindingType(); - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/ReturnHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/ReturnHandler.java deleted file mode 100644 index 55dca77b..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/ReturnHandler.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator; - -import io.ballerina.compiler.syntax.tree.ExpressionNode; - -/** - * Represents an Azure function return value handler. - */ -public interface ReturnHandler { - - /** - * Initializes the {@link ReturnHandler}. This can be used for any - * initialization operations before the invocationVariable call is made. - * - * @param context The handler context - * - * @throws AzureFunctionsException thrown if an error occurs - */ - public void init(FunctionDeploymentContext context) throws AzureFunctionsException; - - /** - * Called after the function invocation statement is done, and the return value is passed here - * as an expression to be use for further statement creation to populate the JSON result. - * - * @param returnValueExpr The function invocation return value expression - * - * @throws AzureFunctionsException thrown if an error occurs - */ - public void postInvocationProcess(ExpressionNode returnValueExpr) throws AzureFunctionsException; - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/AbstractParameterHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/AbstractParameterHandler.java deleted file mode 100644 index 477f21fb..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/AbstractParameterHandler.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.FunctionDeploymentContext; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.ParameterHandler; - -import java.util.Map; - -/** - * Abstract class with common operations implemented for {@link ParameterHandler}. - */ -public abstract class AbstractParameterHandler implements ParameterHandler { - - protected FunctionDeploymentContext ctx; - - protected RequiredParameterNode param; - - protected String name; - - protected BindingType bindingType; - - protected ParameterSymbol variableSymbol; - - public AbstractParameterHandler(ParameterSymbol variableSymbol, RequiredParameterNode param, - BindingType bindingType) { - this.variableSymbol = variableSymbol; - this.param = param; - this.name = this.param.paramName().get().text(); - this.bindingType = bindingType; - } - - public void init(FunctionDeploymentContext ctx) throws AzureFunctionsException { - this.ctx = ctx; - this.processBinding(); - } - - private String extractBindingDirection() { - if (BindingType.INPUT.equals(this.bindingType) || BindingType.TRIGGER.equals(this.bindingType)) { - return "in"; - } else { - return "out"; - } - } - - private void processBinding() throws AzureFunctionsException { - Map binding = this.generateBinding(); - if (binding == null) { - return; - } - binding.put("direction", this.extractBindingDirection()); - binding.put("name", this.name); - GeneratorUtil.addFunctionBinding(this.ctx, binding); - } - - public BindingType getBindingType() { - return bindingType; - } - - public abstract Map generateBinding() throws AzureFunctionsException; - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/AbstractReturnHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/AbstractReturnHandler.java deleted file mode 100644 index 4e9d809e..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/AbstractReturnHandler.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers; - -import io.ballerina.compiler.api.symbols.TypeSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.FunctionDeploymentContext; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.ReturnHandler; - -import java.util.Map; - -/** - * Abstract class with common operations implemented for {@link ReturnHandler}. - */ -public abstract class AbstractReturnHandler implements ReturnHandler { - - protected FunctionDeploymentContext ctx; - - protected TypeSymbol retType; - - protected AnnotationNode annotation; - - public AbstractReturnHandler(TypeSymbol retType, AnnotationNode annotation) { - this.retType = retType; - this.annotation = annotation; - } - - public void init(FunctionDeploymentContext ctx) throws AzureFunctionsException { - this.ctx = ctx; - this.processBinding(); - } - - private void processBinding() throws AzureFunctionsException { - Map binding = this.generateBinding(); - if (binding == null) { - return; - } - binding.put("direction", "out"); - binding.put("name", "$return"); - GeneratorUtil.addFunctionBinding(this.ctx, binding); - } - - public abstract Map generateBinding() throws AzureFunctionsException; - - public AnnotationNode getAnnotation() { - return annotation; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/blob/BlobInputParameterHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/blob/BlobInputParameterHandler.java deleted file mode 100644 index 2266780e..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/blob/BlobInputParameterHandler.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.blob; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractParameterHandler; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Optional; - -/** - * Implementation for the input parameter handler annotation "@BlobInput". - */ -public class BlobInputParameterHandler extends AbstractParameterHandler { - - public BlobInputParameterHandler(ParameterSymbol variableSymbol, RequiredParameterNode param) { - super(variableSymbol, param, BindingType.INPUT); - } - - @Override - public ExpressionNode invocationProcess() throws AzureFunctionsException { - PositionalArgumentNode paramsArg = NodeFactory.createPositionalArgumentNode( - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken(Constants.PARAMS))); - if (GeneratorUtil.isOptionalByteArrayType(this.variableSymbol)) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - return GeneratorUtil - .createAfFunctionInvocationNode("getOptionalBytesFromInputData", true, paramsArg, stringArg); - } else if (GeneratorUtil.isOptionalStringType(this.variableSymbol)) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - return GeneratorUtil - .createAfFunctionInvocationNode("getOptionalStringConvertedBytesFromInputData", true, paramsArg, - stringArg); - } else { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(this.param.typeName().location(), "AZ0008", - "unsupported.param.type", DiagnosticSeverity.ERROR, - "type '" + this.param.typeName().toString() + "'" + - " is not supported")); - } - } - - @Override - public void postInvocationProcess() throws AzureFunctionsException { - } - - @Override - public Map generateBinding() throws AzureFunctionsException { - Map binding = new LinkedHashMap<>(); - Optional annotationNode = GeneratorUtil.extractAzureFunctionAnnotation(param.annotations()); - Map annonMap = GeneratorUtil.extractAnnotationKeyValues(annotationNode.orElseThrow()); - binding.put("type", "blob"); - binding.put("path", annonMap.get("path")); - binding.put("dataType", "binary"); - String connection = (String) annonMap.get("connection"); - if (connection == null) { - connection = Constants.DEFAULT_STORAGE_CONNECTION_NAME; - } - binding.put("connection", connection); - return binding; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/blob/BlobOutputParameterHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/blob/BlobOutputParameterHandler.java deleted file mode 100644 index 3d2f965d..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/blob/BlobOutputParameterHandler.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.blob; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractParameterHandler; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Optional; - -/** - * Implementation for the output parameter handler annotation "@BlobOutput". - */ -public class BlobOutputParameterHandler extends AbstractParameterHandler { - - private SimpleNameReferenceNode var; - - public BlobOutputParameterHandler(ParameterSymbol variableSymbol, RequiredParameterNode param) { - super(variableSymbol, param, BindingType.OUTPUT); - } - - @Override - public ExpressionNode invocationProcess() throws AzureFunctionsException { - if (GeneratorUtil.isAzurePkgType(this.variableSymbol, "BytesOutputBinding")) { - this.var = GeneratorUtil.addAzurePkgRecordVarDef(this.ctx, "BytesOutputBinding", this.ctx.getNextVarName()); - } else if (GeneratorUtil.isAzurePkgType(this.variableSymbol, "StringOutputBinding")) { - this.var = GeneratorUtil - .addAzurePkgRecordVarDef(this.ctx, "StringOutputBinding", this.ctx.getNextVarName()); - } else { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(param.typeName().location(), "AZ0007", - "required.type", DiagnosticSeverity.ERROR, - "Type must be 'BytesOutputBinding' or 'StringOutputBinding'")); - } - return this.var; - } - - @Override - public void postInvocationProcess() throws AzureFunctionsException { - PositionalArgumentNode paramsArg = NodeFactory.createPositionalArgumentNode( - GeneratorUtil.createVariableRef("params")); - - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - - PositionalArgumentNode varArg = NodeFactory.createPositionalArgumentNode( - GeneratorUtil.createVariableRef(var.name().text())); - - GeneratorUtil.addAzurePkgFunctionCallStatement(this.ctx, "setBlobOutput", true, paramsArg, stringArg, varArg); - } - - @Override - public Map generateBinding() throws AzureFunctionsException { - Map binding = new LinkedHashMap<>(); - Optional annotationNode = GeneratorUtil.extractAzureFunctionAnnotation(param.annotations()); - Map annonMap = GeneratorUtil.extractAnnotationKeyValues(annotationNode.orElseThrow()); - binding.put("type", "blob"); - binding.put("path", annonMap.get("path")); - // According to: https://github.com/Azure/azure-functions-host/issues/6091 - binding.put("dataType", "string"); - String connection = (String) annonMap.get("connection"); - if (connection == null) { - connection = Constants.DEFAULT_STORAGE_CONNECTION_NAME; - } - binding.put("connection", connection); - return binding; - - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/blob/BlobTriggerParameterHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/blob/BlobTriggerParameterHandler.java deleted file mode 100644 index 135451b3..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/blob/BlobTriggerParameterHandler.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.blob; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractParameterHandler; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Optional; - -/** - * Implementation for the input parameter handler annotation "@BlobTrigger". - */ -public class BlobTriggerParameterHandler extends AbstractParameterHandler { - - public BlobTriggerParameterHandler(ParameterSymbol variableSymbol, RequiredParameterNode param) { - super(variableSymbol, param, BindingType.TRIGGER); - } - - @Override - public ExpressionNode invocationProcess() throws AzureFunctionsException { - PositionalArgumentNode paramsArg = NodeFactory.createPositionalArgumentNode( - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken(Constants.PARAMS))); - if (GeneratorUtil.isByteArrayType(this.variableSymbol)) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - return GeneratorUtil.createAfFunctionInvocationNode("getBytesFromInputData", true, paramsArg, stringArg); - } else if (GeneratorUtil.isStringType(this.variableSymbol)) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - return GeneratorUtil.createAfFunctionInvocationNode("getStringConvertedBytesFromInputData", true, paramsArg, - stringArg); - } else { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(this.param.typeName().location(), "AZ0008", - "unsupported.param.type", DiagnosticSeverity.ERROR, - "type '" + this.param.typeName().toString() + "'" + - " is not supported")); - } - } - - @Override - public void postInvocationProcess() throws AzureFunctionsException { - } - - @Override - public Map generateBinding() throws AzureFunctionsException { - Map binding = new LinkedHashMap<>(); - Optional annotationNode = GeneratorUtil.extractAzureFunctionAnnotation(param.annotations()); - Map annonMap = GeneratorUtil.extractAnnotationKeyValues(annotationNode.orElseThrow()); - binding.put("type", "blobTrigger"); - binding.put("path", annonMap.get("path")); - binding.put("dataType", "binary"); - String connection = (String) annonMap.get("connection"); - if (connection == null) { - connection = Constants.DEFAULT_STORAGE_CONNECTION_NAME; - } - binding.put("connection", connection); - return binding; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/context/ContextParameterHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/context/ContextParameterHandler.java deleted file mode 100644 index 58d496c3..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/context/ContextParameterHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.context; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.compiler.syntax.tree.SyntaxKind; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractParameterHandler; - -import java.util.Map; - -/** - * Implementation for the input parameter handler for the Context object. - */ -public class ContextParameterHandler extends AbstractParameterHandler { - - public ContextParameterHandler(ParameterSymbol variableSymbol, RequiredParameterNode param) { - super(variableSymbol, param, BindingType.CONTEXT); - } - - @Override - public ExpressionNode invocationProcess() throws AzureFunctionsException { - PositionalArgumentNode params = NodeFactory.createPositionalArgumentNode( - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken("params"))); - PositionalArgumentNode trueArg = NodeFactory.createPositionalArgumentNode( - NodeFactory.createBasicLiteralNode(SyntaxKind.BOOLEAN_LITERAL, - NodeFactory.createToken(SyntaxKind.TRUE_KEYWORD))); - - return GeneratorUtil.createAfFunctionInvocationNode("createContext", true, params, trueArg); - } - - @Override - public void postInvocationProcess() { - } - - @Override - public Map generateBinding() { - return null; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/cosmosdb/CosmosDBInputParameterHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/cosmosdb/CosmosDBInputParameterHandler.java deleted file mode 100644 index 3d94ddf2..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/cosmosdb/CosmosDBInputParameterHandler.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.cosmosdb; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ArrayTypeDescriptorNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.OptionalTypeDescriptorNode; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.compiler.syntax.tree.SyntaxKind; -import io.ballerina.compiler.syntax.tree.TypeDefinitionNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractParameterHandler; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Optional; - -/** - * Implementation for the input parameter handler annotation "@CosmosDBInput". - */ -public class CosmosDBInputParameterHandler extends AbstractParameterHandler { - - private Map generatedTypeDefinitions; - - public CosmosDBInputParameterHandler(ParameterSymbol variableSymbol, RequiredParameterNode param, - Map generatedTypeDefinitions) { - super(variableSymbol, param, BindingType.INPUT); - this.generatedTypeDefinitions = generatedTypeDefinitions; - } - - @Override - public ExpressionNode invocationProcess() throws AzureFunctionsException { - boolean singleRecordQuery = this.isSingleRecordQuery(); - PositionalArgumentNode params = NodeFactory.createPositionalArgumentNode( - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken(Constants.PARAMS))); - if (singleRecordQuery) { - if (GeneratorUtil.isJsonType(this.variableSymbol)) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(NodeFactory - .createBasicLiteralNode(SyntaxKind.STRING_LITERAL, NodeFactory - .createLiteralValueToken(SyntaxKind.STRING_LITERAL_TOKEN, - "\"" + this.name + "\"", - NodeFactory.createEmptyMinutiaeList(), - NodeFactory.createEmptyMinutiaeList()))); - return GeneratorUtil - .createAfFunctionInvocationNode("getParsedJsonFromJsonStringFromInputData", true, params, - stringArg); - } else if (GeneratorUtil.isOptionalRecordType(this.variableSymbol)) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(NodeFactory - .createBasicLiteralNode(SyntaxKind.STRING_LITERAL, NodeFactory - .createLiteralValueToken(SyntaxKind.STRING_LITERAL_TOKEN, - "\"" + this.name + "\"", - NodeFactory.createEmptyMinutiaeList(), - NodeFactory.createEmptyMinutiaeList()))); - OptionalTypeDescriptorNode optionalTypeDescriptor = (OptionalTypeDescriptorNode) param.typeName(); - TypeDefinitionNode optionalTypeDefinitionNode = - GeneratorUtil.createOptionalTypeDefinitionNode(optionalTypeDescriptor); - generatedTypeDefinitions.put(optionalTypeDefinitionNode.typeName().text(), optionalTypeDefinitionNode); - PositionalArgumentNode typeDesc = - NodeFactory.createPositionalArgumentNode(NodeFactory.createSimpleNameReferenceNode( - NodeFactory.createIdentifierToken(optionalTypeDefinitionNode.typeName().text()))); - ExpressionNode checkedExpr = - GeneratorUtil - .createAfFunctionInvocationNode("getOptionalBallerinaValueFromInputData", true, params, - stringArg, typeDesc); - return NodeFactory.createTypeCastExpressionNode(NodeFactory.createToken(SyntaxKind.LT_TOKEN), - NodeFactory.createTypeCastParamNode(NodeFactory.createEmptyNodeList(), optionalTypeDescriptor), - NodeFactory.createToken(SyntaxKind.GT_TOKEN), checkedExpr); - } else { - throw new AzureFunctionsException( - GeneratorUtil.getAFDiagnostic(this.param.typeName().location(), "AZ0008", - "unsupported.param.type", DiagnosticSeverity.ERROR, - "type '" + this.param.typeName().toString() + "'" + - " is not supported")); - } - } else { - if (GeneratorUtil.isJsonType(this.variableSymbol)) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(NodeFactory - .createBasicLiteralNode(SyntaxKind.STRING_LITERAL, NodeFactory - .createLiteralValueToken(SyntaxKind.STRING_LITERAL_TOKEN, - "\"" + this.name + "\"", - NodeFactory.createEmptyMinutiaeList(), - NodeFactory.createEmptyMinutiaeList()))); - return GeneratorUtil.createAfFunctionInvocationNode("getJsonFromInput", true, params, stringArg); - } else if (GeneratorUtil.isRecordArrayType(this.variableSymbol)) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(NodeFactory - .createBasicLiteralNode(SyntaxKind.STRING_LITERAL, NodeFactory - .createLiteralValueToken(SyntaxKind.STRING_LITERAL_TOKEN, - "\"" + this.name + "\"", - NodeFactory.createEmptyMinutiaeList(), - NodeFactory.createEmptyMinutiaeList()))); - ArrayTypeDescriptorNode arrayTypeDescriptor = (ArrayTypeDescriptorNode) param.typeName(); - TypeDefinitionNode arrayTypeDefinitionNode = GeneratorUtil - .createArrayTypeDefinitionNode(arrayTypeDescriptor); - generatedTypeDefinitions.put(arrayTypeDefinitionNode.typeName().text(), arrayTypeDefinitionNode); - PositionalArgumentNode typeDesc = - NodeFactory.createPositionalArgumentNode(NodeFactory.createSimpleNameReferenceNode( - NodeFactory.createIdentifierToken(arrayTypeDefinitionNode.typeName().text()))); - ExpressionNode checkedExpr = - GeneratorUtil.createAfFunctionInvocationNode("getBallerinaValueFromInputData", true, params, - stringArg, typeDesc); - - return NodeFactory.createTypeCastExpressionNode(NodeFactory.createToken(SyntaxKind.LT_TOKEN), - NodeFactory.createTypeCastParamNode(NodeFactory.createEmptyNodeList(), arrayTypeDescriptor), - NodeFactory.createToken(SyntaxKind.GT_TOKEN), checkedExpr); - } else { - throw new AzureFunctionsException( - GeneratorUtil.getAFDiagnostic(this.param.typeName().location(), "AZ0008", - "unsupported.param.type", DiagnosticSeverity.ERROR, - "type '" + this.param.typeName().toString() + "'" + - " is not supported")); - } - } - } - - @Override - public void postInvocationProcess() throws AzureFunctionsException { - } - - @Override - public Map generateBinding() throws AzureFunctionsException { - Map binding = new LinkedHashMap<>(); - Optional annotationNode = GeneratorUtil.extractAzureFunctionAnnotation(param.annotations()); - Map annonMap = GeneratorUtil.extractAnnotationKeyValues(annotationNode.orElseThrow()); - binding.put("type", "cosmosDB"); - binding.put("connectionStringSetting", annonMap.get("connectionStringSetting")); - binding.put("databaseName", annonMap.get("databaseName")); - binding.put("collectionName", annonMap.get("collectionName")); - binding.put("id", annonMap.get("id")); - binding.put("sqlQuery", annonMap.get("sqlQuery")); - binding.put("partitionKey", annonMap.get("partitionKey")); - binding.put("preferredLocations", annonMap.get("preferredLocations")); - return binding; - } - - private boolean isSingleRecordQuery() throws AzureFunctionsException { - Optional annotationNode = GeneratorUtil.extractAzureFunctionAnnotation(param.annotations()); - Map annonMap = GeneratorUtil.extractAnnotationKeyValues(annotationNode.orElseThrow()); - return annonMap.get("id") != null; - } -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/cosmosdb/CosmosDBReturnHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/cosmosdb/CosmosDBReturnHandler.java deleted file mode 100644 index 0e078d5b..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/cosmosdb/CosmosDBReturnHandler.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.cosmosdb; - -import io.ballerina.compiler.api.symbols.TypeDescKind; -import io.ballerina.compiler.api.symbols.TypeSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.IdentifierToken; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.QualifiedNameReferenceNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractReturnHandler; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Implementation for the return handler annotation "@CosmosDBOutput". - */ -public class CosmosDBReturnHandler extends AbstractReturnHandler { - - public CosmosDBReturnHandler(TypeSymbol retType, AnnotationNode annotation) { - super(retType, annotation); - } - - @Override - public void postInvocationProcess(ExpressionNode returnValueExpr) throws AzureFunctionsException { - PositionalArgumentNode paramsArg = NodeFactory.createPositionalArgumentNode( - GeneratorUtil.createVariableRef(Constants.PARAMS)); - if (retType.typeKind() == TypeDescKind.JSON) { - PositionalArgumentNode returnExpr = NodeFactory.createPositionalArgumentNode(returnValueExpr); - GeneratorUtil.addAzurePkgFunctionCallStatement(this.ctx, "setJsonReturn", true, paramsArg, returnExpr); - } else if (retType.typeKind() == TypeDescKind.TYPE_REFERENCE) { - PositionalArgumentNode returnExpr = NodeFactory.createPositionalArgumentNode(returnValueExpr); - GeneratorUtil.addAzurePkgFunctionCallStatement(this.ctx, "setBallerinaValueAsJsonReturn", true, paramsArg, - returnExpr); - } else if (GeneratorUtil.isRecordArrayType(retType)) { - PositionalArgumentNode returnExpr = NodeFactory.createPositionalArgumentNode(returnValueExpr); - GeneratorUtil.addAzurePkgFunctionCallStatement(this.ctx, "setBallerinaValueAsJsonReturn", true, paramsArg, - returnExpr); - } else { - IdentifierToken identifier = ((QualifiedNameReferenceNode) annotation.annotReference()).identifier(); - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(returnValueExpr.location(), "AZ0007", - "unsupported.return.annotation", DiagnosticSeverity.ERROR, "Type '" + identifier.text() + "' is " + - "not supported")); - } - //TODO handle record array - } - - @Override - public Map generateBinding() throws AzureFunctionsException { - Map binding = new LinkedHashMap<>(); - Map annonMap = GeneratorUtil.extractAnnotationKeyValues(annotation); - binding.put("type", "cosmosDB"); - binding.put("connectionStringSetting", annonMap.get("connectionStringSetting")); - binding.put("databaseName", annonMap.get("databaseName")); - binding.put("collectionName", annonMap.get("collectionName")); - binding.put("createIfNotExists", annonMap.get("createIfNotExists")); - binding.put("partitionKey", annonMap.get("partitionKey")); - binding.put("collectionThroughput", annonMap.get("collectionThroughput")); - binding.put("preferredLocations", annonMap.get("preferredLocations")); - binding.put("useMultipleWriteLocations", annonMap.get("useMultipleWriteLocations")); - return binding; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/cosmosdb/CosmosDBTriggerHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/cosmosdb/CosmosDBTriggerHandler.java deleted file mode 100644 index 1bd7611f..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/cosmosdb/CosmosDBTriggerHandler.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.cosmosdb; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ArrayTypeDescriptorNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.compiler.syntax.tree.SyntaxKind; -import io.ballerina.compiler.syntax.tree.TypeDefinitionNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractParameterHandler; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Optional; - -/** - * Implementation for the input parameter handler annotation "@CosmosDBTrigger". - */ -public class CosmosDBTriggerHandler extends AbstractParameterHandler { - - private Map generatedTypeDefinitions; - - public CosmosDBTriggerHandler(ParameterSymbol variableSymbol, RequiredParameterNode param, - Map generatedTypeDefinitions) { - super(variableSymbol, param, BindingType.TRIGGER); - this.generatedTypeDefinitions = generatedTypeDefinitions; - } - - @Override - public ExpressionNode invocationProcess() throws AzureFunctionsException { - PositionalArgumentNode params = NodeFactory.createPositionalArgumentNode( - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken(Constants.PARAMS))); - if (GeneratorUtil.isJsonType(this.variableSymbol)) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(NodeFactory - .createBasicLiteralNode(SyntaxKind.STRING_LITERAL, NodeFactory - .createLiteralValueToken(SyntaxKind.STRING_LITERAL_TOKEN, "\"" + this.name + "\"", - NodeFactory.createEmptyMinutiaeList(), - NodeFactory.createEmptyMinutiaeList()))); - return GeneratorUtil.createAfFunctionInvocationNode("getJsonFromInputData", true, params, stringArg); - } else if (GeneratorUtil.isRecordArrayType(this.variableSymbol)) { - PositionalArgumentNode stringArg = NodeFactory.createPositionalArgumentNode( - NodeFactory.createBasicLiteralNode(SyntaxKind.STRING_LITERAL, NodeFactory - .createLiteralValueToken(SyntaxKind.STRING_LITERAL_TOKEN, "\"" + this.name + "\"", - NodeFactory.createEmptyMinutiaeList(), - NodeFactory.createEmptyMinutiaeList()))); - ArrayTypeDescriptorNode arrayTypeDescriptor = (ArrayTypeDescriptorNode) param.typeName(); - TypeDefinitionNode arrayTypeDefinitionNode = GeneratorUtil - .createArrayTypeDefinitionNode(arrayTypeDescriptor); - generatedTypeDefinitions.put(arrayTypeDefinitionNode.typeName().text(), arrayTypeDefinitionNode); - PositionalArgumentNode typeDesc = - NodeFactory.createPositionalArgumentNode(NodeFactory.createSimpleNameReferenceNode( - NodeFactory.createIdentifierToken(arrayTypeDefinitionNode.typeName().text()))); - ExpressionNode checkedExpr = - GeneratorUtil - .createAfFunctionInvocationNode("getBallerinaValueFromInputData", true, params, stringArg, - typeDesc); - return NodeFactory.createTypeCastExpressionNode(NodeFactory.createToken(SyntaxKind.LT_TOKEN), - NodeFactory.createTypeCastParamNode(NodeFactory.createEmptyNodeList(), arrayTypeDescriptor), - NodeFactory.createToken(SyntaxKind.GT_TOKEN), checkedExpr); - } else { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(this.param.typeName().location(), "AZ0008", - "unsupported.param.type", DiagnosticSeverity.ERROR, - "type '" + this.param.typeName().toString() + "'" + - " is not supported")); - } - } - - @Override - public void postInvocationProcess() throws AzureFunctionsException { - } - - @Override - public Map generateBinding() throws AzureFunctionsException { - Map binding = new LinkedHashMap<>(); - Optional annotationNode = GeneratorUtil.extractAzureFunctionAnnotation(param.annotations()); - Map annonMap = GeneratorUtil.extractAnnotationKeyValues(annotationNode.orElseThrow()); - binding.put("type", "cosmosDBTrigger"); - binding.put("connectionStringSetting", annonMap.get("connectionStringSetting")); - binding.put("databaseName", annonMap.get("databaseName")); - binding.put("collectionName", annonMap.get("collectionName")); - binding.put("leaseConnectionStringSetting", annonMap.get("leaseConnectionStringSetting")); - binding.put("leaseDatabaseName", annonMap.get("leaseDatabaseName")); - binding.put("leaseCollectionName", annonMap.get("leaseCollectionName")); - Boolean createLeaseCollectionIfNotExists = (Boolean) annonMap.get("createLeaseCollectionIfNotExists"); - if (createLeaseCollectionIfNotExists == null) { - createLeaseCollectionIfNotExists = Constants.DEFAULT_COSMOS_DB_CREATELEASECOLLECTIONIFNOTEXISTS; - } - binding.put("createLeaseCollectionIfNotExists", createLeaseCollectionIfNotExists); - binding.put("leasesCollectionThroughput", annonMap.get("leasesCollectionThroughput")); - binding.put("leaseCollectionPrefix", annonMap.get("leaseCollectionPrefix")); - binding.put("feedPollDelay", annonMap.get("feedPollDelay")); - binding.put("leaseAcquireInterval", annonMap.get("leaseAcquireInterval")); - binding.put("leaseExpirationInterval", annonMap.get("leaseExpirationInterval")); - binding.put("leaseRenewInterval", annonMap.get("leaseRenewInterval")); - binding.put("checkpointFrequency", annonMap.get("checkpointFrequency")); - binding.put("maxItemsPerInvocation", annonMap.get("maxItemsPerInvocation")); - binding.put("startFromBeginning", annonMap.get("startFromBeginning")); - binding.put("preferredLocations", annonMap.get("preferredLocations")); - return binding; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/http/HTTPOutputParameterHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/http/HTTPOutputParameterHandler.java deleted file mode 100644 index 17e860b1..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/http/HTTPOutputParameterHandler.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.http; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractParameterHandler; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Implementation for the output parameter handler annotation "@HTTPOutput". - */ -public class HTTPOutputParameterHandler extends AbstractParameterHandler { - - private SimpleNameReferenceNode var; - - public HTTPOutputParameterHandler(ParameterSymbol variableSymbol, RequiredParameterNode param) { - super(variableSymbol, param, BindingType.OUTPUT); - } - - @Override - public ExpressionNode invocationProcess() throws AzureFunctionsException { - if (!GeneratorUtil.isAzurePkgType(this.variableSymbol, "HTTPBinding")) { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(param.typeName().location(), "AZ0007", - "required.type", DiagnosticSeverity.ERROR, "type must be HTTPBinding")); - } - this.var = GeneratorUtil.addAzurePkgRecordVarDef(this.ctx, "HTTPBinding", this.ctx.getNextVarName()); - return this.var; - } - - @Override - public void postInvocationProcess() throws AzureFunctionsException { - PositionalArgumentNode paramsArg = NodeFactory.createPositionalArgumentNode( - GeneratorUtil.createVariableRef(Constants.PARAMS)); - - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - - PositionalArgumentNode varArg = NodeFactory.createPositionalArgumentNode( - GeneratorUtil.createVariableRef(var.name().text())); - - GeneratorUtil.addAzurePkgFunctionCallStatement(this.ctx, "setHTTPOutput", true, paramsArg, stringArg, varArg); - } - - @Override - public Map generateBinding() { - Map binding = new LinkedHashMap<>(); - binding.put("type", "http"); - return binding; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/http/HTTPReturnHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/http/HTTPReturnHandler.java deleted file mode 100644 index 43eb4883..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/http/HTTPReturnHandler.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.http; - -import io.ballerina.compiler.api.symbols.TypeDescKind; -import io.ballerina.compiler.api.symbols.TypeSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.IdentifierToken; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.QualifiedNameReferenceNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractReturnHandler; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Implementation for the return handler annotation "@HTTPOutput". - */ -public class HTTPReturnHandler extends AbstractReturnHandler { - - public HTTPReturnHandler(TypeSymbol retType, AnnotationNode annotation) { - super(retType, annotation); - } - - @Override - public void postInvocationProcess(ExpressionNode returnValueExpr) throws AzureFunctionsException { - PositionalArgumentNode paramsArg = NodeFactory.createPositionalArgumentNode( - GeneratorUtil.createVariableRef(Constants.PARAMS)); - if (retType.typeKind() == TypeDescKind.STRING) { - PositionalArgumentNode returnExpr = NodeFactory.createPositionalArgumentNode(returnValueExpr); - GeneratorUtil.addAzurePkgFunctionCallStatement(this.ctx, "setStringReturn", true, paramsArg, returnExpr); - } else if (retType.typeKind() == TypeDescKind.JSON) { - PositionalArgumentNode returnExpr = NodeFactory.createPositionalArgumentNode(returnValueExpr); - GeneratorUtil.addAzurePkgFunctionCallStatement(this.ctx, "setJsonReturn", true, paramsArg, returnExpr); - } else if (retType.typeKind() == TypeDescKind.TYPE_REFERENCE && retType.signature().endsWith("HTTPBinding")) { - PositionalArgumentNode returnExpr = NodeFactory.createPositionalArgumentNode(returnValueExpr); - GeneratorUtil.addAzurePkgFunctionCallStatement(this.ctx, "setHTTPReturn", true, paramsArg, returnExpr); - } else { - IdentifierToken identifier = ((QualifiedNameReferenceNode) annotation.annotReference()).identifier(); - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(returnValueExpr.location(), "AZ0007", - "unsupported.return.annotation", DiagnosticSeverity.ERROR, "Type '" + identifier.text() + "' is " + - "not supported")); - } - } - - @Override - public Map generateBinding() { - Map binding = new LinkedHashMap<>(); - binding.put("type", "http"); - return binding; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/http/HTTPTriggerParameterHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/http/HTTPTriggerParameterHandler.java deleted file mode 100644 index 3fdb8d4e..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/http/HTTPTriggerParameterHandler.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.http; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.compiler.syntax.tree.SyntaxKind; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractParameterHandler; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Optional; - -/** - * Implementation for the input parameter handler annotation "@HTTPTrigger". - */ -public class HTTPTriggerParameterHandler extends AbstractParameterHandler { - - public HTTPTriggerParameterHandler(ParameterSymbol variableSymbol, RequiredParameterNode param) { - super(variableSymbol, param, BindingType.TRIGGER); - } - - @Override - public ExpressionNode invocationProcess() throws AzureFunctionsException { - PositionalArgumentNode paramsArg = NodeFactory.createPositionalArgumentNode( - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken(Constants.PARAMS))); - if (GeneratorUtil.isAzurePkgType(this.variableSymbol, "HTTPRequest")) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - return GeneratorUtil - .createAfFunctionInvocationNode("getHTTPRequestFromInputData", true, paramsArg, stringArg); - } else if (GeneratorUtil.isStringType(this.variableSymbol)) { - PositionalArgumentNode stringArg = NodeFactory.createPositionalArgumentNode(NodeFactory - .createBasicLiteralNode(SyntaxKind.STRING_LITERAL, NodeFactory - .createLiteralValueToken(SyntaxKind.STRING_LITERAL_TOKEN, "\"" + this.name + "\"", - NodeFactory.createEmptyMinutiaeList(), NodeFactory.createEmptyMinutiaeList()))); - return GeneratorUtil.createAfFunctionInvocationNode("getBodyFromHTTPInputData", true, paramsArg, stringArg); - } else { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(this.param.typeName().location(), "AZ0008", - "unsupported.param.type", DiagnosticSeverity.ERROR, - "type '" + this.param.typeName().toString() + "'" + - " is not supported")); - } - } - - @Override - public void postInvocationProcess() { - } - - @Override - public Map generateBinding() throws AzureFunctionsException { - Map binding = new LinkedHashMap<>(); - Optional annotationNode = GeneratorUtil.extractAzureFunctionAnnotation(param.annotations()); - Map annonMap = GeneratorUtil.extractAnnotationKeyValues(annotationNode.orElseThrow()); - binding.put("type", "httpTrigger"); - binding.put("authLevel", annonMap.get("authLevel")); - binding.put("route", annonMap.get("route")); - binding.put("methods", new String[]{ "get", "post", "put", "delete" }); - return binding; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/metadata/MetadataBindingParameterHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/metadata/MetadataBindingParameterHandler.java deleted file mode 100644 index 3a548771..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/metadata/MetadataBindingParameterHandler.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.metadata; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractParameterHandler; - -import java.util.Map; -import java.util.Optional; - -/** - * Implementation for the input parameter handler annotation "@BindingName". - */ -public class MetadataBindingParameterHandler extends AbstractParameterHandler { - - public MetadataBindingParameterHandler(ParameterSymbol variableSymbol, RequiredParameterNode param) - throws AzureFunctionsException { - super(variableSymbol, param, BindingType.METADATA); - Optional annotationNode = GeneratorUtil.extractAzureFunctionAnnotation(param.annotations()); - Map annonMap = GeneratorUtil.extractAnnotationKeyValues(annotationNode.orElseThrow()); - Object name = annonMap.get("name"); - if (name != null) { - this.name = name.toString(); - } - } - - @Override - public ExpressionNode invocationProcess() throws AzureFunctionsException { - PositionalArgumentNode paramsArg = NodeFactory.createPositionalArgumentNode( - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken(Constants.PARAMS))); - if (GeneratorUtil.isJsonType(this.variableSymbol)) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - return GeneratorUtil.createAfFunctionInvocationNode("getJsonFromMetadata", true, paramsArg, stringArg); - } else if (GeneratorUtil.isStringType(this.variableSymbol)) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - return GeneratorUtil.createAfFunctionInvocationNode("getStringFromMetadata", true, paramsArg, stringArg); - } else { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(this.param.typeName().location(), "AZ0008", - "unsupported.param.type", DiagnosticSeverity.ERROR, - "type '" + this.param.typeName().toString() + "'" + - " is not supported")); - } - } - - @Override - public void postInvocationProcess() { - } - - @Override - public Map generateBinding() { - return null; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/queue/QueueOutputParameterHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/queue/QueueOutputParameterHandler.java deleted file mode 100644 index 36e288f9..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/queue/QueueOutputParameterHandler.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.queue; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractParameterHandler; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Optional; - -/** - * Implementation for the output parameter handler annotation "@QueueOutput". - */ -public class QueueOutputParameterHandler extends AbstractParameterHandler { - - private SimpleNameReferenceNode var; - - public QueueOutputParameterHandler(ParameterSymbol variableSymbol, RequiredParameterNode param) { - super(variableSymbol, param, BindingType.OUTPUT); - } - - @Override - public ExpressionNode invocationProcess() throws AzureFunctionsException { - if (!GeneratorUtil.isAzurePkgType(this.variableSymbol, "StringOutputBinding")) { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(param.typeName().location(), "AZ0007", - "required.type", DiagnosticSeverity.ERROR, "type must be StringOutputBinding")); - } - this.var = GeneratorUtil.addAzurePkgRecordVarDef(this.ctx, "StringOutputBinding", this.ctx.getNextVarName()); - return this.var; - } - - @Override - public void postInvocationProcess() throws AzureFunctionsException { - PositionalArgumentNode paramsArg = NodeFactory.createPositionalArgumentNode( - GeneratorUtil.createVariableRef("params")); - - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - - PositionalArgumentNode varArg = NodeFactory.createPositionalArgumentNode( - GeneratorUtil.createVariableRef(var.name().text())); - - GeneratorUtil.addAzurePkgFunctionCallStatement(this.ctx, "setStringOutput", true, paramsArg, stringArg, varArg); - } - - @Override - public Map generateBinding() throws AzureFunctionsException { - Map binding = new LinkedHashMap<>(); - Optional annotationNode = GeneratorUtil.extractAzureFunctionAnnotation(param.annotations()); - Map annonMap = GeneratorUtil.extractAnnotationKeyValues(annotationNode.orElseThrow()); - binding.put("type", "queue"); - binding.put("queueName", annonMap.get("queueName")); - String connection = (String) annonMap.get("connection"); - if (connection == null) { - connection = Constants.DEFAULT_STORAGE_CONNECTION_NAME; - } - binding.put("connection", connection); - return binding; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/queue/QueueTriggerHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/queue/QueueTriggerHandler.java deleted file mode 100644 index 71dc24da..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/queue/QueueTriggerHandler.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.queue; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractParameterHandler; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Optional; - -/** - * Implementation for the input parameter handler annotation "@QueueTrigger". - */ -public class QueueTriggerHandler extends AbstractParameterHandler { - - public QueueTriggerHandler(ParameterSymbol variableSymbol, RequiredParameterNode param) { - super(variableSymbol, param, BindingType.TRIGGER); - } - - @Override - public ExpressionNode invocationProcess() throws AzureFunctionsException { - PositionalArgumentNode paramsArg = NodeFactory.createPositionalArgumentNode( - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken(Constants.PARAMS))); - if (GeneratorUtil.isStringType(this.variableSymbol)) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - return GeneratorUtil - .createAfFunctionInvocationNode("getJsonStringFromInputData", true, paramsArg, stringArg); - } else if (GeneratorUtil.isJsonType(this.variableSymbol)) { - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - return GeneratorUtil - .createAfFunctionInvocationNode("getParsedJsonFromJsonStringFromInputData", true, paramsArg, - stringArg); - } else { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(this.param.typeName().location(), "AZ0008", - "unsupported.param.type", DiagnosticSeverity.ERROR, - "type '" + this.param.typeName().toString() + "'" + - " is not supported")); - } - } - - @Override - public void postInvocationProcess() throws AzureFunctionsException { - } - - @Override - public Map generateBinding() throws AzureFunctionsException { - Map binding = new LinkedHashMap<>(); - Optional annotationNode = GeneratorUtil.extractAzureFunctionAnnotation(param.annotations()); - Map annonMap = GeneratorUtil.extractAnnotationKeyValues(annotationNode.orElseThrow()); - binding.put("type", "queueTrigger"); - binding.put("queueName", annonMap.get("queueName")); - String connection = (String) annonMap.get("connection"); - if (connection == null) { - connection = Constants.DEFAULT_STORAGE_CONNECTION_NAME; - } - binding.put("connection", connection); - return binding; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/timer/TimerTriggerHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/timer/TimerTriggerHandler.java deleted file mode 100644 index 98e467ce..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/timer/TimerTriggerHandler.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.timer; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractParameterHandler; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Optional; - -/** - * Implementation for the input parameter handler annotation "@TimerTrigger". - */ -public class TimerTriggerHandler extends AbstractParameterHandler { - - public TimerTriggerHandler(ParameterSymbol variableSymbol, RequiredParameterNode param) { - super(variableSymbol, param, BindingType.TRIGGER); - } - - @Override - public ExpressionNode invocationProcess() throws AzureFunctionsException { - if (GeneratorUtil.isJsonType(this.variableSymbol)) { - PositionalArgumentNode paramsArg = NodeFactory.createPositionalArgumentNode( - NodeFactory.createSimpleNameReferenceNode(NodeFactory.createIdentifierToken("params"))); - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - return GeneratorUtil.createAfFunctionInvocationNode("getJsonFromInputData", true, paramsArg, stringArg); - } else { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(this.param.typeName().location(), "AZ0008", - "unsupported.param.type", DiagnosticSeverity.ERROR, - "type '" + this.param.typeName().toString() + "'" + - " is not supported")); - } - } - - @Override - public void postInvocationProcess() throws AzureFunctionsException { - } - - @Override - public Map generateBinding() throws AzureFunctionsException { - Map binding = new LinkedHashMap<>(); - Optional annotationNode = GeneratorUtil.extractAzureFunctionAnnotation(param.annotations()); - Map annonMap = GeneratorUtil.extractAnnotationKeyValues(annotationNode.orElseThrow()); - binding.put("type", "timerTrigger"); - binding.put("schedule", annonMap.get("schedule")); - Boolean runOnStartup = (Boolean) annonMap.get("runOnStartup"); - if (runOnStartup == null) { - runOnStartup = Constants.DEFAULT_TIMER_TRIGGER_RUNONSTARTUP; - } - binding.put("runOnStartup", runOnStartup); - return binding; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/twilio/TwilioSmsOutputParameterHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/twilio/TwilioSmsOutputParameterHandler.java deleted file mode 100644 index 77771b4f..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/handlers/twilio/TwilioSmsOutputParameterHandler.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.handlers.twilio; - -import io.ballerina.compiler.api.symbols.ParameterSymbol; -import io.ballerina.compiler.syntax.tree.AnnotationNode; -import io.ballerina.compiler.syntax.tree.ExpressionNode; -import io.ballerina.compiler.syntax.tree.NodeFactory; -import io.ballerina.compiler.syntax.tree.PositionalArgumentNode; -import io.ballerina.compiler.syntax.tree.RequiredParameterNode; -import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.AzureFunctionsException; -import org.ballerinax.azurefunctions.generator.BindingType; -import org.ballerinax.azurefunctions.generator.Constants; -import org.ballerinax.azurefunctions.generator.GeneratorUtil; -import org.ballerinax.azurefunctions.generator.handlers.AbstractParameterHandler; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Optional; - -/** - * Implementation for the output parameter handler annotation "@TwilioSmsOutput". - */ -public class TwilioSmsOutputParameterHandler extends AbstractParameterHandler { - - private SimpleNameReferenceNode var; - - public TwilioSmsOutputParameterHandler(ParameterSymbol variableSymbol, RequiredParameterNode param) { - super(variableSymbol, param, BindingType.OUTPUT); - } - - @Override - public ExpressionNode invocationProcess() throws AzureFunctionsException { - if (!GeneratorUtil.isAzurePkgType(this.variableSymbol, "TwilioSmsOutputBinding")) { - throw new AzureFunctionsException(GeneratorUtil.getAFDiagnostic(param.typeName().location(), "AZ0007", - "required.type", DiagnosticSeverity.ERROR, "Type must be 'TwilioSmsOutputBinding'")); - } - this.var = GeneratorUtil.addAzurePkgRecordVarDef(this.ctx, "TwilioSmsOutputBinding", this.ctx.getNextVarName()); - return this.var; - } - - @Override - public void postInvocationProcess() throws AzureFunctionsException { - PositionalArgumentNode paramsArg = NodeFactory.createPositionalArgumentNode( - GeneratorUtil.createVariableRef("params")); - - PositionalArgumentNode stringArg = - NodeFactory.createPositionalArgumentNode(GeneratorUtil.createStringLiteral(this.name)); - - PositionalArgumentNode varArg = NodeFactory.createPositionalArgumentNode( - GeneratorUtil.createVariableRef(var.name().text())); - - GeneratorUtil - .addAzurePkgFunctionCallStatement(this.ctx, "setTwilioSmsOutput", true, paramsArg, stringArg, varArg); - } - - @Override - public Map generateBinding() throws AzureFunctionsException { - Map binding = new LinkedHashMap<>(); - Optional annotationNode = GeneratorUtil.extractAzureFunctionAnnotation(param.annotations()); - Map annonMap = GeneratorUtil.extractAnnotationKeyValues(annotationNode.orElseThrow()); - binding.put("type", "twilioSms"); - binding.put("from", annonMap.get("fromNumber")); - String accountSidSetting = (String) annonMap.get("accountSidSetting"); - if (accountSidSetting == null) { - accountSidSetting = Constants.DEFAULT_TWILIO_ACCOUNT_SID_SETTING; - } - binding.put("accountSidSetting", accountSidSetting); - String authTokenSetting = (String) annonMap.get("authTokenSetting"); - if (authTokenSetting == null) { - authTokenSetting = Constants.DEFAULT_TWILIO_AUTH_TOKEN_SETTING; - } - binding.put("authTokenSetting", authTokenSetting); - return binding; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/validators/AzureFunctionsCodeAnalyzerTask.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/validators/AzureFunctionsCodeAnalyzerTask.java deleted file mode 100644 index 436522a0..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/validators/AzureFunctionsCodeAnalyzerTask.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.validators; - -import io.ballerina.compiler.syntax.tree.Node; -import io.ballerina.compiler.syntax.tree.NodeLocation; -import io.ballerina.projects.Document; -import io.ballerina.projects.DocumentId; -import io.ballerina.projects.Module; -import io.ballerina.projects.ModuleId; -import io.ballerina.projects.Package; -import io.ballerina.projects.ProjectKind; -import io.ballerina.projects.plugins.AnalysisTask; -import io.ballerina.projects.plugins.CompilationAnalysisContext; -import io.ballerina.tools.diagnostics.Diagnostic; -import io.ballerina.tools.diagnostics.DiagnosticFactory; -import io.ballerina.tools.diagnostics.DiagnosticInfo; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.Constants; - -import java.util.ArrayList; -import java.util.List; - -/*** - * Code analyzer for azure function specific validations. - * - * @since 2.0.0 - */ -public class AzureFunctionsCodeAnalyzerTask implements AnalysisTask { - - @Override - public void perform(CompilationAnalysisContext compilationAnalysisContext) { - Package currentPackage = compilationAnalysisContext.currentPackage(); - List diagnostics = new ArrayList<>(); - if (currentPackage.project().kind() != ProjectKind.BUILD_PROJECT) { - DiagnosticInfo diagnosticInfo = new DiagnosticInfo("A000", "azure functions are only allowed in ballerina" + - " projects", DiagnosticSeverity.ERROR); - DocumentId firsDocument = currentPackage.getDefaultModule().documentIds().iterator().next(); - Document document = currentPackage.getDefaultModule().document(firsDocument); - NodeLocation location = document.syntaxTree().rootNode().location(); - diagnostics.add(DiagnosticFactory.createDiagnostic(diagnosticInfo, location)); - } - - - for (ModuleId moduleId : currentPackage.moduleIds()) { - Module module = currentPackage.module(moduleId); - for (DocumentId documentId : module.documentIds()) { - Document document = module.document(documentId); - Node rootNode = document.syntaxTree().rootNode(); - if (document.name().startsWith(Constants.AZ_FUNCTION_PREFIX)) { - continue; - } - diagnostics.addAll(validateMainFunction(rootNode)); - if (module.isDefaultModule()) { - continue; - } - diagnostics.addAll(validateSubmoduleDocument(rootNode)); - } - } - diagnostics.forEach(compilationAnalysisContext::reportDiagnostic); - } - - private List validateMainFunction(Node node) { - List diagnostics = new ArrayList<>(); - node.accept(new MainFunctionValidator(diagnostics)); - return diagnostics; - } - - private List validateSubmoduleDocument(Node node) { - List diagnostics = new ArrayList<>(); - node.accept(new SubmoduleValidator(diagnostics)); - return diagnostics; - } - -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/validators/MainFunctionValidator.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/validators/MainFunctionValidator.java deleted file mode 100644 index 8691d512..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/validators/MainFunctionValidator.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.validators; - -import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; -import io.ballerina.compiler.syntax.tree.ImportDeclarationNode; -import io.ballerina.compiler.syntax.tree.NodeVisitor; -import io.ballerina.tools.diagnostics.Diagnostic; -import io.ballerina.tools.diagnostics.DiagnosticFactory; -import io.ballerina.tools.diagnostics.DiagnosticInfo; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.Constants; - -import java.util.List; - -/** - * Responsible for disallowing main function in a ballerina document. - * - * @since 2.0.0 - */ -public class MainFunctionValidator extends NodeVisitor { - private final List diagnostics; - private boolean isAzureFunctionsImportExist = false; - - public MainFunctionValidator(List diagnostics) { - this.diagnostics = diagnostics; - } - - @Override - public void visit(ImportDeclarationNode importDeclarationNode) { - if (importDeclarationNode.orgName().isEmpty()) { - return; - } - String orgName = importDeclarationNode.orgName().get().orgName().text(); - if (!Constants.AZURE_FUNCTIONS_PACKAGE_ORG.equals(orgName)) { - return; - } - if (importDeclarationNode.moduleName().size() != 1) { - return; - } - String moduleName = importDeclarationNode.moduleName().get(0).text(); - if (Constants.AZURE_FUNCTIONS_MODULE_NAME.equals(moduleName)) { - isAzureFunctionsImportExist = true; - } - } - - @Override - public void visit(FunctionDefinitionNode functionDefinitionNode) { - if (!isAzureFunctionsImportExist) { - return; - } - String text = functionDefinitionNode.functionName().text(); - if (Constants.MAIN_FUNC_NAME.equals(text)) { - DiagnosticInfo diagnosticInfo = new DiagnosticInfo("AZ010", "main function is not allowed in " + - "azure functions", DiagnosticSeverity.ERROR); - diagnostics.add(DiagnosticFactory.createDiagnostic(diagnosticInfo, - functionDefinitionNode.location())); - } - } -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/validators/SubmoduleValidator.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/validators/SubmoduleValidator.java deleted file mode 100644 index ca8de0b9..00000000 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/validators/SubmoduleValidator.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you under the Apache License, - * Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.ballerinax.azurefunctions.generator.validators; - -import io.ballerina.compiler.syntax.tree.ImportDeclarationNode; -import io.ballerina.compiler.syntax.tree.NodeVisitor; -import io.ballerina.tools.diagnostics.Diagnostic; -import io.ballerina.tools.diagnostics.DiagnosticFactory; -import io.ballerina.tools.diagnostics.DiagnosticInfo; -import io.ballerina.tools.diagnostics.DiagnosticSeverity; -import org.ballerinax.azurefunctions.generator.Constants; - -import java.util.List; - -/** - * Responsible for disallowing azure functions in submodule document. - * - * @since 2.0.0 - */ -public class SubmoduleValidator extends NodeVisitor { - private final List diagnostics; - - public SubmoduleValidator(List diagnostics) { - this.diagnostics = diagnostics; - } - - @Override - public void visit(ImportDeclarationNode importDeclarationNode) { - if (importDeclarationNode.orgName().isEmpty()) { - return; - } - String orgName = importDeclarationNode.orgName().get().orgName().text(); - if (!Constants.AZURE_FUNCTIONS_PACKAGE_ORG.equals(orgName)) { - return; - } - if (importDeclarationNode.moduleName().size() != 1) { - return; - } - String moduleName = importDeclarationNode.moduleName().get(0).text(); - if (Constants.AZURE_FUNCTIONS_MODULE_NAME.equals(moduleName)) { - DiagnosticInfo diagnosticInfo = new DiagnosticInfo("AZ011", "azure functions is not allowed inside" + - " sub modules", DiagnosticSeverity.ERROR); - this.diagnostics.add(DiagnosticFactory.createDiagnostic(diagnosticInfo, - importDeclarationNode.location())); - } - } -} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/Binding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/Binding.java new file mode 100644 index 00000000..773f148f --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/Binding.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service; + +import com.google.gson.JsonObject; + +/** + * Represents a binding in the functions.json. + * + * @since 2.0.0 + */ +public abstract class Binding { + private String triggerType; + private String varName; + private String direction; + + public Binding(String triggerType, String direction) { + this.triggerType = triggerType; + this.direction = direction; + } + + public String getTriggerType() { + return triggerType; + } + + public String getVarName() { + return varName; + } + + public String getDirection() { + return direction; + } + + public void setTriggerType(String triggerType) { + this.triggerType = triggerType; + } + + public void setVarName(String varName) { + this.varName = varName; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public abstract JsonObject getJsonObject(); +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/BindingType.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/InputBinding.java similarity index 61% rename from compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/BindingType.java rename to compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/InputBinding.java index af227a42..c5d97b15 100644 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/BindingType.java +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/InputBinding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -15,15 +15,18 @@ * specific language governing permissions and limitations * under the License. */ -package org.ballerinax.azurefunctions.generator; +package org.ballerinax.azurefunctions.service; + +import org.ballerinax.azurefunctions.Constants; /** - * Represents the binding type. + * Represents an Input Binding in Azure Functions. + * + * @since 2.0.0 */ -public enum BindingType { - TRIGGER, - INPUT, - OUTPUT, - CONTEXT, - METADATA +public abstract class InputBinding extends Binding { + + public InputBinding(String triggerType) { + super(triggerType, Constants.DIRECTION_IN); + } } diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/InputBindingBuilder.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/InputBindingBuilder.java new file mode 100644 index 00000000..3db5ea90 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/InputBindingBuilder.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service; + +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.QualifiedNameReferenceNode; +import io.ballerina.compiler.syntax.tree.SyntaxKind; +import org.ballerinax.azurefunctions.Constants; +import org.ballerinax.azurefunctions.service.blob.BlobInputBinding; +import org.ballerinax.azurefunctions.service.cosmosdb.CosmosDBInputBinding; + +import java.util.Optional; + +/** + * Represents an Input Binding builder for Azure Function services. + * + * @since 2.0.0 + */ + +public class InputBindingBuilder { + + public Optional getInputBinding(NodeList annotations, String varName) { + for (AnnotationNode annotation : annotations) { + Node annotRef = annotation.annotReference(); + if (SyntaxKind.QUALIFIED_NAME_REFERENCE == annotRef.kind()) { + QualifiedNameReferenceNode annotationRef = (QualifiedNameReferenceNode) annotRef; + String annotationText = annotationRef.identifier().text(); + if (Constants.COSMOS_INPUT_BINDING.equals(annotationText)) { + return Optional.of(new CosmosDBInputBinding(annotation, varName)); + } + if (Constants.BLOB_INPUT_BINDING.equals(annotationText)) { + return Optional.of(new BlobInputBinding(annotation, varName)); + } + } + } + return Optional.empty(); + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureCodeGenerator.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/OutputBinding.java similarity index 56% rename from compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureCodeGenerator.java rename to compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/OutputBinding.java index 26555277..6748eb3d 100644 --- a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/generator/AzureCodeGenerator.java +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/OutputBinding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -15,20 +15,17 @@ * specific language governing permissions and limitations * under the License. */ -package org.ballerinax.azurefunctions.generator; +package org.ballerinax.azurefunctions.service; -import io.ballerina.projects.plugins.CodeGenerator; -import io.ballerina.projects.plugins.CodeGeneratorContext; +import org.ballerinax.azurefunctions.Constants; /** - * Registers Code generators for azure functions. + * Represents an Output Binding in Azure Functions. * * @since 2.0.0 */ -public class AzureCodeGenerator extends CodeGenerator { - - @Override - public void init(CodeGeneratorContext codeGeneratorContext) { - codeGeneratorContext.addSourceGeneratorTask(new AzureCodegenTask()); +public abstract class OutputBinding extends Binding { + public OutputBinding(String triggerType) { + super(triggerType, Constants.DIRECTION_OUT); } } diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/OutputBindingBuilder.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/OutputBindingBuilder.java new file mode 100644 index 00000000..38c69de7 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/OutputBindingBuilder.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service; + +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.QualifiedNameReferenceNode; +import io.ballerina.compiler.syntax.tree.SyntaxKind; +import org.ballerinax.azurefunctions.Constants; +import org.ballerinax.azurefunctions.service.blob.BlobOutputBinding; +import org.ballerinax.azurefunctions.service.cosmosdb.CosmosDBOutputBinding; +import org.ballerinax.azurefunctions.service.http.HTTPOutputBinding; +import org.ballerinax.azurefunctions.service.queue.QueueOutputBinding; +import org.ballerinax.azurefunctions.service.twilio.TwilioSmsOutputBinding; + +import java.util.Optional; + +/** + * Represents an Output Binding builder for Azure Function services. + * + * @since 2.0.0 + */ +public class OutputBindingBuilder { + + public Optional getOutputBinding(NodeList nodes) { + for (AnnotationNode annotationNode : nodes) { + Node node = annotationNode.annotReference(); + if (SyntaxKind.QUALIFIED_NAME_REFERENCE != node.kind()) { + continue; + } + QualifiedNameReferenceNode qualifiedNameReferenceNode = (QualifiedNameReferenceNode) node; + String annotationName = qualifiedNameReferenceNode.identifier().text(); + switch (annotationName) { + case Constants.QUEUE_OUTPUT_BINDING: + return Optional.of(new QueueOutputBinding(annotationNode)); + case Constants.HTTP_OUTPUT_BINDING: + return Optional.of(new HTTPOutputBinding(annotationNode)); + case Constants.COSMOS_OUTPUT_BINDING: + return Optional.of(new CosmosDBOutputBinding(annotationNode)); + case Constants.TWILIO_OUTPUT_BINDING: + return Optional.of(new TwilioSmsOutputBinding(annotationNode)); + case Constants.BLOB_OUTPUT_BINDING: + return Optional.of(new BlobOutputBinding(annotationNode)); + default: + throw new RuntimeException("Unexpected property in the annotation"); + } + } + return Optional.empty(); + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/RemoteTriggerBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/RemoteTriggerBinding.java new file mode 100644 index 00000000..24e0dd05 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/RemoteTriggerBinding.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service; + +import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; +import io.ballerina.compiler.syntax.tree.MappingFieldNode; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.ParameterNode; +import io.ballerina.compiler.syntax.tree.RequiredParameterNode; +import io.ballerina.compiler.syntax.tree.ReturnTypeDescriptorNode; +import io.ballerina.compiler.syntax.tree.SeparatedNodeList; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import io.ballerina.compiler.syntax.tree.SyntaxKind; +import org.ballerinax.azurefunctions.FunctionContext; +import org.ballerinax.azurefunctions.Util; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * Represents a queue trigger binding in function.json. + * + * @since 2.0.0 + */ +public abstract class RemoteTriggerBinding extends TriggerBinding { + private String methodName; + private String annotationName; + + public RemoteTriggerBinding(String triggerType, String methodName, + String annotationName, ServiceDeclarationNode serviceDeclarationNode, + SemanticModel semanticModel) { + super(triggerType); + this.serviceDeclarationNode = serviceDeclarationNode; + this.semanticModel = semanticModel; + this.methodName = methodName; + this.annotationName = annotationName; + } + + @Override + public List getBindings() { + Optional queueTrigger = getListenerAnnotation(this.serviceDeclarationNode, this.annotationName); + List functionContexts = new ArrayList<>(); + if (queueTrigger.isEmpty()) { + return functionContexts; + } + getAnnotation(queueTrigger.get()); + String servicePath = Util.resourcePathToString(serviceDeclarationNode.absoluteResourcePath()); + NodeList members = this.serviceDeclarationNode.members(); + for (Node node : members) { + List bindings = new ArrayList<>(); + if (SyntaxKind.OBJECT_METHOD_DEFINITION != node.kind()) { + continue; + } + FunctionDefinitionNode functionDefinitionNode = (FunctionDefinitionNode) node; + String method = functionDefinitionNode.functionName().text(); + if (!method.equals(this.methodName)) { + continue; + } + + for (ParameterNode parameterNode : functionDefinitionNode.functionSignature().parameters()) { + if (SyntaxKind.REQUIRED_PARAM != parameterNode.kind()) { + continue; + } + RequiredParameterNode reqParam = (RequiredParameterNode) parameterNode; + if (reqParam.paramName().isEmpty()) { + continue; + } + String variableName = reqParam.paramName().get().text(); + if (!isAzureFunctionsAnnotationExist(reqParam.annotations())) { + this.setVarName(variableName); + continue; + } + + InputBindingBuilder inputBuilder = new InputBindingBuilder(); + Optional inputBinding = inputBuilder.getInputBinding(reqParam.annotations(), variableName); + inputBinding.ifPresent(bindings::add); + } + bindings.add(this); + ReturnTypeDescriptorNode returnTypeDescriptorNode = + functionDefinitionNode.functionSignature().returnTypeDesc().get(); //TODO recheck if return is must + OutputBindingBuilder outputBuilder = new OutputBindingBuilder(); + Optional returnBinding = outputBuilder.getOutputBinding(returnTypeDescriptorNode.annotations()); + bindings.add(returnBinding.orElseThrow()); //TODO handle in code analyzer + functionContexts.add(new FunctionContext(servicePath.replace("/", ""), bindings)); + } + return functionContexts; + } + + private void getAnnotation(AnnotationNode queueTrigger) { + SeparatedNodeList fields = queueTrigger.annotValue().orElseThrow().fields(); + for (MappingFieldNode fieldNode : fields) { + extractValueFromAnnotation((SpecificFieldNode) fieldNode); + } + } + + protected abstract void extractValueFromAnnotation(SpecificFieldNode fieldNode); +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/ServiceHandler.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/ServiceHandler.java new file mode 100644 index 00000000..608c5dc4 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/ServiceHandler.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service; + +import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.api.symbols.TypeDescKind; +import io.ballerina.compiler.api.symbols.TypeReferenceTypeSymbol; +import io.ballerina.compiler.api.symbols.TypeSymbol; +import io.ballerina.compiler.api.symbols.UnionTypeSymbol; +import io.ballerina.compiler.syntax.tree.ExpressionNode; +import io.ballerina.compiler.syntax.tree.SeparatedNodeList; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import org.ballerinax.azurefunctions.Constants; +import org.ballerinax.azurefunctions.service.blob.BlobTriggerBinding; +import org.ballerinax.azurefunctions.service.cosmosdb.CosmosDBTriggerBinding; +import org.ballerinax.azurefunctions.service.http.HTTPTriggerBinding; +import org.ballerinax.azurefunctions.service.queue.QueueTriggerBinding; +import org.ballerinax.azurefunctions.service.timer.TimerTriggerBinding; + +import java.util.Optional; + +/** + * Represents the base handler for each azure service. + * + * @since 2.0.0 + */ +public abstract class ServiceHandler { + + public static TriggerBinding getBuilder(ServiceDeclarationNode svcDeclarationNode, SemanticModel semanticModel) { + SeparatedNodeList expressions = svcDeclarationNode.expressions(); + for (ExpressionNode expressionNode : expressions) { + Optional typeSymbol = semanticModel.typeOf(expressionNode); + if (typeSymbol.isEmpty()) { + continue; + } + TypeReferenceTypeSymbol typeSymbol1; + if (TypeDescKind.UNION == typeSymbol.get().typeKind()) { + UnionTypeSymbol union = (UnionTypeSymbol) typeSymbol.get(); + typeSymbol1 = (TypeReferenceTypeSymbol) union.memberTypeDescriptors().get(0); + + } else { + typeSymbol1 = (TypeReferenceTypeSymbol) typeSymbol.get(); + } + Optional name = typeSymbol1.definition().getName(); + if (name.isEmpty()) { + continue; + } + + String serviceTypeName = name.get(); + switch (serviceTypeName) { + case Constants.AZURE_HTTP_LISTENER: + return new HTTPTriggerBinding(svcDeclarationNode, semanticModel); + case Constants.AZURE_QUEUE_LISTENER: + return new QueueTriggerBinding(svcDeclarationNode, semanticModel); + case Constants.AZURE_COSMOS_LISTENER: + return new CosmosDBTriggerBinding(svcDeclarationNode, semanticModel); + case Constants.AZURE_TIMER_LISTENER: + return new TimerTriggerBinding(svcDeclarationNode, semanticModel); + case Constants.AZURE_BLOB_LISTENER: + return new BlobTriggerBinding(svcDeclarationNode, semanticModel); + default: + throw new RuntimeException("Unsupported Listener type"); + } + } + throw new RuntimeException("Unsupported Listener type"); + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/TriggerBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/TriggerBinding.java new file mode 100644 index 00000000..0294458b --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/TriggerBinding.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service; + +import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.api.symbols.ModuleSymbol; +import io.ballerina.compiler.api.symbols.Symbol; +import io.ballerina.compiler.api.symbols.SymbolKind; +import io.ballerina.compiler.api.symbols.VariableSymbol; +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import io.ballerina.compiler.syntax.tree.ExpressionNode; +import io.ballerina.compiler.syntax.tree.ListenerDeclarationNode; +import io.ballerina.compiler.syntax.tree.MetadataNode; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import org.ballerinax.azurefunctions.Constants; +import org.ballerinax.azurefunctions.FunctionContext; +import org.ballerinax.azurefunctions.Util; + +import java.util.List; +import java.util.Optional; + +import static io.ballerina.compiler.syntax.tree.SyntaxKind.EXPLICIT_NEW_EXPRESSION; +/** + * Represents an Trigger Binding in Azure Functions. + * + * @since 2.0.0 + */ +public abstract class TriggerBinding extends Binding { + protected ServiceDeclarationNode serviceDeclarationNode; + protected SemanticModel semanticModel; + + public TriggerBinding(String triggerType) { + super(triggerType, Constants.DIRECTION_IN); + } + + public abstract List getBindings(); + + public Optional getListenerAnnotation(ServiceDeclarationNode svcDeclNode, String annotationName) { + for (ExpressionNode expression : svcDeclNode.expressions()) { + Optional metadata; + if (EXPLICIT_NEW_EXPRESSION == expression.kind()) { + metadata = svcDeclNode.metadata(); + } else { + Optional symbol = this.semanticModel.symbol(expression); + if (symbol.isEmpty()) { + continue; + } + Symbol listenerSymbol = symbol.get(); + if (SymbolKind.VARIABLE != listenerSymbol.kind()) { + continue; + } + VariableSymbol variableSymbol = (VariableSymbol) listenerSymbol; + ListenerDeclarationNode listenerDeclarationNode = + (ListenerDeclarationNode) Util.findNode(svcDeclNode, variableSymbol); + metadata = listenerDeclarationNode != null ? listenerDeclarationNode.metadata() : Optional.empty(); + } + if (metadata.isEmpty()) { + continue; + } + NodeList annotations = metadata.get().annotations(); + for (AnnotationNode annotationNode : annotations) { + Optional typeSymbol = this.semanticModel.symbol(annotationNode); + if (typeSymbol.isEmpty()) { + continue; + } + Symbol annotationType = typeSymbol.get(); + Optional name = annotationType.getName(); + if (name.isEmpty()) { + continue; + } + if (name.get().equals(annotationName)) { + return Optional.of(annotationNode); + } + } + } + return Optional.empty(); + } + + protected boolean isAzureFunctionsAnnotationExist(NodeList nodes) { + for (AnnotationNode annotation : nodes) { + Node annotRef = annotation.annotReference(); + Optional annotationSymbol = semanticModel.symbol(annotRef); + if (annotationSymbol.isEmpty()) { + continue; + } + Optional module = annotationSymbol.get().getModule(); + if (module.isEmpty()) { + continue; + } + Optional name = module.get().getName(); + if (name.isEmpty()) { + continue; + } + + if (Constants.AZURE_FUNCTIONS_MODULE_NAME.equals(name.get())) { + return true; + } + } + return false; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/blob/BlobInputBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/blob/BlobInputBinding.java new file mode 100644 index 00000000..9c85abaf --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/blob/BlobInputBinding.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service.blob; + +import com.google.gson.JsonObject; +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.MappingFieldNode; +import io.ballerina.compiler.syntax.tree.SeparatedNodeList; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import org.ballerinax.azurefunctions.Util; +import org.ballerinax.azurefunctions.service.InputBinding; + +import java.util.Optional; + +/** + * Represents CosmosDB Binding in functions.json. + */ +public class BlobInputBinding extends InputBinding { + + private String path; + private String connection = "AzureWebJobsStorage"; + private String dataType = "string"; + + public BlobInputBinding(AnnotationNode queueTrigger, String varName) { + super("blob"); + this.setVarName(varName); + SeparatedNodeList fields = queueTrigger.annotValue().orElseThrow().fields(); + for (MappingFieldNode fieldNode : fields) { + extractValueFromAnnotation((SpecificFieldNode) fieldNode); + } + } + + private void extractValueFromAnnotation(SpecificFieldNode fieldNode) { + String text = ((IdentifierToken) fieldNode.fieldName()).text(); + Optional value = Util.extractValueFromAnnotationField(fieldNode); + switch (text) { + case "path": + value.ifPresent(this::setPath); + break; + case "connection": + value.ifPresent(this::setConnection); + break; + case "dataType": + value.ifPresent(this::setDataType); + break; + default: + throw new RuntimeException("Unexpected property in the annotation"); + } + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getConnection() { + return connection; + } + + public void setConnection(String connection) { + this.connection = connection; + } + + public String getDataType() { + return dataType; + } + + public void setDataType(String dataType) { + this.dataType = dataType; + } + + @Override + public JsonObject getJsonObject() { + JsonObject inputTrigger = new JsonObject(); + inputTrigger.addProperty("type", this.getTriggerType()); + inputTrigger.addProperty("direction", this.getDirection()); + inputTrigger.addProperty("name", this.getVarName()); + inputTrigger.addProperty("path", this.path); + inputTrigger.addProperty("connection", this.connection); + inputTrigger.addProperty("dataType", this.dataType); + return inputTrigger; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/blob/BlobOutputBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/blob/BlobOutputBinding.java new file mode 100644 index 00000000..689830f2 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/blob/BlobOutputBinding.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service.blob; + +import com.google.gson.JsonObject; +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.MappingFieldNode; +import io.ballerina.compiler.syntax.tree.SeparatedNodeList; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import org.ballerinax.azurefunctions.Constants; +import org.ballerinax.azurefunctions.Util; +import org.ballerinax.azurefunctions.service.OutputBinding; + +import java.util.Optional; + +/** + * Represents Queue output binding in functions.json. + * + * @since 2.0.0 + */ +public class BlobOutputBinding extends OutputBinding { + + private String path; + private String connection = "AzureWebJobsStorage"; + private String dataType = "string"; + + public BlobOutputBinding(AnnotationNode annotationNode) { + super("blob"); + this.setVarName(Constants.RETURN_VAR_NAME); + SeparatedNodeList fields = annotationNode.annotValue().orElseThrow().fields(); + for (MappingFieldNode fieldNode : fields) { + extractValueFromAnnotation((SpecificFieldNode) fieldNode); + } + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getConnection() { + return connection; + } + + public void setConnection(String connection) { + this.connection = connection; + } + + public String getDataType() { + return dataType; + } + + public void setDataType(String dataType) { + this.dataType = dataType; + } + + private void extractValueFromAnnotation(SpecificFieldNode fieldNode) { + String text = ((IdentifierToken) fieldNode.fieldName()).text(); + Optional value = Util.extractValueFromAnnotationField(fieldNode); + switch (text) { + case "path": + value.ifPresent(this::setPath); + break; + case "connection": + value.ifPresent(this::setConnection); + break; + case "dataType": + value.ifPresent(this::setDataType); + break; + default: + throw new RuntimeException("Unexpected property in the annotation"); + } + } + + @Override + public JsonObject getJsonObject() { + JsonObject output = new JsonObject(); + output.addProperty("type", this.getTriggerType()); + output.addProperty("direction", this.getDirection()); + output.addProperty("name", this.getVarName()); + output.addProperty("path", this.path); + output.addProperty("connection", this.connection); + output.addProperty("dataType", this.dataType); + return output; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/blob/BlobTriggerBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/blob/BlobTriggerBinding.java new file mode 100644 index 00000000..3fb32459 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/blob/BlobTriggerBinding.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service.blob; + +import com.google.gson.JsonObject; +import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import org.ballerinax.azurefunctions.Constants; +import org.ballerinax.azurefunctions.Util; +import org.ballerinax.azurefunctions.service.RemoteTriggerBinding; + +import java.util.Optional; + +/** + * Represents a HTTP Trigger binding in functions.json. + * + * @since 2.0.0 + */ +public class BlobTriggerBinding extends RemoteTriggerBinding { + + private String path; + private String connection = "AzureWebJobsStorage"; + private String dataType = "string"; + + public BlobTriggerBinding(ServiceDeclarationNode serviceDeclarationNode, SemanticModel semanticModel) { + super("blobTrigger", "onUpdated", Constants.ANNOTATION_BLOB_TRIGGER, serviceDeclarationNode, + semanticModel); + } + + @Override + protected void extractValueFromAnnotation(SpecificFieldNode fieldNode) { + String text = ((IdentifierToken) fieldNode.fieldName()).text(); + Optional value = Util.extractValueFromAnnotationField(fieldNode); + switch (text) { + case "path": + value.ifPresent(this::setPath); + break; + case "connection": + value.ifPresent(this::setConnection); + break; + case "dataType": + value.ifPresent(this::setDataType); + break; + default: + throw new RuntimeException("Unexpected property in the annotation"); + } + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public String getConnection() { + return connection; + } + + public void setConnection(String connection) { + this.connection = connection; + } + + public String getDataType() { + return dataType; + } + + public void setDataType(String dataType) { + this.dataType = dataType; + } + + @Override + public JsonObject getJsonObject() { + JsonObject inputTrigger = new JsonObject(); + inputTrigger.addProperty("type", this.getTriggerType()); + inputTrigger.addProperty("name", this.getVarName()); + inputTrigger.addProperty("direction", this.getDirection()); + inputTrigger.addProperty("path", this.path); + inputTrigger.addProperty("connection", this.connection); + return inputTrigger; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/cosmosdb/CosmosDBInputBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/cosmosdb/CosmosDBInputBinding.java new file mode 100644 index 00000000..d6b20b60 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/cosmosdb/CosmosDBInputBinding.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service.cosmosdb; + +import com.google.gson.JsonObject; +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.MappingFieldNode; +import io.ballerina.compiler.syntax.tree.SeparatedNodeList; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import org.ballerinax.azurefunctions.Util; +import org.ballerinax.azurefunctions.service.InputBinding; + +import java.util.Optional; + +/** + * Represents CosmosDB Binding in functions.json. + */ +public class CosmosDBInputBinding extends InputBinding { + + private String connectionStringSetting; + private String databaseName; + private String collectionName; + private String id; + private String partitionKey; + private String sqlQuery; + + public CosmosDBInputBinding(AnnotationNode queueTrigger, String varName) { + super("cosmosDB"); + this.setVarName(varName); + SeparatedNodeList fields = queueTrigger.annotValue().orElseThrow().fields(); + for (MappingFieldNode fieldNode : fields) { + extractValueFromAnnotation((SpecificFieldNode) fieldNode); + } + } + + private void extractValueFromAnnotation(SpecificFieldNode fieldNode) { + String text = ((IdentifierToken) fieldNode.fieldName()).text(); + Optional value = Util.extractValueFromAnnotationField(fieldNode); + switch (text) { + case "connectionStringSetting": + value.ifPresent(this::setConnectionStringSetting); + break; + case "databaseName": + value.ifPresent(this::setDatabaseName); + break; + case "collectionName": + value.ifPresent(this::setCollectionName); + break; + case "sqlQuery": + value.ifPresent(this::setSqlQuery); + break; + case "id": + value.ifPresent(this::setId); + break; + case "partitionKey": + value.ifPresent(this::setPartitionKey); + break; + default: + throw new RuntimeException("Unexpected property in the annotation"); + } + } + + public String getConnectionStringSetting() { + return connectionStringSetting; + } + + public void setConnectionStringSetting(String connectionStringSetting) { + this.connectionStringSetting = connectionStringSetting; + } + + public String getDatabaseName() { + return databaseName; + } + + public void setDatabaseName(String databaseName) { + this.databaseName = databaseName; + } + + public String getCollectionName() { + return collectionName; + } + + public void setCollectionName(String collectionName) { + this.collectionName = collectionName; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getPartitionKey() { + return partitionKey; + } + + public void setPartitionKey(String partitionKey) { + this.partitionKey = partitionKey; + } + + public String getSqlQuery() { + return sqlQuery; + } + + public void setSqlQuery(String sqlQuery) { + this.sqlQuery = sqlQuery; + } + + @Override + public JsonObject getJsonObject() { + JsonObject inputTrigger = new JsonObject(); + inputTrigger.addProperty("type", this.getTriggerType()); + inputTrigger.addProperty("direction", this.getDirection()); + inputTrigger.addProperty("name", this.getVarName()); + inputTrigger.addProperty("connectionStringSetting", this.connectionStringSetting); + inputTrigger.addProperty("databaseName", databaseName); + inputTrigger.addProperty("collectionName", this.collectionName); + if (this.partitionKey != null) { + inputTrigger.addProperty("partitionKey", this.partitionKey); + } + if (this.id != null) { + inputTrigger.addProperty("id", this.id); + } + if (this.sqlQuery != null) { + inputTrigger.addProperty("sqlQuery", this.sqlQuery); + } + return inputTrigger; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/cosmosdb/CosmosDBOutputBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/cosmosdb/CosmosDBOutputBinding.java new file mode 100644 index 00000000..3db1f098 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/cosmosdb/CosmosDBOutputBinding.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service.cosmosdb; + +import com.google.gson.JsonObject; +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.MappingFieldNode; +import io.ballerina.compiler.syntax.tree.SeparatedNodeList; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import org.ballerinax.azurefunctions.Constants; +import org.ballerinax.azurefunctions.Util; +import org.ballerinax.azurefunctions.service.OutputBinding; + +import java.util.Optional; + +/** + * Represents Queue output binding in functions.json. + * + * @since 2.0.0 + */ +public class CosmosDBOutputBinding extends OutputBinding { + + private String connectionStringSetting; + private String databaseName; + private String collectionName; + + public CosmosDBOutputBinding(AnnotationNode annotationNode) { + super("cosmosDB"); + this.setVarName(Constants.RETURN_VAR_NAME); + SeparatedNodeList fields = annotationNode.annotValue().orElseThrow().fields(); + for (MappingFieldNode fieldNode : fields) { + extractValueFromAnnotation((SpecificFieldNode) fieldNode); + } + } + + private void extractValueFromAnnotation(SpecificFieldNode fieldNode) { + String text = ((IdentifierToken) fieldNode.fieldName()).text(); + Optional value = Util.extractValueFromAnnotationField(fieldNode); + switch (text) { + case "connectionStringSetting": + value.ifPresent(this::setConnectionStringSetting); + break; + case "databaseName": + value.ifPresent(this::setDatabaseName); + break; + case "collectionName": + value.ifPresent(this::setCollectionName); + break; + default: + throw new RuntimeException("Unexpected property in the annotation"); + } + } + + public String getConnectionStringSetting() { + return connectionStringSetting; + } + + public void setConnectionStringSetting(String connectionStringSetting) { + this.connectionStringSetting = connectionStringSetting; + } + + public String getDatabaseName() { + return databaseName; + } + + public void setDatabaseName(String databaseName) { + this.databaseName = databaseName; + } + + public String getCollectionName() { + return collectionName; + } + + public void setCollectionName(String collectionName) { + this.collectionName = collectionName; + } + + @Override + public JsonObject getJsonObject() { + JsonObject output = new JsonObject(); + output.addProperty("type", this.getTriggerType()); + output.addProperty("connectionStringSetting", this.connectionStringSetting); + output.addProperty("databaseName", this.databaseName); + output.addProperty("collectionName", this.collectionName); + output.addProperty("direction", this.getDirection()); + output.addProperty("name", this.getVarName()); + return output; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/cosmosdb/CosmosDBTriggerBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/cosmosdb/CosmosDBTriggerBinding.java new file mode 100644 index 00000000..15bb983f --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/cosmosdb/CosmosDBTriggerBinding.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service.cosmosdb; + +import com.google.gson.JsonObject; +import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import org.ballerinax.azurefunctions.Constants; +import org.ballerinax.azurefunctions.Util; +import org.ballerinax.azurefunctions.service.RemoteTriggerBinding; + +import java.util.Optional; + +/** + * Represents a HTTP Trigger binding in functions.json. + * + * @since 2.0.0 + */ +public class CosmosDBTriggerBinding extends RemoteTriggerBinding { + + private String connectionStringSetting; + private String databaseName; + private String collectionName; + private boolean createLeaseCollectionIfNotExists = true; + private int leasesCollectionThroughput = 400; + + public CosmosDBTriggerBinding(ServiceDeclarationNode serviceDeclarationNode, SemanticModel semanticModel) { + super("cosmosDBTrigger", "onUpdated", Constants.ANNOTATION_COSMOS_TRIGGER, serviceDeclarationNode, + semanticModel); + } + + @Override + protected void extractValueFromAnnotation(SpecificFieldNode fieldNode) { + String text = ((IdentifierToken) fieldNode.fieldName()).text(); + Optional value = Util.extractValueFromAnnotationField(fieldNode); + switch (text) { + case "connectionStringSetting": + value.ifPresent(this::setConnectionStringSetting); + break; + case "databaseName": + value.ifPresent(this::setDatabaseName); + break; + case "collectionName": + value.ifPresent(this::setCollectionName); + break; + case "createLeaseCollectionIfNotExists": + value.ifPresent(s -> this.setCreateLeaseCollectionIfNotExists(Boolean.parseBoolean(s))); + break; + case "leasesCollectionThroughput": + value.ifPresent(s -> this.setLeasesCollectionThroughput(Integer.parseInt(s))); + break; + default: + throw new RuntimeException("Unexpected property in the annotation"); + } + } + + public String getConnectionStringSetting() { + return connectionStringSetting; + } + + public void setConnectionStringSetting(String connectionStringSetting) { + this.connectionStringSetting = connectionStringSetting; + } + + public String getDatabaseName() { + return databaseName; + } + + public void setDatabaseName(String databaseName) { + this.databaseName = databaseName; + } + + public String getCollectionName() { + return collectionName; + } + + public void setCollectionName(String collectionName) { + this.collectionName = collectionName; + } + + public boolean getCreateLeaseCollectionIfNotExists() { + return createLeaseCollectionIfNotExists; + } + + public void setCreateLeaseCollectionIfNotExists(boolean createLeaseCollectionIfNotExists) { + this.createLeaseCollectionIfNotExists = createLeaseCollectionIfNotExists; + } + + public boolean isCreateLeaseCollectionIfNotExists() { + return createLeaseCollectionIfNotExists; + } + + public int getLeasesCollectionThroughput() { + return leasesCollectionThroughput; + } + + public void setLeasesCollectionThroughput(int leasesCollectionThroughput) { + this.leasesCollectionThroughput = leasesCollectionThroughput; + } + + @Override + public JsonObject getJsonObject() { + JsonObject inputTrigger = new JsonObject(); + inputTrigger.addProperty("type", this.getTriggerType()); + inputTrigger.addProperty("connectionStringSetting", this.connectionStringSetting); + inputTrigger.addProperty("databaseName", databaseName); + inputTrigger.addProperty("collectionName", this.collectionName); + inputTrigger.addProperty("name", this.getVarName()); + inputTrigger.addProperty("direction", this.getDirection()); + inputTrigger.addProperty("createLeaseCollectionIfNotExists", this.createLeaseCollectionIfNotExists); + inputTrigger.addProperty("leasesCollectionThroughput", this.leasesCollectionThroughput); + return inputTrigger; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/http/HTTPOutputBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/http/HTTPOutputBinding.java new file mode 100644 index 00000000..74084ed0 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/http/HTTPOutputBinding.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service.http; + +import com.google.gson.JsonObject; +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import org.ballerinax.azurefunctions.service.OutputBinding; + +/** + * Represents a HTTP Output binding in function.json. + * + * @since 2.0.0 + */ +public class HTTPOutputBinding extends OutputBinding { + + public HTTPOutputBinding(AnnotationNode annotationNode) { + super("http"); + this.setVarName("resp"); + } + + @Override + public JsonObject getJsonObject() { + JsonObject output = new JsonObject(); + output.addProperty("type", this.getTriggerType()); + output.addProperty("direction", this.getDirection()); + output.addProperty("name", this.getVarName()); + return output; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/http/HTTPTriggerBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/http/HTTPTriggerBinding.java new file mode 100644 index 00000000..72fbca56 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/http/HTTPTriggerBinding.java @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service.http; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import io.ballerina.compiler.syntax.tree.BasicLiteralNode; +import io.ballerina.compiler.syntax.tree.ExpressionNode; +import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.MappingConstructorExpressionNode; +import io.ballerina.compiler.syntax.tree.MappingFieldNode; +import io.ballerina.compiler.syntax.tree.MetadataNode; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.ParameterNode; +import io.ballerina.compiler.syntax.tree.QualifiedNameReferenceNode; +import io.ballerina.compiler.syntax.tree.RequiredParameterNode; +import io.ballerina.compiler.syntax.tree.ResourcePathParameterNode; +import io.ballerina.compiler.syntax.tree.ReturnTypeDescriptorNode; +import io.ballerina.compiler.syntax.tree.SeparatedNodeList; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import io.ballerina.compiler.syntax.tree.SyntaxKind; +import org.ballerinax.azurefunctions.Constants; +import org.ballerinax.azurefunctions.FunctionContext; +import org.ballerinax.azurefunctions.Util; +import org.ballerinax.azurefunctions.service.Binding; +import org.ballerinax.azurefunctions.service.InputBindingBuilder; +import org.ballerinax.azurefunctions.service.OutputBindingBuilder; +import org.ballerinax.azurefunctions.service.TriggerBinding; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * Represents a HTTP Trigger binding in functions.json. + * + * @since 2.0.0 + */ +public class HTTPTriggerBinding extends TriggerBinding { + + private String path; + private String authLevel = "anonymous"; + private String methods; + + public HTTPTriggerBinding(ServiceDeclarationNode serviceDeclarationNode, SemanticModel semanticModel) { + super("httpTrigger"); + this.setVarName("httpPayload"); + this.serviceDeclarationNode = serviceDeclarationNode; + this.semanticModel = semanticModel; + } + + @Override + public List getBindings() { + Optional httpTriggerAnnot = + getListenerAnnotation(this.serviceDeclarationNode, Constants.ANNOTATION_HTTP_TRIGGER); + String servicePath = Util.resourcePathToString(serviceDeclarationNode.absoluteResourcePath()); + servicePath = servicePath.replace("\\", ""); + List functionContexts = new ArrayList<>(); + NodeList members = this.serviceDeclarationNode.members(); + for (Node node : members) { + HTTPTriggerBinding httpTriggerBinding = + new HTTPTriggerBinding(this.serviceDeclarationNode, this.semanticModel); + httpTriggerAnnot.ifPresent(trigger -> getAnnotation(httpTriggerBinding, trigger)); + List bindings = new ArrayList<>(); + if (SyntaxKind.RESOURCE_ACCESSOR_DEFINITION != node.kind()) { + continue; + } + FunctionDefinitionNode functionDefinitionNode = (FunctionDefinitionNode) node; + String method = functionDefinitionNode.functionName().text(); + httpTriggerBinding.setMethods(method); + StringBuilder resourcePath = new StringBuilder(); + resourcePath.append(servicePath); + for (Node pathBlock : functionDefinitionNode.relativeResourcePath()) { + if (pathBlock.kind() == SyntaxKind.IDENTIFIER_TOKEN) { + String specialCharReplacedPathBlock = (((IdentifierToken) pathBlock).text()).replace("\\", ""); + resourcePath.append("/").append(specialCharReplacedPathBlock); + continue; + } + if (pathBlock.kind() == SyntaxKind.RESOURCE_PATH_SEGMENT_PARAM) { + ResourcePathParameterNode pathParamNode = (ResourcePathParameterNode) pathBlock; + //TODO Handle optional + resourcePath.append("/" + "{").append(pathParamNode.paramName().get().text()).append("}"); + } + //TODO add wildcard + } + httpTriggerBinding.setPath(getFunctionPath(resourcePath.toString())); + bindings.add(httpTriggerBinding); + String variableName; + SeparatedNodeList parameters = functionDefinitionNode.functionSignature().parameters(); + for (ParameterNode parameterNode : parameters) { + if (parameterNode.kind() != SyntaxKind.REQUIRED_PARAM) { + continue; + } + RequiredParameterNode reqParam = (RequiredParameterNode) parameterNode; + if (reqParam.paramName().isEmpty()) { + continue; + } + variableName = reqParam.paramName().get().text(); + InputBindingBuilder inputBuilder = new InputBindingBuilder(); + Optional inputBinding = inputBuilder.getInputBinding(reqParam.annotations(), variableName); + inputBinding.ifPresent(bindings::add); + } + Optional returnTypeDescriptor = + functionDefinitionNode.functionSignature().returnTypeDesc(); + if (returnTypeDescriptor.isEmpty()) { + bindings.add(new HTTPOutputBinding(null)); + } else { + ReturnTypeDescriptorNode returnTypeNode = returnTypeDescriptor.get(); + OutputBindingBuilder outputBuilder = new OutputBindingBuilder(); + Optional returnBinding = outputBuilder.getOutputBinding(returnTypeNode.annotations()); + if (returnBinding.isEmpty()) { + bindings.add(new HTTPOutputBinding(null)); + } else { + bindings.add(returnBinding.get()); //TODO handle in code analyzer + } + } + Optional functionName = getFunctionNameFromAnnotation(functionDefinitionNode); + functionContexts.add(new FunctionContext(functionName.get(), bindings)); + } + return functionContexts; + } + + private String getFunctionPath(String resourcePath) { + if (resourcePath.startsWith("/")) { + return resourcePath.substring(1); + } else { + return resourcePath; + } + } + + private void getAnnotation(HTTPTriggerBinding triggerBinding, AnnotationNode queueTrigger) { + SeparatedNodeList fields = queueTrigger.annotValue().orElseThrow().fields(); + for (MappingFieldNode fieldNode : fields) { + extractValueFromAnnotation(triggerBinding, (SpecificFieldNode) fieldNode); + } + } + + private void extractValueFromAnnotation(HTTPTriggerBinding triggerBinding, SpecificFieldNode fieldNode) { + String text = ((IdentifierToken) fieldNode.fieldName()).text(); + Optional value = Util.extractValueFromAnnotationField(fieldNode); + switch (text) { + case "authLevel": + value.ifPresent(triggerBinding::setAuthLevel); + break; + default: + throw new RuntimeException("Unexpected property in the annotation"); + } + } + + public Optional getFunctionNameFromAnnotation(FunctionDefinitionNode functionDefinitionNode) { + MetadataNode metadataNode = functionDefinitionNode.metadata().orElseThrow(); + NodeList annotations = metadataNode.annotations(); + for (AnnotationNode annotationNode : annotations) { + Node ref = annotationNode.annotReference(); + if (ref.kind() != SyntaxKind.QUALIFIED_NAME_REFERENCE) { + continue; + } + QualifiedNameReferenceNode qualifiedRef = (QualifiedNameReferenceNode) ref; + if (!qualifiedRef.identifier().text().equals(Constants.FUNCTION_ANNOTATION)) { + continue; + } + Optional val = + annotationNode.annotValue(); + if (val.isEmpty()) { + continue; + } + SeparatedNodeList fields = val.get().fields(); + for (MappingFieldNode field : fields) { + if (field.kind() != SyntaxKind.SPECIFIC_FIELD) { + continue; + } + SpecificFieldNode specificFieldNode = (SpecificFieldNode) field; + Node fieldNameNode = specificFieldNode.fieldName(); + if (fieldNameNode.kind() != SyntaxKind.IDENTIFIER_TOKEN) { + continue; + } + String fieldName = ((IdentifierToken) fieldNameNode).text(); + if (!fieldName.equals("name")) { + continue; + } + Optional expressionNode = specificFieldNode.valueExpr(); + if (expressionNode.isEmpty()) { + continue; + } + ExpressionNode value = expressionNode.get(); + if (value.kind() != SyntaxKind.STRING_LITERAL) { + continue; + } + BasicLiteralNode literalNode = (BasicLiteralNode) value; + String functionName = literalNode.literalToken().text(); + return Optional.of(functionName.substring(1, functionName.length() - 1)); + } + } + return Optional.empty(); + } + + public void setPath(String path) { + this.path = path; + } + + public void setAuthLevel(String authLevel) { + this.authLevel = authLevel; + } + + public void setMethods(String methods) { + this.methods = methods; + } + + public String getPath() { + return path; + } + + public String getAuthLevel() { + return authLevel; + } + + public String getMethods() { + return methods; + } + + @Override + public JsonObject getJsonObject() { + JsonObject inputTrigger = new JsonObject(); + inputTrigger.addProperty("type", this.getTriggerType()); + inputTrigger.addProperty("authLevel", this.authLevel); + inputTrigger.add("methods", generateMethods()); + inputTrigger.addProperty("direction", this.getDirection()); + inputTrigger.addProperty("name", this.getVarName()); + inputTrigger.addProperty("route", this.getPath()); + return inputTrigger; + } + + private JsonArray generateMethods() { + JsonArray methods = new JsonArray(); + if (this.methods.equals("default")) { + methods.add("DELETE"); + methods.add("GET"); + methods.add("HEAD"); + methods.add("OPTIONS"); + methods.add("POST"); + methods.add("PUT"); + } else { + methods.add(this.methods); + } + return methods; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/queue/QueueOutputBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/queue/QueueOutputBinding.java new file mode 100644 index 00000000..3c2a7107 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/queue/QueueOutputBinding.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service.queue; + +import com.google.gson.JsonObject; +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.MappingFieldNode; +import io.ballerina.compiler.syntax.tree.SeparatedNodeList; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import org.ballerinax.azurefunctions.Constants; +import org.ballerinax.azurefunctions.Util; +import org.ballerinax.azurefunctions.service.OutputBinding; + +import java.util.Optional; + +/** + * Represents Queue output binding in functions.json. + * + * @since 2.0.0 + */ +public class QueueOutputBinding extends OutputBinding { + + private String connection = "AzureWebJobsStorage"; + private String queueName; + + public QueueOutputBinding(AnnotationNode annotationNode) { + super("queue"); + this.setVarName(Constants.RETURN_VAR_NAME); + SeparatedNodeList fields = annotationNode.annotValue().orElseThrow().fields(); + for (MappingFieldNode fieldNode : fields) { + extractValueFromAnnotation((SpecificFieldNode) fieldNode); + } + } + + private void extractValueFromAnnotation(SpecificFieldNode fieldNode) { + String text = ((IdentifierToken) fieldNode.fieldName()).text(); + Optional value = Util.extractValueFromAnnotationField(fieldNode); + switch (text) { + case "queueName": + value.ifPresent(this::setQueueName); + break; + case "connection": + value.ifPresent(this::setConnection); + break; + default: + throw new RuntimeException("Unexpected property in the annotation"); + } + } + + public String getConnection() { + return connection; + } + + public void setConnection(String connection) { + this.connection = connection; + } + + public String getQueueName() { + return queueName; + } + + public void setQueueName(String queueName) { + this.queueName = queueName; + } + + @Override + public JsonObject getJsonObject() { + JsonObject output = new JsonObject(); + output.addProperty("type", this.getTriggerType()); + output.addProperty("connection", this.connection); + output.addProperty("queueName", this.queueName); + output.addProperty("direction", this.getDirection()); + output.addProperty("name", this.getVarName()); + return output; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/queue/QueueTriggerBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/queue/QueueTriggerBinding.java new file mode 100644 index 00000000..68340178 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/queue/QueueTriggerBinding.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service.queue; + +import com.google.gson.JsonObject; +import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import org.ballerinax.azurefunctions.Constants; +import org.ballerinax.azurefunctions.Util; +import org.ballerinax.azurefunctions.service.RemoteTriggerBinding; + +import java.util.Optional; + +/** + * Represents a queue trigger binding in function.json. + * + * @since 2.0.0 + */ +public class QueueTriggerBinding extends RemoteTriggerBinding { + + private String connection = "AzureWebJobsStorage"; + private String queueName; + + public QueueTriggerBinding(ServiceDeclarationNode serviceDeclarationNode, SemanticModel semanticModel) { + super("queueTrigger", "onMessage", Constants.ANNOTATION_QUEUE_TRIGGER, serviceDeclarationNode, semanticModel); + } + + @Override + protected void extractValueFromAnnotation(SpecificFieldNode fieldNode) { + String text = ((IdentifierToken) fieldNode.fieldName()).text(); + Optional value = Util.extractValueFromAnnotationField(fieldNode); + switch (text) { + case "queueName": + value.ifPresent(this::setQueueName); + break; + case "connection": + value.ifPresent(this::setConnection); + break; + default: + throw new RuntimeException("Unexpected property in the annotation"); + } + } + + public String getConnection() { + return connection; + } + + public void setConnection(String connection) { + this.connection = connection; + } + + public String getQueueName() { + return queueName; + } + + public void setQueueName(String queueName) { + this.queueName = queueName; + } + + @Override + public JsonObject getJsonObject() { + JsonObject inputTrigger = new JsonObject(); + inputTrigger.addProperty("type", this.getTriggerType()); + inputTrigger.addProperty("connection", this.connection); + if (this.queueName != null) { + inputTrigger.addProperty("queueName", this.queueName); + } + inputTrigger.addProperty("direction", this.getDirection()); + inputTrigger.addProperty("name", this.getVarName()); + return inputTrigger; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/timer/TimerTriggerBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/timer/TimerTriggerBinding.java new file mode 100644 index 00000000..bd8955f6 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/timer/TimerTriggerBinding.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service.timer; + +import com.google.gson.JsonObject; +import io.ballerina.compiler.api.SemanticModel; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import org.ballerinax.azurefunctions.Constants; +import org.ballerinax.azurefunctions.Util; +import org.ballerinax.azurefunctions.service.RemoteTriggerBinding; + +import java.util.Optional; + +/** + * Represents a timer trigger binding in function.json. + * + * @since 2.0.0 + */ +public class TimerTriggerBinding extends RemoteTriggerBinding { + + private String schedule; + private boolean runOnStartup = true; + + public TimerTriggerBinding(ServiceDeclarationNode serviceDeclarationNode, SemanticModel semanticModel) { + super("timerTrigger", "onTrigger", Constants.ANNOTATION_TIMER_TRIGGER, serviceDeclarationNode, semanticModel); + } + + @Override + protected void extractValueFromAnnotation(SpecificFieldNode fieldNode) { + String text = ((IdentifierToken) fieldNode.fieldName()).text(); + Optional value = Util.extractValueFromAnnotationField(fieldNode); + switch (text) { + case "schedule": + value.ifPresent(this::setSchedule); + break; + case "runOnStartup": + value.ifPresent(runOnStartup1 -> setRunOnStartup(Boolean.parseBoolean(runOnStartup1))); + break; + default: + throw new RuntimeException("Unexpected property in the annotation"); + } + } + + public String getSchedule() { + return schedule; + } + + public void setSchedule(String schedule) { + this.schedule = schedule; + } + + public boolean isRunOnStartup() { + return runOnStartup; + } + + public void setRunOnStartup(boolean runOnStartup) { + this.runOnStartup = runOnStartup; + } + + @Override + public JsonObject getJsonObject() { + JsonObject inputTrigger = new JsonObject(); + inputTrigger.addProperty("type", this.getTriggerType()); + inputTrigger.addProperty("schedule", this.schedule); + inputTrigger.addProperty("runOnStartup", this.runOnStartup); + inputTrigger.addProperty("direction", this.getDirection()); + inputTrigger.addProperty("name", this.getVarName()); + return inputTrigger; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/twilio/TwilioSmsOutputBinding.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/twilio/TwilioSmsOutputBinding.java new file mode 100644 index 00000000..5432d73d --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/service/twilio/TwilioSmsOutputBinding.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.service.twilio; + +import com.google.gson.JsonObject; +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.MappingFieldNode; +import io.ballerina.compiler.syntax.tree.SeparatedNodeList; +import io.ballerina.compiler.syntax.tree.SpecificFieldNode; +import org.ballerinax.azurefunctions.Constants; +import org.ballerinax.azurefunctions.Util; +import org.ballerinax.azurefunctions.service.OutputBinding; + +import java.util.Optional; + +/** + * Represents Twilio SMS output binding in functions.json. + * + * @since 2.0.0 + */ +public class TwilioSmsOutputBinding extends OutputBinding { + + private String accountSidSetting = "AzureWebJobsTwilioAccountSid"; + private String authTokenSetting = "AzureWebJobsTwilioAuthToken"; + private String from; + private String to; + + public TwilioSmsOutputBinding(AnnotationNode annotationNode) { + super("twilioSms"); + this.setVarName(Constants.RETURN_VAR_NAME); + SeparatedNodeList fields = annotationNode.annotValue().orElseThrow().fields(); + for (MappingFieldNode fieldNode : fields) { + extractValueFromAnnotation((SpecificFieldNode) fieldNode); + } + } + + private void extractValueFromAnnotation(SpecificFieldNode fieldNode) { + String text = ((IdentifierToken) fieldNode.fieldName()).text(); + Optional value = Util.extractValueFromAnnotationField(fieldNode); + switch (text) { + case "accountSidSetting": + value.ifPresent(this::setAccountSidSetting); + break; + case "authTokenSetting": + value.ifPresent(this::setAuthTokenSetting); + break; + case "'from": + value.ifPresent(this::setFrom); + break; + case "to": + value.ifPresent(this::setTo); + break; + default: + throw new RuntimeException("Unexpected property in the annotation"); + } + } + + public String getAccountSidSetting() { + return accountSidSetting; + } + + public void setAccountSidSetting(String accountSidSetting) { + this.accountSidSetting = accountSidSetting; + } + + public String getAuthTokenSetting() { + return authTokenSetting; + } + + public void setAuthTokenSetting(String authTokenSetting) { + this.authTokenSetting = authTokenSetting; + } + + public String getFrom() { + return from; + } + + public void setFrom(String from) { + this.from = from; + } + + public String getTo() { + return to; + } + + public void setTo(String to) { + this.to = to; + } + + @Override + public JsonObject getJsonObject() { + JsonObject output = new JsonObject(); + output.addProperty("type", this.getTriggerType()); + output.addProperty("accountSidSetting", this.accountSidSetting); + output.addProperty("authTokenSetting", this.authTokenSetting); + output.addProperty("from", this.from); + output.addProperty("to", this.to); + output.addProperty("direction", this.getDirection()); + output.addProperty("name", this.getVarName()); + return output; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/tooling/Extensions.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/tooling/Extensions.java new file mode 100644 index 00000000..4a1bd61e --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/tooling/Extensions.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.tooling; + +/** + * Represents extensions.json in the .vscode directory. + * + * @since 2201.3.0 + */ +public class Extensions { + + private String[] recommendations; + + public Extensions() { + this.recommendations = new String[1]; + this.recommendations[0] = "ms-azuretools.vscode-azurefunctions"; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/tooling/LocalSettings.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/tooling/LocalSettings.java new file mode 100644 index 00000000..56a5ea74 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/tooling/LocalSettings.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.tooling; + +import com.google.gson.annotations.SerializedName; + +import java.util.HashMap; +import java.util.Map; + +/** + * Represents local.settings.json in the target directory. + * + * @since 2201.3.0 + */ +public class LocalSettings { + + @SerializedName("IsEncrypted") + private boolean isEncrypted; + + @SerializedName("Values") + private Map values; + + public LocalSettings() { + this.isEncrypted = false; + this.values = new HashMap<>(); + this.values.put("AzureWebJobsStorage", ""); + this.values.put("FUNCTIONS_WORKER_RUNTIME", "java"); + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/tooling/Settings.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/tooling/Settings.java new file mode 100644 index 00000000..a62a92a3 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/tooling/Settings.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.tooling; + +import com.google.gson.annotations.SerializedName; +import org.ballerinax.azurefunctions.Constants; + +/** + * Represents settings.json in the .vscode directory. + * + * @since 2201.3.0 + */ +public class Settings { + + @SerializedName("azureFunctions.deploySubpath") + private String deploySubpath; + + @SerializedName("azureFunctions.projectLanguage") + private String projectLanguage; + + @SerializedName("azureFunctions.projectRuntime") + private String projectRuntime; + + @SerializedName("debug.internalConsoleOptions") + private String internalConsoleOptions; + + public Settings() { + this.deploySubpath = Constants.ARTIFACT_PATH; + this.projectLanguage = "Custom"; + this.projectRuntime = "~4"; + this.internalConsoleOptions = "neverOpen"; + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/tooling/Tasks.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/tooling/Tasks.java new file mode 100644 index 00000000..03c96a17 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/tooling/Tasks.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.tooling; + +import org.ballerinax.azurefunctions.Constants; + +import java.util.HashMap; +import java.util.Map; + +/** + * Represents tasks.json in the .vscode directory. + * + * @since 2201.3.0 + */ +public class Tasks { + + private String version; + private Tasks.Task[] tasks; + + public Tasks() { + this.version = "2.0.0"; + this.tasks = new Tasks.Task[1]; + this.tasks[0] = new Tasks.Task(); + } + + static class Task { + + private String type; + private String command; + private String problemMatcher; + private boolean isBackground; + private Map options; + + public Task() { + this.type = "func"; + this.command = "host start"; + this.problemMatcher = "$func-watch"; + this.isBackground = true; + this.options = new HashMap<>(); + this.options.put("cwd", "${workspaceFolder}/" + Constants.ARTIFACT_PATH); + } + } +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/validators/AzureFunctionsCodeAnalyzerTask.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/validators/AzureFunctionsCodeAnalyzerTask.java new file mode 100644 index 00000000..3add33dc --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/validators/AzureFunctionsCodeAnalyzerTask.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.ballerinax.azurefunctions.validators; + +import io.ballerina.compiler.api.symbols.ModuleSymbol; +import io.ballerina.compiler.api.symbols.ServiceDeclarationSymbol; +import io.ballerina.compiler.api.symbols.Symbol; +import io.ballerina.compiler.api.symbols.TypeDescKind; +import io.ballerina.compiler.api.symbols.TypeReferenceTypeSymbol; +import io.ballerina.compiler.api.symbols.TypeSymbol; +import io.ballerina.compiler.api.symbols.UnionTypeSymbol; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import io.ballerina.projects.plugins.AnalysisTask; +import io.ballerina.projects.plugins.SyntaxNodeAnalysisContext; +import io.ballerina.tools.diagnostics.Diagnostic; +import io.ballerina.tools.diagnostics.DiagnosticSeverity; +import org.ballerinax.azurefunctions.Constants; + +import java.util.List; +import java.util.Optional; + +import static org.ballerinax.azurefunctions.Constants.AZURE_FUNCTIONS_MODULE_NAME; +import static org.ballerinax.azurefunctions.Constants.AZURE_FUNCTIONS_PACKAGE_ORG; +import static org.ballerinax.azurefunctions.validators.HttpListenerValidator.validate; + +/*** + * Code analyzer for azure function specific validations. + * + * @since 2.0.0 + */ +public class AzureFunctionsCodeAnalyzerTask implements AnalysisTask { + + @Override + public void perform(SyntaxNodeAnalysisContext syntaxNodeAnalysisContext) { + List diagnostics = syntaxNodeAnalysisContext.semanticModel().diagnostics(); + boolean erroneousCompilation = diagnostics.stream() + .anyMatch(d -> DiagnosticSeverity.ERROR.equals(d.diagnosticInfo().severity())); + if (erroneousCompilation) { + return; + } + + ServiceDeclarationNode serviceDeclarationNode = (ServiceDeclarationNode) syntaxNodeAnalysisContext.node(); + Optional serviceSymOptional = syntaxNodeAnalysisContext.semanticModel().symbol(serviceDeclarationNode); + + if (serviceSymOptional.isPresent()) { + List listenerTypes = ((ServiceDeclarationSymbol) serviceSymOptional.get()).listenerTypes(); + if (listenerTypes.stream().noneMatch(this::isListenerBelongsToAzureFuncModule)) { + return; + } + if (listenerTypes.stream().anyMatch(this::isHTTPListener)) { + validate(syntaxNodeAnalysisContext, serviceDeclarationNode); + } + } + } + + + + private boolean isHTTPListener(TypeSymbol listenerType) { + return listenerType.nameEquals(Constants.AZURE_HTTP_LISTENER); + } + + private boolean isListenerBelongsToAzureFuncModule(TypeSymbol listenerType) { + if (TypeDescKind.UNION == listenerType.typeKind()) { + return ((UnionTypeSymbol) listenerType).memberTypeDescriptors().stream() + .filter(typeDescriptor -> typeDescriptor instanceof TypeReferenceTypeSymbol) + .map(typeReferenceTypeSymbol -> (TypeReferenceTypeSymbol) typeReferenceTypeSymbol) + .anyMatch(typeReferenceTypeSymbol -> isAzureFuncModule(typeReferenceTypeSymbol.getModule().get())); + } + + if (TypeDescKind.TYPE_REFERENCE == listenerType.typeKind()) { + return isAzureFuncModule(((TypeReferenceTypeSymbol) listenerType).typeDescriptor().getModule().get()); + } + return false; + } + + private boolean isAzureFuncModule(ModuleSymbol moduleSymbol) { + return AZURE_FUNCTIONS_MODULE_NAME.equals(moduleSymbol.getName().get()) && + AZURE_FUNCTIONS_PACKAGE_ORG.equals(moduleSymbol.id().orgName()); + } + +} diff --git a/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/validators/HttpListenerValidator.java b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/validators/HttpListenerValidator.java new file mode 100644 index 00000000..183998b5 --- /dev/null +++ b/compiler-plugin/src/main/java/org/ballerinax/azurefunctions/validators/HttpListenerValidator.java @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.ballerinax.azurefunctions.validators; + +import io.ballerina.compiler.api.symbols.AnnotationSymbol; +import io.ballerina.compiler.api.symbols.ArrayTypeSymbol; +import io.ballerina.compiler.api.symbols.IntersectionTypeSymbol; +import io.ballerina.compiler.api.symbols.ModuleSymbol; +import io.ballerina.compiler.api.symbols.ParameterSymbol; +import io.ballerina.compiler.api.symbols.RecordFieldSymbol; +import io.ballerina.compiler.api.symbols.RecordTypeSymbol; +import io.ballerina.compiler.api.symbols.ResourceMethodSymbol; +import io.ballerina.compiler.api.symbols.Symbol; +import io.ballerina.compiler.api.symbols.TypeDescKind; +import io.ballerina.compiler.api.symbols.TypeReferenceTypeSymbol; +import io.ballerina.compiler.api.symbols.TypeSymbol; +import io.ballerina.compiler.api.symbols.UnionTypeSymbol; +import io.ballerina.compiler.syntax.tree.AnnotationNode; +import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode; +import io.ballerina.compiler.syntax.tree.IdentifierToken; +import io.ballerina.compiler.syntax.tree.MappingConstructorExpressionNode; +import io.ballerina.compiler.syntax.tree.MappingFieldNode; +import io.ballerina.compiler.syntax.tree.MetadataNode; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NodeList; +import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; +import io.ballerina.compiler.syntax.tree.SyntaxKind; +import io.ballerina.projects.plugins.SyntaxNodeAnalysisContext; +import io.ballerina.tools.diagnostics.DiagnosticFactory; +import io.ballerina.tools.diagnostics.DiagnosticInfo; +import io.ballerina.tools.diagnostics.Location; +import org.ballerinax.azurefunctions.AzureDiagnosticCodes; +import org.wso2.ballerinalang.compiler.diagnostic.properties.BSymbolicProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import static org.ballerinax.azurefunctions.AzureDiagnosticCodes.AF_008; +import static org.ballerinax.azurefunctions.Constants.AZURE_FUNCTIONS_MODULE_NAME; +import static org.ballerinax.azurefunctions.Constants.COLON; +import static org.ballerinax.azurefunctions.Constants.HEADER_ANNOTATION_TYPE; +import static org.ballerinax.azurefunctions.Constants.HTTP; +import static org.ballerinax.azurefunctions.Constants.SERVICE_CONFIG_ANNOTATION; +import static org.ballerinax.azurefunctions.Constants.TREAT_NILABLE_AS_OPTIONAL; +import static org.ballerinax.azurefunctions.Util.updateDiagnostic; + +/** + * Validates azure-function service on a HTTPListener . + */ +class HttpListenerValidator { + + static void validate(SyntaxNodeAnalysisContext syntaxNodeAnalysisContext, + ServiceDeclarationNode serviceDeclarationNode) { + extractServiceAnnotationAndValidate(syntaxNodeAnalysisContext, serviceDeclarationNode); + NodeList members = serviceDeclarationNode.members(); + for (Node member : members) { + if (member.kind() == SyntaxKind.RESOURCE_ACCESSOR_DEFINITION) { + validateResourceFunction(syntaxNodeAnalysisContext, (FunctionDefinitionNode) member); + } + } + + } + + private static void validateResourceFunction(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode member) { + validateInputParameters(ctx, member); + //TODO : Other necessary validation for a resource function + } + + private static void extractServiceAnnotationAndValidate(SyntaxNodeAnalysisContext syntaxNodeAnalysisContext, + ServiceDeclarationNode serviceDeclarationNode) { + //HTTP serviceconfig validation currently supports only for treatNilableAsTrue field + Optional metadataNodeOptional = serviceDeclarationNode.metadata(); + if (metadataNodeOptional.isEmpty()) { + return; + } + NodeList annotations = metadataNodeOptional.get().annotations(); + for (AnnotationNode annotation : annotations) { + Node annotReference = annotation.annotReference(); + String annotName = annotReference.toString(); + Optional annotValue = annotation.annotValue(); + if (annotReference.kind() != SyntaxKind.QUALIFIED_NAME_REFERENCE) { + continue; + } + String[] annotStrings = annotName.split(COLON); + if (SERVICE_CONFIG_ANNOTATION.equals(annotStrings[annotStrings.length - 1].trim()) + && (annotValue.isPresent())) { + MappingConstructorExpressionNode mapping = annotValue.get(); + NodeList fields = mapping.fields(); + if (fields.size() == 1) { + MappingFieldNode field = (MappingFieldNode) fields.get(0); + String fieldName = ((IdentifierToken) (field.children()).get(0)).text(); + if (!TREAT_NILABLE_AS_OPTIONAL.equals(fieldName)) { + warnInvalidServiceConfig(syntaxNodeAnalysisContext, field); + } + } else { + warnInvalidServiceConfig(syntaxNodeAnalysisContext, mapping); + } + } + } + + } + + private static void validateInputParameters(SyntaxNodeAnalysisContext ctx, FunctionDefinitionNode member) { + Optional resourceMethodSymbolOptional = ctx.semanticModel().symbol(member); + Location paramLocation = member.location(); + if (resourceMethodSymbolOptional.isEmpty()) { + return; + } + Optional> parametersOptional = + ((ResourceMethodSymbol) resourceMethodSymbolOptional.get()).typeDescriptor().params(); + if (parametersOptional.isEmpty()) { + return; + } + + for (ParameterSymbol param : parametersOptional.get()) { + Optional paramLocationOptional = param.getLocation(); + if (paramLocationOptional.isPresent()) { + paramLocation = paramLocationOptional.get(); + } + Optional nameOptional = param.getName(); + String paramName = nameOptional.isEmpty() ? "" : nameOptional.get(); + + List annotations = param.annotations().stream() + .filter(annotationSymbol -> annotationSymbol.typeDescriptor().isPresent()) + .collect(Collectors.toList()); + + if (!annotations.isEmpty()) { + validateAnnotatedInputParam(ctx, paramLocation, param, paramName, annotations); + } + + } + } + + private static void validateAnnotatedInputParam(SyntaxNodeAnalysisContext ctx, Location paramLocation, + ParameterSymbol param, String paramName, + List annotations) { + + for (AnnotationSymbol annotation : annotations) { + Optional typeSymbolOptional = annotation.typeDescriptor(); + if (typeSymbolOptional.isEmpty()) { + reportInvalidParameter(ctx, paramLocation, paramName); + continue; + } + // validate annotation module + Optional moduleSymbolOptional = typeSymbolOptional.get().getModule(); + if (moduleSymbolOptional.isEmpty()) { + reportInvalidParameter(ctx, paramLocation, paramName); + continue; + } + Optional nameSymbolOptional = moduleSymbolOptional.get().getName(); + if (nameSymbolOptional.isEmpty()) { + reportInvalidParameter(ctx, paramLocation, paramName); + continue; + } + if (!HTTP.equals(nameSymbolOptional.get()) && + !AZURE_FUNCTIONS_MODULE_NAME.equals(nameSymbolOptional.get())) { + reportInvalidParameterAnnotation(ctx, paramLocation, paramName); + continue; + } + + Optional annotationTypeNameOptional = typeSymbolOptional.get().getName(); + if (annotationTypeNameOptional.isEmpty()) { + reportInvalidParameter(ctx, paramLocation, paramName); + continue; + } + String typeName = annotationTypeNameOptional.get(); + TypeSymbol typeDescriptor = param.typeDescriptor(); + if (typeDescriptor.typeKind() == TypeDescKind.INTERSECTION) { + typeDescriptor = + getEffectiveTypeFromReadonlyIntersection((IntersectionTypeSymbol) typeDescriptor); + if (typeDescriptor == null) { + reportInvalidIntersectionType(ctx, paramLocation, typeName); + continue; + } + } + if (HEADER_ANNOTATION_TYPE.equals(typeName)) { + if (annotations.size() == 2) { + reportInvalidMultipleAnnotation(ctx, paramLocation, paramName); + continue; + } + validateHeaderParamType(ctx, paramLocation, param, paramName, typeDescriptor); + break; + } + } + } + + private static void validateHeaderParamType(SyntaxNodeAnalysisContext ctx, Location paramLocation, Symbol param, + String paramName, TypeSymbol paramTypeDescriptor) { + switch (paramTypeDescriptor.typeKind()) { + case STRING: + case INT: + case DECIMAL: + case FLOAT: + case BOOLEAN: + break; + case ARRAY: + TypeSymbol arrTypeSymbol = ((ArrayTypeSymbol) paramTypeDescriptor).memberTypeDescriptor(); + TypeDescKind arrElementKind = arrTypeSymbol.typeKind(); + checkAllowedHeaderParamTypes(ctx, paramLocation, param, paramName, arrElementKind); + break; + case UNION: + List symbolList = ((UnionTypeSymbol) paramTypeDescriptor).memberTypeDescriptors(); + int size = symbolList.size(); + if (size > 2) { + reportInvalidUnionHeaderType(ctx, paramLocation, paramName); + return; + } + if (symbolList.stream().noneMatch(type -> type.typeKind() == TypeDescKind.NIL)) { + reportInvalidUnionHeaderType(ctx, paramLocation, paramName); + return; + } + for (TypeSymbol type : symbolList) { + TypeDescKind elementKind = type.typeKind(); + if (elementKind == TypeDescKind.ARRAY) { + elementKind = ((ArrayTypeSymbol) type).memberTypeDescriptor().typeKind(); + checkAllowedHeaderParamUnionType(ctx, paramLocation, param, paramName, elementKind); + continue; + } + if (elementKind == TypeDescKind.TYPE_REFERENCE) { + validateHeaderParamType(ctx, paramLocation, param, paramName, type); + return; + } + checkAllowedHeaderParamTypes(ctx, paramLocation, param, paramName, elementKind); + } + break; + case TYPE_REFERENCE: + TypeSymbol typeDescriptor = ((TypeReferenceTypeSymbol) paramTypeDescriptor).typeDescriptor(); + TypeDescKind typeDescKind = typeDescriptor.typeKind(); + if (typeDescKind == TypeDescKind.RECORD) { + validateHeaderRecordFields(ctx, paramLocation, typeDescriptor); + } else { + reportInvalidHeaderParameterType(ctx, paramLocation, paramName, param); + } + break; + case RECORD: + validateHeaderRecordFields(ctx, paramLocation, paramTypeDescriptor); + break; + default: + reportInvalidHeaderParameterType(ctx, paramLocation, paramName, param); + break; + } + } + + private static void checkAllowedHeaderParamTypes(SyntaxNodeAnalysisContext ctx, Location paramLocation, + Symbol param, String paramName, TypeDescKind elementKind) { + if (!isAllowedHeaderParamPureType(elementKind)) { + reportInvalidHeaderParameterType(ctx, paramLocation, paramName, param); + } + } + + private static void checkAllowedHeaderParamUnionType(SyntaxNodeAnalysisContext ctx, Location paramLocation, + Symbol param, String paramName, TypeDescKind elementKind) { + if (!isAllowedHeaderParamPureType(elementKind)) { + reportInvalidUnionHeaderType(ctx, paramLocation, paramName); + } + } + + private static boolean isAllowedHeaderParamPureType(TypeDescKind elementKind) { + return elementKind == TypeDescKind.NIL || elementKind == TypeDescKind.STRING || + elementKind == TypeDescKind.INT || elementKind == TypeDescKind.FLOAT || + elementKind == TypeDescKind.DECIMAL || elementKind == TypeDescKind.BOOLEAN; + } + + private static void validateHeaderRecordFields(SyntaxNodeAnalysisContext ctx, Location paramLocation, + TypeSymbol typeDescriptor) { + RecordTypeSymbol recordTypeSymbol = (RecordTypeSymbol) typeDescriptor; + Map recordFieldSymbolMap = recordTypeSymbol.fieldDescriptors(); + for (Map.Entry entry : recordFieldSymbolMap.entrySet()) { + RecordFieldSymbol value = entry.getValue(); + typeDescriptor = value.typeDescriptor(); + String typeName = typeDescriptor.signature(); + TypeDescKind typeDescKind = typeDescriptor.typeKind(); + if (typeDescKind == TypeDescKind.INTERSECTION) { + typeDescriptor = getEffectiveTypeFromReadonlyIntersection((IntersectionTypeSymbol) typeDescriptor); + if (typeDescriptor == null) { + reportInvalidIntersectionType(ctx, paramLocation, typeName); + continue; + } + } + validateHeaderParamType(ctx, paramLocation, value, entry.getKey(), typeDescriptor); + } + Optional restTypeDescriptor = recordTypeSymbol.restTypeDescriptor(); + if (restTypeDescriptor.isPresent()) { + reportInvalidHeaderRecordRestFieldType(ctx, paramLocation); + } + } + + private static TypeSymbol getEffectiveTypeFromReadonlyIntersection(IntersectionTypeSymbol intersectionTypeSymbol) { + List effectiveTypes = new ArrayList<>(); + for (TypeSymbol typeSymbol : intersectionTypeSymbol.memberTypeDescriptors()) { + if (typeSymbol.typeKind() == TypeDescKind.READONLY) { + continue; + } + effectiveTypes.add(typeSymbol); + } + if (effectiveTypes.size() == 1) { + return effectiveTypes.get(0); + } + return null; + } + + private static void reportInvalidParameterAnnotation(SyntaxNodeAnalysisContext ctx, Location location, + String paramName) { + updateDiagnostic(ctx, location, AzureDiagnosticCodes.AF_001, paramName); + } + + private static void reportInvalidParameter(SyntaxNodeAnalysisContext ctx, Location location, + String paramName) { + updateDiagnostic(ctx, location, AzureDiagnosticCodes.AF_002, paramName); + } + + private static void reportInvalidHeaderParameterType(SyntaxNodeAnalysisContext ctx, Location location, + String paramName, Symbol parameterSymbol) { + updateDiagnostic(ctx, location, AzureDiagnosticCodes.AF_003, List.of(new BSymbolicProperty(parameterSymbol)) + , paramName); + } + + private static void reportInvalidUnionHeaderType(SyntaxNodeAnalysisContext ctx, Location location, + String paramName) { + updateDiagnostic(ctx, location, AzureDiagnosticCodes.AF_004, paramName); + } + + private static void reportInvalidIntersectionType(SyntaxNodeAnalysisContext ctx, Location location, + String typeName) { + updateDiagnostic(ctx, location, AzureDiagnosticCodes.AF_005, typeName); + } + + private static void reportInvalidHeaderRecordRestFieldType(SyntaxNodeAnalysisContext ctx, Location location) { + updateDiagnostic(ctx, location, AzureDiagnosticCodes.AF_006); + } + + private static void reportInvalidMultipleAnnotation(SyntaxNodeAnalysisContext ctx, Location location, + String paramName) { + updateDiagnostic(ctx, location, AzureDiagnosticCodes.AF_007, paramName); + } + + private static void warnInvalidServiceConfig(SyntaxNodeAnalysisContext ctx, Node node) { + DiagnosticInfo diagInfo = new DiagnosticInfo(AF_008.getCode(), AF_008.getMessage(), AF_008.getSeverity()); + ctx.reportDiagnostic(DiagnosticFactory.createDiagnostic(diagInfo, node.location())); + } +} + + diff --git a/gradle.properties b/gradle.properties index 0c86c84f..52f6feed 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,26 +1,26 @@ org.gradle.caching=true org.gradle.jvmargs='-Dfile.encoding=UTF-8' group=org.ballerinax.azurefunctions -version=2.1.1-SNAPSHOT +version=3.0.0-alpha.1 systemProp.org.gradle.internal.publish.checksums.insecure=true -ballerinaLangVersion=2201.2.0-rc1.5 -ballerinaGradlePluginVersion=0.15.0 -stdlibConstraintVersion=1.0.0-20220726-233800-e82b939 -stdlibIoVersion=1.3.0-20220726-234900-e51598f -stdlibLogVersion=2.4.0-20220727-001500-4a36356 -stdlibHttpVersion=2.4.0-20220727-144300-3e37b95 -stdlibAuthVersion=2.4.0-20220727-002600-eb5dacb -stdlibFileVersion=1.4.0-20220727-002600-75ae25a +ballerinaLangVersion=2201.2.1 +stdlibConstraintVersion=1.0.0 +stdlibIoVersion=1.3.0 +stdlibLogVersion=2.4.0 +stdlibHttpVersion=2.4.0 +stdlibAuthVersion=2.4.0 +stdlibFileVersion=1.4.0 stdlibRegexVersion=1.3.0 stdlibCacheVersion=3.2.2 stdlibCryptoVersion=2.2.2 stdlibTimeVersion=2.2.2 -stdlibMimeVersion=2.4.0-20220727-002600-4748bde -stdlibOsVersion=1.4.0-20220727-000400-fcf165d +stdlibMimeVersion=2.4.0 +stdlibOsVersion=1.4.0 stdlibTaskVersion=2.2.2 -stdlibJwtVersion=2.4.0-20220727-002600-ffaab89 -stdlibOAuth2Version=2.4.0-20220727-002900-170dc7f +stdlibJwtVersion=2.4.0 +stdlibOAuth2Version=2.4.0 stdlibUuidVersion=1.3.0 stdlibUrlVersion=2.2.2 observeVersion=1.0.5 observeInternalVersion=1.0.4 +ballerinaGradlePluginVersion=0.14.3 diff --git a/native/build.gradle b/native/build.gradle new file mode 100644 index 00000000..3f592d3e --- /dev/null +++ b/native/build.gradle @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +plugins { + id 'java' + id 'checkstyle' + id 'com.github.spotbugs' +} + +description = 'Ballerina - Azure Functions Java Utils' + +dependencies { + checkstyle project(':checkstyle') + checkstyle "com.puppycrawl.tools:checkstyle:${puppycrawlCheckstyleVersion}" + implementation group: 'org.ballerinalang', name: 'ballerina-lang', version: "${ballerinaLangVersion}" + implementation group: 'org.ballerinalang', name: 'ballerina-tools-api', version: "${ballerinaLangVersion}" + implementation group: 'org.ballerinalang', name: 'value', version: "${ballerinaLangVersion}" + implementation group: 'org.ballerinalang', name: 'bool', version: "${ballerinaLangVersion}" + implementation group: 'org.ballerinalang', name: 'floatingpoint', version: "${ballerinaLangVersion}" + implementation group: 'org.ballerinalang', name: 'integer', version: "${ballerinaLangVersion}" + implementation group: 'org.ballerinalang', name: 'decimal', version: "${ballerinaLangVersion}" + implementation group: 'org.ballerinalang', name: 'array', version: "${ballerinaLangVersion}" + implementation group: 'org.ballerinalang', name: 'string', version: "${ballerinaLangVersion}" + implementation group: 'org.ballerinalang', name: 'ballerina-core', version: "${ballerinaLangVersion}" + implementation (group: 'org.ballerinalang', name: 'ballerina-runtime', version: "${ballerinaLangVersion}") { + transitive = false + } + +// implementation group: 'io.ballerina.stdlib', name: 'http-native', version: "${stdlibHttpVersion}" +// implementation group: 'io.ballerina.stdlib', name: 'mime-native', version: "${stdlibMimeVersion}" +} + +checkstyle { + toolVersion '7.8.2' + configFile rootProject.file("build-config/checkstyle/build/checkstyle.xml") + configProperties = ["suppressionFile" : file("${rootDir}/build-config/checkstyle/build/suppressions.xml")] +} + +checkstyleMain.dependsOn(":checkstyle:downloadCheckstyleRuleFiles") + +spotbugsMain { + effort "max" + reportLevel "low" + reportsDir = file("$project.buildDir/reports/spotbugs") + reports { + html.enabled true + text.enabled = true + } + def excludeFile = file("spotbugs-exclude.xml") + if(excludeFile.exists()) { + excludeFilter = excludeFile + } +} + +def excludePattern = '**/module-info.java' +tasks.withType(Checkstyle) { + exclude excludePattern +} + +compileJava { + doFirst { + options.compilerArgs = [ + '--module-path', classpath.asPath, + ] + classpath = files() + } +} diff --git a/native/spotbugs-exclude.xml b/native/spotbugs-exclude.xml new file mode 100644 index 00000000..960de62e --- /dev/null +++ b/native/spotbugs-exclude.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/AZFParameter.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/AZFParameter.java new file mode 100644 index 00000000..b7b0d553 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/AZFParameter.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.stdlib.azure.functions; + +import io.ballerina.runtime.api.types.Parameter; + +/** + * Represents an parameter of resource/remote function. + * + * @since 2.0.0 + */ +public abstract class AZFParameter implements Comparable { + private int index; + private Parameter parameter; + + public AZFParameter(int index, Parameter parameter) { + this.index = index; + this.parameter = parameter; + } + + public int getIndex() { + return index; + } + + public Parameter getParameter() { + return parameter; + } + + @Override + public int compareTo(AZFParameter o) { + return this.index - o.index; + } + + public abstract Object getValue(); +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/Constants.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/Constants.java new file mode 100644 index 00000000..ff2ede11 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/Constants.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2022 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions; + +/** + * {@code Constants} contains the public constants to be used. + */ +public interface Constants { + + String SLASH = "/"; + + String PACKAGE_ORG = "ballerinax"; + String PACKAGE_NAME = "azure_functions"; + + //TODO restrict "httpPayload" from the param names. + String HTTP_TRIGGER_IDENTIFIER = "httpPayload"; + + String PARAMETER_ANNOTATION = "$param$."; + String RETURN_ANNOTATION = "$returns$"; + + String PACKAGE_COMPLETE = PACKAGE_ORG + "/" + PACKAGE_NAME + ":3"; + String FUNCTION_ANNOTATION_COMPLETE = PACKAGE_COMPLETE + ":Function"; + String FUNCTION_ANNOTATION_NAME_FIELD = "name"; + + String HTTP_PACKAGE_ORG = "ballerina"; + String HTTP_PACKAGE_NAME = "http"; + + String HTTP_ANNOTATION_PREFIX = Constants.HTTP_PACKAGE_ORG + Constants.SLASH + Constants.HTTP_PACKAGE_NAME + ":" + + Constants.HTTP_PACKAGE_VERSION + ":"; + + String SERVICE_OBJECT = "AZURE_FUNCTION_SERVICE_OBJECT"; + + String QUEUE_OUTPUT = "QueueOutput"; + String COSMOS_DBOUTPUT = "CosmosDBOutput"; + String HTTP_OUTPUT = "HttpOutput"; + String BLOB_OUTPUT = "BlobOutput"; + + String OUT_MSG = "outMsg"; + + String PAYLOAD_ANNOTATAION = "Payload"; + String HEADER_ANNOTATION = "Header"; + String SERVICE_CONF_ANNOTATION = "ServiceConfig"; + String STATUS = "status"; + String CODE = "code"; + String STATUS_CODE = "statusCode"; + String BODY = "body"; + String HEADERS = "headers"; + String CONTENT_TYPE = "Content-Type"; + String MEDIA_TYPE = "mediaType"; + String RESPONSE_FIELD = "resp"; + + String POST = "post"; + String CREATED_201 = "201"; + String GET = "get"; + String PUT = "put"; + String PATCH = "patch"; + String DELETE = "delete"; + String HEAD = "head"; + String OPTIONS = "options"; + String DEFAULT = "default"; + + String OK_200 = "200"; + String ACCEPTED = "202"; + + String TEXT_PLAIN = "text/plain"; + String APPLICATION_XML = "application/xml"; + String APPLICATION_OCTET_STREAM = "application/octet-stream"; + String APPLICATION_JSON = "application/json"; + + String BYTE_TYPE = "byte"; + String MAP_TYPE = "map"; + String JSON_TYPE = "json"; + String TABLE_TYPE = "table"; + + String PAYLOAD_NOT_FOUND_ERROR = "PayloadNotFoundError"; + String FUNCTION_NOT_FOUND_ERROR = "FunctionNotFoundError"; + String INVALID_PAYLOAD_ERROR = "InvalidPayloadError"; + String HEADER_NOT_FOUND_ERROR = "HeaderNotFoundError"; + String HTTP_PACKAGE_VERSION = "2"; + + String PATH_PARAM = "*"; + + String AZURE_PAYLOAD_PARAMS = "Params"; + String AZURE_PAYLOAD_HEADERS = "Headers"; + String AZURE_QUERY_HEADERS = "Query"; + String AZURE_BODY_HEADERS = "Body"; +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/FunctionCallback.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/FunctionCallback.java new file mode 100644 index 00000000..9a936d89 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/FunctionCallback.java @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions; + +import io.ballerina.runtime.api.Future; +import io.ballerina.runtime.api.Module; +import io.ballerina.runtime.api.PredefinedTypes; +import io.ballerina.runtime.api.async.Callback; +import io.ballerina.runtime.api.creators.ErrorCreator; +import io.ballerina.runtime.api.creators.TypeCreator; +import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.types.MapType; +import io.ballerina.runtime.api.types.MethodType; +import io.ballerina.runtime.api.types.ResourceMethodType; +import io.ballerina.runtime.api.types.TableType; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BArray; +import io.ballerina.runtime.api.values.BDecimal; +import io.ballerina.runtime.api.values.BError; +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BObject; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.runtime.api.values.BTable; +import io.ballerina.runtime.api.values.BXmlItem; +import org.ballerinalang.langlib.array.ToBase64; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import static io.ballerina.runtime.api.utils.StringUtils.fromString; + +/** + * {@code FunctionCallback} used to handle the Azure function service method invocation results. + */ +public class FunctionCallback implements Callback { + + private final Future future; + private final Module module; + private final List annotations; + private final MethodType methodType; + + public FunctionCallback(Future future, Module module, MethodType methodType) { + this.future = future; + this.module = module; + this.methodType = methodType; + this.annotations = new ArrayList<>(); + BMap annotations = + (BMap) methodType.getAnnotation(StringUtils.fromString(Constants.RETURN_ANNOTATION)); + if (annotations != null) { + for (BString annotation : annotations.getKeys()) { + String[] split = annotation.getValue().split(":"); + this.annotations.add(split[split.length - 1]); + } + } + } + + private String getOutputAnnotation() { + if (this.annotations.size() == 0) { + if (methodType instanceof ResourceMethodType) { + return Constants.HTTP_OUTPUT; + } + //TODO impl compiler ext validations to make sure output annotations exists + } + return this.annotations.get(0); + } + + @Override + public void notifySuccess(Object result) { + if (result instanceof BError) { + BError error = (BError) result; + if (!isModuleDefinedError(error)) { + error.printStackTrace(); + } + future.complete(result); + return; + } + + BMap mapValue = + ValueCreator.createMapValue(TypeCreator.createMapType(PredefinedTypes.TYPE_ANYDATA)); + //Refactor to readable + if (result == null) { + handleNilReturnType(mapValue); + future.complete(mapValue); + return; + } + + String outputBinding = getOutputAnnotation(); + + if (Constants.QUEUE_OUTPUT.equals(outputBinding) || Constants.COSMOS_DBOUTPUT.equals(outputBinding)) { + mapValue.put(StringUtils.fromString(Constants.OUT_MSG), result); + + } else if (Constants.BLOB_OUTPUT.equals(outputBinding)) { + if (result instanceof BArray) { + BArray arrayValue = (BArray) result; + BString encodedString = ToBase64.toBase64(arrayValue); + mapValue.put(StringUtils.fromString(Constants.OUT_MSG), encodedString); + } + + } else if (outputBinding == null || Constants.HTTP_OUTPUT.equals(outputBinding)) { + if (isHTTPStatusCodeResponse(result)) { + handleStatusCodeResponse((BMap) result, mapValue); + } else { + handleNonStatusCodeResponse(result, mapValue); + } + } + future.complete(mapValue); + } + + private void handleNilReturnType(BMap mapValue) { + BString statusCode = StringUtils.fromString(Constants.ACCEPTED); + BMap respMap = + ValueCreator.createMapValue(TypeCreator.createMapType(PredefinedTypes.TYPE_ANYDATA)); + respMap.put(StringUtils.fromString(Constants.STATUS_CODE), statusCode); + mapValue.put(StringUtils.fromString(Constants.RESPONSE_FIELD), respMap); + } + + @Override + public void notifyFailure(BError bError) { + bError.printStackTrace(); + BString errorMessage = fromString("service method invocation failed: " + bError.getErrorMessage()); + BError invocationError = ErrorCreator.createError(module, "ServiceExecutionError", + errorMessage, bError, null); + future.complete(invocationError); + } + + private boolean isModuleDefinedError(BError error) { + Type errorType = error.getType(); + Module packageDetails = errorType.getPackage(); + String orgName = packageDetails.getOrg(); + String packageName = packageDetails.getName(); + return Constants.PACKAGE_ORG.equals(orgName) && Constants.PACKAGE_NAME.equals(packageName); + } + + private boolean isHTTPStatusCodeResponse(Object result) { + return (result instanceof BMap) && (((BMap) result).containsKey(fromString(Constants.STATUS))); + //TODO : Check inheritance + //(https://github.com/ballerina-platform/module-ballerinax-azure.functions/issues/490) + } + + private boolean isContentTypeExist(BMap headersMap) { + for (BString headerKey : headersMap.getKeys()) { + if (headerKey.getValue().toLowerCase(Locale.ROOT).equals(Constants.CONTENT_TYPE.toLowerCase(Locale.ROOT))) { + return true; + } + } + return false; + } + + private void addStatusCodeImplicitly(BMap respMap) { + String accessor = ((ResourceMethodType) this.methodType).getAccessor(); + Object statusCode = ""; + if (Constants.POST.equals(accessor)) { + statusCode = Constants.CREATED_201; + } else if (Constants.GET.equals(accessor) || Constants.PUT.equals(accessor) || + Constants.PATCH.equals(accessor) || Constants.DELETE.equals(accessor) || + Constants.HEAD.equals(accessor) || Constants.OPTIONS.equals(accessor) || + Constants.DEFAULT.equals(accessor)) { + statusCode = Constants.OK_200; + } + statusCode = StringUtils.fromString((String) statusCode); + respMap.put(StringUtils.fromString(Constants.STATUS_CODE), statusCode); + } + + private void addContentTypeImplicitly(Object result, BMap headers) { + if (result instanceof BString) { + headers.put(StringUtils.fromString(Constants.CONTENT_TYPE), StringUtils.fromString(Constants.TEXT_PLAIN)); + + } else if (result instanceof BXmlItem) { + headers.put(StringUtils.fromString(Constants.CONTENT_TYPE), + StringUtils.fromString(Constants.APPLICATION_XML)); + + } else if (result instanceof BArray) { + BArray arrayResult = (BArray) result; + if (Constants.BYTE_TYPE.equals(arrayResult.getElementType().getName())) { + headers.put(StringUtils.fromString(Constants.CONTENT_TYPE), + StringUtils.fromString(Constants.APPLICATION_OCTET_STREAM)); + + } else if (Constants.MAP_TYPE.equals(arrayResult.getElementType().getName())) { + MapType mapContent = (MapType) arrayResult.getElementType(); + if (Constants.JSON_TYPE.equals(mapContent.getConstrainedType().getName())) { + headers.put(StringUtils.fromString(Constants.CONTENT_TYPE), + StringUtils.fromString(Constants.APPLICATION_JSON)); + } + + } else if (Constants.TABLE_TYPE.equals(arrayResult.getElementType().getName())) { + TableType tableContent = (TableType) arrayResult.getElementType(); + if (Constants.MAP_TYPE.equals(tableContent.getConstrainedType().getName())) { + MapType mapContent = (MapType) tableContent.getConstrainedType(); + if (Constants.JSON_TYPE.equals(mapContent.getConstrainedType().getName())) { + headers.put(StringUtils.fromString(Constants.CONTENT_TYPE), + StringUtils.fromString(Constants.APPLICATION_JSON)); + } + + } + } + + } else if (result instanceof BTable) { + BTable tableResult = (BTable) result; + TableType tableContent = (TableType) tableResult.getType(); + if (Constants.MAP_TYPE.equals(tableContent.getConstrainedType().getName())) { + MapType mapContent = (MapType) tableContent.getConstrainedType(); + if (Constants.JSON_TYPE.equals(mapContent.getConstrainedType().getName())) { + headers.put(StringUtils.fromString(Constants.CONTENT_TYPE), + StringUtils.fromString(Constants.APPLICATION_JSON)); + } + + } + } else if (result instanceof BDecimal || result instanceof Long || result instanceof Double || + result instanceof Boolean) { + headers.put(StringUtils.fromString(Constants.CONTENT_TYPE), + StringUtils.fromString(Constants.APPLICATION_JSON)); + } else if (result instanceof BMap) { + headers.put(StringUtils.fromString(Constants.CONTENT_TYPE), + StringUtils.fromString(Constants.APPLICATION_JSON)); + } + } + + private void handleNonStatusCodeResponse(Object result, BMap mapValue) { + BMap respMap = + ValueCreator.createMapValue(TypeCreator.createMapType(PredefinedTypes.TYPE_ANYDATA)); + BMap headers = + ValueCreator.createMapValue(TypeCreator.createMapType(PredefinedTypes.TYPE_ANYDATA)); + + addStatusCodeImplicitly(respMap); + addContentTypeImplicitly(result, headers); + + respMap.put(StringUtils.fromString(Constants.HEADERS), headers); + if (result instanceof BArray) { + BArray arrayResult = (BArray) result; + if (Constants.BYTE_TYPE.equals(arrayResult.getElementType().getName())) { + respMap.put(StringUtils.fromString(Constants.BODY), ToBase64.toBase64(arrayResult)); + } else { + respMap.put(StringUtils.fromString(Constants.BODY), result); + } + } else { + respMap.put(StringUtils.fromString(Constants.BODY), result); + } + mapValue.put(StringUtils.fromString(Constants.RESPONSE_FIELD), respMap); + } + + private void handleStatusCodeResponse(BMap result, BMap mapValue) { + BMap resultMap = result; + + // Extract status code + BObject status = (BObject) (resultMap.get(StringUtils.fromString(Constants.STATUS))); + Object statusCode = Long.toString(status.getIntValue(StringUtils.fromString(Constants.CODE))); + statusCode = StringUtils.fromString((String) statusCode); + + // Create a BMap for response field + BMap respMap = + ValueCreator.createMapValue(TypeCreator.createMapType(PredefinedTypes.TYPE_ANYDATA)); + respMap.put(StringUtils.fromString(Constants.STATUS_CODE), statusCode); + + // Create body field in the response Map + if (resultMap.containsKey(StringUtils.fromString(Constants.BODY))) { + Object body = resultMap.get(StringUtils.fromString(Constants.BODY)); + respMap.put(StringUtils.fromString(Constants.BODY), body); + } + + // Create header field in the response Map + if (resultMap.containsKey(StringUtils.fromString(Constants.HEADERS))) { + Object headers = resultMap.get(StringUtils.fromString(Constants.HEADERS)); + BMap headersMap = (BMap) headers; + // Add Content-type field in headers if there is not + if (!isContentTypeExist(headersMap)) { + headersMap.put(StringUtils.fromString(Constants.CONTENT_TYPE), + StringUtils.fromString(Constants.APPLICATION_JSON)); + } + respMap.put(StringUtils.fromString(Constants.HEADERS), headers); + } else { + // If there is no headers add one with default content-type + Object headers = + ValueCreator.createMapValue(TypeCreator.createMapType(PredefinedTypes.TYPE_ANYDATA)); + ((BMap) headers).put(StringUtils.fromString(Constants.CONTENT_TYPE), + StringUtils.fromString(Constants.APPLICATION_JSON)); + respMap.put(StringUtils.fromString(Constants.HEADERS), headers); + + } + + // If there is mediaType replace content-type in headers + if (resultMap.containsKey(StringUtils.fromString(Constants.MEDIA_TYPE))) { + Object headers = resultMap.get(StringUtils.fromString(Constants.HEADERS)); + if (headers != null) { + Object mediaType = resultMap.get(StringUtils.fromString(Constants.MEDIA_TYPE)); + ((BMap) headers).put(StringUtils.fromString(Constants.CONTENT_TYPE), mediaType); + } + } + mapValue.put(StringUtils.fromString(Constants.RESPONSE_FIELD), respMap); + } +} + + diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/HeaderParameter.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/HeaderParameter.java new file mode 100644 index 00000000..99b1d0c1 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/HeaderParameter.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.stdlib.azure.functions; + +import io.ballerina.runtime.api.types.Parameter; + +/** + * Represents the header parameter in azure functions. + * + * @since 2.0.0 + */ +public class HeaderParameter extends AZFParameter { + + private Object value; + + public HeaderParameter(int index, Parameter parameter, Object value) { + super(index, parameter); + this.value = value; + } + + @Override + public Object getValue() { + return value; + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/HttpResource.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/HttpResource.java new file mode 100644 index 00000000..b18562b2 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/HttpResource.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.stdlib.azure.functions; + +import io.ballerina.runtime.api.TypeTags; +import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.types.Field; +import io.ballerina.runtime.api.types.Parameter; +import io.ballerina.runtime.api.types.RecordType; +import io.ballerina.runtime.api.types.ReferenceType; +import io.ballerina.runtime.api.types.ResourceMethodType; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BArray; +import io.ballerina.runtime.api.values.BError; +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.stdlib.azure.functions.bindings.input.InputBinding; +import io.ballerina.stdlib.azure.functions.builder.AbstractPayloadBuilder; +import io.ballerina.stdlib.azure.functions.exceptions.HeaderNotFoundException; +import io.ballerina.stdlib.azure.functions.exceptions.InvalidPayloadException; +import io.ballerina.stdlib.azure.functions.exceptions.PayloadNotFoundException; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; + +/** + * Represents an Azure Resource function property. + * + * @since 2.0.0 + */ +public class HttpResource { + + private PathParameter[] pathParams; + private QueryParameter[] queryParameter; + private PayloadParameter payloadParameter; + private InputBindingParameter[] inputBindingParameters; + private HeaderParameter headerParameter; + + public HttpResource(ResourceMethodType resourceMethodType, BMap body, BMap serviceAnnotations) { + this.pathParams = getPathParams(resourceMethodType, body); + this.payloadParameter = processPayloadParam(resourceMethodType, body).orElse(null); + this.queryParameter = getQueryParams(resourceMethodType, body); + this.inputBindingParameters = getInputBindingParams(resourceMethodType, body); + this.headerParameter = processHeaderParam(resourceMethodType, body, serviceAnnotations).orElse(null); + } + + private InputBindingParameter[] getInputBindingParams(ResourceMethodType resourceMethod, BMap body) + throws InvalidPayloadException { + Parameter[] parameters = resourceMethod.getParameters(); + List inputBindingParameters = new ArrayList<>(); + for (int i = this.pathParams.length, parametersLength = parameters.length; i < parametersLength; i++) { + Parameter parameter = parameters[i]; + String name = parameter.name; + Object annotation = + resourceMethod.getAnnotation(StringUtils.fromString(Constants.PARAMETER_ANNOTATION + name)); + Optional inputBindingHandler = ParamHandler.getInputBindingHandler(annotation); + if (inputBindingHandler.isEmpty()) { + continue; + } + BString bodyValue = body.getStringValue(StringUtils.fromString(name)); + InputBinding inputBinding = inputBindingHandler.get(); + Type type = parameter.type; + try { + AbstractPayloadBuilder payloadBuilder = inputBinding.getPayloadBuilder(type); + Object bValue = payloadBuilder.getValue(bodyValue, false); + inputBindingParameters.add(new InputBindingParameter(i, parameter, bValue)); + } catch (BError error) { + throw new InvalidPayloadException(error.getMessage()); + } + } + + return inputBindingParameters.toArray(InputBindingParameter[]::new); + } + + private QueryParameter[] getQueryParams(ResourceMethodType resourceMethod, BMap body) { + BMap queryParams = body.getMapValue(StringUtils.fromString(Constants.HTTP_TRIGGER_IDENTIFIER)) + .getMapValue(StringUtils.fromString(Constants.AZURE_QUERY_HEADERS)); + Parameter[] parameters = resourceMethod.getParameters(); + List queryParameters = new ArrayList<>(); + for (int i = this.pathParams.length, parametersLength = parameters.length; i < parametersLength; i++) { + Parameter parameter = parameters[i]; + String name = parameter.name; + Object annotation = + resourceMethod.getAnnotation(StringUtils.fromString(Constants.PARAMETER_ANNOTATION + name)); + if (Utils.isAzAnnotationExist(annotation)) { + continue; + } + BString queryValue = queryParams.getStringValue(StringUtils.fromString(name)); + try { + Object bValue = Utils.createValue(parameter.type, queryValue); + queryParameters.add(new QueryParameter(i, parameter, bValue)); + } catch (BError bError) { + throw new InvalidPayloadException(bError.getMessage()); + } + } + return queryParameters.toArray(QueryParameter[]::new); + } + + private PathParameter[] getPathParams(ResourceMethodType resourceMethod, BMap body) { + String[] resourcePath = resourceMethod.getResourcePath(); + Parameter[] parameters = resourceMethod.getParameters(); + List pathParams = new ArrayList<>(); + int count = 0; + for (String path : resourcePath) { + if (path.equals(Constants.PATH_PARAM)) { + Parameter parameter = parameters[count]; + BMap payload = body.getMapValue(StringUtils.fromString(Constants.HTTP_TRIGGER_IDENTIFIER)); + BMap params = payload.getMapValue(StringUtils.fromString(Constants.AZURE_PAYLOAD_PARAMS)); + BString param = params.getStringValue(StringUtils.fromString(parameter.name)); + pathParams.add(new PathParameter(count, parameter, param.getValue())); + count++; + } + //TODO handle wildcard + } + + return pathParams.toArray(PathParameter[]::new); + } + + private Optional processPayloadParam(ResourceMethodType resourceMethod, BMap body) + throws PayloadNotFoundException { + Parameter[] parameters = resourceMethod.getParameters(); + for (int i = this.pathParams.length, parametersLength = parameters.length; i < parametersLength; i++) { + Parameter parameter = parameters[i]; + String name = parameter.name; + Object annotation = + resourceMethod.getAnnotation(StringUtils.fromString(Constants.PARAMETER_ANNOTATION + name)); + if (!ParamHandler.isPayloadAnnotationParam(annotation)) { + continue; + } + BMap httpPayload = body.getMapValue(StringUtils.fromString(Constants.HTTP_TRIGGER_IDENTIFIER)); + BMap headers = httpPayload.getMapValue(StringUtils.fromString(Constants.AZURE_PAYLOAD_HEADERS)); + Type type = parameter.type; + String contentType = Utils.getContentTypeHeader(headers); + BString bodyValue = Utils.getRequestBody(httpPayload, name, type); + if (Utils.isNilType(type) && bodyValue == null) { + return Optional.of(new PayloadParameter(i, parameter, null)); + } + try { + AbstractPayloadBuilder builder = AbstractPayloadBuilder.getBuilder(contentType, type); + Object bValue = builder.getValue(bodyValue, false); + return Optional.of(new PayloadParameter(i, parameter, bValue)); + } catch (BError error) { + throw new InvalidPayloadException(error.getMessage()); + } + } + return Optional.empty(); + } + + private Optional processHeaderParam(ResourceMethodType resourceMethod, BMap body, + BMap serviceAnnotations) { + Parameter[] parameters = resourceMethod.getParameters(); + Object headerParam; + Boolean treatNilableAsOptional = true; + String serviceConfig = Constants.HTTP_ANNOTATION_PREFIX + Constants.SERVICE_CONF_ANNOTATION; + boolean isServiceConfExist = ParamHandler.isHttpServiceConfExist(serviceAnnotations); + if (isServiceConfExist) { + treatNilableAsOptional = serviceAnnotations.getMapValue(StringUtils.fromString(serviceConfig)). + getBooleanValue(StringUtils.fromString("treatNilableAsOptional")); + } + for (int i = this.pathParams.length, parametersLength = parameters.length; i < parametersLength; i++) { + Parameter parameter = parameters[i]; + String name = parameter.name; + Object annotation = + resourceMethod.getAnnotation(StringUtils.fromString(Constants.PARAMETER_ANNOTATION + name)); + if (annotation == null) { + continue; + } + boolean isHeaderAnnotation = ParamHandler.isHeaderAnnotationParam(annotation); + if (!isHeaderAnnotation) { + continue; + } + BMap httpPayload = body.getMapValue(StringUtils.fromString(Constants.HTTP_TRIGGER_IDENTIFIER)); + BMap headers = + (BMap) httpPayload.getMapValue(StringUtils.fromString(Constants.AZURE_PAYLOAD_HEADERS)); + + String headerAnnotation = Constants.HTTP_ANNOTATION_PREFIX + Constants.HEADER_ANNOTATION; + BMap headerAnnotationField = + (BMap) ((BMap) annotation).get(StringUtils.fromString(headerAnnotation)); + if (headerAnnotationField.size() == 0) { + //No annotation field defined {name: ....} + if ((parameter.type).getTag() == TypeTags.TYPE_REFERENCED_TYPE_TAG) { + ReferenceType type = (ReferenceType) parameter.type; + headerParam = processHeaderRecordParam(headers, type, treatNilableAsOptional); + return Optional.of(new HeaderParameter(i, parameter, headerParam)); + } + headerParam = getHeaderValue(headers, parameter.type, name, treatNilableAsOptional); + return Optional.of(new HeaderParameter(i, parameter, headerParam)); + } else if (headerAnnotationField.size() == 1) { + // Annotation field is defined + BString headerName = headerAnnotationField.getStringValue(StringUtils.fromString("name")); + headerParam = getHeaderValue(headers, parameter.type, headerName.getValue(), treatNilableAsOptional); + return Optional.of(new HeaderParameter(i, parameter, headerParam)); + } else { + throw new RuntimeException("Header annotation can have only one name field."); + } + } + return Optional.empty(); + } + + private Object getHeaderValue(BMap headers, Type type, String fieldName, + boolean treatNilableAsOptional) { + BString headerValue = null; + boolean isHeaderExist = false; + for (BString headerKey : headers.getKeys()) { + if (headerKey.getValue().toLowerCase(Locale.ROOT).equals(fieldName.toLowerCase(Locale.ROOT))) { + isHeaderExist = true; + if (((BArray) (headers.get(headerKey))).size() == 0) { + break; + } + headerValue = (BString) ((BArray) (headers.get(headerKey))).get(0); + } + } + if (!isHeaderExist) { + //Header name not exist case + if (Utils.isNilType(type) && treatNilableAsOptional) { + return null; + } + throw new HeaderNotFoundException("no header value found for '" + fieldName + "'"); + } else if (headerValue.getValue().equals("")) { + //Handle header value not exist case + if (Utils.isNilType(type)) { + return null; + } + throw new HeaderNotFoundException("no header value found for '" + fieldName + "'"); + + } + return Utils.createValue(type, headerValue); + } + + private Object processHeaderRecordParam(BMap headers, ReferenceType parameter, + Boolean treatNilableAsOptional) { + RecordType recordType = (RecordType) parameter.getReferredType(); + Map fields = recordType.getFields(); + BMap recordValue = ValueCreator.createRecordValue(recordType); + for (Map.Entry field : fields.entrySet()) { + String fieldName = field.getKey(); + Type fieldType = field.getValue().getFieldType(); + Object headerValue = getHeaderValue(headers, fieldType, fieldName, treatNilableAsOptional); + recordValue.put(StringUtils.fromString(fieldName), headerValue); + } + return recordValue; + } + + public Object[] getArgList() { + List parameters = new ArrayList<>(Arrays.asList(pathParams)); + parameters.addAll(Arrays.asList(queryParameter)); + parameters.addAll(Arrays.asList(inputBindingParameters)); + if (payloadParameter != null) { + parameters.add(payloadParameter); + } + if (headerParameter != null) { + parameters.add(headerParameter); + } + //TODO add more input output binding params + Collections.sort(parameters); + + Object[] args = new Object[parameters.size() * 2]; + int i = 0; + for (AZFParameter parameter : parameters) { + Object bValue = parameter.getValue(); + args[i++] = bValue; + args[i++] = true; + } + return args; + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/InputBindingParameter.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/InputBindingParameter.java new file mode 100644 index 00000000..38eb713e --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/InputBindingParameter.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.stdlib.azure.functions; + +import io.ballerina.runtime.api.types.Parameter; + +/** + * Represents an Input Binding Parameter. + * + * @since 2.0.0 + */ +public class InputBindingParameter extends AZFParameter { + private Object value; + + public InputBindingParameter(int index, Parameter parameter, Object value) { + super(index, parameter); + this.value = value; + } + + @Override + public Object getValue() { + return value; + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/ModuleUtils.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/ModuleUtils.java new file mode 100644 index 00000000..99db0300 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/ModuleUtils.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions; + +import io.ballerina.runtime.api.Environment; +import io.ballerina.runtime.api.Module; + +/** + * {@code ModuleUtils} contains the utility methods for the module. + */ +public class ModuleUtils { + + private static Module module; + + private ModuleUtils() {} + + public static void setModule(Environment environment) { + module = environment.getCurrentModule(); + } + + public static Module getModule() { + return module; + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/NativeHttpToAzureAdaptor.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/NativeHttpToAzureAdaptor.java new file mode 100644 index 00000000..7cc5b97a --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/NativeHttpToAzureAdaptor.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions; + +import io.ballerina.runtime.api.Environment; +import io.ballerina.runtime.api.Future; +import io.ballerina.runtime.api.Module; +import io.ballerina.runtime.api.PredefinedTypes; +import io.ballerina.runtime.api.async.StrandMetadata; +import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.types.ResourceMethodType; +import io.ballerina.runtime.api.types.ServiceType; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BArray; +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BObject; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.stdlib.azure.functions.exceptions.BadRequestException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static io.ballerina.stdlib.azure.functions.Constants.SERVICE_OBJECT; + +/** + * {@code NativeHttpToAzureAdaptor} is a wrapper object used for service method execution. + */ +public class NativeHttpToAzureAdaptor { + + public static void externInit(BObject adaptor, BObject serviceObj) { + adaptor.addNativeData(SERVICE_OBJECT, serviceObj); + } + + public static BArray getAzureFunctionNames(Environment env, BObject adaptor) { + BObject bHubService = (BObject) adaptor.getNativeData(SERVICE_OBJECT); + ServiceType svcType = (ServiceType) bHubService.getType(); + List functionNameList = new ArrayList<>(); + for (ResourceMethodType resourceMethod : svcType.getResourceMethods()) { + BString functionName = ((BMap) resourceMethod + .getAnnotation(StringUtils.fromString(Constants.FUNCTION_ANNOTATION_COMPLETE))) + .getStringValue(StringUtils.fromString(Constants.FUNCTION_ANNOTATION_NAME_FIELD)); + functionNameList.add(functionName); + } + return ValueCreator.createArrayValue(functionNameList.toArray(BString[]::new)); + } + + public static Object callNativeMethod(Environment env, BObject adaptor, BMap body, BString functionName) { + BObject bHubService = (BObject) adaptor.getNativeData(SERVICE_OBJECT); + return invokeResourceFunction(env, bHubService, + "callNativeMethod", body, functionName); + } + + //Todo See if we can call parent bal method directly and check deprecated usages + private static Object invokeResourceFunction(Environment env, BObject bHubService, String parentFunctionName, + BMap body, BString functionName) { + Future balFuture = env.markAsync(); + Module module = ModuleUtils.getModule(); + StrandMetadata metadata = new StrandMetadata(module.getOrg(), module.getName(), module.getVersion(), + parentFunctionName); + ServiceType serviceType = (ServiceType) bHubService.getType(); + + ResourceMethodType[] resourceMethods = serviceType.getResourceMethods(); + Optional resourceMethodType = getResourceMethodType(resourceMethods, functionName); + if (resourceMethodType.isEmpty()) { + balFuture.complete(Utils.createError(module, "function " + functionName.getValue() + " not found in the " + + "code", Constants.FUNCTION_NOT_FOUND_ERROR)); + return null; + } + ResourceMethodType resourceMethod = resourceMethodType.get(); + try { + BMap serviceAnnotations = serviceType.getAnnotations(); + HttpResource httpResource = new HttpResource(resourceMethod, body, serviceAnnotations); + Object[] args = httpResource.getArgList(); + if (serviceType.isIsolated() && resourceMethod.isIsolated()) { + env.getRuntime().invokeMethodAsyncConcurrently( + bHubService, resourceMethod.getName(), null, metadata, + new FunctionCallback(balFuture, module, resourceMethod), null, PredefinedTypes.TYPE_NULL, + args); + } else { + env.getRuntime().invokeMethodAsyncSequentially( + bHubService, resourceMethod.getName(), null, metadata, + new FunctionCallback(balFuture, module, resourceMethod), null, PredefinedTypes.TYPE_NULL, + args); + } + } catch (BadRequestException e) { + balFuture.complete(Utils.createError(module, e.getMessage(), e.getType())); + } + return null; + } + + private static Optional getResourceMethodType(ResourceMethodType[] types, + BString enteredFunctionName) { + for (ResourceMethodType type : types) { + BString functionName = + ((BMap) type.getAnnotation(StringUtils.fromString(Constants.FUNCTION_ANNOTATION_COMPLETE))) + .getStringValue(StringUtils.fromString(Constants.FUNCTION_ANNOTATION_NAME_FIELD)); + + if (functionName.toString().equals(enteredFunctionName.toString())) { + return Optional.of(type); + } + } + return Optional.empty(); + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/NativeRemoteAdapter.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/NativeRemoteAdapter.java new file mode 100644 index 00000000..85a00193 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/NativeRemoteAdapter.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions; + +import io.ballerina.runtime.api.Environment; +import io.ballerina.runtime.api.Future; +import io.ballerina.runtime.api.Module; +import io.ballerina.runtime.api.PredefinedTypes; +import io.ballerina.runtime.api.async.StrandMetadata; +import io.ballerina.runtime.api.types.Parameter; +import io.ballerina.runtime.api.types.RemoteMethodType; +import io.ballerina.runtime.api.types.ServiceType; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.types.TypeId; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BObject; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.stdlib.azure.functions.bindings.input.InputBinding; +import io.ballerina.stdlib.azure.functions.builder.AbstractPayloadBuilder; +import io.ballerina.stdlib.azure.functions.builder.BinaryPayloadBuilder; +import io.ballerina.stdlib.azure.functions.builder.JsonPayloadBuilder; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static io.ballerina.stdlib.azure.functions.Constants.SERVICE_OBJECT; + +/** + * {@code NativeRemoteAdapter} is a wrapper object used for service method execution. + */ +public class NativeRemoteAdapter { + + public static void externRemoteInit(BObject adaptor, BObject serviceObj) { + adaptor.addNativeData(SERVICE_OBJECT, serviceObj); + } + + public static Object callRemoteFunction(Environment env, BObject adaptor, BMap body, BString remoteFuncName) { + BObject bHubService = (BObject) adaptor.getNativeData(SERVICE_OBJECT); + return invokeRemoteFunction(env, bHubService, "callRemoteFunction", body, remoteFuncName); + } + + private static Object invokeRemoteFunction(Environment env, BObject bHubService, String parentFunctionName, + BMap body, BString remoteFuncName) { + BMap data = body.getMapValue(StringUtils.fromString("Data")); + Future balFuture = env.markAsync(); + Module module = ModuleUtils.getModule(); + StrandMetadata metadata = new StrandMetadata(module.getOrg(), module.getName(), module.getVersion(), + parentFunctionName); + ServiceType serviceType = (ServiceType) bHubService.getType(); + List argList = new ArrayList<>(); + RemoteMethodType methodType = getRemoteMethod(serviceType, remoteFuncName).orElseThrow(); + Parameter[] parameters = methodType.getParameters(); + for (Parameter parameter : parameters) { + String name = parameter.name; + Object annotation = methodType.getAnnotation(StringUtils.fromString(Constants.PARAMETER_ANNOTATION + name)); + if (!ParamHandler.isAzureAnnotationExist(annotation)) { + Object bValue = getDataboundValue(data, parameter, serviceType); + argList.add(bValue); + argList.add(true); + } else if (ParamHandler.isBindingNameParam(annotation)) { + BString nameParam = + body.getMapValue(StringUtils.fromString("Metadata")).getStringValue(StringUtils.fromString( + "name")); + Type type = parameter.type; + JsonPayloadBuilder jsonPayloadBuilder = new JsonPayloadBuilder(type); + Object bValue = jsonPayloadBuilder.getValue(nameParam, false); + argList.add(bValue); + argList.add(true); + } else { + Optional inputBindingHandler = ParamHandler.getInputBindingHandler(annotation); + if (inputBindingHandler.isPresent()) { + BString bodyValue = data.getStringValue(StringUtils.fromString(name)); + Type type = parameter.type; + AbstractPayloadBuilder payloadBuilder = inputBindingHandler.get().getPayloadBuilder(type); + Object bValue = payloadBuilder.getValue(bodyValue, false); + argList.add(bValue); + argList.add(true); + } + } + } + Object[] args = argList.toArray(); + if (serviceType.isIsolated()) { + env.getRuntime().invokeMethodAsyncConcurrently( + bHubService, remoteFuncName.getValue(), null, metadata, + new FunctionCallback(balFuture, module, methodType), null, PredefinedTypes.TYPE_NULL, + args); + } else { + env.getRuntime().invokeMethodAsyncSequentially( + bHubService, remoteFuncName.getValue(), null, metadata, + new FunctionCallback(balFuture, module, methodType), null, PredefinedTypes.TYPE_NULL, + args); + } + return null; + } + + private static Object getDataboundValue(BMap body, Parameter parameter, ServiceType serviceType) { + List ids = serviceType.getTypeIdSet().getIds(); + BString paramBString = StringUtils.fromString(parameter.name); + if (ids.size() >= 1) { + TypeId typeId = ids.get(0); + String name = typeId.getName(); + if (name.equals("TimerService")) { + return body.getMapValue(paramBString); + } else if (name.equals("BlobService")) { + BString bStr = body.getStringValue(paramBString); + BinaryPayloadBuilder binaryPayloadBuilder = new BinaryPayloadBuilder(parameter.type); + return binaryPayloadBuilder.getValue(bStr, false); + } + } + BString bStr = body.getStringValue(paramBString); + JsonPayloadBuilder jsonPayloadBuilder = new JsonPayloadBuilder(parameter.type); + return jsonPayloadBuilder.getValue(bStr, false); + } + + private static Optional getRemoteMethod(ServiceType serviceType, BString remoteFuncName) { + RemoteMethodType[] remoteMethods = serviceType.getRemoteMethods(); + for (RemoteMethodType methodType : remoteMethods) { + if (methodType.getName().equals(remoteFuncName.getValue())) { + return Optional.of(methodType); + } + } + return Optional.empty(); + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/ParamHandler.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/ParamHandler.java new file mode 100644 index 00000000..efe37906 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/ParamHandler.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.stdlib.azure.functions; + +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.stdlib.azure.functions.bindings.input.BlobInput; +import io.ballerina.stdlib.azure.functions.bindings.input.CosmosInput; +import io.ballerina.stdlib.azure.functions.bindings.input.InputBinding; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static io.ballerina.stdlib.azure.functions.Constants.HEADER_ANNOTATION; +import static io.ballerina.stdlib.azure.functions.Constants.HTTP_PACKAGE_NAME; +import static io.ballerina.stdlib.azure.functions.Constants.HTTP_PACKAGE_ORG; +import static io.ballerina.stdlib.azure.functions.Constants.SERVICE_CONF_ANNOTATION; + +/** + * Represents the input binding handler. + * + * @since 2.0.0 + */ +public class ParamHandler { + + public static boolean isAzureAnnotationExist(Object annotation) { + if (annotation == null) { + return false; + } + if (!(annotation instanceof BMap)) { + return false; + } + + for (BString bKey : ((BMap) annotation).getKeys()) { + String key = bKey.getValue(); + if (key.startsWith(Constants.PACKAGE_ORG + Constants.SLASH + Constants.PACKAGE_NAME)) { + return true; + } + } + return false; + } + + public static boolean isPayloadAnnotationParam(Object annotation) { + if (annotation == null) { + return false; + } + if (!(annotation instanceof BMap)) { + return false; + } + + for (BString bKey : ((BMap) annotation).getKeys()) { + String key = bKey.getValue(); + if (key.startsWith(HTTP_PACKAGE_ORG + Constants.SLASH + Constants.HTTP_PACKAGE_NAME) && + key.endsWith(Constants.PAYLOAD_ANNOTATAION)) { + return true; + } + } + return false; + } + + public static boolean isHeaderAnnotationParam(Object annotation) { + if (annotation == null) { + return false; + } + if (!(annotation instanceof BMap)) { + return false; + } + + for (BString bKey : ((BMap) annotation).getKeys()) { + String[] keySegments = (bKey.getValue()).split("[/:]"); + if ((keySegments.length == 4) && HTTP_PACKAGE_ORG.equals(keySegments[0]) && + HTTP_PACKAGE_NAME.equals(keySegments[1]) && HEADER_ANNOTATION.equals(keySegments[3])) { + return true; + } + } + return false; + } + + public static boolean isHttpServiceConfExist(Object annotation) { + if (annotation == null) { + return false; + } + if (!(annotation instanceof BMap)) { + return false; + } + + for (BString bKey : ((BMap) annotation).getKeys()) { + String[] keySegments = (bKey.getValue()).split("[/:]"); + if ((keySegments.length == 4) && HTTP_PACKAGE_ORG.equals(keySegments[0]) && + HTTP_PACKAGE_NAME.equals(keySegments[1]) && SERVICE_CONF_ANNOTATION.equals(keySegments[3])) { + return true; + } + } + return false; + } + + public static Optional getInputBindingHandler(Object annotation) { + if (annotation == null) { + return Optional.empty(); + } + if (!(annotation instanceof BMap)) { + return Optional.empty(); + } + for (BString key : ((BMap) annotation).getKeys()) { + String annotationKey = key.getValue(); + String annotationName = annotationKey.substring(annotationKey.lastIndexOf(':') + 1); + + List inputBindings = new ArrayList<>(); + inputBindings.add(new BlobInput()); + inputBindings.add(new CosmosInput()); + + for (InputBinding inputBinding : inputBindings) { + if (inputBinding.getName().equals(annotationName)) { + return Optional.of(inputBinding); + } + } + } + return Optional.empty(); + } + + public static boolean isBindingNameParam(Object annotation) { + if (annotation == null) { + return false; + } + if (!(annotation instanceof BMap)) { + return false; + } + + Object value = + ((BMap) annotation).get(StringUtils.fromString(Constants.PACKAGE_COMPLETE + ":BindingName")); + return value != null; + } + +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/PathParameter.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/PathParameter.java new file mode 100644 index 00000000..fc2fbe2d --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/PathParameter.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.stdlib.azure.functions; + +import io.ballerina.runtime.api.types.Parameter; +import io.ballerina.runtime.api.utils.StringUtils; + +/** + * Represents a path paramter in azure resource function. + * + * @since 2.0.0 + */ +public class PathParameter extends AZFParameter { + private String value; + + public PathParameter(int index, Parameter parameter, String value) { + super(index, parameter); + this.value = value; + } + + @Override + public Object getValue() { + return StringUtils.fromString(this.value); + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/PayloadParameter.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/PayloadParameter.java new file mode 100644 index 00000000..738d559c --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/PayloadParameter.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.stdlib.azure.functions; + +import io.ballerina.runtime.api.types.Parameter; + +/** + * Represents the payload parameter in azure functions. + * + * @since 2.0.0 + */ +public class PayloadParameter extends AZFParameter { + + private Object value; + + public PayloadParameter(int index, Parameter parameter, Object value) { + super(index, parameter); + this.value = value; + } + + @Override + public Object getValue() { + return value; + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/QueryParameter.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/QueryParameter.java new file mode 100644 index 00000000..ddf558c3 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/QueryParameter.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions; + +import io.ballerina.runtime.api.types.Parameter; + +/** + * Represents a query parameter in a resource function. + * + * @since 2.0.0 + */ +public class QueryParameter extends AZFParameter { + + private Object value; + + public QueryParameter(int index, Parameter parameter, Object value) { + super(index, parameter); + this.value = value; + } + + @Override + public Object getValue() { + return this.value; + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/Utils.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/Utils.java new file mode 100644 index 00000000..697e6e24 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/Utils.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions; + +import io.ballerina.runtime.api.Module; +import io.ballerina.runtime.api.PredefinedTypes; +import io.ballerina.runtime.api.TypeTags; +import io.ballerina.runtime.api.creators.ErrorCreator; +import io.ballerina.runtime.api.creators.TypeCreator; +import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.types.ArrayType; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.types.UnionType; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BArray; +import io.ballerina.runtime.api.values.BError; +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.stdlib.azure.functions.exceptions.InvalidPayloadException; +import io.ballerina.stdlib.azure.functions.exceptions.PayloadNotFoundException; +import org.ballerinalang.langlib.bool.FromString; + +import java.util.List; + +import static io.ballerina.runtime.api.TypeTags.BOOLEAN_TAG; +import static io.ballerina.runtime.api.TypeTags.DECIMAL_TAG; +import static io.ballerina.runtime.api.TypeTags.FLOAT_TAG; +import static io.ballerina.runtime.api.TypeTags.INT_TAG; +import static io.ballerina.runtime.api.utils.StringUtils.fromString; + +/** + * Contains Utilities related to natives. + * + * @since 2.0.0 + */ +public class Utils { + + private static final ArrayType INT_ARR = TypeCreator.createArrayType(PredefinedTypes.TYPE_INT); + private static final ArrayType FLOAT_ARR = TypeCreator.createArrayType(PredefinedTypes.TYPE_FLOAT); + private static final ArrayType BOOLEAN_ARR = TypeCreator.createArrayType(PredefinedTypes.TYPE_BOOLEAN); + private static final ArrayType DECIMAL_ARR = TypeCreator.createArrayType(PredefinedTypes.TYPE_DECIMAL); + + public static BError createError(Module module, String message, String type) { + BString errorMessage = fromString(message); + return ErrorCreator.createError(module, type, errorMessage, ErrorCreator.createError(errorMessage), null); + } + + public static Object createValue(Type type, BString strValue) { + switch (type.getTag()) { + case TypeTags.STRING_TAG: + return strValue; + case TypeTags.BOOLEAN_TAG: + return FromString.fromString(strValue); + case TypeTags.INT_TAG: + return org.ballerinalang.langlib.integer.FromString.fromString(strValue); + case TypeTags.FLOAT_TAG: + return org.ballerinalang.langlib.floatingpoint.FromString.fromString(strValue); + case TypeTags.DECIMAL_TAG: + return org.ballerinalang.langlib.decimal.FromString.fromString(strValue); + case TypeTags.UNION_TAG: + List memberTypes = ((UnionType) type).getMemberTypes(); + for (Type memberType : memberTypes) { + try { + return createValue(memberType, strValue); + } catch (BError ignored) { + // thrown errors are ignored until all the types are iterated + } + } + return null; + case TypeTags.ARRAY_TAG: + ArrayType arrayType = (ArrayType) type; + Type elementType = arrayType.getElementType(); + if (strValue == null) { + return null; + } + String[] values = strValue.getValue().split(","); + return castParamArray(elementType.getTag(), values); + default: + throw new InvalidPayloadException("unsupported parameter type " + type.getName()); + } + } + + public static BArray castParamArray(int targetElementTypeTag, String[] argValueArr) { + switch (targetElementTypeTag) { + case INT_TAG: + return getBArray(argValueArr, INT_ARR, targetElementTypeTag); + case FLOAT_TAG: + return getBArray(argValueArr, FLOAT_ARR, targetElementTypeTag); + case BOOLEAN_TAG: + return getBArray(argValueArr, BOOLEAN_ARR, targetElementTypeTag); + case DECIMAL_TAG: + return getBArray(argValueArr, DECIMAL_ARR, targetElementTypeTag); + default: + return StringUtils.fromStringArray(argValueArr); + } + } + + private static BArray getBArray(String[] valueArray, ArrayType arrayType, int elementTypeTag) { + BArray arrayValue = ValueCreator.createArrayValue(arrayType); + int index = 0; + for (String element : valueArray) { + switch (elementTypeTag) { + case INT_TAG: + arrayValue.add(index++, Long.parseLong(element)); + break; + case FLOAT_TAG: + arrayValue.add(index++, Double.parseDouble(element)); + break; + case BOOLEAN_TAG: + arrayValue.add(index++, Boolean.parseBoolean(element)); + break; + case DECIMAL_TAG: + arrayValue.add(index++, ValueCreator.createDecimalValue(element)); + break; + default: + throw new InvalidPayloadException("Illegal state error: unexpected param type"); + } + } + return arrayValue; + } + + public static boolean isNilType(Type type) { + if (type.getTag() == TypeTags.UNION_TAG) { + List memberTypes = ((UnionType) type).getMemberTypes(); + for (Type memberType : memberTypes) { + if (isNilType(memberType)) { + return true; + } + } + } else if (type.getTag() == TypeTags.NULL_TAG) { + return true; + } + return false; + } + + public static BString getRequestBody(BMap httpPayload, String name, Type type) + throws PayloadNotFoundException { + BString bBody = StringUtils.fromString(Constants.AZURE_BODY_HEADERS); + if (httpPayload.containsKey(bBody)) { + return httpPayload.getStringValue(bBody); + } + if (!isNilType(type)) { + throw new PayloadNotFoundException("payload not found for the variable '" + name + "'"); + } + return null; + } + + public static String getContentTypeHeader(BMap headers) { + //TODO fix lower case + if (headers.containsKey(StringUtils.fromString(Constants.CONTENT_TYPE))) { + BArray headersArrayValue = headers.getArrayValue(StringUtils.fromString(Constants.CONTENT_TYPE)); + return headersArrayValue.getBString(0).getValue(); + } else { + return null; + } + } + + public static boolean isAzAnnotationExist(Object annotation) { + if (annotation == null) { + return false; + } + return true; + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/bindings/input/BlobInput.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/bindings/input/BlobInput.java new file mode 100644 index 00000000..77443a75 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/bindings/input/BlobInput.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.stdlib.azure.functions.bindings.input; + +import io.ballerina.runtime.api.types.Type; +import io.ballerina.stdlib.azure.functions.builder.AbstractPayloadBuilder; +import io.ballerina.stdlib.azure.functions.builder.JsonPayloadBuilder; + +/** + * Represents the BlobInput Input Binding of azure functions. + * + * @since 2.0.0 + */ +public class BlobInput extends InputBinding { + + public BlobInput() { + super("BlobInput"); + } + + @Override + public AbstractPayloadBuilder getPayloadBuilder(Type type) { + return new JsonPayloadBuilder(type); + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/bindings/input/CosmosInput.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/bindings/input/CosmosInput.java new file mode 100644 index 00000000..f51c2a09 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/bindings/input/CosmosInput.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.stdlib.azure.functions.bindings.input; + +import io.ballerina.runtime.api.types.Type; +import io.ballerina.stdlib.azure.functions.builder.AbstractPayloadBuilder; +import io.ballerina.stdlib.azure.functions.builder.JsonPayloadBuilder; + +/** + * Represents the CosmosDB Input in Azure functions input binding. + * + * @since 2.0.0 + */ +public class CosmosInput extends InputBinding { + + public CosmosInput() { + super("CosmosDBInput"); + } + + @Override + public AbstractPayloadBuilder getPayloadBuilder(Type type) { + return new JsonPayloadBuilder(type); + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/bindings/input/InputBinding.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/bindings/input/InputBinding.java new file mode 100644 index 00000000..6ec2156b --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/bindings/input/InputBinding.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.ballerina.stdlib.azure.functions.bindings.input; + +import io.ballerina.runtime.api.types.Type; +import io.ballerina.stdlib.azure.functions.builder.AbstractPayloadBuilder; + +/** + * Represents the base class for Input bindings in azure functions. + * + * @since 2.0.0 + */ +public abstract class InputBinding { + + private final String name; + + public InputBinding(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public abstract AbstractPayloadBuilder getPayloadBuilder(Type type); +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/AbstractPayloadBuilder.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/AbstractPayloadBuilder.java new file mode 100644 index 00000000..bcb5a8c7 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/AbstractPayloadBuilder.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.builder; + +import io.ballerina.runtime.api.TypeTags; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.types.TypedescType; +import io.ballerina.runtime.api.types.UnionType; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.runtime.api.values.BTypedesc; + +import java.util.List; +import java.util.Locale; + +import static io.ballerina.runtime.api.TypeTags.ARRAY_TAG; +import static io.ballerina.runtime.api.TypeTags.STRING_TAG; +import static io.ballerina.runtime.api.TypeTags.XML_TAG; + +/** + * The abstract class to build and convert the payload based on the content-type header. If the content type is not + * standard, the parameter type is used to infer the builder. + * + * @since SwanLake update 1 + */ +public abstract class AbstractPayloadBuilder { + + private static final String JSON_PATTERN = "^.*json.*$"; + private static final String XML_PATTERN = "^.*xml.*$"; + private static final String TEXT_PATTERN = "^.*text.*$"; + private static final String OCTET_STREAM_PATTERN = "^.*octet-stream.*$"; + private static final String URL_ENCODED_PATTERN = "^.*x-www-form-urlencoded.*$"; + + /** + * Get the built inbound payload after binding it to the respective type. + * + * @param dataSource inbound request entity + * @param readonly readonly status of parameter + * @return the payload + */ + public abstract Object getValue(BString dataSource, boolean readonly); + + public static AbstractPayloadBuilder getBuilder(String contentType, Type payloadType) { + if (contentType == null || contentType.isEmpty()) { + return getBuilderFromType(payloadType); + } + contentType = contentType.toLowerCase(Locale.getDefault()); + if (contentType.matches(XML_PATTERN)) { + return new XmlPayloadBuilder(payloadType); + } else if (contentType.matches(TEXT_PATTERN)) { + return new StringPayloadBuilder(payloadType); + } else if (contentType.matches(URL_ENCODED_PATTERN)) { + return new StringPayloadBuilder(payloadType); + } else if (contentType.matches(OCTET_STREAM_PATTERN)) { + return new BinaryPayloadBuilder(payloadType); + } else if (contentType.matches(JSON_PATTERN)) { + return new JsonPayloadBuilder(payloadType); + } else { + return getBuilderFromType(payloadType); + } + } + + private static AbstractPayloadBuilder getBuilderFromType(Type payloadType) { + switch (payloadType.getTag()) { + case STRING_TAG: + return new StringPayloadBuilder(payloadType); + case XML_TAG: + return new XmlPayloadBuilder(payloadType); + case ARRAY_TAG: + return new ArrayBuilder(payloadType); + default: + return new JsonPayloadBuilder(payloadType); + } + } + + public static boolean isSubtypeOfAllowedType(Type payloadType, int targetTypeTag) { + if (payloadType.getTag() == targetTypeTag) { + return true; + } else if (payloadType.getTag() == TypeTags.UNION_TAG) { + assert payloadType instanceof UnionType : payloadType.getClass(); + List memberTypes = ((UnionType) payloadType).getMemberTypes(); + return memberTypes.stream().anyMatch(memberType -> isSubtypeOfAllowedType(memberType, targetTypeTag)); + } + return false; + } + + public static boolean typeIncludedInUnion(BTypedesc unionType, BTypedesc targetType) { + int targetTypeTag = ((TypedescType) targetType.getDescribingType()).getConstraint().getTag(); + Type unionTypeDescribingType = unionType.getDescribingType(); + if (unionTypeDescribingType.getTag() == TypeTags.UNION_TAG) { + List memberTypes = ((UnionType) unionTypeDescribingType).getMemberTypes(); + return memberTypes.stream().anyMatch(memberType -> memberType.getTag() == targetTypeTag); + } + return false; + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/ArrayBuilder.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/ArrayBuilder.java new file mode 100644 index 00000000..6052bed3 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/ArrayBuilder.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.builder; + +import io.ballerina.runtime.api.TypeTags; +import io.ballerina.runtime.api.types.ArrayType; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.values.BString; + +/** + * The array type payload builder. + * + * @since SwanLake update 1 + */ +public class ArrayBuilder extends AbstractPayloadBuilder { + private final Type payloadType; + + public ArrayBuilder(Type payloadType) { + this.payloadType = payloadType; + } + + @Override + public Object getValue(BString entity, boolean readonly) { + Type elementType = ((ArrayType) payloadType).getElementType(); + if (elementType.getTag() == TypeTags.BYTE_TAG) { + return new BinaryPayloadBuilder(payloadType).getValue(entity, readonly); + } + return new JsonPayloadBuilder(payloadType).getValue(entity, readonly); + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/BinaryPayloadBuilder.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/BinaryPayloadBuilder.java new file mode 100644 index 00000000..a8875f84 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/BinaryPayloadBuilder.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.builder; + +import io.ballerina.runtime.api.TypeTags; +import io.ballerina.runtime.api.creators.ErrorCreator; +import io.ballerina.runtime.api.types.ArrayType; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.types.UnionType; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BString; +import org.ballerinalang.langlib.array.FromBase64; + +import java.util.List; + +/** + * The blob type payload builder. + * + * @since SwanLake update 1 + */ +public class BinaryPayloadBuilder extends AbstractPayloadBuilder { + private final Type payloadType; + + public BinaryPayloadBuilder(Type payloadType) { + this.payloadType = payloadType; + } + + @Override + public Object getValue(BString entity, boolean readonly) { + if (payloadType.getTag() == TypeTags.ARRAY_TAG) { + Type elementType = ((ArrayType) payloadType).getElementType(); + if (elementType.getTag() == TypeTags.BYTE_TAG) { + return FromBase64.fromBase64(entity); + } + } else if (payloadType.getTag() == TypeTags.UNION_TAG) { + List memberTypes = ((UnionType) payloadType).getMemberTypes(); + for (Type memberType : memberTypes) { + if (memberType.getTag() == TypeTags.ARRAY_TAG) { + Type elementType = ((ArrayType) memberType).getElementType(); + if (elementType.getTag() == TypeTags.BYTE_TAG) { + return FromBase64.fromBase64(entity); + } + } + } + } + throw ErrorCreator.createError(StringUtils.fromString("incompatible type found: '" + payloadType.toString())); + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/JsonPayloadBuilder.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/JsonPayloadBuilder.java new file mode 100644 index 00000000..b4977bfd --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/JsonPayloadBuilder.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.builder; + +import io.ballerina.runtime.api.TypeTags; +import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.types.ArrayType; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.types.UnionType; +import io.ballerina.runtime.api.values.BError; +import io.ballerina.runtime.api.values.BRefValue; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.stdlib.azure.functions.converter.JsonToRecordConverter; +import io.ballerina.stdlib.azure.functions.converter.StringToByteArrayConverter; +import org.ballerinalang.langlib.value.FromJsonString; +import org.ballerinalang.langlib.value.FromJsonWithType; + +import java.util.List; + +/** + * The json type payload builder. + * + * @since SwanLake update 1 + */ +public class JsonPayloadBuilder extends AbstractPayloadBuilder { + private final Type payloadType; + + public JsonPayloadBuilder(Type payloadType) { + this.payloadType = payloadType; + } + + @Override + public Object getValue(BString dataSource, boolean readonly) { + // Following can be removed based on the solution of + // https://github.com/ballerina-platform/ballerina-lang/issues/35780 + Object obj = FromJsonString.fromJsonString(dataSource); + if (isSubtypeOfAllowedType(payloadType, TypeTags.RECORD_TYPE_TAG)) { + return JsonToRecordConverter.convert(payloadType, obj, readonly); + } + return createValue(this.payloadType, readonly, obj); + } + + public Object createValue(Type payloadType, boolean readonly, Object dataSource) { + + if (dataSource instanceof BString) { + BString datasource = (BString) dataSource; + if (payloadType.getTag() == TypeTags.UNION_TAG) { + List memberTypes = ((UnionType) payloadType).getMemberTypes(); + for (Type memberType : memberTypes) { + try { + return createValue(memberType, readonly, datasource); + } catch (BError ignored) { + // thrown errors are ignored until all the types are iterated + } + } + } else if (payloadType.getTag() == TypeTags.ARRAY_TAG) { + ArrayType arrayType = (ArrayType) payloadType; + if (arrayType.getElementType().getTag() == TypeTags.BYTE_TAG) { + return StringToByteArrayConverter.convert(arrayType, datasource, readonly); + } + } + } + + var result = FromJsonWithType.fromJsonWithType(dataSource, ValueCreator.createTypedescValue(payloadType)); + if (result instanceof BError) { + throw (BError) result; + } + if (readonly && result instanceof BRefValue) { + ((BRefValue) result).freezeDirect(); + } + return result; + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/StringPayloadBuilder.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/StringPayloadBuilder.java new file mode 100644 index 00000000..2783ee60 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/StringPayloadBuilder.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.builder; + +import io.ballerina.runtime.api.TypeTags; +import io.ballerina.runtime.api.creators.ErrorCreator; +import io.ballerina.runtime.api.types.ArrayType; +import io.ballerina.runtime.api.types.MapType; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.types.UnionType; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BError; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.stdlib.azure.functions.converter.StringToByteArrayConverter; +import io.ballerina.stdlib.azure.functions.converter.UrlEncodedStringToMapConverter; + +import java.util.List; + +/** + * The string type payload builder. + * + * @since SwanLake update 1 + */ +public class StringPayloadBuilder extends AbstractPayloadBuilder { + private final Type payloadType; + + public StringPayloadBuilder(Type payloadType) { + this.payloadType = payloadType; + } + + @Override + public Object getValue(BString dataSource, boolean readonly) { + return createValue(payloadType, readonly, dataSource); + } + + private Object createValue(Type payloadType, boolean readonly, BString dataSource) { + if (payloadType.getTag() == TypeTags.STRING_TAG) { + return dataSource; + } else if (payloadType.getTag() == TypeTags.ARRAY_TAG) { + return StringToByteArrayConverter.convert((ArrayType) payloadType, dataSource, readonly); + } else if (payloadType.getTag() == TypeTags.MAP_TAG) { + return UrlEncodedStringToMapConverter.convert((MapType) payloadType, dataSource, readonly); + } else if (payloadType.getTag() == TypeTags.UNION_TAG) { + List memberTypes = ((UnionType) payloadType).getMemberTypes(); + for (Type memberType : memberTypes) { + try { + return createValue(memberType, readonly, dataSource); + } catch (BError ignored) { + // thrown errors are ignored until all the types are iterated + } + } + } + throw ErrorCreator.createError(StringUtils.fromString("incompatible type found: '" + payloadType.toString())); + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/XmlPayloadBuilder.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/XmlPayloadBuilder.java new file mode 100644 index 00000000..70c6c9d2 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/builder/XmlPayloadBuilder.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.builder; + +import io.ballerina.runtime.api.TypeTags; +import io.ballerina.runtime.api.creators.ErrorCreator; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.utils.XmlUtils; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.runtime.api.values.BXml; +/** + * The xml type payload builder. + * + * @since SwanLake update 1 + */ +public class XmlPayloadBuilder extends AbstractPayloadBuilder { + private final Type payloadType; + + public XmlPayloadBuilder(Type payloadType) { + this.payloadType = payloadType; + } + + @Override + public Object getValue(BString entity, boolean readonly) { + if (isSubtypeOfAllowedType(payloadType, TypeTags.XML_TAG)) { + BXml bxml = XmlUtils.parse(entity); + if (readonly) { + bxml.freezeDirect(); + } + return bxml; + } + throw ErrorCreator.createError(StringUtils.fromString("incompatible type found: '" + payloadType.toString())); + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/converter/JsonToRecordConverter.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/converter/JsonToRecordConverter.java new file mode 100644 index 00000000..0ac5cad5 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/converter/JsonToRecordConverter.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.converter; + +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.values.BError; +import io.ballerina.runtime.api.values.BRefValue; +import org.ballerinalang.langlib.value.CloneWithType; + +/** + * The converter binds the JSON payload to a record. + * + * @since SwanLake update 1 + */ +public class JsonToRecordConverter { + + public static Object convert(Type type, Object entity, boolean readonly) { + Object recordEntity = getRecordEntity(entity, type); + if (readonly && recordEntity instanceof BRefValue) { + ((BRefValue) recordEntity).freezeDirect(); + } + return recordEntity; + } + + private static Object getRecordEntity(Object entity, Type entityBodyType) { + Object result = getRecord(entityBodyType, entity); + if (result instanceof BError) { + throw (BError) result; + } + return result; + } + + /** + * Convert a json to the relevant record type. + * + * @param entityBodyType Represents entity body type + * @param bjson Represents the json value that needs to be converted + * @return the relevant ballerina record or object + */ + private static Object getRecord(Type entityBodyType, Object bjson) { + try { + return CloneWithType.convert(entityBodyType, bjson); + } catch (NullPointerException ex) { + throw new RuntimeException("cannot convert payload to record type: " + + entityBodyType.getName()); + } + } + private JsonToRecordConverter() { + + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/converter/StringToByteArrayConverter.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/converter/StringToByteArrayConverter.java new file mode 100644 index 00000000..5e4a9b08 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/converter/StringToByteArrayConverter.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.converter; + +import io.ballerina.runtime.api.TypeTags; +import io.ballerina.runtime.api.creators.ErrorCreator; +import io.ballerina.runtime.api.types.ArrayType; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BString; + +import java.nio.charset.StandardCharsets; + +import static io.ballerina.runtime.api.creators.ValueCreator.createArrayValue; +import static io.ballerina.runtime.api.creators.ValueCreator.createReadonlyArrayValue; + +/** + * The converter binds the String payload to a Byte array. + * + * @since SwanLake update 1 + */ +public class StringToByteArrayConverter { + + public static Object convert(ArrayType type, BString dataSource, boolean readonly) { + Type elementType = type.getElementType(); + if (elementType.getTag() == TypeTags.BYTE_TAG) { + byte[] values = dataSource.getValue().getBytes(StandardCharsets.UTF_8); + return readonly ? createReadonlyArrayValue(values) : createArrayValue(values); + } + return ErrorCreator.createError(StringUtils.fromString("incompatible array element type found: '" + + elementType.toString())); + } + + private StringToByteArrayConverter() { + + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/converter/UrlEncodedStringToMapConverter.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/converter/UrlEncodedStringToMapConverter.java new file mode 100644 index 00000000..a786a12b --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/converter/UrlEncodedStringToMapConverter.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.converter; + +import io.ballerina.runtime.api.PredefinedTypes; +import io.ballerina.runtime.api.creators.ErrorCreator; +import io.ballerina.runtime.api.creators.TypeCreator; +import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.types.MapType; +import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BString; + +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +import static io.ballerina.runtime.api.TypeTags.STRING_TAG; + +/** + * The converter binds the URL encoded string payload to a Map. + * + * @since SwanLake update 1 + */ +public class UrlEncodedStringToMapConverter { + + private static final MapType STRING_MAP = TypeCreator.createMapType(PredefinedTypes.TYPE_STRING); + + public static Object convert(MapType type, BString dataSource, boolean readonly) { + Type constrainedType = type.getConstrainedType(); + if (constrainedType.getTag() == STRING_TAG) { + BMap formParamMap = getFormParamMap(dataSource); + if (readonly) { + formParamMap.freezeDirect(); + } + return formParamMap; + } + throw ErrorCreator.createError(StringUtils.fromString("incompatible type found: '" + type.toString())); + } + + private static BMap getFormParamMap(Object stringDataSource) { + try { + String formData = ((BString) stringDataSource).getValue(); + BMap formParamsMap = ValueCreator.createMapValue(STRING_MAP); + if (formData.isEmpty()) { + return formParamsMap; + } + Map tempParamMap = new HashMap<>(); + String decodedValue = URLDecoder.decode(formData, StandardCharsets.UTF_8); + + if (!decodedValue.contains("=")) { + throw new RuntimeException("Datasource does not contain form data"); + } + String[] formParamValues = decodedValue.split("&"); + for (String formParam : formParamValues) { + int index = formParam.indexOf('='); + if (index == -1) { + if (!tempParamMap.containsKey(formParam)) { + tempParamMap.put(formParam, null); + } + continue; + } + String formParamName = formParam.substring(0, index).trim(); + String formParamValue = formParam.substring(index + 1).trim(); + tempParamMap.put(formParamName, formParamValue); + } + + for (Map.Entry entry : tempParamMap.entrySet()) { + String entryValue = entry.getValue(); + if (entryValue != null) { + formParamsMap.put(StringUtils.fromString(entry.getKey()), StringUtils.fromString(entryValue)); + } else { + formParamsMap.put(StringUtils.fromString(entry.getKey()), null); + } + } + return formParamsMap; + } catch (Exception ex) { + throw ErrorCreator.createError( + StringUtils.fromString("Could not convert payload to map: " + ex.getMessage())); + } + } + + private UrlEncodedStringToMapConverter() { + + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/BadRequestException.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/BadRequestException.java new file mode 100644 index 00000000..7c1ec4a4 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/BadRequestException.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.exceptions; + +/** + * Represents Bad Request related exceptions. + * + * @since 2.0.0 + */ +public abstract class BadRequestException extends RuntimeException { + private String type; + + public BadRequestException(String message, String type) { + super(message); + this.type = type; + } + + public String getType() { + return type; + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/FunctionNotFoundException.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/FunctionNotFoundException.java new file mode 100644 index 00000000..a016ad25 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/FunctionNotFoundException.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.exceptions; + +import io.ballerina.stdlib.azure.functions.Constants; + +/** + * Represents the exception thrown when theres no functions to be routed. + * + * @since 2.0.0 + */ +public class FunctionNotFoundException extends BadRequestException { + + public FunctionNotFoundException(String message) { + super(message, Constants.FUNCTION_NOT_FOUND_ERROR); + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/HeaderNotFoundException.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/HeaderNotFoundException.java new file mode 100644 index 00000000..9f9c3f50 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/HeaderNotFoundException.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.exceptions; + +import io.ballerina.stdlib.azure.functions.Constants; + +/** + * Represents when the expected header is not found. + * + * @since 2.0.0 + */ +public class HeaderNotFoundException extends BadRequestException { + + public HeaderNotFoundException(String message) { + super(message, Constants.HEADER_NOT_FOUND_ERROR); + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/InvalidPayloadException.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/InvalidPayloadException.java new file mode 100644 index 00000000..1ef38297 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/InvalidPayloadException.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.exceptions; + +import io.ballerina.stdlib.azure.functions.Constants; + +/** + * Represents an invalid payload type received from the request. + * + * @since 2.0.0 + */ +public class InvalidPayloadException extends BadRequestException { + + public InvalidPayloadException(String message) { + super(message, Constants.INVALID_PAYLOAD_ERROR); + } +} diff --git a/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/PayloadNotFoundException.java b/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/PayloadNotFoundException.java new file mode 100644 index 00000000..4ba9e210 --- /dev/null +++ b/native/src/main/java/io/ballerina/stdlib/azure/functions/exceptions/PayloadNotFoundException.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.stdlib.azure.functions.exceptions; + +import io.ballerina.stdlib.azure.functions.Constants; + +/** + * Represents when the expected payload is not found. + * + * @since 2.0.0 + */ +public class PayloadNotFoundException extends BadRequestException { + + public PayloadNotFoundException(String message) { + super(message, Constants.PAYLOAD_NOT_FOUND_ERROR); + } +} diff --git a/native/src/main/java/module-info.java b/native/src/main/java/module-info.java new file mode 100644 index 00000000..4e71dd9f --- /dev/null +++ b/native/src/main/java/module-info.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +module io.ballerina.stdlib.azure.functions { + requires io.ballerina.lang; + requires io.ballerina.runtime; + requires io.ballerina.lang.value; + requires io.ballerina.lang.array; + requires io.ballerina.lang.bool; + requires io.ballerina.lang.floatingpoint; + requires io.ballerina.lang.integer; + requires io.ballerina.lang.decimal; + requires io.ballerina.lang.string; +} diff --git a/settings.gradle b/settings.gradle index 1e528fb4..6d91ff41 100644 --- a/settings.gradle +++ b/settings.gradle @@ -21,13 +21,16 @@ plugins { rootProject.name = 'azure_functions' +include(':native') include ':checkstyle' +include ':azure_functions-native' include ':azure_functions-ballerina' include ':azure_functions-compiler-plugin' include ':azure_functions-ballerina-tests' include ':azure_functions-compiler-plugin-tests' project(':checkstyle').projectDir = file("build-config${File.separator}checkstyle") +project(':azure_functions-native').projectDir = file('native') project(':azure_functions-ballerina').projectDir = file('ballerina') project(':azure_functions-compiler-plugin').projectDir = file('compiler-plugin') project(':azure_functions-ballerina-tests').projectDir = file('ballerina-tests') diff --git a/spec/spec.md b/spec/spec.md new file mode 100644 index 00000000..79702331 --- /dev/null +++ b/spec/spec.md @@ -0,0 +1,606 @@ +### Supported Triggers And Bindings + +Supported From Ballerina - :heavy_check_mark: Supported From Azure - :white_check_mark: Not supported - :x: + +| Type | Trigger | Input | Output | +|--------------------- |-------------------- |-------------------- |-------------------- | +| Blob storage | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| Azure Cosmos DB | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| Azure SQL (preview) | | :white_check_mark: | :white_check_mark: | +| Dapr | | :white_check_mark: | :white_check_mark: | +| Event Grid | :white_check_mark: | | :white_check_mark: | +| Event Hubs | :white_check_mark: | | :white_check_mark: | +| HTTP & webhooks | :heavy_check_mark: | | :heavy_check_mark: | +| IoT Hub | :white_check_mark: | | | +| Kafka | :white_check_mark: | | :white_check_mark: | +| Mobile Apps | | :white_check_mark: | :white_check_mark: | +| Notification Hubs | | | :white_check_mark: | +| Queue storage | :heavy_check_mark: | | :heavy_check_mark: | +| RabbitMQ | :white_check_mark: | | :white_check_mark: | +| SendGrid | | | :white_check_mark: | +| Service Bus | :white_check_mark: | | :white_check_mark: | +| SignalR | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| Table storage | | :white_check_mark: | :white_check_mark: | +| Timer | :heavy_check_mark: | | | +| Twilio | | | :heavy_check_mark: | + +## HTTP + +### 2.1 Listener +Azure functions HTTP trigger is mapped to HttpListener defined in the module. You can define the listener in two ways. + +Separate listener declaration +```ballerina +import ballerinax/azure_functions as af; + +listener af:HttpListener ep = new (); + +service "hello" on ep { +} +``` + +Inline listener declaration +```ballerina +import ballerinax/azure_functions as af; + +service "hello" on new af:HttpListener() { +} +``` + + +### 2.2 Service +Service is a collection of resources functions, which are the network entry points of a ballerina program. +In addition to that a service can contain public and private functions which can be accessed by calling with `self`. + +#### 2.2.1. Service type +```ballerina +public type HttpService distinct service object { + +}; +``` +#### 2.2.2.Annotation +Each Listener can be attached with an optional annotation which contains the configurations required for the azure platform. +```ballerina +public type AUTH_LEVEL "anonymous"|"function"|"admin"; + +public type HTTPTriggerConfiguration record {| + AUTH_LEVEL authLevel = "anonymous"; +|}; +``` + +If an output Binding annotation is specified, HttpOutput will be taken implicitly. + +#### 2.2.2. Service base path + +The base path is considered during the request dispatching to discover the service. Identifiers and string literals +are allowed to be stated as base path and it should be started with `/`. The base path is optional and it will be +defaulted to `/` when not defined. If the base path contains any special characters, those should be escaped or defined +as string literals + +```ballerina +service hello\-world on new af:HttpListener() { + resource function get foo() { + + } +} + +service http:Service "hello-world" on new af:HttpListener() { + resource function get foo() { + + } +} +``` + +A service can be declared in three ways upon the requirement. + +#### 2.2.3. Service declaration +The [Service declaration](https://ballerina.io/spec/lang/2021R1/#section_8.3.2) is a syntactic sugar for creating a +service and it is the mostly used approach for creating a service. The declaration gets desugared into creating a +listener object, creating a service object, attaching the service object to the listener object. + +```ballerina +service af:HttpService /foo/bar on new af:HttpListener() { + resource function get greeting() returns string { + return "hello world"; + } +} +``` + +### 2.3. Resource + +A method of a service can be declared as a [resource function](https://ballerina.io/spec/lang/2021R1/#resources) +which is associated with configuration data that is invoked by a network message by a Listener. Users write the +business logic inside a resource and expose it over the network. + +#### 2.3.1. Accessor +The accessor-name of the resource represents the HTTP method and it can be get, post, put, delete, head, patch, options +and default. If the accessor is unmatched, 405 Method Not Allowed response is returned. When the accessor name is +stated as default, any HTTP method can be matched to it in the absence of an exact match. Users can define custom +methods such as copy, move based on their requirement. A resource which can handle any method would look like as +follows. This is useful when handling unmatched verbs. + +```ballerina +resource function 'default NAME_TEMPLATE () { + +} +``` +#### 2.3.2. Resource name +The resource-name represents the path of the resource which is considered during the request dispatching. The name can +be hierarchical(foo/bar/baz). Each path identifier should be separated by `/` and first path identifier should not +contain a prefixing `/`. If the paths are unmatched, 404 NOT FOUND response is returned. +```ballerina +resource function post hello() { + +} +``` +Only the identifiers can be used as resource path not string literals. Dot identifier is +used to denote the `/` only if the path contains a single identifier. +```ballerina +resource function post .() { + +} +``` +Any special characters can be used in the path by escaping. +```ballerina +resource function post hello\-world() { + +} +``` + +#### 2.3.3. Path parameter +The path parameter segment is also a part of the resource name which is declared within brackets along with the type. +As per the following resource name, baz is the path param segment and it’s type is string. Like wise users can define +string, int, boolean, float, and decimal typed path parameters. If the paths are unmatched, 404 NOT FOUND response +is returned. If the segment failed to parse into the expected type, 500 Internal Server Error response is returned. + +```ballerina +resource function post foo/bar/[string baz]/qux() { + // baz is the path param +} + +resource function get data/[int age]/[string name]/[boolean status]/[float weight]() returns json { + int balAge = age + 1; + float balWeight = weight + 2.95; + string balName = name + " lang"; + if (status) { + balName = name; + } + json responseJson = { Name:name, Age:balAge, Weight:balWeight, Status:status, Lang: balName}; + return responseJson; +} +``` + +If multiple path segments needs to be matched after the last identifier, Rest param should be used at the end of the +resource name as the last identifier. string, int, boolean, float, and decimal types are supported as rest parameters. +```ballerina +resource function get foo/[string... bar]() returns json { + json responseJson = {"echo": bar[0]}; + return responseJson; +} +``` + +Using both `'default` accessor and the rest parameters, a default resource can be defined to a service. This +default resource can act as a common destination where the unmatched requests (either HTTP method or resource path) may +get dispatched. + +```ballerina +resource function 'default [string... s]() { + +} +``` + +##### 2.3.4.3. Query parameter + +The query param is a URL parameter which is available as a resource function parameter and it's not associated +with any annotation or additional detail. This parameter is not compulsory and not ordered. The type of query param +are as follows + +```ballerina +type BasicType boolean|int|float|decimal|string|map; +``` + +The same query param can have multiple values. In the presence of multiple such values, If the user has specified +the param as an array type, then all values will return. If not the first param values will be returned. As per the +following resource function, the request may contain at least two query params with the key of bar and id. +Eg : “/hello?bar=hi&id=56” + +```ballerina +resource function get hello(string bar, int id) { + +} +``` + +If the query parameter is not defined in the function signature, then the query param binding does not happen. If a +query param of the request URL has no corresponding parameter in the resource function, then that param is ignored. +If the parameter is defined in the function, but there is no such query param in the URL, that request will lead +to a 400 BAD REQUEST error response unless the type is nilable (string?) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Case Resource argument Query Mapping
1 string foo foo=bar bar
foo= ""
foo Error : no query param value found for 'foo'
No query Error : no query param value found for 'foo'
2 string? foo foo=bar bar
foo= ""
foo nil
No query nil
+ +### Payload parameter + +The payload parameter is used to access the request payload during the resource invocation. When the payload param is +defined with @http:Payload annotation, the listener deserialize the inbound request payload based on the media type +which retrieved by the `Content-type` header of the request. The data binding happens thereafter considering the +parameter type. The type of payload parameter can be one of the `anytype`. If the header is not present or not a +standard header, the binding type is inferred by the parameter type. + +Following table explains the compatible `anydata` types with each common media type. In the absence of a standard media +type, the binding type is inferred by the payload parameter type itself. If the type is not compatible with the media +type, error is returned. + +|Ballerina Type | Structure|"text" | "xml" | "json" | "x-www-form-urlencoded" | "octet-stream"| +|---------------|----------|-------|-------|--------|-------------------------|---------------| +|boolean| | ❌ | ❌ | ✅|❌|❌ +| |boolean[]| ❌ | ❌ | ✅|❌|❌ +| |map\| ❌ | ❌ | ✅|❌|❌ +| |table\\>| ❌ | ❌ | ✅|❌|❌ +|int| | ❌ | ❌ | ✅|❌|❌ +| |int[]| ❌ | ❌ | ✅|❌|❌ +| |map\| ❌ | ❌ | ✅|❌|❌ +| |table\\>| ❌ | ❌ | ✅|❌|❌ +float| | ❌ | ❌ | ✅|❌|❌ +| |float[]| ❌ | ❌ | ✅|❌|❌ +| |map\| ❌ | ❌ | ✅|❌|❌ +| |table\\>| ❌ | ❌ | ✅|❌|❌ +decimal| | ❌ | ❌ | ✅|❌|❌ +| |decimal[]| ❌ | ❌ | ✅|❌|❌ +| |map\| ❌ | ❌ | ✅|❌|❌ +| |table\\>| ❌ | ❌ | ✅|❌|❌ +byte[]| | ✅ | ❌ | ✅|❌|✅ +| |byte[][]| ❌ | ❌ | ✅|❌|❌ +| |map\| ❌ | ❌ | ✅|❌|❌ +| |table\\>| ❌ | ❌ | ✅|❌|❌ +string| |✅|❌|✅|✅|❌ +| |string[]| ❌ | ❌ | ✅|❌|❌ +| |map\| ❌ | ❌ | ✅|✅|❌ +| |table\\>| ❌ | ❌ | ✅|❌|❌ +xml| | ❌ | ✅ | ❌|❌|❌ +json| | ❌ | ❌ | ✅|❌|❌ +| |json[]| ❌ | ❌ | ✅|❌|❌ +| |map\| ❌ | ❌ | ✅|❌|❌ +| |table\\>| ❌ | ❌ | ✅|❌|❌ +map| | ❌ | ❌ | ✅|❌|❌ +| |map[]| ❌ | ❌ | ✅|❌|❌ +| |map\| ❌ | ❌ | ✅|❌|❌ +| |table\\>| ❌ | ❌ | ✅|❌|❌ +record| |❌|❌|✅|❌|❌ +| |record[]| ❌ | ❌ | ✅|❌|❌ +| |map\| ❌ | ❌ | ✅|❌|❌ +| |table\| ❌ | ❌ | ✅|❌|❌ + ```bal + resource function post query(string name, @http:Payload string greeting) returns @af:HttpOutput string|error { + return "Hello from the query " + greeting + " " + name; + } +``` + + +##### 2.3.4.5. Header parameter + +The header parameter is to access the inbound request headers The header param is defined with `@http:Header` annotation +The type of header param can be defined as follows; + +```ballerina +type BasicType string|int|float|decimal|boolean; +public type HeaderParamType ()|BasicType|BasicType[]|record {| BasicType...; |}; +``` + +When multiple header values are present for the given header, the first header value is returned when the param +type is `string` or any of the basic types. To retrieve all the values, use `string[]` type or any array of the +basic types. This parameter is not compulsory and not ordered. + +The header param name is considered as the header name during the value retrieval. However, the header annotation name +field can be used to define the header name whenever user needs some different variable name for the header. + +User cannot denote the type as a union of pure type, array type, or record type together, that way the resource +cannot infer a single type to proceed. Hence, returns a compiler error. + +In the absence of a header when the param is defined in the resource signature, listener returns 400 BAD REQUEST unless +the type is nilable. + +```ballerina +//Single header value extraction +resource function post hello1(@http:Header string referer) { + +} + +//Multiple header value extraction +resource function post hello2(@http:Header {name: "Accept"} string[] accept) { + +} + +public type RateLimitHeaders record {| + string x\-rate\-limit\-id; + int x\-rate\-limit\-remaining; + string[] x\-rate\-limit\-types; +|}; + +//Populate selected headers to a record +resource function get hello3(@http:Header RateLimitHeaders rateLimitHeaders) { +} +``` + +If the requirement is to access all the header of the inbound request, it can be achieved through the `http:Headers` +typed param in the signature. It does not need the annotation and not ordered. + +```ballerina +resource function get hello3(http:Headers headers) { + String|error referer = headers.getHeader("Referer"); + String[]|error accept = headers.getHeaders("Accept"); + String[] keys = headers.getHeaderNames(); +} +``` + +The header consists of header name and values. Sometimes user may send header without value(`foo:`). In such +situations, when the header param type is nilable, the values returns nil and same happened when the complete header is +not present in the request. In order to avoid the missing detail, a service level configuration has introduced naming +`treatNilableAsOptional` + +```ballerina +@http:ServiceConfig { + treatNilableAsOptional : false +} +service /headerparamservice on HeaderBindingIdealEP { + + resource function get test1(@http:Header string? foo) returns json { + + } +} +``` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Case Resource argument Header Current Mapping (treatNilableAsOptional=true - Default) Ideal Mapping (treatNilableAsOptional=false)
1 string foo foo:bar bar bar
foo: Error : no header value found for 'foo' Error : no header value found for 'foo'
No header Error : no header value found for 'foo' Error : no header value found for 'foo'
2 string? foo foo:bar bar bar
foo: nil nil
No header nil Error : no header value found for 'foo'
+ +#### 2.3.5. Return types +The resource function supports anydata, error?, http:Response and http:StatusCodeResponse as return types. + +```ballerina +resource function XXX NAME_TEMPLATE () returns @http:Payload anydata|http:Response|http:StatusCodeResponse|http:Error? { +} +``` + +In addition to that the `@http:Payload` annotation can be specified along with anydata return type +mentioning the content type of the outbound payload. + +```ballerina +resource function get test() returns @http:Payload {mediaType:"text/id+plain"} string { + return "world"; +} +``` + +Based on the return types respective header value is added as the `Content-type` of the `http:Response`. + +| Type | Content Type | +|-----------------------------------------------------------------------|--------------------------| +| () | - | +| string | text/plain | +| xml | application/xml | +| byte[] | application/octet-stream | +| int, float, decimal, boolean | application/json | +| map\, table>, map\[], table>)[] | application/json | +| http:StatusCodeResponse | application/json | + +##### 2.3.5.1. Status Code Response + +The status code response records are defined in the HTTP module for every HTTP status code. + +```ballerina +type Person record { + string name; +}; +resource function put person(string name) returns record {|*http:Created; Person body;|} { + Person person = {name:name}; + return { + mediaType: "application/person+json", + headers: { + "X-Server": "myServer" + }, + body: person + }; +} +``` + +Following is the `http:Ok` definition. Likewise, all the status codes are provided. + +```ballerina +public type Ok record { + readonly StatusOk status; + string mediaType; + map headers?; + anydata body?; +}; + +resource function get greeting() returns http:Ok|http:InternalServerError { + http:Ok ok = { body: "hello world", headers: { xtest: "foo"} }; + return ok; +} +``` + +##### 2.3.5.2. Return nil + + +The return nil from the resource will return 202 ACCEPTED response. +```ballerina +resource function post person(@http:Payload Person p) { + int age = p.age; + io:println(string `Age is: ${age}`); +} +``` + +##### 2.3.5.3. Default response status codes + +To improve the developer experience for RESTful API development, following default status codes will be used in outbound +response when returning `anydata` directly from a resource function. + +| Resource Accessor | Semantics | Status Code | +|-------------------|---------------------------------------------------------------|-------------------------| +| GET | Retrieve the resource | 200 OK | +| POST | Create a new resource | 201 Created | +| PUT | Create a new resource or update an existing resource | 200 OK | +| PATCH | Partially update an existing resource | 200 OK | +| DELETE | Delete an existing resource | 200 OK | +| HEAD | Retrieve headers | 200 OK | +| OPTIONS | Retrieve permitted communication options | 200 OK | + +### Artifact generation +//TODO Fill +#### Function name Generation +//TODO Fill + +## Queue + + ```bal +@af:QueueTrigger { + queueName: "queue2" +} +listener af:QueueListener queueListener = new af:QueueListener(); +service "queue" on queueListener { + remote function onMessage (@http:Payload string inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + return "helloo "+ inMsg; + } +} +``` + + +## CosmosDB + + ```bal +@af:CosmosDBTrigger {connectionStringSetting: "CosmosDBConnection", databaseName: "db1", collectionName: "c2"} +listener af:CosmosDBListener cosmosEp = new (); + +service "cosmos" on cosmosEp { + remote function onUpdated (@http:Payload DBEntry[] inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + string id = inMsg[0].id; + return "helloo "+ id; + } +} +``` + + +## Blob + + ```bal +@af:BlobTrigger { path: "bpath1/{name}" } +listener af:BlobListener blobEp = new (); + +service "blob" on blobEp { + remote function onUpdated (@http:Payload byte[] inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + string id = inMsg[0].id; + return "helloo "+ id; + } +} +``` + +## Timer + + ```bal +@af:TimerTrigger { schedule: "*/10 * * * * *" } +listener af:TimerListener timerEp = new (); + +service "timer" on timerEp { + remote function onTriggered (@http:Payload json inMsg) returns @af:QueueOutput {queueName: "queue3"} string|error { + string id = inMsg[0].id; + return "helloo "+ id; + } +} +``` + + +## Twilio + + + ```bal +@af:TimerTrigger { schedule: "*/10 * * * * *" } +listener af:TimerListener timerEp = new (); + +service "timer" on timerEp { + remote function onTriggered (@http:Payload json inMsg) returns @af:QueueOutput @af:TwilioSmsOutput { fromNumber: "+12069845840" } string|error { + string id = inMsg[0].id; + return "helloo "+ id; + } +} +```