Adding Custom API Methods
Some user-level APIs support adding custom methods.
Method Input Parameters
Input parameters are used to describe the structure of the above function
params`. If the function has no parameters, then do not fill it in.
If the function has parameters, they must be an object. The field structure described in the input parameters should match the structure of the params
actually used by the function; otherwise, errors may occur when used in the Weida application editor.
When using data sources in the Weida application editor, the structure information described in the input parameters
of data source methods will be utilized, for example:
- In the definition of data source variables, the configuration form for variables is generated based on the structure indicated by the input parameters (displaying the Chinese names of fields and showing different form controls based on field types).
- After associating the form container with the data source method, a complete form is generated based on the input parameter structure. For example: the field name in the input parameters becomes the field label in the form input box; the data type of the field may determine different input field types (phone number input/email input/toggle switch, etc.); and enumeration information is used to generate multi-select input fields or dropdown selectors, and so on.
The above is only an example. Data source method input parameters have numerous usage scenarios in the Weida application editor. Therefore, the more complete the information provided when filling in the input parameters
, the more convenient it will be to use in the Weida application editor.
Common Variables
Common variables provide a method for cross-method variable invocation, supporting references across multiple APIs. They are generally suitable for static variables such as APIToken, ClientID, and other constant values, and can be referenced using the template {{ }}
syntax.
For example, to set a common variable ClientId, reference it using the form {{vars.ClientId}}
.
Method Types
Data source methods are divided into two types based on their implementation approach:
- HTTP Request: This method type is only provided in external data sources, enabling simple integration with third-party http interfaces. Methods can be configured by simply setting the HTTP request URL, method, parameters, etc.
- Cloud Function: Achieves more flexible functionality by writing JavaScript code, including initiating HTTP requests.
HTTP Request
HTTP requests are encapsulated based on the underlying cloud function capabilities of Cloud Development, providing visual and rapid integration features for third-party HTTP APIs.
The HTTP configuration sets the underlying request parameters for HTTP requests. When configuring the URL, Query, Headers' value, and Body (only when the request Method is POST or PUT), you can use the template {{ }}
to reference the following fields:
- Reference fields defined in input parameters using the form
{{ params.field_identifier }}
- Reference environment variable information using the form
{{ env.field_identifier }}
, such as{{ env.openId }}
- Reference common variable information using the form
{{ vars.field_identifier }}
When configuring the Body, the content entered will be treated as a complete string template. Ensure the processed template result complies with the Body type requirements (JSON/FORM/XML), otherwise the request will fail directly.
Example:
The input parameter params
is { age: 12, name: 'Saurus', tags: ['aaa', 'bbb'] }
, and the Body type in the HTTP configuration is JSON.
Correct Body example, the request can be sent normally:
- If the Body content is
{ "age": {{params.age}} }
, the result will be{ "age": 12 }
- If the Body content is
{ "age": "{{params.age}}" }
, the result will be{ "age": "12" }
. Note that the value ofage
is a string. - If the Body content is
{ "tags": {{params.tags}} }
, the result will be{ "tags": ["aaa", "bbb"] }
Incorrect Body example, the request will fail directly:
- If the Body content is
{ age: {{params.age}} }
, the result will be{ age: 12 }
. Theage
key lacks double quotes"
wrapping - If the Body content is
{ "name": {{params.name}} }
, the result will be{ "name": Saurus }
. TheSaurus
value lacks double quotes"
wrapping - If the Body content is
{ "tags": "{{params.tags}}" }
, the result will be{ "tags": "["aaa", "bbb"]" }
. The value oftags
has a syntax error
Cloud Function
A Cloud Function is a special type of Javascript function. It is built upon the capabilities of CloudBase Cloud Functions and ultimately runs in a Node.js 10.15 runtime environment on the server side. You can access all features of the CloudBase Node.js sdk via the function's context parameter.
When writing Cloud Functions, note the following points:
- Cloud Functions must use
module.exports
for export - Cloud Functions accept only two parameters:
params
: Parameters accepted by the function, corresponding to the structure described in Method Input Parameters. Ensureparams
remains consistent with the structure described in Method Input Parameters during actual usage.context
: Cloud Function context object, which facilitates the implementation of various functionalities within Cloud Functions. For its specific structure, refer to Cloud Function context
- The result returned by the Cloud Function, i.e., the content returned by the
return
statement, should be an object and must be consistent with the structure described in Method Output Parameters - If an error is encountered in a Cloud Function, you can directly
throw new Error('xxxx')
to throw an error, or usethrow new TCBError(code, 'msg')
to throw an error with a custom error code. - During Cloud Function development, you can output logs via
console.log('xxxx')
, then use Method Testing to test and view the logs - The runtime environment for Cloud Functions is Node.js 10.15. Avoid using JavaScript features unsupported in the current version, such as optional chaining.
Below is the sample code for adding a custom creation method to a self-built data source:
Assuming the self-built data source has two custom data source fields, name and email, the following code will validate the parameters, restrict usage to qq email addresses only, and finally return the ID of the new record
module.exports = async function (params, context) {
// Output logs for debugging purposes; logs can be viewed in [Method Testing](#method-testing)
console.log('params', params);
if (!params.name || !params.email) throw new TCBError(1, 'name or email cannot be empty');
if (!/@qq\.com$/i.test(params.email)) throw new TCBError(2, 'Only QQ email addresses are supported');
const now = Date.now();
// Add creation time, update time
const newParams = Object.assign({}, params, {
createdAt: now,
updatedAt: now,
});
// Use CloudBase collection-related APIs to add records
const result = await context.collection.add(newParams);
// Return the ID of the new record
return { _id: result.id };
}
Custom Code context
context is a context object provided by the low-code platform to Cloud Functions, which includes objects for database operations, CloudBase Cloud Function invocations, and some useful environment variables.
Parameter | Type | Required | Description |
---|---|---|---|
cloudbase | tcb | Yes | CloudBase node sdk object, i.e., the tcb imported via import tcb from '@cloudbase/node-sdk'; , Usage Documentation |
app | tcb.CloudBase | Yes | The app object returned after initializing the CloudBase node sdk, i.e., the app obtained from const app = tcb.init({...}) . By default, initialization uses the CloudBase environment parameters of the current low-code platform. You can use app to directly invoke CloudBase cloud functions and storage-related capabilities (e.g., app.callFunction({...}) , app.uploadFile({...}) ). Usage Documentation |
auth | CloudBase Authentication Object | Yes | The auth object obtained from app.auth() mentioned above, which can be used to directly invoke authentication-related capabilities (e.g., auth.getUserInfo(), auth.getEndUserInfo(), etc.). Usage Documentation |
database | CloudBase Database Object | Yes | The database object of the CloudBase node sdk, i.e., the object returned by app.database() . You can use database to get a reference to a collection (database.collection('<collection-name>') ), access the command object (database.command ), etc. Usage Documentation |
collection | CloudBase Database Collection Object | No | Reference object for the database table associated with the current data source (CloudBase node sdk collection reference object). This property is only available for self-built data sources, i.e., the object returned by context.database.collection(context.env.dataSourceFullName) . You can directly use this object to perform read/write operations on the database table of the current data source. Usage Documentation |
env | Environment variables | Yes | For details, refer to Environment Variables |
httpAuth | auth handling object | No | This object is only available for third-party data sources created using non-blank templates. For specific usage, refer to How to integrate new methods for third-party data sources created using templates |
vars | Object | Yes | Public variables of the current data source |
Environment Variables
Parameter | Type | Required | Description |
---|---|---|---|
openId | string | No | WeChat openId, empty if not logged in via WeChat authorization |
fromOpenId | string | No | In WeChat, when multiple Mini Programs share the same environment (i.e., one WeDa environment bound to multiple Mini Programs), the user openId of the source Mini Program. This value should be prioritized in actual use. |
currentOpenId | string | No | When multiple Mini Programs share the same environment (i.e., one WeDa environment bound to multiple Mini Programs), if the request comes from a shared Mini Program, currentOpenId will be the aforementioned fromOpenId ; otherwise it will be openId |
appId | string | No | WeChat appId, empty if not logged in via WeChat authorization |
fromAppId | string | No | In WeChat, when multiple Mini Programs share the same environment (i.e., one WeDa environment bound to multiple Mini Programs), the appId of the source Mini Program. This value should be prioritized in actual use. |
currentAppId | string | No | When multiple Mini Programs share the same environment (i.e., one WeDa environment bound to multiple Mini Programs), if the request comes from a shared Mini Program, currentAppId will be the aforementioned fromAppId ; otherwise it will be appId |
uid | string | No | tcb user unique ID |
customUserId | string | No | Developer-defined user unique id, empty if not logged in via custom authentication |
isAnonymous | boolean | Yes | Whether the user is anonymous |
dataSourceName | string | Yes | Data source identifier. Only data sources created in Data Source Management have this attribute. |
dataSourceFullName | string | No | Full name of the data source, which serves as the actual identifier used in the underlying infrastructure after deployment (cloud function name/database table name) |
envId | string | Yes | CloudBase environment ID |
isPreview | boolean | Yes | Whether it is a trial environment. Developers generally do not need to use this information. See below Environment Description |
envType | prod pre | Yes | Environment type, pre: trial environment, prod: production environment; Developers generally do not need to use this information. See below Environment Description |
Environment Description
WeDa generated applications fall into two categories:
Trial Application
: Used for developing and testing applications within WeDa. Applications obtained through theReal-time Preview
toggle in the preview area of the application editor, thePreview
button at the top of the editor, or by selecting theTrial
publishing method in the top publish dialog are all categorized asTrial Applications
.Production Application
: Used for official release to end users. Applications obtained by selecting theProduction
publishing method in the top publish dialog of the application editor are categorized asProduction Applications
.
The data sources and WeDa backend support services invoked by
Trial Applicationsand
Production Applications` are isolated from each other and do not interfere with each other, as they call different backend environments respectively.
Trial Environment
: Invoked byTrial Applications
.Production Environment
: Invoked byProduction Applications
.
When users create/edit and save data sources in WeDa's data source management, the data sources in the Trial Environment
are automatically updated. After the data source passes testing and verification, clicking the Publish Now
button in data source management will update the data source to the Production Environment
.
Method Testing
After configuring the methods (http requests and cloud functions) of the data source, use Method Testing for validation. Fill in the test parameters in "Submit Parameters", then click "Run Test" to execute the test. The test output results display the method's operational log information. After successful testing, click Output Parameter Mapping to quickly populate Method Output Parameters.
When writing cloud functions, you can use console.log
in the code to output logs. The log information can be viewed in the "Logs" section of Method Testing.
The
Method Testingfeature cannot simulate different end-user identities. If method processing varies under different user identities and permissions, it cannot be validated through
Method Testing`. It is recommended to use data sources in applications and leverage the preview feature to test applications, enabling comprehensive testing of data sources in real-world scenarios.
Method Output Parameters
The result returned by the cloud function code is the function output parameters.
The structure described in
Output Parameters` must match the method's return result structure and must be an object; otherwise, errors may occur when used in the Weida application editor.
When using data sources in the Weida application editor, the structural information described in the output parameters
of data source methods will be utilized, for example:
- Data source variables will use the
output parameters
of associated data source methods to generate sample data. - After the table is bound to the data source method, the table header information will be generated based on the output parameter structure information.
The above is only an example. Data source method output parameters have numerous usage scenarios in the Weida application editor. Therefore, the more complete the information provided when filling in the output parameters
, the more convenient it will be to use in the Weida application editor.
You can use Method Testing. After clicking Run Test
and then Output Parameter Mapping
, the platform will analyze the structure of the returned result and automatically populate the output parameters.
Field Mapping in HTTP Method Output Parameters
In HTTP methods, after using Method Testing for output parameter mapping, the populated output parameter structure will match the structure of the original HTTP response.
The output parameters of HTTP methods provide the field mapping feature, which allows adjusting the data structure that the frontend application ultimately receives:
- You can delete unnecessary fields in the output parameters. After deletion, the corresponding fields will not be returned when the frontend application calls this method.
- You can edit the fields in the output parameters. The field identifier is the field name obtained by the frontend application when using the data source, while the field mapping is the field path in the original HTTP response corresponding to this field. That is, the value at the field mapping path is assigned to the field named field identifier.
- Modify the field identifier. After modification, the frontend application will receive the field under the modified name.
- Modify the field mapping. After modification, the current field will retrieve its value from the path described by the field mapping in the original response.
Modifying field mapping requires attention to the following points:
- The value of field mapping is an object path string, such as:
abc
,abc.ed
,abc.ed.cf[0].g
. Ensure the path exists during use, otherwise mapping will fail and cause the method to throw an error - You can use the special string
$root
representing the root of the original response. When filling in field mappings,$root.abc
is equivalent toabc
, so$root
can generally be omitted. - When mapping an array of objects, you can use
$item
(representing the current element in the loop;$item.xxx
can be used to specify a field of the object) and$index
(the loop index, starting from 0). Note: the array field must be mapped to the corresponding array of objects in the original response.
Frequently Asked Questions
How to Use Third-Party Dependencies in Cloud Functions
Currently, the built-in libraries request
and @cloudbase/js-sdk
are available in cloud functions. Using other dependencies is not supported at this time.
Simply use the node.js function require
to import the relevant dependencies, for example:
const request = require('request');
module.exports = function (params, context) {
return new Promise(function (resolve, reject) {
request('xxxxx', ...)
})
};
How to Make an HTTP Request in Cloud Functions
You can use the npm package request
to achieve this. For specific usage, refer to the code below:
/**
* Use the npm package `request` to send HTTP requests. For detailed usage documentation, refer to
* https://github.com/request/request#readme
*/
const request = require('request');
/** Determine if the request was successful based on the http status code */
function isSuccessStatusCode(code) {
return code >= 200 && code < 300;
}
module.exports = function (params, context) {
// `params` is the structure defined for input parameters and can be used in the request configuration
return new Promise(function (resolve, reject) {
request(
{
url: 'https://reqres.in/api/users?page=1&per_page=3',
method: 'GET',
// Set json to true, and the response body will be automatically converted to an object
// In POST requests, the Content-Type will also be automatically set to application/json
json: true
},
function (err, response, body) {
if (err) return reject(err);
if (!isSuccessStatusCode(response.statusCode))
return reject(new Error('request failed: ' + response.statusCode));
return resolve(body);
}
);
});
};
How to Integrate New Methods for Third-Party Data Sources Created Using Templates
When creating an external data source, if a non-blank template is used, the cloud function's context
will have an additional httpAuth
object. Through context.httpAuth
, you can access the authentication information for this type of external data source.
context.httpAuth` is defined as follows:
Parameter | Type | Required | Description |
---|---|---|---|
getAuthData | Function | Required | Function to obtain authentication information, defined as (requestConfig: IRequestConfig) => Promise<IAuthData> . requestConfig is the parameter configuration for the request library, which must include at least the uri and method fields. IAuthData authentication information |
transformResponse | Function | No | Transforms the response result, defined as (body: any, response: RequestResponse) => Promise<Record<string, any>> . This method may not exist and should be checked before use. Some third-party data sources return responses wrapped in structures like {code, data, message} (e.g., Tencent Docs) where the actual business result (including success/failure) is encapsulated, or return non-standard formats. In such cases, transformResponse can be used to uniformly convert the returned result: throwing errors for business failures and returning the final result for successful business calls |
IAuthData
The following fields, except for authInfo
, are constructed using authInfo and encapsulated for ease of use. You can also refer to third-party official API documentation to construct them.
Parameter | Type | Required | Description |
---|---|---|---|
authInfo | object | Required | The raw authentication information returned by the backend token interface. The structure of authentication information varies across different types of external data sources. For details, refer to Tencent Meeting Authentication Information and Tencent Docs Authentication Information |
uri | string | No | The converted request address URI. If this field is returned, it should be used as the final request URL |
headers | object | No | Common request headers, including other public headers required for authentication such as accessToken (may vary across different data sources). If this field is returned, it should be merged with the original headers |
body | object | No | Common body parameters, such as the userid field in Tencent Meeting. If this field is returned, it should be merged with the original body |
qs | object | No | Common query string. If this field is returned, it should be merged with the original qs |
Tencent Meeting Authentication Information
Parameter | Type | Required | Description |
---|---|---|---|
AccessToken | string | Required | Tencent Meeting access_token |
OpenId | string | Required | Tencent Meeting openid, which is the userid used in the API |
Tencent Docs Authentication Information
Parameter | Type | Required | Description |
---|---|---|---|
AccessToken | string | Required | Tencent Docs access_token |
ClientId | string | Required | Tencent Docs application id |
OpenId | string | Required | User's openid |
TokenType | string | Required | User's token type |
Scope | string | Required | User authorization scope |
Custom Cloud Function Example:
/**
* Create a Tencent Meeting, official API documentation https://cloud.tencent.com/document/product/1095/42417
*/
const request = require('request');
/** Determine if the request was successful based on the http status code */
function isSuccessStatusCode(code) {
return code >= 200 && code < 300;
}
module.exports = async function (params, context){
const { subject, type, start_time, end_time, password } = params;
// request request configuration information
const requestConfig = {
uri: 'https://api.meeting.qq.com/v1/meetings',
method: 'POST',
body: {
instanceid: 1,
subject,
type,
start_time: `${Math.floor(start_time / 1000)}`,
end_time: `${Math.floor(end_time / 1000)}`,
password,
},
// Set json to true, and the response body will be automatically converted to an object
// In POST requests, the Content-Type will also be automatically set to application/json
json: true
};
// Get authentication information
const authData = await context.httpAuth.getAuthData(requestConfig);
// Merge configuration information
const finalRequestConfig = mergeAuthData(requestConfig, authData);
// `params` is the structure defined for input parameters and can be used in the request configuration
return new Promise(function (resolve, reject) {
// Note: The callback function of request is an async function because there is an await call inside the function
request(finalRequestConfig, async function (err, response, body) {
if (err) return reject(err);
if (!isSuccessStatusCode(response.statusCode)) {
// When the request fails, the body will contain detailed error information
return reject(new Error(`request failed: code: ${response.statusCode}, msg: ${JSON.stringify(body)}`));
}
let result = body
// The data source does not actually provide transformResponse for Tencent Meeting, and the following code can also be removed
if (context.httpAuth.transformResponse) {
result = await context.httpAuth.transformResponse(body, response);
}
// When successful, the body is empty
return resolve(result);
}
);
});
}
/**
* Merge the request configuration with that in IAuthData
*/
function mergeAuthData(requestConfig, authData) {
const newConfig = Object.assign({}, requestConfig);
if (authData.uri) {
newConfig.uri = authData.uri;
}
if (authData.body) {
if (requestConfig.form) {
newConfig.form = Object.assign(newConfig.form || {}, authData.body);
} else if (!newConfig.body || typeof newConfig.body === 'object') {
newConfig.body = Object.assign(newConfig.body || {}, authData.body);
// Set contentType to json again to avoid the issue of contentType not being set when requestConfig.body is empty
newConfig.json = true;
}
}
if (authData.headers) {
newConfig.headers = Object.assign(newConfig.headers || {}, authData.headers);
}
if (authData.qs) {
newConfig.qs = Object.assign(newConfig.qs || {}, authData.qs);
}
return newConfig;
}
Official API Documentation for Built-in Third-Party Data Sources
Tencent Docs:
Currently, WeDa has only integrated sheet-related interfaces, and other APIs can be integrated according to the API documentation.
Tencent Meeting:
WeDa integrates Tencent Meeting using OAuth2.0. Currently, only meeting management related APIs support OAuth2.0 invocation, and all meeting management related APIs have been built into the meeting data source template.
The meeting management related APIs have very rich parameters. For user convenience, WeDa only provides common required parameters in its encapsulation. If you need to use parameters not supported in the WeDa template, you can refer to the official Tencent Meeting API documentation to modify the encapsulation of corresponding methods in the meeting data source.