Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
hassan254-prog committed Feb 21, 2025
2 parents 2e11206 + 979b8ab commit 7f14749
Show file tree
Hide file tree
Showing 29 changed files with 1,657 additions and 1,302 deletions.
97 changes: 97 additions & 0 deletions docs-v2/integrations/all/sage-intacct-oauth.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
title: Sage Intacct (OAuth)
sidebarTitle: Sage Intacct (OAuth)
---

import Overview from "/snippets/overview.mdx"
import PreBuiltTooling from "/snippets/generated/sage-intacct-oauth/PreBuiltTooling.mdx"
import PreBuiltUseCases from "/snippets/generated/sage-intacct-oauth/PreBuiltUseCases.mdx"

<Overview />
<PreBuiltTooling />
<PreBuiltUseCases />

## Access requirements
| Pre-Requisites | Status | Comment|
| - | - | - |
| Paid dev account | ✅ Not required | Free, self-signup [here](https://developer.sage.com/intacct/). |
| Paid test account | ✅ Not required | Create a 30 day free trial account [here](https://online.sageintacct.com/WebsiteAssets_request_trial.html). |
| Partnership || |
| App review || |
| Security audit || |


## Setup guide
- You must have an active Sage Intacct Web Services developer license, which includes a Web Services sender ID and password or access to a free trial period account.
<Tip>If you need a developer license, contact your account manager.</Tip>

<Steps>
<Step title="Create a new developer workspace">
Go to [developer console](https://developer.sage.com/intacct/) and login if you have an account or signup for a free developer's account.

Click **View workspaces**, then enter your Sage account email address and password to log in.

Click **Add workspace** to create a workspace for your company.

Enter a name for your workspace and a contact email address, then click **Create**.
</Step>

<Step title="Add a client application">
Click **Apps** in the left column navigation.

Click **Add application**.

Enter a name to identify the application in your workspace, a home page URL, and a contact email address for the application, then click **Create**.
</Step>
<Step title="Obtaining Client Credentials">
From the list of applications in your workspace, click your new application to open it.

Click **Create API keys**.

From the **Sage Product API** drop-down list, select Sage Intacct.

Enter a Redirect URI as a full URL. During the authorization process, users will be redirected to this URL after authorizing your application to access their data in Sage Intacct. You can configure the following Redirect URL: `https://api.nango.dev/oauth/callback`.

If you have custom applications that send Sage Intacct API requests from your domains, enter those domains in **Allowed Origin Domains** as full https URLs.

Enter your Sage Intacct Web Services sender ID and password.

From the **Client Scope** drop-down list, select the type of company to associate with these API keys:

- **Non-Production**: Choose this option if you're working with a sandbox implementation or other non-production company.

- **Production**: Choose this option if you're working with a live production company. Production companies are limited to no more than five associated API keys.

<Note>You cannot change the client scope after it has been set</Note>

Click **Create**.

When your registration is complete, the Application Details page will include an API Keys section. Click **Sage Intacct** in that list to view your application's **client ID** and **secret key**.
</Step>
<Step title="Next">
Follow the [_Quickstart_](/getting-started/quickstart).
</Step>
</Steps>

<Tip>Need help getting started? Get help in the [community](https://nango.dev/slack).</Tip>

<Note>Contribute improvements to the setup guide by [editing this page](https://github.com/nangohq/nango/tree/master/docs-v2/integrations/all/sage-intacct-oauth.mdx)</Note>


## Useful links

| Topic | Links |
| - | - |
| General | [Website](https://www.sage.com/en-gb/sage-business-cloud/intacct/) |
| | [Create a test account](https://online.sageintacct.com/WebsiteAssets_request_trial.html) |
| Developer | [API documentation](https://developer.sage.com/intacct/docs/) |
| | [Create or Login to a developer account](https://app-registry.sage.com/) |
| | [Developer console](https://developer.sage.com/intacct/) |
| | [Authorization documentation](https://developer.sage.com/intacct/docs/developer-portal/guides/oauth2/#authorization-code-grant-type) |


<Note>Contribute useful links by [editing this page](https://github.com/nangohq/nango/tree/master/docs-v2/integrations/all/sage-intacct-oauth.mdx)</Note>

## API gotchas

<Note>Contribute API gotchas by [editing this page](https://github.com/nangohq/nango/tree/master/docs-v2/integrations/all/sage-intacct-oauth.mdx)</Note>
1 change: 1 addition & 0 deletions docs-v2/mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@
"integrations/all/rippling",
"integrations/all/sage",
"integrations/all/sage-intacct",
"integrations/all/sage-intacct-oauth",
"integrations/all/salesforce",
"integrations/all/salesforce-experience-cloud",
"integrations/all/salesforce-cdp",
Expand Down
16 changes: 16 additions & 0 deletions docs-v2/snippets/generated/netsuite-tba/PreBuiltUseCases.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
<AccordionGroup>


<Accordion title="Bills">
| Endpoint | Description | Readme |
| - | - | - |
| `POST /bills` | Creates a vendor bill in Netsuite. | [🔗](https://github.com/NangoHQ/integration-templates/blob/main/integrations/netsuite-tba/actions/bill-create.md) |
| `PUT /bills` | Updates an existing vendor bill in Netsuite. | [🔗](https://github.com/NangoHQ/integration-templates/blob/main/integrations/netsuite-tba/actions/bill-update.md) |
</Accordion>


<Accordion title="Credit Notes">
| Endpoint | Description | Readme |
| - | - | - |
Expand Down Expand Up @@ -40,6 +48,14 @@
</Accordion>


<Accordion title="Purchase Orders">
| Endpoint | Description | Readme |
| - | - | - |
| `POST /purchase-orders` | Creates a purchase order in Netsuite | [🔗](https://github.com/NangoHQ/integration-templates/blob/main/integrations/netsuite-tba/actions/purchase-order-create.md) |
| `PUT /purchase-orders` | Updates an existing purchase order in Netsuite. | [🔗](https://github.com/NangoHQ/integration-templates/blob/main/integrations/netsuite-tba/actions/purchase-order-update.md) |
</Accordion>


<Accordion title="Others">
| Endpoint | Description | Readme |
| - | - | - |
Expand Down
41 changes: 41 additions & 0 deletions docs-v2/snippets/generated/sage-intacct-oauth/PreBuiltTooling.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
## Pre-built tooling
<AccordionGroup>
<Accordion title="✅ Authorization">
| Tools | Status |
| - | - |
| Pre-built authorization (OAuth) ||
| Credentials auto-refresh ||
| Auth parameters validation ||
| Pre-built authorization UI ||
| Custom authorization UI ||
| Expired credentials detection ||
</Accordion>
<Accordion title="✅ Read & write data">
| Tools | Status |
| - | - |
| Pre-built integrations | 🚫 (time to contribute: &lt;48h) |
| API unification ||
| 2-way sync ||
| Webhooks from Nango on data modifications ||
| Real-time webhooks from 3rd-party API | 🚫 (time to contribute: &lt;48h) |
| Proxy requests ||
</Accordion>
<Accordion title="✅ Observability & data quality">
| Tools | Status |
| - | - |
| HTTP request logging ||
| End-to-type type safety ||
| Data runtime validation ||
| OpenTelemetry export ||
| Slack alerts on errors ||
| Integration status API ||
</Accordion>
<Accordion title="✅ Customization">
| Tools | Status |
| - | - |
| Create or customize use-cases ||
| Pre-configured pagination | 🚫 (time to contribute: &lt;48h) |
| Pre-configured rate-limit handling | 🚫 (time to contribute: &lt;48h) |
| Per-customer configurations ||
</Accordion>
</AccordionGroup>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Pre-built integrations

_No pre-built integration yet (time to contribute: &lt;48h)_

<Tip>Not seeing the integration you need? [Build your own](https://docs.nango.dev/guides/custom-integrations/overview) independently.</Tip>
8 changes: 4 additions & 4 deletions packages/database/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ export class KnexDatabase {

async migrate(): Promise<any> {
return retry(
async () =>
async () => {
await this.knex.migrate.latest({
directory: directory,
tableName: '_nango_auth_migrations',
schemaName: this.schema()
}),
});
},
{
maxAttempts: 4,
delayMs: (attempt) => 500 * attempt,
retryIf: () => true
delayMs: (attempt) => 500 * attempt
}
);
}
Expand Down
23 changes: 23 additions & 0 deletions packages/providers/providers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3387,6 +3387,8 @@ guru-scim:
auth_mode: API_KEY
proxy:
base_url: https://api.getguru.com/api/scim
headers:
authorization: Bearer ${apiKey}
docs: https://docs.nango.dev/integrations/all/guru-scim
docs_connect: https://docs.nango.dev/integrations/all/guru-scim/connect
credentials:
Expand Down Expand Up @@ -5527,6 +5529,9 @@ netsuite-tba:
alias: netsuite
display_name: NetSuite (TBA)
auth_mode: TBA
categories:
- accounting
- erp
docs: https://docs.nango.dev/integrations/all/netsuite-tba

next-cloud-ocs:
Expand Down Expand Up @@ -6632,6 +6637,24 @@ sage:
base_url: https://api.accounting.sage.com
docs: https://docs.nango.dev/integrations/all/sage

sage-intacct-oauth:
display_name: Sage Intacct (OAuth)
categories:
- accounting
- erp
auth_mode: OAUTH2
authorization_url: https://api.intacct.com/ia/api/v1/oauth2/authorize
token_url: https://api.intacct.com/ia/api/v1/oauth2/token
authorization_params:
response_type: code
token_params:
grant_type: authorization_code
refresh_params:
grant_type: refresh_token
proxy:
base_url: https://api.intacct.com/ia/api
docs: https://docs.nango.dev/integrations/all/sage-intacct-oauth

sage-intacct:
display_name: Sage Intacct
categories:
Expand Down
24 changes: 6 additions & 18 deletions packages/runner-sdk/lib/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,24 +107,12 @@ export abstract class NangoActionBase {
}
}

protected proxyConfig(config: ProxyConfiguration): UserProvidedProxyConfiguration {
if (!config.connectionId && this.connectionId) {
config.connectionId = this.connectionId;
}
if (!config.providerConfigKey && this.providerConfigKey) {
config.providerConfigKey = this.providerConfigKey;
}
if (!config.connectionId) {
throw new Error('Missing connection id');
}
if (!config.providerConfigKey) {
throw new Error('Missing provider config key');
}
protected getProxyConfig(config: ProxyConfiguration): UserProvidedProxyConfiguration {
return {
method: 'GET',
...config,
providerConfigKey: config.providerConfigKey,
connectionId: config.connectionId,
providerConfigKey: config.providerConfigKey || this.providerConfigKey,
connectionId: config.connectionId || this.connectionId,
headers: {
...(config.headers || {}),
'user-agent': this.nango.userAgent
Expand Down Expand Up @@ -324,16 +312,16 @@ export abstract class NangoActionBase {
config.method = config.method || 'GET';

const configMethod = config.method.toLocaleLowerCase();
const passPaginationParamsInBody: boolean = config.paginate?.in_body ?? ['post', 'put', 'patch'].includes(configMethod);
const passPaginationParamsInBody = config.paginate?.in_body ?? ['post', 'put', 'patch'].includes(configMethod);

const updatedBodyOrParams: Record<string, any> = ((passPaginationParamsInBody ? config.data : config.params) as Record<string, any>) ?? {};
const limitParameterName: string = paginationConfig.limit_name_in_request;
const limitParameterName = paginationConfig.limit_name_in_request;

if (paginationConfig['limit']) {
updatedBodyOrParams[limitParameterName] = paginationConfig['limit'];
}

const proxyConfig = this.proxyConfig(config);
const proxyConfig = this.getProxyConfig(config);
switch (paginationConfig.type) {
case 'cursor':
return yield* paginateService.cursor<T>(proxyConfig, paginationConfig, updatedBodyOrParams, passPaginationParamsInBody, this.proxy.bind(this));
Expand Down
35 changes: 14 additions & 21 deletions packages/runner/lib/sdk/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { AxiosResponse } from 'axios';
import { Nango } from '@nangohq/node';
import type { ProxyConfiguration } from '@nangohq/runner-sdk';
import { InvalidRecordSDKError, NangoActionBase, NangoSyncBase } from '@nangohq/runner-sdk';
import { proxyService } from '@nangohq/shared';
import { getProxyConfiguration, ProxyRequest } from '@nangohq/shared';
import type { MessageRowInsert, NangoProps, UserLogParameters, MergingStrategy } from '@nangohq/types';
import { isTest, MAX_LOG_PAYLOAD, metrics, redactHeaders, redactURL, stringifyAndTruncateValue, stringifyObject, truncateJson } from '@nangohq/utils';
import { PersistClient } from './persist.js';
Expand Down Expand Up @@ -56,27 +56,20 @@ export class NangoActionRunner extends NangoActionBase {
throw new Error(`Connection not found using the provider config key ${this.providerConfigKey} and connection id ${this.connectionId}`);
}

const proxyConfig = this.proxyConfig(config);

const { response, logs } = await proxyService.route(proxyConfig, {
existingActivityLogId: this.activityLogId as string,
connection,
providerName: this.provider as string
});

// We batch save, since we have buffered the createdAt it shouldn't impact order
await Promise.all(
logs.map(async (log) => {
if (log.level === 'debug') {
return;
}
const computedConfig = getProxyConfiguration({
externalConfig: this.getProxyConfig(config),
internalConfig: {
connection,
providerName: this.provider!
}
}).unwrap();
const proxy = new ProxyRequest({
logger: async (log) => {
await this.sendLogToPersist(log);
})
);

if (response instanceof Error) {
throw response;
}
},
proxyConfig: computedConfig
});
const response = (await proxy.call()).unwrap();

return response;
}
Expand Down
Loading

0 comments on commit 7f14749

Please sign in to comment.