diff --git a/tutorial-demos/firestore-demo/README.md b/tutorial-demos/firestore-demo/README.md new file mode 100644 index 00000000..fd158e24 --- /dev/null +++ b/tutorial-demos/firestore-demo/README.md @@ -0,0 +1,77 @@ +# Apigee Firestore Quickstart & Adapter +This repository contains a quickstart proxy for the [Apige API Management](cloud.google.com/apigee) platform to connect to a collection in a [Firestore](cloud.google.com/firestore) database. The API provided by the proxy can then be easily used by any REST clients, including [AppSheet](cloud.google.com/appsheet) no-code apps. + +## Prerequisites +Firestore is a great document database for storing any kind of unstructured data, however we do need some structures to automatically use any database with this quickstart. +* An **id** field in each document, which should match the document key. This makes identifying the record quick and easy. It's easiest if this field is also called **id** in the document. +* Supported data types - we only support these data types in the documents for now: + * string + * boolean + * geopoint (locations) + * timestamp +* Not-supported data types - we don't support these data types, since they would be recursive and be difficult for REST clients like AppSheet to work with. + * array - It is recommended to have sub-array collections as separate collections (using an id field as link). + * map - This could be easily added and flattened into the REST response object, but on the other hand makes life difficult for clients like AppSheet, so it is recommended to also model sub-map structures as separate collections (using an id field as link). + +As you can see, only primitive data types are supported in the Firestore documents, which makes it easy to map into REST resource structures. + +## Quickstart deploy +The fastest way to deploy and spin up an API offering CRUD operations on your Firestore database is to import the **Firestore Quickstart** proxy bundle in Apigee, and then set these properties: + +1. In the default Endpoint PreFlow, replace the following variables in the 1st policy **Set-Firestore-Variables** to your own values: + 1. **GCP_PROJECT** - replace with the GCP project name where your Firestore database is located. + 2. **firestore.key** - in case the **id** index field isn't named **id** in the Firestore documents (see prerequisites above), then you should set the correct name here (it is recommended to just use **id**). + 3. **GCP_SVC_KEY** - set this to your GCP service account private key (which has the permissions to access Firestore in your GCP project) from the **private_key** field in the key JSON file (beginning with -----BEGIN PRIVATE KEY----- and ending with -----END PRIVATE KEY-----) + 4. **GCP_SVC_EMAIL** - set this to the GCP service account email address from the **client_email** field in the private key JSON file. +2. Change the proxy basepath to something meaningful (default is **/importantstuff**, for no particular reason) +3. Deploy the proxy. By default an API key is activated for the proxy, disable the 2nd policy in the PreFlow if you want to test without one. Now you can call https://host/basepath/collection/document to all CRUD operations on your Firestore data, using simple JSON payload messages. WooHoo! +4. You can also use this proxy as an API data source in an AppSheet app, it will just work. + +## Example +An example is deployed for this Firestore data structure: +```json +{ +"name": "projects/tyler-240211/databases/(default)/documents/jokes/8ebb59f9", +"fields": { +"funny": { +"booleanValue": true +}, +"imagePath": { +"stringValue": "https://dakiniland.files.wordpress.com/2011/05/102-0907085235-simpsons-mutant-fish-blinky.jpg" +}, +"location": { +"geoPointValue": { +"latitude": 29.987294, +"longitude": -39.6875 +} +}, +"punchline": { +"stringValue": "A fiiish." +}, +"text": { +"stringValue": "What do you call a fish with 3 eyes?" +}, +"id": { +"stringValue": "8ebb59f9" +}, +"timestamp": { +"timestampValue": "2020-10-08T13:05:29Z" +} +}, +"createTime": "2020-10-08T11:06:55.234785Z", +"updateTime": "2020-10-08T11:21:56.903039Z" +} +``` +This proxy then offers REST CRUD APIs with this much nicer structure: +```json +{ +"id": "8ebb59f9", +"funny": true, +"text": "What do you call a fish with 3 eyes?", +"imagePath": "https://dakiniland.files.wordpress.com/2011/05/102-0907085235-simpsons-mutant-fish-blinky.jpg", +"timestamp": "2020-10-08T13:05:29Z", +"punchline": "A fiiish.", +"location": "29.987294, -39.6875" +} +``` +The OpenAPI spec for the example is under /specs, and can also be used to create an AppSheet app based on the API. \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/Firestore Quickstart.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/Firestore Quickstart.xml new file mode 100644 index 00000000..ae891f92 --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/Firestore Quickstart.xml @@ -0,0 +1,38 @@ + + + /importantstuff + + 1602160821771 + defaultUser + + Firestore Quickstart + 1602163293230 + defaultUser + SHA-512:f55c15016835194ad271386c01805f23ab7de0f0150b4fe54abdbef4e3234c63d192850e55867d31fcce62f54651cbbc1858305b57ebd95a7743dd1b455c5087 + + Add-Bearer-Token + Assign-Message-2 + Extract-Token + Generate-JWT-1 + Get-Token + Get-Url-Variables + Remove-Key + Set-Firestore-Variables + Set-Verb + Verify-API-Key-1 + set-request + set-response + + + default + + + jsc://set-request.js + jsc://set-response.js + + + + + default + + diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/manifests/manifest.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/manifests/manifest.xml new file mode 100644 index 00000000..c475e3c6 --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/manifests/manifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Add-Bearer-Token.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Add-Bearer-Token.xml new file mode 100644 index 00000000..6a7ba224 --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Add-Bearer-Token.xml @@ -0,0 +1,13 @@ + + + Add Bearer Token + + + +
Bearer {firestore.token}
+
+ +
+ true + +
\ No newline at end of file diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Assign-Message-2.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Assign-Message-2.xml new file mode 100644 index 00000000..da5d1037 --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Assign-Message-2.xml @@ -0,0 +1,11 @@ + + + Assign Message-2 + + + target.copy.pathsuffix + false + + true + + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Extract-Token.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Extract-Token.xml new file mode 100644 index 00000000..55913709 --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Extract-Token.xml @@ -0,0 +1,13 @@ + + + Extract Token + + true + + + $.access_token + + + google-token-response + + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Generate-JWT-1.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Generate-JWT-1.xml new file mode 100644 index 00000000..055d8bb8 --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Generate-JWT-1.xml @@ -0,0 +1,17 @@ + + + RS256 + false + + + + + + https://www.googleapis.com/oauth2/v4/token + 60m + + + https://www.googleapis.com/auth/datastore + + google-jwt + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Get-Token.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Get-Token.xml new file mode 100644 index 00000000..68cda74b --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Get-Token.xml @@ -0,0 +1,29 @@ + + + Get-Google-Token + + + + +
application/x-www-form-urlencoded
+
+ + urn:ietf:params:oauth:grant-type:jwt-bearer + {google-jwt} + + + + + + + 1.1 + POST +
+ false +
+ google-token-response + + + https://www.googleapis.com/oauth2/v4/token + +
\ No newline at end of file diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Get-Url-Variables.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Get-Url-Variables.xml new file mode 100644 index 00000000..429a0fba --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Get-Url-Variables.xml @@ -0,0 +1,11 @@ + + + Get Url Variables + + /{collection} + /{collection}/{document} + + firestore + true + request + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Remove-Key.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Remove-Key.xml new file mode 100644 index 00000000..29b4718f --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Remove-Key.xml @@ -0,0 +1,12 @@ + + + Remove Key + + + +
+ + + true + + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Set-Firestore-Variables.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Set-Firestore-Variables.xml new file mode 100644 index 00000000..9abdaf46 --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Set-Firestore-Variables.xml @@ -0,0 +1,33 @@ + + + Set Firestore Variables + + + firestore.project + GCP_PROJECT + + + firestore.document + + + + firestore.input + request.content + + + firestore.key + id + + + private.gkey + + GCP_SVC_KEY + + + + firestore.serviceemail + GCP_SVC_EMAIL + + true + + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Set-Verb.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Set-Verb.xml new file mode 100644 index 00000000..210325dc --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Set-Verb.xml @@ -0,0 +1,10 @@ + + + Set-Verb + + + PATCH + + true + + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Verify-API-Key-1.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Verify-API-Key-1.xml new file mode 100644 index 00000000..777be960 --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/Verify-API-Key-1.xml @@ -0,0 +1,6 @@ + + + Verify API Key-1 + + + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/set-request.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/set-request.xml new file mode 100644 index 00000000..a4f624d5 --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/set-request.xml @@ -0,0 +1,6 @@ + + + set-request + + jsc://set-request.js + diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/set-response.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/set-response.xml new file mode 100644 index 00000000..8f2b0cea --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/policies/set-response.xml @@ -0,0 +1,6 @@ + + + set-response + + jsc://set-response.js + diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/proxies/default.xml b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/proxies/default.xml new file mode 100644 index 00000000..26e26f60 --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/proxies/default.xml @@ -0,0 +1,53 @@ + + + + + + Set-Firestore-Variables + + + Verify-API-Key-1 + + + Remove-Key + + + Get-Url-Variables + + + Generate-JWT-1 + + + Get-Token + + + Extract-Token + + + request.verb = "PUT" or request.verb = "POST" + set-request + + + request.verb = "PUT" or request.verb = "POST" + Set-Verb + + + + + + + + + + set-response + + + + + /importantstuff + secure + + + default + + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/resources/jsc/set-request.js b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/resources/jsc/set-request.js new file mode 100644 index 00000000..45f11905 --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/resources/jsc/set-request.js @@ -0,0 +1,45 @@ +var inputObject = JSON.parse(context.getVariable("request.content")); +var keyName = context.getVariable("firestore.key"); + +var firestoreObject = { + "fields": {} +} + +if (inputObject) { + for (var key in inputObject) { + var value = inputObject[key]; + + if (value && value.includes(", ")) { + // Is a location + var geos = value.split(','); + firestoreObject["fields"][key] = { + "geoPointValue": { + "latitude": geos[0].trim(), + "longitude": geos[1].trim() + } + } + } + else if (value && !isNaN(Date.parse(value))) { + var dateobj = new Date(value); + firestoreObject["fields"][key] = { + "timestampValue": dateobj.toISOString() + }; + } + else if (value && (value.toLowerCase() === "true" || value.toLowerCase() === "false")){ + firestoreObject["fields"][key] = { + "booleanValue": (value.toLowerCase() == "true") + }; + } + else { + firestoreObject["fields"][key] = { + "stringValue": value + }; + } + + if (key == keyName) { + context.setVariable("firestore.document", value); + } + } +} + +context.setVariable("request.content", JSON.stringify(firestoreObject)); diff --git a/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/resources/jsc/set-response.js b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/resources/jsc/set-response.js new file mode 100644 index 00000000..2e70fd3a --- /dev/null +++ b/tutorial-demos/firestore-demo/proxies/Firestore Quickstart/apiproxy/resources/jsc/set-response.js @@ -0,0 +1,74 @@ +var firestoreResponse = context.getVariable("response.content"); +var keyName = context.getVariable("firestore.key"); +var tableName = context.getVariable("firestore.collection"); + +var singleResponse = false; + +var responseObject = {}; +responseObject[tableName] = []; + +if(firestoreResponse) { + + var inputObject = JSON.parse(firestoreResponse); + + if (!inputObject.documents) { + singleResponse = true; + // This means only a single record is being returned, so just put it into an array to simplify processing + inputObject = { + "documents": [ + inputObject + ] + } + } + + for(i=0; i + + + + + Add-Bearer-Token + + + Assign-Message-2 + + + + + + + + + + + https://firestore.googleapis.com/v1/projects/{firestore.project}/databases/(default)/documents/{firestore.collection}/{firestore.document} + + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/Firebase-Adapter.xml b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/Firebase-Adapter.xml new file mode 100644 index 00000000..44a7fdab --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/Firebase-Adapter.xml @@ -0,0 +1,32 @@ + + + + 1601709479741 + defaultUser + undefined + Firebase-Adapter + 1602161156393 + defaultUser + SHA-512:0ca69693e533bbbc25e73fa42d5ff40d670cdf1a4f2882792fc7390c6e3658708eff90cf143053674bd1b614d39dc487be7ee66730f7d5103bfcf090e012235c + + Add-Bearer-Token + Assign-Google-Key + Convert-Response + Extract-Token + Firestore-API + Generate-JWT-1 + Get-Token + PATCH-Firestore-API + Set-Body + Set-Response + + + jsc://set-body.js + jsc://set-response.js + + + SharedFlow + + default + + diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/manifests/manifest.xml b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/manifests/manifest.xml new file mode 100644 index 00000000..3392c4fb --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/manifests/manifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Add-Bearer-Token.xml b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Add-Bearer-Token.xml new file mode 100644 index 00000000..8db65f06 --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Add-Bearer-Token.xml @@ -0,0 +1,17 @@ + + + Add Bearer Token + + + +
Bearer {firestore.token}
+
+ +
+ + target.copy.pathsuffix + false + + true + +
\ No newline at end of file diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Assign-Google-Key.xml b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Assign-Google-Key.xml new file mode 100644 index 00000000..2132afa5 --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Assign-Google-Key.xml @@ -0,0 +1,14 @@ + + + Assign Google Key + + + private.gkey + + GCP_SVC_KEY + + + + false + + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Convert-Response.xml b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Convert-Response.xml new file mode 100644 index 00000000..d702d608 --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Convert-Response.xml @@ -0,0 +1,6 @@ + + + Convert Response + + jsc://set-response.js + diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Extract-Token.xml b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Extract-Token.xml new file mode 100644 index 00000000..55913709 --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Extract-Token.xml @@ -0,0 +1,13 @@ + + + Extract Token + + true + + + $.access_token + + + google-token-response + + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Firestore-API.xml b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Firestore-API.xml new file mode 100644 index 00000000..693ade07 --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Firestore-API.xml @@ -0,0 +1,19 @@ + + + GET/DEL Firestore API + + + true + + +
Bearer {firestore.token}
+
+ {request.verb} +
+
+ serviceResponse + + + https://firestore.googleapis.com/v1/projects/{firestore.project}/databases/(default)/documents/{firestore.collection}/{firestore.document} + +
\ No newline at end of file diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Generate-JWT-1.xml b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Generate-JWT-1.xml new file mode 100644 index 00000000..c2249b4e --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Generate-JWT-1.xml @@ -0,0 +1,17 @@ + + + RS256 + false + + + + GCP_SVC_EMAIL + GCP_SVC_EMAIL + https://www.googleapis.com/oauth2/v4/token + 60m + + + https://www.googleapis.com/auth/datastore + + google-jwt + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Get-Token.xml b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Get-Token.xml new file mode 100644 index 00000000..68cda74b --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Get-Token.xml @@ -0,0 +1,29 @@ + + + Get-Google-Token + + + + +
application/x-www-form-urlencoded
+
+ + urn:ietf:params:oauth:grant-type:jwt-bearer + {google-jwt} + + + + + + + 1.1 + POST +
+ false +
+ google-token-response + + + https://www.googleapis.com/oauth2/v4/token + +
\ No newline at end of file diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/PATCH-Firestore-API.xml b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/PATCH-Firestore-API.xml new file mode 100644 index 00000000..a6bbb4b4 --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/PATCH-Firestore-API.xml @@ -0,0 +1,22 @@ + + + PATCH Firestore API + + + true + + +
Bearer {firestore.token}
+
+ PATCH + + {firestore.payload} + +
+
+ firestore.response + + + https://firestore.googleapis.com/v1/projects/{firestore.project}/databases/(default)/documents/{firestore.collection}/{firestore.document} + +
\ No newline at end of file diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Set-Body.xml b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Set-Body.xml new file mode 100644 index 00000000..26962c86 --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Set-Body.xml @@ -0,0 +1,6 @@ + + + Set Body + + jsc://set-body.js + diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Set-Response.xml b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Set-Response.xml new file mode 100644 index 00000000..0e48e7eb --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/policies/Set-Response.xml @@ -0,0 +1,12 @@ + + + Set Response + + + firestore.response + + ServiceCallout.response + + true + + \ No newline at end of file diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/resources/jsc/set-body.js b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/resources/jsc/set-body.js new file mode 100644 index 00000000..e3c9bf13 --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/resources/jsc/set-body.js @@ -0,0 +1,45 @@ +var inputObject = JSON.parse(context.getVariable("firestore.input")); +var keyName = context.getVariable("firestore.key"); + +var firestoreObject = { + "fields": {} +} + +if (inputObject) { + for (var key in inputObject) { + var value = inputObject[key]; + + if (value && value.includes(", ")) { + // Is a location + var geos = value.split(','); + firestoreObject["fields"][key] = { + "geoPointValue": { + "latitude": geos[0].trim(), + "longitude": geos[1].trim() + } + } + } + else if (value && !isNaN(Date.parse(value))) { + var dateobj = new Date(value); + firestoreObject["fields"][key] = { + "timestampValue": dateobj.toISOString() + }; + } + else if (value && (value.toLowerCase() === "true" || value.toLowerCase() === "false")){ + firestoreObject["fields"][key] = { + "booleanValue": (value.toLowerCase() == "true") + }; + } + else { + firestoreObject["fields"][key] = { + "stringValue": value + }; + } + + if (key == keyName) { + context.setVariable("firestore.document", value); + } + } +} + +context.setVariable("firestore.payload", JSON.stringify(firestoreObject)); diff --git a/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/resources/jsc/set-response.js b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/resources/jsc/set-response.js new file mode 100644 index 00000000..c0562cfb --- /dev/null +++ b/tutorial-demos/firestore-demo/shared-flows/Firestore Adapter/sharedflowbundle/resources/jsc/set-response.js @@ -0,0 +1,75 @@ +var firestoreResponse = context.getVariable("serviceResponse.content"); +var keyName = context.getVariable("firestore.key"); +var tableName = context.getVariable("firestore.collection"); + +var singleResponse = false; + +var responseObject = {}; +responseObject[tableName] = []; + +if(firestoreResponse) { + + var inputObject = JSON.parse(firestoreResponse); + + if (!inputObject.documents) { + singleResponse = true; + // This means only a single record is being returned, so just put it into an array to simplify processing + inputObject = { + "documents": [ + inputObject + ] + } + } + + for(i=0; i + + + Assign-Google-Key + + + Generate-JWT-1 + + + Get-Token + + + Extract-Token + + + Add-Bearer-Token + + + Set-Body + request.verb = "POST" or request.verb = "PUT" + + + Firestore-API + request.verb = "GET" or request.verb = "DELETE" + + + PATCH-Firestore-API + request.verb = "POST" or request.verb = "PUT" + + + Set-Response + + + Convert-Response + + \ No newline at end of file diff --git a/tutorial-demos/firestore-appsheet-demo/specs/jokes-api.yaml b/tutorial-demos/firestore-demo/specs/jokes-api.yaml similarity index 100% rename from tutorial-demos/firestore-appsheet-demo/specs/jokes-api.yaml rename to tutorial-demos/firestore-demo/specs/jokes-api.yaml