Cloud Hooks
What’s on this page?
As highlighted in the Extensibility Overview, this page provides an update on some out-of-the-box extensibility hooks (which are feature extensions from the Cloud Platform) that are available to be integrated by a partner. Tulip can provide assistance in enabling an environment where the extensibility code can be hosted and run.
Available Hooks
The following hooks are available as of November 2019:
Event | Before Hook | After Hook | Instead Hook |
---|---|---|---|
Customer Create | yes | yes | yes |
Customer Update | yes | yes | yes |
Customer Note Create | yes | yes | yes |
Customer Note Delete | yes | yes | yes |
Send Email | yes | yes | yes |
Send SMS | yes | yes | yes |
Customer Association Create | yes | yes | yes |
Customer Association Update | yes | yes | yes |
Customer Association Delete | yes | yes | yes |
Address Prediction Get | yes | yes | yes |
Address External ID Get | yes | yes | yes |
Product Inventory Get | yes | yes | yes |
External Cart Get | yes | yes | yes |
External Cart Create | yes | yes | yes |
External Cart Item Create | yes | yes | yes |
External Cart Item Update | yes | yes | yes |
External Cart Item Delete | yes | yes | yes |
External Order Create | yes | yes | yes |
Calculate Tax | no | no | yes |
Model for Extensibility
Tulip provides the ability to override several core functions that it performs. The model for extensibility is based:
- Before Hooks
- After Hooks
- Instead Hooks
When extensibility is added to a function, a developer can ask that Tulip runs, in JavaScript or TypeScript, provided code in the cloud (called a “hook”).
SDK
Once a hook is run, the hook is provided, as an object, context information needed to understand the current data and context that can be modified or interpreted.
The JavaScript or TypeScript code has full access to the Tulip Direct API and Bulk API and Config API. This is the core way in which to fetch and modify data when inside a hook.
They are presented as:
sdk.epiClient
sdk.dalClient
sdk.configApiClient
To help ensure that the hooks are isolated, portable, and secure, they are run inside the context of a sandbox. This sandbox overwrites the global namespace so that hooks are only able to do things that have been explicitly allowed. This also means that hooks can’t “require” external libraries or other files on the container’s file system.
The hooks do have access to an SDK which provides tools for connecting to external and internal services.
Write a Hook
Structure of a Hook
The basic structure of a hook looks like this:
module.exports = async function(some_input_value) { // ... your logic here return some_output_value; }
Additional functions can be added at the writer of the hook’s discretion, but only one (the main function) should be exported.
Hook Sandbox
To help ensure that the hooks are isolated, portable, and secure, they are run inside the context of a sandbox. This sandbox overwrites the global namespace so that hooks are only able to do things that have been explicitly allowed. This also means that hooks can’t “require” external libraries or other files on the container’s file system. The hooks do have access to an SDK which provides tools for connecting to external and internal services.
SDK
The SDK is available inside the hooks as the global variable sdk. The SDK is written in TypeScript, and its source code can be provided to the partner team (through access to Tulip’s git repository).
SDK Key Value Store Manager
The key value store manager allows hooks to store and key-value pairs. This allows hooks to persist simple data across multiple calls. Behind the scenes, this uses redis and prefixes the keys with hooks-{CLUSTER_ID}..
Unlike data stored in Config API, these values aren’t accessible to the outside world/the app.
sdk.keyValueStoreManager.get(key: string): Promise<string>
sdk.keyValueStoreManager.set(key: string, value: string): Promise<string>
SDK Secret Manager
The secret manager allows hooks to access secrets which are securely encrypted and decrypted in the Tulip Cloud Secret Manager.
sdk.secretManager.get(key: string): Promise<string>
Additionally, hooks can encrypt and decrypt strings. This can be used in conjunction with the keyValueStoreManager to encrypt and decrypt dynamic secrets.
sdk.secretManager.encrypt(value: string): Promise<string>
sdk.secretManager.decrypt(encryptedValue: string): Promise<string>
SDK HTTP Clients
The HTTP clients available in the SDK provide a simple interface on top of the axios http client library.
.get(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<any>>
.delete(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<any>>
.post(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<any>>
.put(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<any>>
.patch(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<any>>
The SDK provides several of these http clients which have been configured according to their purpose.
Module | Purpose | Example |
---|---|---|
sdk.httpClient | Accessing External Services | await sdk.httpClient.get("https://example.com/something") |
sdk.dalClient | Accessing DAL | await sdk.dalClient.get("/dataAccess/v1/crm/customers/1") |
sdk.epiClient | Access EPI | await sdk.epiClient.get("/v2/crm/customers/1") |
sdk.configApiClient | Access Config API | await sdk.configApiClient.get("/config/v2/domains/d1/resources/r1/settings/s1") |
Detailed Hook Documentation
Hook documentation is available for each hook that includes the custom payload it provides.