Skip to content
This repository was archived by the owner on Jun 10, 2026. It is now read-only.

Commit e4759d6

Browse files
committed
feat: add contacts and segments
1 parent ca4c11c commit e4759d6

8 files changed

Lines changed: 204 additions & 9 deletions

File tree

bun.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/client.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { REST } from '@rewritetoday/rest';
22
import { APIKeyManager } from './resources/api-key';
3+
import { ContactManager } from './resources/contact';
34
import { LogManager } from './resources/logs';
45
import { MessageManager } from './resources/message';
56
import { OTPManager } from './resources/otp';
7+
import { SegmentManager } from './resources/segment';
68
import { TemplateManager } from './resources/template';
79
import { WebhookManager } from './resources/webhook';
810
import type { RewriteOptions } from './types';
@@ -20,6 +22,12 @@ export class Rewrite {
2022
/** OTP resource client. */
2123
public readonly otp: OTPManager;
2224

25+
/** Contact resource client. */
26+
public readonly contacts: ContactManager;
27+
28+
/** Segment resource client. */
29+
public readonly segments: SegmentManager;
30+
2331
/** Webhook logs resource client. */
2432
public readonly logs: LogManager;
2533

@@ -53,6 +61,8 @@ export class Rewrite {
5361
});
5462

5563
this.otp = new OTPManager(this.rest);
64+
this.contacts = new ContactManager(this.rest);
65+
this.segments = new SegmentManager(this.rest);
5666
this.logs = new LogManager(this.rest);
5767
this.apiKeys = new APIKeyManager(this.rest);
5868
this.webhooks = new WebhookManager(this.rest);

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ export * from '@rewritetoday/types';
22

33
export { Rewrite } from './client';
44
export { APIKeyManager } from './resources/api-key';
5+
export { ContactManager } from './resources/contact';
56
export { LogManager } from './resources/logs';
67
export { MessageManager } from './resources/message';
78
export { OTPManager } from './resources/otp';
9+
export { SegmentManager } from './resources/segment';
810
export { TemplateManager } from './resources/template';
911
export { WebhookManager } from './resources/webhook';
1012
export * from './types';

src/resources/contact.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import {
2+
type RESTDeleteContactData,
3+
type RESTGetContactData,
4+
type RESTGetListContactsData,
5+
type RESTGetListContactsQueryParams,
6+
type RESTPatchUpdateContactBody,
7+
type RESTPatchUpdateContactData,
8+
type RESTPostCreateContactBody,
9+
type RESTPostCreateContactData,
10+
Routes,
11+
type Snowflake,
12+
} from '@rewritetoday/types';
13+
import { BaseManager } from './base';
14+
15+
/**
16+
* Contact resource operations.
17+
*/
18+
export class ContactManager extends BaseManager {
19+
/**
20+
* Lists contacts for a project.
21+
*/
22+
public async list(options?: RESTGetListContactsQueryParams) {
23+
return await this.rest.get<RESTGetListContactsData>(
24+
Routes.contacts.list(options),
25+
);
26+
}
27+
28+
/**
29+
* Creates a contact for a project.
30+
*/
31+
public async create(options: RESTPostCreateContactBody) {
32+
return await this.rest.post<RESTPostCreateContactData>(
33+
Routes.contacts.create(),
34+
options,
35+
);
36+
}
37+
38+
/**
39+
* Fetches a contact by id or phone number.
40+
*/
41+
public async get(identifier: string) {
42+
return await this.rest.get<RESTGetContactData>(
43+
Routes.contacts.get(identifier),
44+
);
45+
}
46+
47+
/**
48+
* Updates a contact by id.
49+
*/
50+
public async update(id: Snowflake, options: RESTPatchUpdateContactBody) {
51+
return await this.rest.patch<RESTPatchUpdateContactData>(
52+
Routes.contacts.update(id),
53+
options,
54+
);
55+
}
56+
57+
/**
58+
* Deletes a contact by id.
59+
*/
60+
public async delete(id: Snowflake) {
61+
return await this.rest.delete<RESTDeleteContactData>(
62+
Routes.contacts.delete(id),
63+
);
64+
}
65+
}

