cogfy-messenger 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/tests.yml +18 -0
- package/README.md +25 -0
- package/package.json +24 -0
- package/src/clients/base-client.ts +13 -0
- package/src/clients/contacts/contacts-client.test.ts +89 -0
- package/src/clients/contacts/contacts-client.ts +49 -0
- package/src/clients/contacts/index.ts +2 -0
- package/src/clients/contacts/types/create-contact.ts +16 -0
- package/src/clients/contacts/types/delete-contact.ts +3 -0
- package/src/clients/contacts/types/get-contact.ts +18 -0
- package/src/clients/contacts/types/index.ts +5 -0
- package/src/clients/contacts/types/list-contacts.ts +20 -0
- package/src/clients/contacts/types/update-contact.ts +15 -0
- package/src/clients/conversations/conversations-client.test.ts +56 -0
- package/src/clients/conversations/conversations-client.ts +41 -0
- package/src/clients/conversations/index.ts +2 -0
- package/src/clients/conversations/types/get-conversation.ts +11 -0
- package/src/clients/conversations/types/get-messages.ts +35 -0
- package/src/clients/conversations/types/index.ts +4 -0
- package/src/clients/conversations/types/list-conversations.ts +37 -0
- package/src/clients/conversations/types/send-message.ts +13 -0
- package/src/clients/index.ts +2 -0
- package/src/clients/tags/index.ts +2 -0
- package/src/clients/tags/tags-client.test.ts +80 -0
- package/src/clients/tags/tags-client.ts +49 -0
- package/src/clients/tags/types/create-tag.ts +8 -0
- package/src/clients/tags/types/delete-tag.ts +4 -0
- package/src/clients/tags/types/get-tag.ts +4 -0
- package/src/clients/tags/types/index.ts +5 -0
- package/src/clients/tags/types/list-tags.ts +6 -0
- package/src/clients/tags/types/update-tag.ts +8 -0
- package/src/cogfy-messenger.ts +33 -0
- package/src/index.ts +2 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
on: [push, workflow_dispatch]
|
|
2
|
+
|
|
3
|
+
jobs:
|
|
4
|
+
tests:
|
|
5
|
+
timeout-minutes: 5
|
|
6
|
+
runs-on: ubuntu-latest
|
|
7
|
+
steps:
|
|
8
|
+
- uses: actions/checkout@v4
|
|
9
|
+
with:
|
|
10
|
+
fetch-depth: 0
|
|
11
|
+
- uses: actions/setup-node@v4
|
|
12
|
+
with:
|
|
13
|
+
node-version: 22.x
|
|
14
|
+
cache: npm
|
|
15
|
+
cache-dependency-path: package-lock.json
|
|
16
|
+
- run: npm ci
|
|
17
|
+
- run: npm run test
|
|
18
|
+
- run: npm run build
|
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Cogfy Messenger Node.js SDK
|
|
2
|
+
|
|
3
|
+
A Node.js SDK for integrating with the Cogfy Messenger API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install cogfy-messenger
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
1. Import the CogfyMessenger class from the package
|
|
14
|
+
2. Create an instance of CogfyMessenger with your API key
|
|
15
|
+
3. Use the instance to interact with the API
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { CogfyMessenger } from 'cogfy-messenger'
|
|
19
|
+
|
|
20
|
+
const cogfy = new CogfyMessenger({
|
|
21
|
+
apiKey: process.env.COGFY_MESSENGER_API_KEY
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const contacts = await cogfy.contacts.list()
|
|
25
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cogfy-messenger",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "rimraf dist && tsc",
|
|
7
|
+
"prepublishOnly": "npm run build",
|
|
8
|
+
"test": "vitest"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"description": "",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@faker-js/faker": "^9.9.0",
|
|
16
|
+
"axios-mock-adapter": "^2.1.0",
|
|
17
|
+
"rimraf": "^6.0.1",
|
|
18
|
+
"typescript": "^5.8.3",
|
|
19
|
+
"vitest": "^3.2.4"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"axios": "^1.11.0"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios'
|
|
2
|
+
|
|
3
|
+
export type BaseClientOptions = {
|
|
4
|
+
axios: AxiosInstance
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export abstract class BaseClient {
|
|
8
|
+
protected axios: AxiosInstance
|
|
9
|
+
|
|
10
|
+
constructor (options: BaseClientOptions) {
|
|
11
|
+
this.axios = options.axios
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import AxiosMockAdapter from 'axios-mock-adapter'
|
|
2
|
+
import { afterEach, describe, expect, test } from 'vitest'
|
|
3
|
+
import { CogfyMessenger } from '../../cogfy-messenger'
|
|
4
|
+
import axios from 'axios'
|
|
5
|
+
import { faker } from '@faker-js/faker'
|
|
6
|
+
|
|
7
|
+
describe('contacts', () => {
|
|
8
|
+
const mock = new AxiosMockAdapter(axios)
|
|
9
|
+
const cogfy = new CogfyMessenger({ apiKey: 'test' })
|
|
10
|
+
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
mock.restore()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
describe('list', () => {
|
|
16
|
+
test('calls the list endpoint', async () => {
|
|
17
|
+
mock.onGet('/contacts').reply(200, { data: [{ id: '1' }]})
|
|
18
|
+
|
|
19
|
+
const result = await cogfy.contacts.list()
|
|
20
|
+
|
|
21
|
+
expect(result).toMatchObject({ data: [{ id: '1' }] })
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('get', () => {
|
|
26
|
+
test('calls the get endpoint', async () => {
|
|
27
|
+
const randomId = faker.string.uuid()
|
|
28
|
+
mock.onGet(`/contacts/${randomId}`).reply(200, { id: randomId })
|
|
29
|
+
|
|
30
|
+
const result = await cogfy.contacts.get(randomId)
|
|
31
|
+
|
|
32
|
+
expect(result).toMatchObject({ id: randomId })
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
describe('create', () => {
|
|
37
|
+
test('calls the create endpoint', async () => {
|
|
38
|
+
const randomId = faker.string.uuid()
|
|
39
|
+
mock.onPost(`/contacts`).reply(201, { id: randomId })
|
|
40
|
+
|
|
41
|
+
const result = await cogfy.contacts.create({
|
|
42
|
+
waProfileName: faker.person.fullName(),
|
|
43
|
+
firstName: faker.person.firstName(),
|
|
44
|
+
lastName: faker.person.lastName(),
|
|
45
|
+
email: faker.internet.email(),
|
|
46
|
+
phone: faker.phone.number(),
|
|
47
|
+
occupation: faker.person.jobTitle(),
|
|
48
|
+
gender: faker.person.gender(),
|
|
49
|
+
birthdate: faker.date.birthdate().toISOString(),
|
|
50
|
+
age: faker.number.int({ min: 18, max: 80 }),
|
|
51
|
+
notes: faker.lorem.sentence()
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
expect(result).toMatchObject({ id: randomId })
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
describe('delete', () => {
|
|
59
|
+
test('calls the delete endpoint', async () => {
|
|
60
|
+
const randomId = faker.string.uuid()
|
|
61
|
+
mock.onDelete(`/contacts/${randomId}`).reply(200, { id: randomId })
|
|
62
|
+
|
|
63
|
+
const result = await cogfy.contacts.delete(randomId)
|
|
64
|
+
|
|
65
|
+
expect(result).toMatchObject({ id: randomId })
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
describe('update', () => {
|
|
70
|
+
test('calls the update endpoint', async () => {
|
|
71
|
+
const randomId = faker.string.uuid()
|
|
72
|
+
mock.onPatch(`/contacts/${randomId}`).reply(200, { id: randomId })
|
|
73
|
+
|
|
74
|
+
const result = await cogfy.contacts.update(randomId, {
|
|
75
|
+
firstName: faker.person.firstName(),
|
|
76
|
+
lastName: faker.person.lastName(),
|
|
77
|
+
email: faker.internet.email(),
|
|
78
|
+
phone: faker.phone.number(),
|
|
79
|
+
occupation: faker.person.jobTitle(),
|
|
80
|
+
gender: faker.person.gender(),
|
|
81
|
+
birthdate: faker.date.birthdate().toISOString(),
|
|
82
|
+
age: faker.number.int({ min: 18, max: 80 }),
|
|
83
|
+
notes: faker.lorem.sentence()
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
expect(result).toMatchObject({ id: randomId })
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
})
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { BaseClient } from '../base-client'
|
|
2
|
+
import { CreateContactCommand, CreateContactResult, DeleteContactResult, GetContactResult, ListContactsResult, UpdateContactCommand, UpdateContactResult } from './types'
|
|
3
|
+
|
|
4
|
+
export class ContactsClient extends BaseClient {
|
|
5
|
+
/**
|
|
6
|
+
* Calls the POST /contacts endpoint
|
|
7
|
+
* @param contact The contact data to create
|
|
8
|
+
* @returns An object with the ID of the newly created contact
|
|
9
|
+
*/
|
|
10
|
+
async create (contact: CreateContactCommand): Promise<CreateContactResult> {
|
|
11
|
+
return (await this.axios.post('/contacts', contact)).data
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Calls the GET /contacts/:id endpoint
|
|
16
|
+
* @param id The ID of the contact to retrieve
|
|
17
|
+
* @returns The contact with the specified ID
|
|
18
|
+
*/
|
|
19
|
+
async get (id: string): Promise<GetContactResult> {
|
|
20
|
+
return (await this.axios.get(`/contacts/${id}`)).data
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Calls the GET /contacts endpoint
|
|
25
|
+
* @returns A list of all contacts in the workspace
|
|
26
|
+
*/
|
|
27
|
+
async list (): Promise<ListContactsResult> {
|
|
28
|
+
return (await this.axios.get('/contacts')).data
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Calls the PATCH /contacts/:id endpoint
|
|
33
|
+
* @param id The ID of the contact to update
|
|
34
|
+
* @param contact The updated contact data
|
|
35
|
+
* @returns An object with the ID of the updated contact
|
|
36
|
+
*/
|
|
37
|
+
async update (id: string, contact: UpdateContactCommand): Promise<UpdateContactResult> {
|
|
38
|
+
return (await this.axios.patch(`/contacts/${id}`, contact)).data
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Calls the DELETE /contacts/:id endpoint
|
|
43
|
+
* @param id The ID of the contact to delete
|
|
44
|
+
* @returns An object with the ID of the deleted contact
|
|
45
|
+
*/
|
|
46
|
+
async delete (id: string): Promise<DeleteContactResult> {
|
|
47
|
+
return (await this.axios.delete(`/contacts/${id}`)).data
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type CreateContactResult = {
|
|
2
|
+
id: string
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export type CreateContactCommand = {
|
|
6
|
+
waProfileName: string | null
|
|
7
|
+
firstName: string | null
|
|
8
|
+
lastName: string | null
|
|
9
|
+
email: string | null
|
|
10
|
+
phone: string | null
|
|
11
|
+
occupation: string | null
|
|
12
|
+
gender: string | null
|
|
13
|
+
birthdate: string | null
|
|
14
|
+
age: number | null
|
|
15
|
+
notes: string | null
|
|
16
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type GetContactResult = {
|
|
2
|
+
id: string
|
|
3
|
+
workspaceId: string
|
|
4
|
+
statusId: string | null
|
|
5
|
+
waId: string | null
|
|
6
|
+
waProfileName: string | null
|
|
7
|
+
firstName: string | null
|
|
8
|
+
lastName: string | null
|
|
9
|
+
email: string | null
|
|
10
|
+
phone: string | null
|
|
11
|
+
occupation: string | null
|
|
12
|
+
gender: string | null
|
|
13
|
+
birthdate: string | null
|
|
14
|
+
age: number | null
|
|
15
|
+
notes: string | null
|
|
16
|
+
createDate: string
|
|
17
|
+
updateDate: string
|
|
18
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type ListContactsResult = {
|
|
2
|
+
data: {
|
|
3
|
+
id: string
|
|
4
|
+
workspaceId: string
|
|
5
|
+
statusId: string | null
|
|
6
|
+
waId: string | null
|
|
7
|
+
waProfileName: string | null
|
|
8
|
+
firstName: string | null
|
|
9
|
+
lastName: string | null
|
|
10
|
+
email: string | null
|
|
11
|
+
phone: string | null
|
|
12
|
+
occupation: string | null
|
|
13
|
+
gender: string | null
|
|
14
|
+
birthdate: string | null
|
|
15
|
+
age: number | null
|
|
16
|
+
notes: string | null
|
|
17
|
+
createDate: string
|
|
18
|
+
updateDate: string
|
|
19
|
+
}[]
|
|
20
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type UpdateContactCommand = {
|
|
2
|
+
firstName: string | null
|
|
3
|
+
lastName: string | null
|
|
4
|
+
email: string | null
|
|
5
|
+
phone: string | null
|
|
6
|
+
occupation: string | null
|
|
7
|
+
gender: string | null
|
|
8
|
+
birthdate: string | null
|
|
9
|
+
age: number | null
|
|
10
|
+
notes: string | null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type UpdateContactResult = {
|
|
14
|
+
id: string
|
|
15
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import AxiosMockAdapter from 'axios-mock-adapter'
|
|
2
|
+
import { ConversationsClient } from './conversations-client'
|
|
3
|
+
import axios from 'axios'
|
|
4
|
+
import { CogfyMessenger } from '../../cogfy-messenger'
|
|
5
|
+
import { faker } from '@faker-js/faker'
|
|
6
|
+
import { describe, expect, it, beforeEach } from 'vitest'
|
|
7
|
+
|
|
8
|
+
describe(ConversationsClient, () => {
|
|
9
|
+
const axiosMock = new AxiosMockAdapter(axios)
|
|
10
|
+
const cogfy = new CogfyMessenger({ apiKey: 'test' })
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
axiosMock.restore()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
describe(ConversationsClient.prototype.get, () => {
|
|
17
|
+
it('should call GET /conversations/:id endpoint', async () => {
|
|
18
|
+
const id = faker.string.uuid()
|
|
19
|
+
const name = faker.lorem.word()
|
|
20
|
+
axiosMock.onGet(`/conversations/${id}`).reply(200, { id, name })
|
|
21
|
+
|
|
22
|
+
const result = await cogfy.conversations.get(id)
|
|
23
|
+
|
|
24
|
+
expect(result).toEqual({ id, name })
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
describe(ConversationsClient.prototype.list, () => {
|
|
29
|
+
it('should call GET /conversations endpoint', async () => {
|
|
30
|
+
const conversations = Array.from({ length: 3 }, () => ({
|
|
31
|
+
id: faker.string.uuid(),
|
|
32
|
+
name: faker.lorem.word()
|
|
33
|
+
}))
|
|
34
|
+
axiosMock.onGet('/conversations').reply(200, { data: conversations })
|
|
35
|
+
|
|
36
|
+
const result = await cogfy.conversations.list({ phoneNumberId: faker.string.uuid() })
|
|
37
|
+
|
|
38
|
+
expect(result.data).toEqual(conversations)
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
describe('send message', () => {
|
|
43
|
+
it('calls the send message endpoint', async () => {
|
|
44
|
+
const conversationId = faker.string.uuid()
|
|
45
|
+
const messageId = faker.string.uuid()
|
|
46
|
+
axiosMock.onPost(`/conversations/${conversationId}/messages`).reply(201, { id: messageId })
|
|
47
|
+
|
|
48
|
+
const result = await cogfy.conversations.sendMessage(conversationId, {
|
|
49
|
+
type: 'text',
|
|
50
|
+
content: faker.lorem.sentence()
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
expect(result).toMatchObject({ id: messageId })
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { BaseClient } from '../base-client'
|
|
2
|
+
import { SendMessageCommand } from './types/send-message'
|
|
3
|
+
import { GetConversationResult, GetMessagesResult, ListConversationsParams, ListConversationsResult, ListMessagesParams } from './types'
|
|
4
|
+
|
|
5
|
+
export class ConversationsClient extends BaseClient {
|
|
6
|
+
/**
|
|
7
|
+
* Calls the GET /conversations/:id endpoint
|
|
8
|
+
* @param id The ID of the conversation to retrieve
|
|
9
|
+
* @returns The conversation with the specified ID
|
|
10
|
+
*/
|
|
11
|
+
async get (id: string): Promise<GetConversationResult> {
|
|
12
|
+
return (await this.axios.get(`/conversations/${id}`)).data
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Calls the GET /conversations endpoint
|
|
17
|
+
* @param params Params for listing conversations, such as pagination cursors
|
|
18
|
+
* @returns A list of all conversations in the workspace
|
|
19
|
+
*/
|
|
20
|
+
async list (params: ListConversationsParams): Promise<ListConversationsResult> {
|
|
21
|
+
const axiosResponse = await this.axios.get(`/conversations`, {
|
|
22
|
+
params,
|
|
23
|
+
})
|
|
24
|
+
return axiosResponse.data
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Calls the GET /conversations/:id/messages endpoint
|
|
29
|
+
* @param params Params for listing messages in a conversation, such as pagination cursors
|
|
30
|
+
* @returns A list of all messages in the specified conversation
|
|
31
|
+
*/
|
|
32
|
+
async getMessages (params: ListMessagesParams): Promise<GetMessagesResult> {
|
|
33
|
+
const axiosResponse = await this.axios.get(`/conversations/${params.conversationId}/messages`, {
|
|
34
|
+
params
|
|
35
|
+
})
|
|
36
|
+
return axiosResponse.data
|
|
37
|
+
}
|
|
38
|
+
async sendMessage (id: string, payload: SendMessageCommand): Promise<any> {
|
|
39
|
+
return (await this.axios.post(`/conversations/${id}/messages`, payload)).data
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type GetConversationResult = {
|
|
2
|
+
id: string
|
|
3
|
+
workspaceId: string
|
|
4
|
+
phoneNumberId: string | null
|
|
5
|
+
recipientId: string | null
|
|
6
|
+
assigneeId: string | null
|
|
7
|
+
lastMessageId: string | null
|
|
8
|
+
data: any | null
|
|
9
|
+
createDate: string
|
|
10
|
+
serviceWindowExpireDate: string | null
|
|
11
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type GetMessagesResult = {
|
|
2
|
+
data: {
|
|
3
|
+
id: string
|
|
4
|
+
workspaceId: string
|
|
5
|
+
conversationId: string | null
|
|
6
|
+
assistantId: string | null
|
|
7
|
+
userId: string | null
|
|
8
|
+
broadcastId: string | null
|
|
9
|
+
whatsappMessageId: string | null
|
|
10
|
+
from: string | null
|
|
11
|
+
to: string | null
|
|
12
|
+
role: string
|
|
13
|
+
status: string | null
|
|
14
|
+
type: string | null
|
|
15
|
+
content: string | null
|
|
16
|
+
contentData: string | null
|
|
17
|
+
toolCallId: string | null
|
|
18
|
+
toolCalls: string | null
|
|
19
|
+
data: string | null
|
|
20
|
+
contextId: string | null
|
|
21
|
+
contextFrom: string | null
|
|
22
|
+
createDate: Date
|
|
23
|
+
sendDate: Date
|
|
24
|
+
deliverDate: Date | null
|
|
25
|
+
readDate: Date | null
|
|
26
|
+
promptTokens: number | null
|
|
27
|
+
completionTokens: number | null
|
|
28
|
+
order: number
|
|
29
|
+
traceId: string | null
|
|
30
|
+
}[]
|
|
31
|
+
cursors: {
|
|
32
|
+
next: string | null
|
|
33
|
+
prev: string | null
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type ListConversationsParams =
|
|
2
|
+
| {
|
|
3
|
+
phoneNumberId: string
|
|
4
|
+
cursor?: never
|
|
5
|
+
}
|
|
6
|
+
| {
|
|
7
|
+
phoneNumberId?: never
|
|
8
|
+
cursor: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type ListMessagesParams =
|
|
12
|
+
| {
|
|
13
|
+
conversationId: string
|
|
14
|
+
cursor?: never
|
|
15
|
+
}
|
|
16
|
+
| {
|
|
17
|
+
conversationId?: never
|
|
18
|
+
cursor: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type ListConversationsResult = {
|
|
22
|
+
data: ListConversationsResultData[]
|
|
23
|
+
cursors: {
|
|
24
|
+
next: string | null
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type ListConversationsResultData = {
|
|
29
|
+
id: string
|
|
30
|
+
workspaceId: string
|
|
31
|
+
phoneNumberId: string | null
|
|
32
|
+
recipientId: string | null
|
|
33
|
+
assigneeId: string | null
|
|
34
|
+
lastMessageId: string | null
|
|
35
|
+
createDate: string
|
|
36
|
+
serviceWindowExpireDate: string | null
|
|
37
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import AxiosMockAdapter from 'axios-mock-adapter'
|
|
2
|
+
import { TagsClient } from './tags-client'
|
|
3
|
+
import axios from 'axios'
|
|
4
|
+
import { CogfyMessenger } from '../../cogfy-messenger'
|
|
5
|
+
import { faker } from '@faker-js/faker'
|
|
6
|
+
import { describe, expect, it, beforeEach } from 'vitest'
|
|
7
|
+
|
|
8
|
+
describe(TagsClient, () => {
|
|
9
|
+
const axiosMock = new AxiosMockAdapter(axios)
|
|
10
|
+
const cogfy = new CogfyMessenger({ apiKey: 'test' })
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
axiosMock.restore()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
describe(TagsClient.prototype.create, () => {
|
|
17
|
+
it('should call POST /tags endpoint', async () => {
|
|
18
|
+
const fakeId = faker.string.uuid()
|
|
19
|
+
axiosMock.onPost('/tags').reply(201, { id: fakeId })
|
|
20
|
+
|
|
21
|
+
const result = await cogfy.tags.create({
|
|
22
|
+
name: faker.lorem.word()
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
expect(result).toEqual({
|
|
26
|
+
id: fakeId
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
describe(TagsClient.prototype.delete, () => {
|
|
32
|
+
it('should call DELETE /tags/:id endpoint', async () => {
|
|
33
|
+
const name = faker.lorem.word()
|
|
34
|
+
const id = faker.string.uuid()
|
|
35
|
+
axiosMock.onDelete(`/tags/${id}`).reply(200, { id, name })
|
|
36
|
+
|
|
37
|
+
const result = await cogfy.tags.delete(id)
|
|
38
|
+
|
|
39
|
+
expect(result).toEqual({ id, name })
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
describe(TagsClient.prototype.get, () => {
|
|
44
|
+
it('should call GET /tags/:id endpoint', async () => {
|
|
45
|
+
const id = faker.string.uuid()
|
|
46
|
+
const name = faker.lorem.word()
|
|
47
|
+
axiosMock.onGet(`/tags/${id}`).reply(200, { id, name })
|
|
48
|
+
|
|
49
|
+
const result = await cogfy.tags.get(id)
|
|
50
|
+
|
|
51
|
+
expect(result).toEqual({ id, name })
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
describe(TagsClient.prototype.list, () => {
|
|
56
|
+
it('should call GET /tags endpoint', async () => {
|
|
57
|
+
const tags = Array.from({ length: 3 }, () => ({
|
|
58
|
+
id: faker.string.uuid(),
|
|
59
|
+
name: faker.lorem.word()
|
|
60
|
+
}))
|
|
61
|
+
axiosMock.onGet('/tags').reply(200, { data: tags })
|
|
62
|
+
|
|
63
|
+
const result = await cogfy.tags.list()
|
|
64
|
+
|
|
65
|
+
expect(result.data).toEqual(tags)
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
describe(TagsClient.prototype.update, () => {
|
|
70
|
+
it('should call PATCH /tags/:id endpoint', async () => {
|
|
71
|
+
const id = faker.string.uuid()
|
|
72
|
+
const name = faker.lorem.word()
|
|
73
|
+
axiosMock.onPatch(`/tags/${id}`).reply(200, { id, name })
|
|
74
|
+
|
|
75
|
+
const result = await cogfy.tags.update(id, { name })
|
|
76
|
+
|
|
77
|
+
expect(result).toEqual({ id, name })
|
|
78
|
+
})
|
|
79
|
+
})
|
|
80
|
+
})
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { BaseClient } from '../base-client'
|
|
2
|
+
import { CreateTagCommand, CreateTagResult, DeleteTagResult, GetTagResult, ListTagsResult, UpdateTagCommand, UpdateTagResult } from './types'
|
|
3
|
+
|
|
4
|
+
export class TagsClient extends BaseClient {
|
|
5
|
+
/**
|
|
6
|
+
* Calls the POST /tags endpoint
|
|
7
|
+
* @param payload The tag data to create
|
|
8
|
+
* @returns An object with the ID and the name of the newly created tag
|
|
9
|
+
*/
|
|
10
|
+
async create(payload: CreateTagCommand): Promise<CreateTagResult> {
|
|
11
|
+
return (await this.axios.post('/tags', payload)).data
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Calls the DELETE /tags/:id endpoint
|
|
16
|
+
* @param id The ID of the tag to delete
|
|
17
|
+
* @returns An object with the ID and the name of the deleted tag
|
|
18
|
+
*/
|
|
19
|
+
async delete(id: string): Promise<DeleteTagResult> {
|
|
20
|
+
return (await this.axios.delete(`/tags/${id}`)).data
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Calls the GET /tags/:id endpoint
|
|
25
|
+
* @param id The ID of the tag to retrieve
|
|
26
|
+
* @returns The tag with the specified ID
|
|
27
|
+
*/
|
|
28
|
+
async get(id: string): Promise<GetTagResult> {
|
|
29
|
+
return (await this.axios.get(`/tags/${id}`)).data
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Calls the GET /tags endpoint
|
|
34
|
+
* @returns A list of all tags in the workspace
|
|
35
|
+
*/
|
|
36
|
+
async list(): Promise<ListTagsResult> {
|
|
37
|
+
return (await this.axios.get('/tags')).data
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Calls the PATCH /tags/:id endpoint
|
|
42
|
+
* @param id The ID of the tag to update
|
|
43
|
+
* @param payload The updated tag data
|
|
44
|
+
* @returns An object with the ID and the name of the updated tag
|
|
45
|
+
*/
|
|
46
|
+
async update(id: string, payload: UpdateTagCommand): Promise<UpdateTagResult> {
|
|
47
|
+
return (await this.axios.patch(`/tags/${id}`, payload)).data
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
import { ContactsClient } from './clients/contacts'
|
|
3
|
+
import { BaseClientOptions } from './clients/base-client'
|
|
4
|
+
import { TagsClient } from './clients/tags'
|
|
5
|
+
import { ConversationsClient } from './clients/conversations'
|
|
6
|
+
|
|
7
|
+
export type CogfyMessengerOptions = {
|
|
8
|
+
apiKey: string
|
|
9
|
+
baseURL?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const DEFAULT_BASE_URL = 'https://messenger-public-api.cogfy.com'
|
|
13
|
+
|
|
14
|
+
export class CogfyMessenger {
|
|
15
|
+
contacts: ContactsClient
|
|
16
|
+
conversations: ConversationsClient
|
|
17
|
+
tags: TagsClient
|
|
18
|
+
|
|
19
|
+
constructor (options: CogfyMessengerOptions) {
|
|
20
|
+
const clientOptions: BaseClientOptions = {
|
|
21
|
+
axios: axios.create({
|
|
22
|
+
baseURL: options.baseURL || DEFAULT_BASE_URL,
|
|
23
|
+
headers: {
|
|
24
|
+
'Authorization': `Bearer ${options.apiKey}`
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.contacts = new ContactsClient(clientOptions)
|
|
30
|
+
this.conversations = new ConversationsClient(clientOptions)
|
|
31
|
+
this.tags = new TagsClient(clientOptions)
|
|
32
|
+
}
|
|
33
|
+
}
|
package/src/index.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"exclude": [
|
|
3
|
+
"dist",
|
|
4
|
+
"**/*.test.ts"
|
|
5
|
+
],
|
|
6
|
+
"compilerOptions": {
|
|
7
|
+
"target": "es2016",
|
|
8
|
+
"module": "commonjs",
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"outDir": "./dist",
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"forceConsistentCasingInFileNames": true,
|
|
13
|
+
"strict": true,
|
|
14
|
+
"skipLibCheck": true
|
|
15
|
+
}
|
|
16
|
+
}
|