Skip to content

Commit

Permalink
Improve scripts reference docs (#1905)
Browse files Browse the repository at this point in the history
## Describe your changes

## Issue ticket number and link

## Checklist before requesting a review (skip if just adding/editing
APIs & templates)
- [ ] I added tests, otherwise the reason is: 
- [ ] I added observability, otherwise the reason is:
- [ ] I added analytics, otherwise the reason is:
  • Loading branch information
bastienbeurier committed Mar 25, 2024
1 parent 05319e5 commit e065491
Show file tree
Hide file tree
Showing 2 changed files with 264 additions and 303 deletions.
281 changes: 249 additions & 32 deletions docs-v2/reference/scripts.mdx
Expand Up @@ -56,37 +56,78 @@ Read more about [integration scripts](/understand/concepts/scripts) to understan

Integration scripts expose a helper object (`NangoSync` for sync scripts, `NangoAction` for action scripts), which allows to interact with external APIs & Nango more easily.

<Tip>
The script helper object shares some methods, but not all, with the [Node backend SDK](/reference/sdks/node), which is why this reference will link to the Node SDK reference a lot.
</Tip>

# Common helper methods

### HTTP requests
# HTTP requests

HTTP requests in integration scripts are made with the proxy ([concept]((/understand/concepts/proxy)) / [step-by-step guide](/integrate/guides/proxy-requests-to-an-api) / [reference](/reference/sdks/node#proxy)).
Makes an HTTP request inside an integration script:
```js
const config = { endpoint: '/some-endpoint' };

await nango.get(config); // GET request
await nango.post(config); // POST request
await nango.put(config); // PUT request
await nango.patch(config); // PATCH request
await nango.delete(config); // DELETE request
```

<Tip>
There is one simplification to using the proxy in integration scripts. Because integration scripts always execute in the context of a specific integration & connection, you do not need to specify the `providerConfigKey` & `connectionId` parameters when calling the proxy from integration script.
Note that all HTTP requests benefit from automatic credential injection. Because scripts are executed in the context of a specific integration & connection, Nango can automatically retrieve & refresh the relevant API credentials.
</Tip>

Instead of writing:
```ts
const res = await nango.get({
endpoint: '/external-endpoint',
providerConfigKey: '<string>',
connectionId: '<string>'
});
```
**Parameters**

You can write:
<Expandable>
<ResponseField name="config" type="object" required>
<Expandable title="config" defaultOpen>
<ResponseField name="endpoint" type="string" required>
The endpoint of the request.
</ResponseField>
<ResponseField name="headers" type="Record<string, string>">
The headers of the request.
</ResponseField>
<ResponseField name="params" type="Record<string, string | number>">
The query parameters of the request.
</ResponseField>
<ResponseField name="data" type="unknown">
The body of the request.
</ResponseField>
<ResponseField name="retries" type="number">
The number of retries in case of failure (with exponential back-off). Optional, default 0.
</ResponseField>
<ResponseField name="retryOn" type="number[]">
Array of additional status codes to retry a request in addition to the 5xx, 429, ECONNRESET, ETIMEDOUT, and ECONNABORTED
</ResponseField>
<ResponseField name="baseUrlOverride" type="string">
The API base URL. Can be ommitted if the base URL is configured for this API in the [providers.yaml](https://nango.dev/providers.yaml).
</ResponseField>
<ResponseField name="decompress" type="boolean">
Override the decompress option when making requests. Optional, defaults to false
</ResponseField>
<ResponseField name="responseType" type="'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'">
The type of the response.
</ResponseField>
</Expandable>
</ResponseField>
</Expandable>

```ts
const res = await nango.get({ endpoint: '/external-endpoint' });
**Response**

<Expandable>
```json
{
data: {}, // the response provided by the server
status: 200, // the HTTP status code
headers: {}, // the HTTP headers
config: {}, // the config provided for the request
request: {} // the request that generated this response
}
```

<Tip>
The response object is an [Axios response](https://axios-http.com/docs/res_schema).
</Tip>
</Expandable>

### Logging
# Logging

You can collect logs in integration scripts. This is particularly useful when:
- developing, to debug your integration scripts
Expand All @@ -99,29 +140,205 @@ await nango.log("This is a log.");

Logs can be viewed & searched in the Nango UI. We plan to make them exportable in the future as well.

### Environment variables
# Environment variables

Integration scripts sometimes need to access sensitive variables that should not be revealed directly in the code.

Integration scripts sometimes need to access sensitive variables that should not be revealed directly in the integration script code.
For this, you can define environment variables in the Nango UI, in the _Environment Settings_ tab. Then you can retrieve these environment variables from integration scripts with:

For this, you can define environment variables in the Nango UI, in the _Environment Settings_ tab. Then you can retrieve these environment variables from integration scripts ([reference](/reference/sdks/node#get-environment-variables)).
```js
await nango.getEnvironmentVariables();
```

**Parameters**

No parameters.

**Response**

<Expandable>
```json
[
{
"name": "MY_SECRET_KEY",
"value": "SK_373892NSHFNCOWFO..."
}
]
```
</Expandable>

### Trigger action
# Trigger action

Integration scripts currently do not support importing files, which limits the ability to share code between integration scripts.

As a temporary workaround, you can call action scripts from other integration scripts ([reference](/reference/sdks/node#trigger-an-action)).
As a temporary workaround, you can call action scripts from other integration scripts with:

```js
await nango.triggerAction('<ACTION-NAME>', { 'custom_key1': 'custom_value1' });
```

**Parameters**

<Expandable>
<ResponseField name="actionName" type="string" required>
The name of the action to trigger.
</ResponseField>
<ResponseField name="input" type="unkown" required>
The necessary input for your action's `runAction` function.
</ResponseField>
</Expandable>

**Response**

<Expandable>
```json
{
"your-properties": "The data returned by the action"
}
```
</Expandable>

# Paginate through API responses

### Paginate through API responses
Follow the pagination [step-by-step guides](/customize/guides/advanced/paginate-api-responses) to learn how to paginate through API responses easily.

Follow the pagination [step-by-step guides](/customize/guides/advanced/paginate-api-responses) to learn how to easily paginate through API responses.
# Manage connection metadata

### Manage connection metadata
### Get connection metadata

[Retrieve](/reference/sdks/node#get-connection-metadata), [edit](/reference/sdks/node#edit-connection-metadata) or [override](/reference/sdks/node#set-connection-metadata) the connection metadata.
Returns the connection's metadata.

### Get connection
```js
await nango.getMetadata();
```

Better, you can specify the type of the metadata;

```ts
interface CustomMetadata {
anyKey: Record<string, string>;
}
const myTypedMetadata = await nango.getMetadata<CustomMetadata>();
```

**Parameters**

Get the connection details, including the API credentials ([reference](/reference/sdks/node#get-a-connection-with-credentials)).
No parameters.

**Example Response**

<Expandable>
```json
{
"custom_key1": "custom_value1"
}
```
</Expandable>

### Set connection metadata

Set custom metadata for the connection (overrides existing metadata).

```js
await nango.setMetadata({ 'CUSTOM_KEY1': 'CUSTOM_VALUE1' });
```

**Parameters**

<Expandable>
<ResponseField name="metadata" type="Record<string, any>" required>
The custom metadata to store in the connection.
</ResponseField>
</Expandable>

**Response**

Empty response.

### Edit connection metadata

Edit custom metadata for the connection. Only overrides & adds specified properties, not the entire metadata.

```js
await nango.updateMetadata({ 'CUSTOM_KEY1': 'CUSTOM_VALUE1' });
```

**Parameters**

<Expandable>
<ResponseField name="metadata" type="Record<string, any>" required>
The custom metadata to store in the connection.
</ResponseField>
</Expandable>

**Response**

Empty response.

# Get the connection credentials

Returns a specific connection with credentials.

```js
await nango.getConnection();
```

<Info>
The response content depends on the API authentication type (OAuth 2, OAuth 1, API key, Basic auth, etc.).
</Info>

<Tip>
When you fetch the connection with this API endpoint, Nango will check if the access token has expired. If it has, it will refresh it.

We recommend not caching tokens for longer than 5 minutes to ensure they are fresh.
</Tip>

**Parameters**

<Expandable>
<ResponseField name="forceRefresh" type="boolean">
Defaults to `false`. If `false`, the token will only be refreshed if it expires within 15 minutes. If `true`, a token refresh attempt will happen on each request. This is only useful for testing and should not be done at high traffic.
</ResponseField>
<ResponseField name="refreshToken" type="boolean">
Defaults to `false`. If `false`, the refresh token is not included in the response, otherwise it is. In production, it is not advised to return the refresh token, for security reasons, since only the access token is needed to sign requests.
</ResponseField>
</Expandable>

**Example Response**

<Expandable>
```json
{
"id": 18393,
"created_at": "2023-03-08T09:43:03.725Z",
"updated_at": "2023-03-08T09:43:03.725Z",
"provider_config_key": "github",
"connection_id": "1",
"credentials": {
"type": "OAUTH2",
"access_token": "gho_tsXLG73f....",
"refresh_token": "gho_fjofu84u9....",
"expires_at": "2024-03-08T09:43:03.725Z",
"raw": { // Raw token response from the OAuth provider: Contents vary!
"access_token": "gho_tsXLG73f....",
"refresh_token": "gho_fjofu84u9....",
"token_type": "bearer",
"scope": "public_repo,user"
}
},
"connection_config": {
"subdomain": "myshop",
"realmId": "XXXXX",
"instance_id": "YYYYYYY"
},
"account_id": 0,
"metadata": {
"myProperty": "yes",
"filter": "closed=true"
}
}
```
</Expandable>

# Sync-specific helper methods

Expand Down

0 comments on commit e065491

Please sign in to comment.