Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add scripts reference #1870

Merged
merged 2 commits into from Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs-v2/reference/integration-configuration.mdx
Expand Up @@ -4,7 +4,8 @@ sidebarTitle: 'Integration config (nango.yaml)'
icon: 'arrow-right-arrow-left'
---

Example of an integration configuration:
# Example

```yaml nango.yaml
integrations:
asana: # Integration ID.
Expand Down
201 changes: 198 additions & 3 deletions docs-v2/reference/scripts.mdx
Expand Up @@ -4,6 +4,201 @@ sidebarTitle: 'Scripts'
icon: 'code'
---

<Info>
The docs recently underwent a makeover, leaving this page empty. We are working hard to fill in all the missing pages within the next two weeks. Meanwhile, ask any questions on the [community](https://nango.dev/slack).
</Info>
# Examples

<Tabs>

<Tab title="Sync script">
```ts
import type { GithubIssueDemo, NangoSync } from './models';

export default async function fetchData(nango: NangoSync) {
// Fetch issues from GitHub.
const res = await nango.get({
endpoint: '/repos/NangoHQ/interactive-demo/issues?labels=demo&sort=created&direction=asc'
});

// Map issues to your preferred schema.
const issues: GithubIssueDemo[] = res.data.map(({ id, title, html_url }: any) => {
return { id, title, url: html_url };
});

// Persist issues to the Nango cache.
await nango.batchSave(issues, 'GithubIssueDemo');
}
```
</Tab>

<Tab title="Action script">
```ts
import type { NangoAction, GithubCreateIssueInput, GithubCreateIssueResult } from './models';

export default async function runAction(nango: NangoAction, input: GithubCreateIssueInput): Promise<GithubCreateIssueResult> {
// Create a GitHub issue.
const res = await nango.post({
endpoint: '/repos/NangoHQ/interactive-demo/issues',
data: {
title: `[demo] ${input.title}`,
body: `The body of the issue.`,
labels: ['automatic']
}
});

// Send response.
return { url: res.data.html_url, status: res.status };
}
```
</Tab>

</Tabs>

Read more about [scripts](/understand/concepts/scripts) to understand what role they play in Nango.

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 in 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)).


<Tip>
There is one simplification to using the proxy in scripts. Because 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 script.

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

You can write:

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

### Logging

You can collect logs in scripts. This is particularly useful when:
- developing, to debug your scripts
- in production, to collect information about script executions & understand issues

Collect logs in scripts as follows:
```ts
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

Scripts sometimes need to access sensitive variables that should not be revealed directly in the 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 scripts ([reference](/reference/sdks/node#get-environment-variables)).

### Trigger action

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

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

### Paginate through API responses

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

[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.

### Get connection

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

# Sync-specific helper methods

Sync scripts persist data updates to the Nango cache, which your app later fetches (cf. [step-by-step guide](/integrate/guides/sync-data-from-an-api)).

### Save records

Upserts records to the Nango cache (i.e. create new records, update existing ones). Each record needs to contain a unique `id` field used to dedupe records.

```js
const githubIssues: GitHubIssue[] = ...; // Fetch issues from GitHub API.

await nango.batchSave(githubIssues, 'GitHubIssue');
```

**Parameters**

<Expandable>
<ResponseField name="recordList" type="Model[]" required>
The list of records to persist.
</ResponseField>

<ResponseField name="modelType" type="string" required>
The model type of the records to persist.
</ResponseField>
</Expandable>

### Delete records

Marks records as deleted in the Nango cache. Deleted records are still returned when you fetch them, but they are marked as deleted in the record's metadata (i.e. soft delete).

The only field that needs to be present in each record when calling `batchDelete` is the unique `id`; the other fields are ignored.

```js
const githubIssuesToDelete: { id: string }[] = ...; // Fetch issues to delete from GitHub API.

await nango.batchDelete(githubIssuesToDelete, 'GitHubIssue');
```

**Parameters**

<Expandable>
<ResponseField name="recordList" type="{ id: string }[]" required>
The list of records to delete.
</ResponseField>

<ResponseField name="modelType" type="string" required>
The model type of the records to delete.
</ResponseField>
</Expandable>


# Action-specific helper methods

### `ActionError`

You can use `ActionError` in an action script to return a descriptive error to your app when needed:
```ts

export default async function runAction(nango: NangoAction): Promise<Response> {
// Something went wrong...

throw new ActionError({ any_key: 'any_value' });
}

```

In this case, the response to the trigger action call will be:
```json
{
"error_type": "action_script_failure",
"payload": {
"any_key": "any_value"
}
}
```

<Tip>
**Questions, problems, feedback?** Please reach out in the [Slack community](https://nango.dev/slack).
</Tip>
4 changes: 2 additions & 2 deletions docs-v2/reference/sdks/node.mdx
Expand Up @@ -335,9 +335,9 @@ If you do not want to deal with collecting & injecting credentials in requests f
</Info>

<Tip>
Every time you fetch the connection with this API endpoint, Nango will check if the access token has expired. If it has, it will refresh it.
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 you always fetch the token just before you use it to make sure it is fresh!**
We recommend not caching tokens for longer than 5 minutes to ensure they are fresh.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

</Tip>

**Parameters**
Expand Down