Skip to content

Commit 3aaa24f

Browse files
committed
feat: add Zendesk ticket integration
1 parent a3e7b84 commit 3aaa24f

File tree

17 files changed

+654
-7
lines changed

17 files changed

+654
-7
lines changed

apps/api-harmonization/src/app.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export const AuthModuleBaseModule = AuthModule.Module.register(AppConfig);
7878

7979
@Module({
8080
imports: [
81-
HttpModule,
81+
HttpModule.register({ global: true }),
8282
LoggerModule,
8383
ConfigModule.forRoot({
8484
isGlobal: true,
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
sidebar_position: 4
3+
---
4+
5+
# Zendesk
6+
7+
Integration with Zendesk for retrieving user tickets.
8+
9+
## Overview and prerequisites
10+
11+
This integration allows users to view their Zendesk support tickets within the Open Self Service platform. It implements the Tickets service contract to retrieve tickets for a user from Zendesk using the Search API.
12+
13+
### Requirements
14+
15+
- Zendesk account with API access
16+
- API token with read-only access to tickets
17+
18+
## Configuration
19+
20+
Set the following environment variables:
21+
22+
```
23+
ZENDESK_API_URL=https://your-subdomain.zendesk.com
24+
ZENDESK_API_TOKEN=your-base64-encoded-token
25+
```
26+
27+
The token should be base64-encoded and will be sent in the header: `Authentication: Basic ${ZENDESK_API_TOKEN}`.
28+
29+
## Data mapping
30+
31+
### Zendesk to Tickets model
32+
33+
| Zendesk field | Tickets model field | Notes |
34+
|---------------|---------------------|-------|
35+
| id | id | |
36+
| created_at | createdAt | ISO timestamp preserved |
37+
| updated_at | updatedAt | ISO timestamp preserved |
38+
| tags[0] | topic | First tag is used as topic |
39+
| priority | type | |
40+
| status | status | Mapped to OPEN, CLOSED, or IN_PROGRESS |
41+
| subject | properties[].value | Added as a property with id 'subject' |
42+
| description | properties[].value | Added as a property with id 'description' |
43+
| custom_fields | properties[] | Added as properties with id 'custom_field_X' |
44+
45+
## Usage examples
46+
47+
### Getting a list of tickets
48+
49+
```typescript
50+
import { Tickets } from '@o2s/framework/modules';
51+
52+
@Injectable()
53+
export class YourService {
54+
constructor(private readonly ticketsService: Tickets.Service) {}
55+
56+
getTickets() {
57+
return this.ticketsService.getTicketList({
58+
limit: 10,
59+
offset: 0,
60+
status: 'OPEN',
61+
});
62+
}
63+
}
64+
```
65+
66+
### Getting a specific ticket
67+
68+
```typescript
69+
import { Tickets } from '@o2s/framework/modules';
70+
71+
@Injectable()
72+
export class YourService {
73+
constructor(private readonly ticketsService: Tickets.Service) {}
74+
75+
getTicket(id: string) {
76+
return this.ticketsService.getTicket({ id });
77+
}
78+
}
79+
```
80+
81+
## Limitations
82+
83+
- Creating tickets is not implemented in this version
84+
- User identification is done by email address only
85+
- Pagination mapping: Zendesk uses page/per_page while our API uses offset/limit

packages/configs/integrations/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"dependencies": {
1919
"@o2s/framework": "*",
2020
"@o2s/integrations.mocked": "*",
21-
"@o2s/integrations.strapi-cms": "*"
21+
"@o2s/integrations.strapi-cms": "*",
22+
"@o2s/integrations.zendesk": "*"
2223
},
2324
"devDependencies": {
2425
"@o2s/eslint-config": "*",
Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1-
import { Config, Integration } from '@o2s/integrations.mocked/integration';
1+
// Switch between Zendesk and Mocked integrations
2+
// Option 1: Zendesk Integration (uncomment to use)
3+
import { Config as ZendeskConfig, Integration as ZendeskIntegration } from '@o2s/integrations.zendesk/integration';
4+
5+
// Option 2: Mocked Integration (comment out to use Zendesk)
6+
// import { Config, Integration } from '@o2s/integrations.mocked/integration';
27

38
import { ApiConfig } from '@o2s/framework/modules';
49

5-
export const TicketsIntegrationConfig: ApiConfig['integrations']['tickets'] = Config.tickets!;
10+
// Use Zendesk
11+
export const TicketsIntegrationConfig: ApiConfig['integrations']['tickets'] = ZendeskConfig.tickets!;
12+
export import Service = ZendeskIntegration.Tickets.Service;
13+
export import Request = ZendeskIntegration.Tickets.Request;
14+
export import Model = ZendeskIntegration.Tickets.Model;
615

7-
export import Service = Integration.Tickets.Service;
8-
export import Request = Integration.Tickets.Request;
9-
export import Model = Integration.Tickets.Model;
16+
// Use Mocked (comment out the Zendesk lines above and uncomment below)
17+
// export const TicketsIntegrationConfig: ApiConfig['integrations']['tickets'] = Config.tickets!;
18+
// export import Service = Integration.Tickets.Service;
19+
// export import Request = Integration.Tickets.Request;
20+
// export import Model = Integration.Tickets.Model;
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
2+
# compiled output
3+
/dist
4+
/node_modules
5+
/build
6+
7+
# Logs
8+
logs
9+
*.log
10+
npm-debug.log*
11+
pnpm-debug.log*
12+
yarn-debug.log*
13+
yarn-error.log*
14+
lerna-debug.log*
15+
16+
# OS
17+
.DS_Store
18+
19+
# Tests
20+
/coverage
21+
/.nyc_output
22+
23+
# IDEs and editors
24+
/.idea
25+
.project
26+
.classpath
27+
.c9/
28+
*.launch
29+
.settings/
30+
*.sublime-workspace
31+
32+
# IDE - VSCode
33+
.vscode/*
34+
!.vscode/settings.json
35+
!.vscode/tasks.json
36+
!.vscode/launch.json
37+
!.vscode/extensions.json
38+
39+
# dotenv environment variable files
40+
.env
41+
.env.development.local
42+
.env.test.local
43+
.env.production.local
44+
45+
# temp directory
46+
.temp
47+
.tmp
48+
49+
# Runtime data
50+
pids
51+
*.pid
52+
*.seed
53+
*.pid.lock
54+
55+
# Diagnostic reports (https://nodejs.org/api/report.html)
56+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import apiConfig from '@o2s/prettier-config/api.mjs';
2+
3+
/**
4+
* @see https://prettier.io/docs/en/configuration.html
5+
* @type {import("prettier").Config}
6+
*/
7+
const config = {
8+
...apiConfig,
9+
};
10+
11+
export default config;
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Zendesk Integration for Open Self Service
2+
3+
This package provides integration with Zendesk for retrieving user tickets.
4+
5+
## Features
6+
7+
- Retrieve tickets for a user from Zendesk using the Search API
8+
- Get detailed ticket information including comments and attachments
9+
- Map Zendesk responses to the normalized Tickets model
10+
11+
## Configuration
12+
13+
Set the following environment variables:
14+
15+
```
16+
ZENDESK_API_URL=https://your-subdomain.zendesk.com
17+
ZENDESK_API_TOKEN=your-base64-encoded-token
18+
```
19+
20+
The token should be base64-encoded and will be sent in the header: `Authentication: Basic ${ZENDESK_API_TOKEN}`.
21+
22+
## Usage
23+
24+
### Enabling in DI
25+
26+
In your `main.ts` or configuration file:
27+
28+
```typescript
29+
import { Config as ZendeskConfig } from '@o2s/integrations.zendesk';
30+
31+
// Add to your API configuration
32+
const apiConfig: ApiConfig = {
33+
integrations: {
34+
...ZendeskConfig,
35+
// other integrations
36+
},
37+
};
38+
```
39+
40+
### Examples
41+
42+
#### Getting a list of tickets
43+
44+
```typescript
45+
import { Tickets } from '@o2s/framework/modules';
46+
47+
@Injectable()
48+
export class YourService {
49+
constructor(private readonly ticketsService: Tickets.Service) {}
50+
51+
getTickets() {
52+
return this.ticketsService.getTicketList({
53+
limit: 10,
54+
offset: 0,
55+
status: 'OPEN',
56+
});
57+
}
58+
}
59+
```
60+
61+
#### Getting a specific ticket
62+
63+
```typescript
64+
import { Tickets } from '@o2s/framework/modules';
65+
66+
@Injectable()
67+
export class YourService {
68+
constructor(private readonly ticketsService: Tickets.Service) {}
69+
70+
getTicket(id: string) {
71+
return this.ticketsService.getTicket({ id });
72+
}
73+
}
74+
```
75+
76+
## Limitations
77+
78+
- Creating tickets is not implemented in this version
79+
- User identification is done by email address only
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { config } from '@o2s/eslint-config/api';
2+
3+
/** @type {import("eslint").Linter.Config} */
4+
export default config;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export default {
2+
'*.{js,jsx,ts,tsx,css,scss}': ['prettier --write'],
3+
'*.{js,jsx,ts,tsx}': () => 'tsc --noEmit',
4+
};
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "@o2s/integrations.zendesk",
3+
"version": "1.0.0",
4+
"private": false,
5+
"license": "MIT",
6+
"exports": {
7+
"./integration": "./dist/integration.js"
8+
},
9+
"files": [
10+
"dist"
11+
],
12+
"scripts": {
13+
"dev": "tsc && (concurrently \"tsc -w\" \"tsc-alias -w\")",
14+
"build": "tsc && tsc-alias",
15+
"lint": "tsc --noEmit && eslint . --max-warnings 0",
16+
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,scss,json}\""
17+
},
18+
"dependencies": {
19+
"@nestjs/axios": "^3.0.0",
20+
"@nestjs/common": "^10.0.0",
21+
"@o2s/framework": "*",
22+
"@o2s/utils.logger": "*",
23+
"axios": "^1.6.0",
24+
"rxjs": "^7.8.1"
25+
},
26+
"devDependencies": {
27+
"@o2s/eslint-config": "*",
28+
"@o2s/prettier-config": "*",
29+
"@o2s/typescript-config": "*",
30+
"concurrently": "^9.2.1",
31+
"eslint": "^9.37.0",
32+
"prettier": "^3.6.2",
33+
"tsc-alias": "^1.8.10",
34+
"typescript": "^5.7.3"
35+
}
36+
}

0 commit comments

Comments
 (0)