diff --git a/apps/webapp/app/components/icon-utils.tsx b/apps/webapp/app/components/icon-utils.tsx
index 1e7042d3..de3ff8ab 100644
--- a/apps/webapp/app/components/icon-utils.tsx
+++ b/apps/webapp/app/components/icon-utils.tsx
@@ -32,6 +32,7 @@ import { Resend } from "./icons/resend";
import { Ynab } from "./icons/ynab";
import { Jira } from "./icons/jira";
import { Confluence } from "./icons/confluence";
+import { Intercom } from "./icons/intercom";
import { BacklogLine } from "./icons/backlog";
import { TodoLine } from "./icons/todo";
import { InProgressLine } from "./icons/in-progress";
@@ -82,6 +83,7 @@ export const ICON_MAPPING = {
ynab: Ynab,
jira: Jira,
confluence: Confluence,
+ intercom: Intercom,
cli: Code,
"core-extension": Chromium,
task: Task,
diff --git a/apps/webapp/app/components/icons/intercom.tsx b/apps/webapp/app/components/icons/intercom.tsx
new file mode 100644
index 00000000..9e65c984
--- /dev/null
+++ b/apps/webapp/app/components/icons/intercom.tsx
@@ -0,0 +1,36 @@
+import type { IconProps } from './types';
+
+export function Intercom({ size = 18, className }: IconProps) {
+ return (
+
+ );
+}
diff --git a/integrations/intercom/.gitignore b/integrations/intercom/.gitignore
new file mode 100644
index 00000000..d487609b
--- /dev/null
+++ b/integrations/intercom/.gitignore
@@ -0,0 +1,4 @@
+node_modules/
+bin/
+dist/
+*.js.map
diff --git a/integrations/intercom/.prettierrc b/integrations/intercom/.prettierrc
new file mode 100644
index 00000000..ca8527e0
--- /dev/null
+++ b/integrations/intercom/.prettierrc
@@ -0,0 +1,7 @@
+{
+ "semi": true,
+ "trailingComma": "all",
+ "singleQuote": true,
+ "printWidth": 100,
+ "tabWidth": 2
+}
diff --git a/integrations/intercom/README.md b/integrations/intercom/README.md
new file mode 100644
index 00000000..9f76f1aa
--- /dev/null
+++ b/integrations/intercom/README.md
@@ -0,0 +1,47 @@
+# Intercom Integration for CORE
+
+Connects your Intercom workspace to CORE, syncing conversations, contacts, and events as activities.
+
+## Features
+
+- **Conversations**: Syncs new and updated support conversations with contact info, state, assignee, and message preview.
+- **Contacts**: Tracks newly created or updated contacts (users and leads).
+- **Events**: Captures custom events triggered by contacts.
+
+## Authentication
+
+Uses **OAuth2**. Users authorize via Intercom's OAuth flow:
+
+- Authorization URL: `https://app.intercom.com/oauth`
+- Token URL: `https://api.intercom.io/auth/eagle/token`
+- Scopes: `read_users read_conversations`
+
+## Setup
+
+### Prerequisites
+
+- An Intercom account with admin access.
+- An OAuth app registered in the [Intercom Developer Hub](https://developers.intercom.com/).
+
+### Build
+
+```bash
+cd integrations/intercom
+pnpm install
+pnpm build
+```
+
+### Register to Database
+
+```bash
+DATABASE_URL= npx ts-node scripts/register.ts
+```
+
+## Sync Schedule
+
+Runs every 15 minutes (`*/15 * * * *`).
+
+## API Reference
+
+- [Intercom REST API](https://developers.intercom.com/docs/references/rest-api/overview/)
+- [OAuth Setup](https://developers.intercom.com/docs/build-an-integration/getting-started/)
diff --git a/integrations/intercom/eslint.config.js b/integrations/intercom/eslint.config.js
new file mode 100644
index 00000000..e190363a
--- /dev/null
+++ b/integrations/intercom/eslint.config.js
@@ -0,0 +1,98 @@
+const eslint = require('@eslint/js');
+const tseslint = require('typescript-eslint');
+const reactPlugin = require('eslint-plugin-react');
+const jestPlugin = require('eslint-plugin-jest');
+const importPlugin = require('eslint-plugin-import');
+const prettierPlugin = require('eslint-plugin-prettier');
+const unusedImportsPlugin = require('eslint-plugin-unused-imports');
+const jsxA11yPlugin = require('eslint-plugin-jsx-a11y');
+
+module.exports = [
+ eslint.configs.recommended,
+ ...tseslint.configs.recommended,
+ {
+ files: ['**/*.{js,jsx,ts,tsx}'],
+ plugins: {
+ react: reactPlugin,
+ jest: jestPlugin,
+ import: importPlugin,
+ prettier: prettierPlugin,
+ 'unused-imports': unusedImportsPlugin,
+ 'jsx-a11y': jsxA11yPlugin,
+ },
+ languageOptions: {
+ ecmaVersion: 2020,
+ sourceType: 'module',
+ parser: tseslint.parser,
+ parserOptions: {
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
+ },
+ rules: {
+ 'jsx-a11y/label-has-associated-control': 'error',
+ curly: 'warn',
+ 'dot-location': 'warn',
+ eqeqeq: 'error',
+ 'prettier/prettier': 'warn',
+ 'unused-imports/no-unused-imports': 'warn',
+ 'no-else-return': 'warn',
+ 'no-lonely-if': 'warn',
+ 'no-inner-declarations': 'off',
+ 'no-unused-vars': 'off',
+ 'no-useless-computed-key': 'warn',
+ 'no-useless-return': 'warn',
+ 'no-var': 'warn',
+ 'object-shorthand': ['warn', 'always'],
+ 'prefer-arrow-callback': 'warn',
+ 'prefer-const': 'warn',
+ 'prefer-destructuring': ['warn', { AssignmentExpression: { array: true } }],
+ 'prefer-object-spread': 'warn',
+ 'prefer-template': 'warn',
+ 'spaced-comment': ['warn', 'always', { markers: ['/'] }],
+ yoda: 'warn',
+ 'import/order': [
+ 'warn',
+ {
+ 'newlines-between': 'always',
+ groups: ['type', 'builtin', 'external', 'internal', ['parent', 'sibling'], 'index'],
+ pathGroupsExcludedImportTypes: ['builtin'],
+ pathGroups: [],
+ alphabetize: {
+ order: 'asc',
+ caseInsensitive: true,
+ },
+ },
+ ],
+ '@typescript-eslint/array-type': ['warn', { default: 'array-simple' }],
+ '@typescript-eslint/ban-ts-comment': [
+ 'warn',
+ {
+ 'ts-expect-error': 'allow-with-description',
+ },
+ ],
+ '@typescript-eslint/consistent-indexed-object-style': ['warn', 'record'],
+ '@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
+ '@typescript-eslint/no-unused-vars': 'warn',
+ 'react/function-component-definition': [
+ 'warn',
+ {
+ namedComponents: 'arrow-function',
+ unnamedComponents: 'arrow-function',
+ },
+ ],
+ 'react/jsx-boolean-value': 'warn',
+ 'react/jsx-curly-brace-presence': 'warn',
+ 'react/jsx-fragments': 'warn',
+ 'react/jsx-no-useless-fragment': ['warn', { allowExpressions: true }],
+ 'react/self-closing-comp': 'warn',
+ },
+ },
+ {
+ files: ['scripts/**/*'],
+ rules: {
+ '@typescript-eslint/no-var-requires': 'off',
+ },
+ },
+];
diff --git a/integrations/intercom/package.json b/integrations/intercom/package.json
new file mode 100644
index 00000000..1608b44e
--- /dev/null
+++ b/integrations/intercom/package.json
@@ -0,0 +1,45 @@
+{
+ "name": "@core/intercom",
+ "version": "0.1.0",
+ "description": "Intercom integration for CORE - sync conversations, contacts, and events",
+ "main": "./bin/index.cjs",
+ "type": "module",
+ "files": [
+ "intercom",
+ "bin"
+ ],
+ "bin": {
+ "intercom": "./bin/index.cjs"
+ },
+ "scripts": {
+ "build": "tsup",
+ "lint": "eslint --ext js,ts,tsx src/ --fix",
+ "prettier": "prettier --config .prettierrc --write ."
+ },
+ "devDependencies": {
+ "@babel/preset-typescript": "^7.26.0",
+ "@types/node": "^18.0.20",
+ "eslint": "^9.24.0",
+ "eslint-config-prettier": "^10.1.2",
+ "eslint-import-resolver-alias": "^1.1.2",
+ "eslint-plugin-import": "^2.31.0",
+ "eslint-plugin-jest": "^27.9.0",
+ "eslint-plugin-prettier": "^5.2.1",
+ "eslint-plugin-unused-imports": "^2.0.0",
+ "prettier": "^3.4.2",
+ "rimraf": "^3.0.2",
+ "tslib": "^2.8.1",
+ "typescript": "^4.7.2",
+ "tsup": "^8.0.1"
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "dependencies": {
+ "axios": "^1.7.9",
+ "commander": "^12.0.0",
+ "@redplanethq/sdk": "0.1.14",
+ "zod": "^3.22.4",
+ "zod-to-json-schema": "^3.22.4"
+ }
+}
diff --git a/integrations/intercom/scripts/register.ts b/integrations/intercom/scripts/register.ts
new file mode 100644
index 00000000..39432d3e
--- /dev/null
+++ b/integrations/intercom/scripts/register.ts
@@ -0,0 +1,65 @@
+import pg from 'pg';
+const { Client } = pg;
+
+async function main() {
+ const connectionString = process.env.DATABASE_URL;
+ if (!connectionString) {
+ console.error('DATABASE_URL environment variable is required');
+ process.exit(1);
+ }
+
+ const client = new Client({ connectionString });
+
+ const spec = {
+ name: 'Intercom',
+ key: 'intercom',
+ description:
+ 'Connect your Intercom workspace to CORE. Sync conversations, contacts, and events — stay on top of customer support and engagement directly from your workspace.',
+ icon: 'intercom',
+ schedule: {
+ frequency: '*/15 * * * *',
+ },
+ auth: {
+ OAuth2: {
+ token_url: 'https://api.intercom.io/auth/eagle/token',
+ authorization_url: 'https://app.intercom.com/oauth',
+ scopes: ['read_users', 'read_conversations'],
+ scope_separator: ' ',
+ },
+ },
+ };
+
+ try {
+ await client.connect();
+
+ await client.query(
+ `
+ INSERT INTO core."IntegrationDefinitionV2" ("id", "name", "slug", "description", "icon", "spec", "config", "version", "url", "updatedAt", "createdAt")
+ VALUES (gen_random_uuid(), 'Intercom', 'intercom', 'Connect your Intercom workspace to CORE. Sync conversations, contacts, and events — stay on top of customer support and engagement directly from your workspace.', 'intercom', $1, $2, '0.1.0', $3, NOW(), NOW())
+ ON CONFLICT (name) DO UPDATE SET
+ "slug" = EXCLUDED."slug",
+ "description" = EXCLUDED."description",
+ "icon" = EXCLUDED."icon",
+ "spec" = EXCLUDED."spec",
+ "config" = EXCLUDED."config",
+ "version" = EXCLUDED."version",
+ "url" = EXCLUDED."url",
+ "updatedAt" = NOW()
+ RETURNING *;
+ `,
+ [
+ JSON.stringify(spec),
+ JSON.stringify({}),
+ '../../integrations/intercom/bin/index.cjs',
+ ],
+ );
+
+ console.log('Intercom integration registered successfully in the database.');
+ } catch (error) {
+ console.error('Error registering Intercom integration:', error);
+ } finally {
+ await client.end();
+ }
+}
+
+main().catch(console.error);
diff --git a/integrations/intercom/src/account-create.ts b/integrations/intercom/src/account-create.ts
new file mode 100644
index 00000000..944d7031
--- /dev/null
+++ b/integrations/intercom/src/account-create.ts
@@ -0,0 +1,40 @@
+import { getIntercomClient } from './utils';
+
+export async function integrationCreate(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ data: any,
+) {
+ const { oauthResponse } = data;
+ const integrationConfiguration = {
+ refresh_token: oauthResponse.refresh_token,
+ access_token: oauthResponse.access_token,
+ };
+
+ const client = getIntercomClient(integrationConfiguration.access_token);
+
+ // Fetch the authenticated admin/user info
+ const meResponse = await client.get('/me');
+ const me = meResponse.data;
+
+ const accountId = me.id?.toString() ?? me.email ?? 'intercom-account';
+ const email = me.email ?? '';
+ const name = me.name ?? '';
+
+ return [
+ {
+ type: 'account',
+ data: {
+ settings: {
+ email,
+ name,
+ app_id: me.app?.id_code ?? '',
+ app_name: me.app?.name ?? '',
+ },
+ accountId,
+ config: {
+ ...integrationConfiguration,
+ },
+ },
+ },
+ ];
+}
diff --git a/integrations/intercom/src/create-activity.ts b/integrations/intercom/src/create-activity.ts
new file mode 100644
index 00000000..b24a196c
--- /dev/null
+++ b/integrations/intercom/src/create-activity.ts
@@ -0,0 +1,14 @@
+export interface ActivityParams {
+ text: string;
+ sourceURL: string;
+}
+
+export function createActivity(params: ActivityParams) {
+ return {
+ type: 'activity',
+ data: {
+ text: params.text,
+ sourceURL: params.sourceURL,
+ },
+ };
+}
diff --git a/integrations/intercom/src/index.ts b/integrations/intercom/src/index.ts
new file mode 100644
index 00000000..45fa5c10
--- /dev/null
+++ b/integrations/intercom/src/index.ts
@@ -0,0 +1,68 @@
+import {
+ IntegrationCLI,
+ IntegrationEventPayload,
+ IntegrationEventType,
+ Spec,
+} from '@redplanethq/sdk';
+import { fileURLToPath } from 'url';
+
+import { integrationCreate } from './account-create';
+import { handleSchedule } from './schedule';
+
+export async function run(eventPayload: IntegrationEventPayload) {
+ switch (eventPayload.event) {
+ case IntegrationEventType.SETUP:
+ return await integrationCreate(eventPayload.eventBody);
+
+ case IntegrationEventType.SYNC:
+ return await handleSchedule(eventPayload.config, eventPayload.state);
+
+ default:
+ return [
+ {
+ type: 'message',
+ data: { message: `The event payload type is ${eventPayload.event}` },
+ },
+ ];
+ }
+}
+
+class IntercomCLI extends IntegrationCLI {
+ constructor() {
+ super('intercom', '1.0.0');
+ }
+
+ protected async handleEvent(eventPayload: IntegrationEventPayload): Promise {
+ return await run(eventPayload);
+ }
+
+ protected async getSpec(): Promise {
+ return {
+ name: 'Intercom',
+ key: 'intercom',
+ description:
+ 'Connect your Intercom workspace to CORE. Sync conversations, contacts, and events — stay on top of customer support and engagement directly from your workspace.',
+ icon: 'intercom',
+ schedule: {
+ frequency: '*/15 * * * *',
+ },
+ auth: {
+ OAuth2: {
+ token_url: 'https://api.intercom.io/auth/eagle/token',
+ authorization_url: 'https://app.intercom.com/oauth',
+ scopes: ['read_users', 'read_conversations'],
+ scope_separator: ' ',
+ },
+ },
+ };
+ }
+}
+
+function main() {
+ const intercomCLI = new IntercomCLI();
+ intercomCLI.parse();
+}
+
+if (process.argv[1] === fileURLToPath(import.meta.url)) {
+ main();
+}
diff --git a/integrations/intercom/src/schedule.ts b/integrations/intercom/src/schedule.ts
new file mode 100644
index 00000000..ad5444f4
--- /dev/null
+++ b/integrations/intercom/src/schedule.ts
@@ -0,0 +1,245 @@
+import { getIntercomClient, IntercomConfig } from './utils';
+import { createActivity } from './create-activity';
+
+interface IntercomState {
+ lastSyncTime?: string;
+}
+
+function getDefaultSyncTime(): string {
+ return new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
+}
+
+function timestampToIso(ts: number | null | undefined): string | null {
+ if (!ts) {
+ return null;
+ }
+ return new Date(ts * 1000).toISOString();
+}
+
+async function syncConversations(
+ client: ReturnType,
+ lastSyncTime: string,
+): Promise {
+ const activities: any[] = [];
+
+ try {
+ const sinceTs = Math.floor(new Date(lastSyncTime).getTime() / 1000);
+
+ // Search for conversations updated since the last sync
+ const response = await client.post('/conversations/search', {
+ query: {
+ operator: 'AND',
+ value: [
+ {
+ field: 'updated_at',
+ operator: '>',
+ value: sinceTs,
+ },
+ ],
+ },
+ pagination: { per_page: 50 },
+ });
+
+ const conversations: any[] = response.data?.conversations ?? [];
+
+ for (const conversation of conversations) {
+ const updatedAt = timestampToIso(conversation.updated_at);
+ if (!updatedAt || updatedAt <= lastSyncTime) {
+ continue;
+ }
+
+ const contactName =
+ conversation.source?.author?.name ||
+ conversation.source?.author?.email ||
+ 'Unknown contact';
+
+ const subject = conversation.source?.subject || '(no subject)';
+ const body = conversation.source?.body
+ ? conversation.source.body.replace(/<[^>]*>/g, '').substring(0, 200)
+ : '';
+
+ const state = conversation.state ?? 'unknown';
+ const assigneeName =
+ conversation.assignee?.name || conversation.assignee?.email || 'Unassigned';
+
+ const sourceURL = `https://app.intercom.com/a/inbox/${conversation.app_id ?? ''}/conversations/${conversation.id}`;
+
+ const text = `## Intercom Conversation: ${subject}
+
+**Contact:** ${contactName}
+**State:** ${state}
+**Assignee:** ${assigneeName}
+**Updated:** ${updatedAt}
+${body ? `\n**Message preview:** ${body}` : ''}
+**Conversation ID:** ${conversation.id}`;
+
+ activities.push(createActivity({ text, sourceURL }));
+ }
+ } catch (error) {
+ console.error('Error syncing Intercom conversations:', error);
+ }
+
+ return activities;
+}
+
+async function syncContacts(
+ client: ReturnType,
+ lastSyncTime: string,
+): Promise {
+ const activities: any[] = [];
+
+ try {
+ const sinceTs = Math.floor(new Date(lastSyncTime).getTime() / 1000);
+
+ const response = await client.post('/contacts/search', {
+ query: {
+ operator: 'AND',
+ value: [
+ {
+ field: 'updated_at',
+ operator: '>',
+ value: sinceTs,
+ },
+ ],
+ },
+ pagination: { per_page: 50 },
+ });
+
+ const contacts: any[] = response.data?.data ?? [];
+
+ for (const contact of contacts) {
+ const updatedAt = timestampToIso(contact.updated_at);
+ if (!updatedAt || updatedAt <= lastSyncTime) {
+ continue;
+ }
+
+ const name = contact.name || contact.email || 'Unknown';
+ const email = contact.email ?? 'N/A';
+ const role = contact.role ?? 'N/A';
+ const createdAt = timestampToIso(contact.created_at) ?? 'N/A';
+
+ const sourceURL = `https://app.intercom.com/a/contacts/${contact.id}`;
+
+ const text = `## Intercom Contact: ${name}
+
+**Email:** ${email}
+**Role:** ${role}
+**Created:** ${createdAt}
+**Updated:** ${updatedAt}
+**Contact ID:** ${contact.id}`;
+
+ activities.push(createActivity({ text, sourceURL }));
+ }
+ } catch (error) {
+ console.error('Error syncing Intercom contacts:', error);
+ }
+
+ return activities;
+}
+
+async function syncEvents(
+ client: ReturnType,
+ lastSyncTime: string,
+): Promise {
+ const activities: any[] = [];
+
+ try {
+ // Fetch recently updated contacts to get their events
+ const sinceTs = Math.floor(new Date(lastSyncTime).getTime() / 1000);
+
+ const contactsResponse = await client.post('/contacts/search', {
+ query: {
+ operator: 'AND',
+ value: [
+ {
+ field: 'updated_at',
+ operator: '>',
+ value: sinceTs,
+ },
+ ],
+ },
+ pagination: { per_page: 20 },
+ });
+
+ const contacts: any[] = contactsResponse.data?.data ?? [];
+
+ for (const contact of contacts) {
+ try {
+ const eventsResponse = await client.get(`/events`, {
+ params: {
+ type: 'user',
+ intercom_user_id: contact.id,
+ per_page: 10,
+ },
+ });
+
+ const events: any[] = eventsResponse.data?.events ?? [];
+
+ for (const event of events) {
+ const createdAt = timestampToIso(event.created_at);
+ if (!createdAt || createdAt <= lastSyncTime) {
+ continue;
+ }
+
+ const contactName = contact.name || contact.email || contact.id;
+ const sourceURL = `https://app.intercom.com/a/contacts/${contact.id}`;
+
+ const text = `## Intercom Event: ${event.event_name}
+
+**Contact:** ${contactName}
+**Event:** ${event.event_name}
+**Occurred:** ${createdAt}
+**Contact ID:** ${contact.id}`;
+
+ activities.push(createActivity({ text, sourceURL }));
+ }
+ } catch (_err) {
+ // Skip if events are not accessible for this contact
+ }
+ }
+ } catch (error) {
+ console.error('Error syncing Intercom events:', error);
+ }
+
+ return activities;
+}
+
+export async function handleSchedule(
+ config?: Record,
+ state?: Record,
+): Promise {
+ try {
+ if (!config?.access_token) {
+ return [];
+ }
+
+ const intercomConfig = config as unknown as IntercomConfig;
+ const client = getIntercomClient(intercomConfig.access_token);
+ const settings = (state || {}) as IntercomState;
+ const lastSyncTime = settings.lastSyncTime || getDefaultSyncTime();
+
+ const messages: any[] = [];
+
+ const [conversationActivities, contactActivities, eventActivities] = await Promise.all([
+ syncConversations(client, lastSyncTime),
+ syncContacts(client, lastSyncTime),
+ syncEvents(client, lastSyncTime),
+ ]);
+
+ messages.push(...conversationActivities, ...contactActivities, ...eventActivities);
+
+ messages.push({
+ type: 'state',
+ data: {
+ ...settings,
+ lastSyncTime: new Date().toISOString(),
+ },
+ });
+
+ return messages;
+ } catch (error) {
+ console.error('Error in Intercom handleSchedule:', error);
+ return [];
+ }
+}
+
diff --git a/integrations/intercom/src/utils.ts b/integrations/intercom/src/utils.ts
new file mode 100644
index 00000000..49642555
--- /dev/null
+++ b/integrations/intercom/src/utils.ts
@@ -0,0 +1,61 @@
+import axios, { AxiosInstance } from 'axios';
+
+export const INTERCOM_API_BASE = 'https://api.intercom.io';
+
+export interface IntercomConfig {
+ access_token: string;
+}
+
+export function getIntercomClient(accessToken: string): AxiosInstance {
+ return axios.create({
+ baseURL: INTERCOM_API_BASE,
+ headers: {
+ Authorization: `Bearer ${accessToken}`,
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+ },
+ });
+}
+
+/**
+ * Paginate through all pages of an Intercom list endpoint.
+ * Intercom uses cursor-based pagination with a `pages.next.starting_after` cursor.
+ */
+export async function paginateAll(
+ client: AxiosInstance,
+ path: string,
+ dataKey: string,
+ params?: Record,
+ maxPages = 10,
+): Promise {
+ const results: T[] = [];
+ let page = 0;
+ let startingAfter: string | null = null;
+
+ while (page < maxPages) {
+ const requestParams: Record = { ...(params || {}), per_page: 50 };
+ if (startingAfter) {
+ requestParams['starting_after'] = startingAfter;
+ }
+
+ const response: { data: Record } = await client.get(path, {
+ params: requestParams,
+ });
+ const data: Record = response.data;
+
+ if (Array.isArray(data[dataKey])) {
+ results.push(...(data[dataKey] as T[]));
+ }
+
+ const nextCursor = data?.pages?.next?.starting_after;
+ if (nextCursor) {
+ startingAfter = nextCursor;
+ } else {
+ break;
+ }
+
+ page++;
+ }
+
+ return results;
+}
diff --git a/integrations/intercom/tsconfig.json b/integrations/intercom/tsconfig.json
new file mode 100644
index 00000000..b3966f45
--- /dev/null
+++ b/integrations/intercom/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "target": "es2022",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": false,
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "strictNullChecks": true,
+ "removeComments": true,
+ "preserveConstEnums": true,
+ "sourceMap": true,
+ "noUnusedParameters": true,
+ "noUnusedLocals": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noFallthroughCasesInSwitch": true,
+ "useUnknownInCatchVariables": false
+ },
+ "include": ["src/**/*"],
+ "exclude": ["node_modules", "build", "dist", "bin"]
+}
diff --git a/integrations/intercom/tsup.config.ts b/integrations/intercom/tsup.config.ts
new file mode 100644
index 00000000..05d2bbd7
--- /dev/null
+++ b/integrations/intercom/tsup.config.ts
@@ -0,0 +1,20 @@
+import { defineConfig } from 'tsup';
+import { dependencies } from './package.json';
+
+export default defineConfig({
+ entry: ['src/index.ts'],
+ format: ['cjs'],
+ bundle: true,
+ target: 'node16',
+ outDir: 'bin',
+ splitting: false,
+ shims: true,
+ clean: true,
+ name: 'intercom',
+ platform: 'node',
+ legacyOutput: false,
+ noExternal: Object.keys(dependencies || {}),
+ treeshake: {
+ preset: 'recommended',
+ },
+});