src/resources/message.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
type RESTPostSendBatchMessagesData,
88
type RESTPostSendMessageData,
99
Routes,
10+
type Snowflake,
1011
} from '@rewritetoday/types';
1112
import type {
1213
SendBatchMessageOptions,
@@ -63,7 +64,7 @@ export class MessageManager extends BaseManager {
6364
/**
6465
* Cancels a message by id.
6566
*/
66-
public async cancel(id: string) {
67+
public async cancel(id: Snowflake) {
6768
return await this.rest.post<RESTPostCancelMessageData>(
6869
Routes.messages.cancel(id),
6970
);
@@ -72,7 +73,7 @@ export class MessageManager extends BaseManager {
7273
/**
7374
* Fetches a message by id.
7475
*/
75-
public async get(id: string) {
76+
public async get(id: Snowflake) {
7677
return await this.rest.get<RESTGetMessageData>(Routes.messages.get(id));
7778
}
7879
}

src/resources/segment.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import {
2+
type RESTDeleteDetachSegmentContactData,
3+
type RESTDeleteSegmentData,
4+
type RESTGetListSegmentContactsData,
5+
type RESTGetListSegmentContactsQueryParams,
6+
type RESTGetListSegmentsData,
7+
type RESTGetListSegmentsQueryParams,
8+
type RESTGetSegmentData,
9+
type RESTPatchUpdateSegmentBody,
10+
type RESTPatchUpdateSegmentData,
11+
type RESTPostAttachSegmentContactBody,
12+
type RESTPostAttachSegmentContactData,
13+
type RESTPostCreateSegmentBody,
14+
type RESTPostCreateSegmentData,
15+
Routes,
16+
type Snowflake,
17+
} from '@rewritetoday/types';
18+
import { BaseManager } from './base';
19+
20+
/**
21+
* Segment resource operations.
22+
*/
23+
export class SegmentManager extends BaseManager {
24+
/**
25+
* Lists segments for a project.
26+
*/
27+
public async list(options?: RESTGetListSegmentsQueryParams) {
28+
return await this.rest.get<RESTGetListSegmentsData>(
29+
Routes.segments.list(options),
30+
);
31+
}
32+
33+
/**
34+
* Creates a segment for a project.
35+
*/
36+
public async create(options: RESTPostCreateSegmentBody) {
37+
return await this.rest.post<RESTPostCreateSegmentData>(
38+
Routes.segments.create(),
39+
options,
40+
);
41+
}
42+
43+
/**
44+
* Fetches a segment by id.
45+
*/
46+
public async get(id: Snowflake) {
47+
return await this.rest.get<RESTGetSegmentData>(Routes.segments.get(id));
48+
}
49+
50+
/**
51+
* Updates a segment by id.
52+
*/
53+
public async update(id: Snowflake, options: RESTPatchUpdateSegmentBody) {
54+
return await this.rest.patch<RESTPatchUpdateSegmentData>(
55+
Routes.segments.update(id),
56+
options,
57+
);
58+
}
59+
60+
/**
61+
* Deletes a segment by id.
62+
*/
63+
public async delete(id: Snowflake) {
64+
return await this.rest.delete<RESTDeleteSegmentData>(
65+
Routes.segments.delete(id),
66+
);
67+
}
68+
69+
/**
70+
* Lists contacts attached to a segment.
71+
*/
72+
public async contacts(
73+
id: Snowflake,
74+
options?: RESTGetListSegmentContactsQueryParams,
75+
) {
76+
return await this.rest.get<RESTGetListSegmentContactsData>(
77+
Routes.segments.contacts.list(id, options),
78+
);
79+
}
80+
81+
/**
82+
* Attaches a contact to a segment.
83+
*/
84+
public async attach(
85+
id: Snowflake,
86+
options: RESTPostAttachSegmentContactBody,
87+
) {
88+
return await this.rest.post<RESTPostAttachSegmentContactData>(
89+
Routes.segments.contacts.attach(id),
90+
options,
91+
);
92+
}
93+
94+
/**
95+
* Detaches a contact from a segment.
96+
*/
97+
public async detach(id: Snowflake, contactId: Snowflake) {
98+
return await this.rest.delete<RESTDeleteDetachSegmentContactData>(
99+
Routes.segments.contacts.detach(id, contactId),
100+
);
101+
}
102+
}

src/resources/template.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import {
33
type RESTGetListTemplatesData,
44
type RESTGetListTemplatesQueryParams,
55
type RESTGetTemplateData,
6+
type RESTGetTemplateQueryParams,
7+
type RESTPatchUpdateTemplateBody,
8+
type RESTPatchUpdateTemplateData,
69
type RESTPostCreateTemplateBody,
710
type RESTPostCreateTemplateData,
811
Routes,
@@ -27,8 +30,8 @@ export class TemplateManager extends BaseManager {
2730
/**
2831
* Updates a template by id.
2932
*/
30-
public async update(id: Snowflake, options: RESTPostCreateTemplateBody) {
31-
return await this.rest.patch<RESTPostCreateTemplateData>(
33+
public async update(id: Snowflake, options: RESTPatchUpdateTemplateBody) {
34+
return await this.rest.patch<RESTPatchUpdateTemplateData>(
3235
Routes.templates.update(id),
3336
options,
3437
);
@@ -53,9 +56,11 @@ export class TemplateManager extends BaseManager {
5356
}
5457

5558
/**
56-
* Fetches a template by id.
59+
* Fetches a template by id or name.
5760
*/
58-
public async get(id: Snowflake) {
59-
return await this.rest.get<RESTGetTemplateData>(Routes.templates.get(id));
61+
public async get(identifier: string, options?: RESTGetTemplateQueryParams) {
62+
return await this.rest.get<RESTGetTemplateData>(
63+
Routes.templates.get(identifier, options),
64+
);
6065
}
6166
}

test/index.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
import { describe, expect, test } from 'bun:test';
22
import { createHmac } from 'node:crypto';
3+
import { Rewrite } from '../src/client';
34
import { WebhookManager } from '../src/resources/webhook';
45

56
const webhooks = new WebhookManager({} as never);
67

8+
describe('Rewrite', () => {
9+
test('exposes contacts and segments managers', () => {
10+
const rewrite = new Rewrite('rw_test');
11+
12+
expect(rewrite.contacts).toBeDefined();
13+
expect(rewrite.segments).toBeDefined();
14+
});
15+
});
16+
717
describe('WebhookManager.verify', () => {
818
test('returns true for valid svix headers', () => {
919
const payload = JSON.stringify({ type: 'message.sent' });

0 commit comments

Comments
 (0)