Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 21 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,14 @@ const response = await client.articles.create(..., {
### Retries

The SDK is instrumented with automatic retries with exponential backoff. A request will be retried as long
as the request is deemed retriable and the number of retry attempts has not grown larger than the configured
as the request is deemed retryable and the number of retry attempts has not grown larger than the configured
retry limit (default: 2).

A request is deemed retriable when any of the following HTTP status codes is returned:
A request is deemed retryable when any of the following HTTP status codes is returned:

- [408](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) (Timeout)
- [429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) (Too Many Requests)
- [5XX](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) (Internal Server Errors)
- [408](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) (Timeout)
- [429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) (Too Many Requests)
- [5XX](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) (Internal Server Errors)

Use the `maxRetries` request option to configure this behavior.

Expand Down Expand Up @@ -149,12 +149,12 @@ controller.abort(); // aborts the request
The SDK defaults to `node-fetch` but will use the global fetch client if present. The SDK works in the following
runtimes:

- Node.js 18+
- Vercel
- Cloudflare Workers
- Deno v1.25+
- Bun 1.0+
- React Native
- Node.js 18+
- Vercel
- Cloudflare Workers
- Deno v1.25+
- Bun 1.0+
- React Native

### Customizing Fetch Client

Expand All @@ -170,6 +170,16 @@ const client = new IntercomClient({
});
```

## Contributing

While we value open-source contributions to this SDK, this library is generated programmatically.
Additions made directly to this library would have to be moved over to our generation code,
otherwise they would be overwritten upon the next generated release. Feel free to open a PR as
a proof of concept, but know that we will not be able to merge it as-is. We suggest opening
an issue first to discuss with us!

On the other hand, contributions to the README are always very welcome!

## Request Options

This client library also supports passing in [`request` options](https://github.com/axios/axios#request-config):
Expand All @@ -191,13 +201,3 @@ client.useRequestOpts({
baseURL: "https://api.eu.intercom.io",
});
```

## Contributing

While we value open-source contributions to this SDK, this library is generated programmatically.
Additions made directly to this library would have to be moved over to our generation code,
otherwise they would be overwritten upon the next generated release. Feel free to open a PR as
a proof of concept, but know that we will not be able to merge it as-is. We suggest opening
an issue first to discuss with us!

On the other hand, contributions to the README are always very welcome!
5 changes: 4 additions & 1 deletion jest.config.js → jest.config.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/** @type {import('jest').Config} */
module.exports = {
export default {
preset: "ts-jest",
testEnvironment: "node",
moduleNameMapper: {
"(.+)\.js$": "$1",
},
};
32 changes: 16 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "intercom-client",
"version": "v6.1.1",
"version": "6.2.0",
"private": false,
"repository": "https://github.com/intercom/intercom-node",
"main": "./index.js",
Expand All @@ -15,25 +15,25 @@
"url-join": "4.0.1",
"form-data": "^4.0.0",
"formdata-node": "^6.0.3",
"node-fetch": "2.7.0",
"qs": "6.11.2",
"node-fetch": "^2.7.0",
"qs": "^6.13.1",
"readable-stream": "^4.5.2",
"js-base64": "3.7.2"
"js-base64": "3.7.7"
},
"devDependencies": {
"@types/url-join": "4.0.1",
"@types/qs": "6.9.8",
"@types/node-fetch": "2.6.9",
"@types/readable-stream": "^4.0.15",
"webpack": "^5.94.0",
"ts-loader": "^9.3.1",
"jest": "29.7.0",
"@types/jest": "29.5.5",
"ts-jest": "29.1.1",
"jest-environment-jsdom": "29.7.0",
"@types/node": "17.0.33",
"prettier": "2.7.1",
"typescript": "4.6.4"
"@types/qs": "^6.9.17",
"@types/node-fetch": "^2.6.12",
"@types/readable-stream": "^4.0.18",
"webpack": "^5.97.1",
"ts-loader": "^9.5.1",
"jest": "^29.7.0",
"@types/jest": "^29.5.14",
"ts-jest": "^29.1.1",
"jest-environment-jsdom": "^29.7.0",
"@types/node": "^18.19.70",
"prettier": "^3.4.2",
"typescript": "~5.7.2"
},
"browser": {
"fs": false,
Expand Down
64 changes: 32 additions & 32 deletions reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1457,9 +1457,9 @@ while (page.hasNextPage()) {

The `list all companies` functionality does not work well for huge datasets, and can result in errors and performance problems when paging deeply. The Scroll API provides an efficient mechanism for iterating over all companies in a dataset.

- Each app can only have 1 scroll open at a time. You'll get an error message if you try to have more than one open per app.
- If the scroll isn't used for 1 minute, it expires and calls with that scroll param will fail
- If the end of the scroll is reached, "companies" will be empty and the scroll parameter will expire
- Each app can only have 1 scroll open at a time. You'll get an error message if you try to have more than one open per app.
- If the scroll isn't used for 1 minute, it expires and calls with that scroll param will fail
- If the end of the scroll is reached, "companies" will be empty and the scroll parameter will expire

{% admonition type="info" name="Scroll Parameter" %}
You can get the first page of companies by simply sending a GET request to the scroll endpoint.
Expand Down Expand Up @@ -2376,8 +2376,8 @@ If a contact has recently been created, there is a possibility that it will not
You can nest these filters in order to get even more granular insights that pinpoint exactly what you need. Example: (1 OR 2) AND (3 OR 4).
There are some limitations to the amount of multiple's there can be:

- There's a limit of max 2 nested filters
- There's a limit of max 15 filters for each AND or OR group
- There's a limit of max 2 nested filters
- There's a limit of max 15 filters for each AND or OR group

### Searching for Timestamp Fields

Expand Down Expand Up @@ -4023,8 +4023,8 @@ See the [pagination section](https://developers.intercom.com/docs/build-an-integ
You can nest these filters in order to get even more granular insights that pinpoint exactly what you need. Example: (1 OR 2) AND (3 OR 4).
There are some limitations to the amount of multiple's there can be:

- There's a limit of max 2 nested filters
- There's a limit of max 15 filters for each AND or OR group
- There's a limit of max 2 nested filters
- There's a limit of max 15 filters for each AND or OR group

### Accepted Fields

Expand Down Expand Up @@ -4278,14 +4278,14 @@ await client.conversations.reply({

For managing conversations you can:

- Close a conversation
- Snooze a conversation to reopen on a future date
- Open a conversation which is `snoozed` or `closed`
- Assign a conversation to an admin and/or team.
</dd>
</dl>
</dd>
</dl>
- Close a conversation
- Snooze a conversation to reopen on a future date
- Open a conversation which is `snoozed` or `closed`
- Assign a conversation to an admin and/or team.
</dd>
</dl>
</dd>
</dl>

#### 🔌 Usage

Expand Down Expand Up @@ -4921,9 +4921,9 @@ await client.dataAttributes.update({

The events belonging to a customer can be listed by sending a GET request to `https://api.intercom.io/events` with a user or lead identifier along with a `type` parameter. The identifier parameter can be one of `user_id`, `email` or `intercom_user_id`. The `type` parameter value must be `user`.

- `https://api.intercom.io/events?type=user&user_id={user_id}`
- `https://api.intercom.io/events?type=user&email={email}`
- `https://api.intercom.io/events?type=user&intercom_user_id={id}` (this call can be used to list leads)
- `https://api.intercom.io/events?type=user&user_id={user_id}`
- `https://api.intercom.io/events?type=user&email={email}`
- `https://api.intercom.io/events?type=user&intercom_user_id={id}` (this call can be used to list leads)

The `email` parameter value should be [url encoded](http://en.wikipedia.org/wiki/Percent-encoding) when sending.

Expand Down Expand Up @@ -5015,9 +5015,9 @@ When submitting events for Leads, you will need to specify the Lead's `id`.

**Metadata behaviour**

- We currently limit the number of tracked metadata keys to 10 per event. Once the quota is reached, we ignore any further keys we receive. The first 10 metadata keys are determined by the order in which they are sent in with the event.
- It is not possible to change the metadata keys once the event has been sent. A new event will need to be created with the new keys and you can archive the old one.
- There might be up to 24 hrs delay when you send a new metadata for an existing event.
- We currently limit the number of tracked metadata keys to 10 per event. Once the quota is reached, we ignore any further keys we receive. The first 10 metadata keys are determined by the order in which they are sent in with the event.
- It is not possible to change the metadata keys once the event has been sent. A new event will need to be created with the new keys and you can archive the old one.
- There might be up to 24 hrs delay when you send a new metadata for an existing event.

**Event de-duplication**

Expand All @@ -5027,15 +5027,15 @@ Duplicated events are responded to using the normal `202 Accepted` code - an err

### HTTP API Responses

- Successful responses to submitted events return `202 Accepted` with an empty body.
- Unauthorised access will be rejected with a `401 Unauthorized` or `403 Forbidden` response code.
- Events sent about users that cannot be found will return a `404 Not Found`.
- Event lists containing duplicate events will have those duplicates ignored.
- Server errors will return a `500` response code and may contain an error message in the body.
</dd>
</dl>
</dd>
</dl>
- Successful responses to submitted events return `202 Accepted` with an empty body.
- Unauthorised access will be rejected with a `401 Unauthorized` or `403 Forbidden` response code.
- Events sent about users that cannot be found will return a `404 Not Found`.
- Event lists containing duplicate events will have those duplicates ignored.
- Server errors will return a `500` response code and may contain an error message in the body.
</dd>
</dl>
</dd>
</dl>

#### 🔌 Usage

Expand Down Expand Up @@ -6488,8 +6488,8 @@ See the [pagination section](https://developers.intercom.com/docs/build-an-integ
You can nest these filters in order to get even more granular insights that pinpoint exactly what you need. Example: (1 OR 2) AND (3 OR 4).
There are some limitations to the amount of multiples there can be:

- There's a limit of max 2 nested filters
- There's a limit of max 15 filters for each AND or OR group
- There's a limit of max 2 nested filters
- There's a limit of max 15 filters for each AND or OR group

### Accepted Fields

Expand Down
115 changes: 115 additions & 0 deletions scripts/rename-to-esm-files.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#!/usr/bin/env node

const fs = require("fs").promises;
const path = require("path");

const extensionMap = {
".js": ".mjs",
".d.ts": ".d.mts",
};
const oldExtensions = Object.keys(extensionMap);

async function findFiles(rootPath) {
const files = [];

async function scan(directory) {
const entries = await fs.readdir(directory, { withFileTypes: true });

for (const entry of entries) {
const fullPath = path.join(directory, entry.name);

if (entry.isDirectory()) {
if (entry.name !== "node_modules" && !entry.name.startsWith(".")) {
await scan(fullPath);
}
} else if (entry.isFile()) {
if (oldExtensions.some((ext) => entry.name.endsWith(ext))) {
files.push(fullPath);
}
}
}
}

await scan(rootPath);
return files;
}

async function updateFiles(files) {
const updatedFiles = [];
for (const file of files) {
const updated = await updateFileContents(file);
updatedFiles.push(updated);
}

console.log(`Updated imports in ${updatedFiles.length} files.`);
}

async function updateFileContents(file) {
const content = await fs.readFile(file, "utf8");

let newContent = content;
// Update each extension type defined in the map
for (const [oldExt, newExt] of Object.entries(extensionMap)) {
const regex = new RegExp(`(import|export)(.+from\\s+['"])(\\.\\.?\\/[^'"]+)(\\${oldExt})(['"])`, "g");
newContent = newContent.replace(regex, `$1$2$3${newExt}$5`);
}

if (content !== newContent) {
await fs.writeFile(file, newContent, "utf8");
return true;
}
return false;
}

async function renameFiles(files) {
let counter = 0;
for (const file of files) {
const ext = oldExtensions.find((ext) => file.endsWith(ext));
const newExt = extensionMap[ext];

if (newExt) {
const newPath = file.slice(0, -ext.length) + newExt;
await fs.rename(file, newPath);
counter++;
}
}

console.log(`Renamed ${counter} files.`);
}

async function main() {
try {
const targetDir = process.argv[2];
if (!targetDir) {
console.error("Please provide a target directory");
process.exit(1);
}

const targetPath = path.resolve(targetDir);
const targetStats = await fs.stat(targetPath);

if (!targetStats.isDirectory()) {
console.error("The provided path is not a directory");
process.exit(1);
}

console.log(`Scanning directory: ${targetDir}`);

const files = await findFiles(targetDir);

if (files.length === 0) {
console.log("No matching files found.");
process.exit(0);
}

console.log(`Found ${files.length} files.`);
await updateFiles(files);
await renameFiles(files);
console.log("\nDone!");
} catch (error) {
console.error("An error occurred:", error.message);
process.exit(1);
}
}

main();
6 changes: 4 additions & 2 deletions src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ import { Visitors } from "./api/resources/visitors/client/Client";
import { News } from "./api/resources/news/client/Client";

export declare namespace IntercomClient {
interface Options {
export interface Options {
environment?: core.Supplier<environments.IntercomEnvironment | string>;
/** Specify a custom URL to connect the client to. */
baseUrl?: core.Supplier<string>;
token?: core.Supplier<core.BearerToken | undefined>;
/** Override the Intercom-Version header */
version?:
Expand All @@ -52,7 +54,7 @@ export declare namespace IntercomClient {
fetcher?: core.FetchFunction;
}

interface RequestOptions {
export interface RequestOptions {
/** The maximum time to wait for a response in seconds. */
timeoutInSeconds?: number;
/** The number of times to retry the request. Defaults to 2. */
Expand Down
Loading