@knocklabs/client 0.9.2 → 0.9.4
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/CHANGELOG.md +12 -0
- package/dist/cjs/clients/users/index.js +1 -1
- package/dist/cjs/clients/users/index.js.map +1 -1
- package/dist/esm/clients/users/index.mjs +15 -0
- package/dist/esm/clients/users/index.mjs.map +1 -1
- package/dist/types/clients/users/index.d.ts +3 -1
- package/dist/types/clients/users/index.d.ts.map +1 -1
- package/package.json +4 -1
- package/src/api.ts +110 -0
- package/src/clients/feed/feed.ts +774 -0
- package/src/clients/feed/index.ts +39 -0
- package/src/clients/feed/interfaces.ts +105 -0
- package/src/clients/feed/store.ts +93 -0
- package/src/clients/feed/types.ts +64 -0
- package/src/clients/feed/utils.ts +23 -0
- package/src/clients/objects/constants.ts +1 -0
- package/src/clients/objects/index.ts +61 -0
- package/src/clients/preferences/index.ts +196 -0
- package/src/clients/preferences/interfaces.ts +34 -0
- package/src/clients/slack/index.ts +89 -0
- package/src/clients/slack/interfaces.ts +36 -0
- package/src/clients/users/index.ts +110 -0
- package/src/clients/users/interfaces.ts +8 -0
- package/src/index.ts +16 -0
- package/src/interfaces.ts +52 -0
- package/src/knock.ts +182 -0
- package/src/networkStatus.ts +19 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import Knock from "../../knock";
|
|
2
|
+
|
|
3
|
+
import Feed from "./feed";
|
|
4
|
+
import { FeedClientOptions } from "./interfaces";
|
|
5
|
+
|
|
6
|
+
class FeedClient {
|
|
7
|
+
private instance: Knock;
|
|
8
|
+
private feedInstances: Feed[] = [];
|
|
9
|
+
|
|
10
|
+
constructor(instance: Knock) {
|
|
11
|
+
this.instance = instance;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
initialize(feedChannelId: string, options: FeedClientOptions = {}) {
|
|
15
|
+
const feedInstance = new Feed(this.instance, feedChannelId, options);
|
|
16
|
+
this.feedInstances.push(feedInstance);
|
|
17
|
+
|
|
18
|
+
return feedInstance;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
removeInstance(feed: Feed) {
|
|
22
|
+
this.feedInstances = this.feedInstances.filter((f) => f !== feed);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
teardownInstances() {
|
|
26
|
+
for (const feed of this.feedInstances) {
|
|
27
|
+
feed.teardown();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
reinitializeInstances() {
|
|
32
|
+
for (const feed of this.feedInstances) {
|
|
33
|
+
feed.reinitialize();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { Feed };
|
|
39
|
+
export default FeedClient;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { GenericData, PageInfo } from "@knocklabs/types";
|
|
2
|
+
|
|
3
|
+
import { Activity, Recipient } from "../../interfaces";
|
|
4
|
+
import { NetworkStatus } from "../../networkStatus";
|
|
5
|
+
|
|
6
|
+
// Specific feed interfaces
|
|
7
|
+
|
|
8
|
+
export interface FeedClientOptions {
|
|
9
|
+
before?: string;
|
|
10
|
+
after?: string;
|
|
11
|
+
page_size?: number;
|
|
12
|
+
status?: "unread" | "read" | "unseen" | "seen" | "all";
|
|
13
|
+
// Optionally scope all notifications to a particular source only
|
|
14
|
+
source?: string;
|
|
15
|
+
// Optionally scope all requests to a particular tenant
|
|
16
|
+
tenant?: string;
|
|
17
|
+
// Optionally scope to notifications with any tenancy or no tenancy
|
|
18
|
+
has_tenant?: boolean;
|
|
19
|
+
// Optionally scope to notifications with any of the categories provided
|
|
20
|
+
workflow_categories?: string[];
|
|
21
|
+
// Optionally scope to a given archived status (defaults to `exclude`)
|
|
22
|
+
archived?: "include" | "exclude" | "only";
|
|
23
|
+
// Optionally scope all notifications that contain this argument as part of their trigger payload
|
|
24
|
+
trigger_data?: GenericData;
|
|
25
|
+
// Optionally enable cross browser feed updates for this feed
|
|
26
|
+
__experimentalCrossBrowserUpdates?: boolean;
|
|
27
|
+
// Optionally automatically manage socket connections on changes to tab visibility (defaults to `false`)
|
|
28
|
+
auto_manage_socket_connection?: boolean;
|
|
29
|
+
// Optionally set the delay amount in milliseconds when automatically disconnecting sockets from inactive tabs (defaults to `2000`)
|
|
30
|
+
// Requires `auto_manage_socket_connection` to be `true`
|
|
31
|
+
auto_manage_socket_connection_delay?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type FetchFeedOptions = {
|
|
35
|
+
__loadingType?: NetworkStatus.loading | NetworkStatus.fetchMore;
|
|
36
|
+
__fetchSource?: "socket" | "http";
|
|
37
|
+
} & Omit<FeedClientOptions, "__experimentalCrossBrowserUpdates">;
|
|
38
|
+
|
|
39
|
+
export interface ContentBlockBase {
|
|
40
|
+
name: string;
|
|
41
|
+
type: "markdown" | "text" | "button_set";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface ActionButton {
|
|
45
|
+
name: string;
|
|
46
|
+
label: string;
|
|
47
|
+
action: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface ButtonSetContentBlock extends ContentBlockBase {
|
|
51
|
+
type: "button_set";
|
|
52
|
+
buttons: ActionButton[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface TextContentBlock extends ContentBlockBase {
|
|
56
|
+
type: "text";
|
|
57
|
+
rendered: string;
|
|
58
|
+
content: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface MarkdownContentBlock extends ContentBlockBase {
|
|
62
|
+
type: "markdown";
|
|
63
|
+
rendered: string;
|
|
64
|
+
content: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface NotificationSource {
|
|
68
|
+
key: string;
|
|
69
|
+
version_id: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type ContentBlock =
|
|
73
|
+
| MarkdownContentBlock
|
|
74
|
+
| TextContentBlock
|
|
75
|
+
| ButtonSetContentBlock;
|
|
76
|
+
|
|
77
|
+
export interface FeedItem<T = GenericData> {
|
|
78
|
+
__cursor: string;
|
|
79
|
+
id: string;
|
|
80
|
+
activities: Activity<T>[];
|
|
81
|
+
actors: Recipient[];
|
|
82
|
+
blocks: ContentBlock[];
|
|
83
|
+
inserted_at: string;
|
|
84
|
+
updated_at: string;
|
|
85
|
+
read_at: string | null;
|
|
86
|
+
seen_at: string | null;
|
|
87
|
+
archived_at: string | null;
|
|
88
|
+
total_activities: number;
|
|
89
|
+
total_actors: number;
|
|
90
|
+
data: T | null;
|
|
91
|
+
source: NotificationSource;
|
|
92
|
+
tenant: string | null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface FeedMetadata {
|
|
96
|
+
total_count: number;
|
|
97
|
+
unread_count: number;
|
|
98
|
+
unseen_count: number;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface FeedResponse {
|
|
102
|
+
entries: FeedItem[];
|
|
103
|
+
meta: FeedMetadata;
|
|
104
|
+
page_info: PageInfo;
|
|
105
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import create from "zustand/vanilla";
|
|
2
|
+
|
|
3
|
+
import { NetworkStatus } from "../../networkStatus";
|
|
4
|
+
|
|
5
|
+
import { FeedItem } from "./interfaces";
|
|
6
|
+
import { FeedStoreState } from "./types";
|
|
7
|
+
import { deduplicateItems, sortItems } from "./utils";
|
|
8
|
+
|
|
9
|
+
function processItems(items: FeedItem[]) {
|
|
10
|
+
const deduped = deduplicateItems(items);
|
|
11
|
+
const sorted = sortItems(deduped);
|
|
12
|
+
|
|
13
|
+
return sorted;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const defaultSetResultOptions = {
|
|
17
|
+
shouldSetPage: true,
|
|
18
|
+
shouldAppend: false,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const initialStoreState = {
|
|
22
|
+
items: [],
|
|
23
|
+
metadata: {
|
|
24
|
+
total_count: 0,
|
|
25
|
+
unread_count: 0,
|
|
26
|
+
unseen_count: 0,
|
|
27
|
+
},
|
|
28
|
+
pageInfo: {
|
|
29
|
+
before: null,
|
|
30
|
+
after: null,
|
|
31
|
+
page_size: 50,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export default function createStore() {
|
|
36
|
+
return create<FeedStoreState>((set) => ({
|
|
37
|
+
// Keeps track of all of the items loaded
|
|
38
|
+
...initialStoreState,
|
|
39
|
+
// The network status indicates what's happening with the request
|
|
40
|
+
networkStatus: NetworkStatus.ready,
|
|
41
|
+
loading: false,
|
|
42
|
+
|
|
43
|
+
setNetworkStatus: (networkStatus: NetworkStatus) =>
|
|
44
|
+
set(() => ({
|
|
45
|
+
networkStatus,
|
|
46
|
+
loading: networkStatus === NetworkStatus.loading,
|
|
47
|
+
})),
|
|
48
|
+
|
|
49
|
+
setResult: (
|
|
50
|
+
{ entries, meta, page_info },
|
|
51
|
+
options = defaultSetResultOptions,
|
|
52
|
+
) =>
|
|
53
|
+
set((state) => {
|
|
54
|
+
// We resort the list on set, so concating everything is fine (if a bit suboptimal)
|
|
55
|
+
const items = options.shouldAppend
|
|
56
|
+
? processItems(state.items.concat(entries))
|
|
57
|
+
: entries;
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
items,
|
|
61
|
+
metadata: meta,
|
|
62
|
+
pageInfo: options.shouldSetPage ? page_info : state.pageInfo,
|
|
63
|
+
loading: false,
|
|
64
|
+
networkStatus: NetworkStatus.ready,
|
|
65
|
+
};
|
|
66
|
+
}),
|
|
67
|
+
|
|
68
|
+
setMetadata: (metadata) => set(() => ({ metadata })),
|
|
69
|
+
|
|
70
|
+
resetStore: (metadata = initialStoreState.metadata) =>
|
|
71
|
+
set(() => ({ ...initialStoreState, metadata })),
|
|
72
|
+
|
|
73
|
+
setItemAttrs: (itemIds, attrs) => {
|
|
74
|
+
// Create a map for the items to the updates to be made
|
|
75
|
+
const itemUpdatesMap: { [id: string]: object } = itemIds.reduce(
|
|
76
|
+
(acc, itemId) => ({ ...acc, [itemId]: attrs }),
|
|
77
|
+
{},
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return set((state) => {
|
|
81
|
+
const items = state.items.map((item) => {
|
|
82
|
+
if (itemUpdatesMap[item.id]) {
|
|
83
|
+
return { ...item, ...itemUpdatesMap[item.id] };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return item;
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return { items };
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { PageInfo } from "@knocklabs/types";
|
|
2
|
+
|
|
3
|
+
import { NetworkStatus } from "../../networkStatus";
|
|
4
|
+
|
|
5
|
+
import { FeedItem, FeedMetadata, FeedResponse } from "./interfaces";
|
|
6
|
+
|
|
7
|
+
export type StoreFeedResultOptions = {
|
|
8
|
+
shouldSetPage?: boolean;
|
|
9
|
+
shouldAppend?: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type FeedStoreState = {
|
|
13
|
+
items: FeedItem[];
|
|
14
|
+
pageInfo: PageInfo;
|
|
15
|
+
metadata: FeedMetadata;
|
|
16
|
+
loading: boolean;
|
|
17
|
+
networkStatus: NetworkStatus;
|
|
18
|
+
setResult: (response: FeedResponse, opts?: StoreFeedResultOptions) => void;
|
|
19
|
+
setMetadata: (metadata: FeedMetadata) => void;
|
|
20
|
+
setNetworkStatus: (networkStatus: NetworkStatus) => void;
|
|
21
|
+
setItemAttrs: (itemIds: string[], attrs: object) => void;
|
|
22
|
+
resetStore: (metadata?: FeedMetadata) => void;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type FeedMessagesReceivedPayload = {
|
|
26
|
+
metadata: FeedMetadata;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/*
|
|
30
|
+
Event types:
|
|
31
|
+
- `messages.new`: legacy event fired for all messages (feed items) received, real-time or not
|
|
32
|
+
- `items.received.realtime`: all real-time items received via a socket update
|
|
33
|
+
- `items.received.page`: invoked every time a page is fetched (like on initial load)
|
|
34
|
+
*/
|
|
35
|
+
export type FeedRealTimeEvent = "messages.new";
|
|
36
|
+
|
|
37
|
+
export type FeedEvent =
|
|
38
|
+
| FeedRealTimeEvent
|
|
39
|
+
| "items.received.page"
|
|
40
|
+
| "items.received.realtime"
|
|
41
|
+
| "items.archived"
|
|
42
|
+
| "items.unarchived"
|
|
43
|
+
| "items.seen"
|
|
44
|
+
| "items.unseen"
|
|
45
|
+
| "items.read"
|
|
46
|
+
| "items.unread"
|
|
47
|
+
| "items.all_archived"
|
|
48
|
+
| "items.all_read"
|
|
49
|
+
| "items.all_seen";
|
|
50
|
+
|
|
51
|
+
// Because we can bind to wild card feed events, this is here to accomodate whatever can be bound to
|
|
52
|
+
export type BindableFeedEvent = FeedEvent | "items.received.*" | "items.*";
|
|
53
|
+
|
|
54
|
+
export type FeedEventPayload = {
|
|
55
|
+
event: Omit<FeedEvent, "messages.new">;
|
|
56
|
+
items: FeedItem[];
|
|
57
|
+
metadata: FeedMetadata;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export type FeedRealTimeCallback = (resp: FeedResponse) => void;
|
|
61
|
+
|
|
62
|
+
export type FeedEventCallback = (payload: FeedEventPayload) => void;
|
|
63
|
+
|
|
64
|
+
export type FeedItemOrItems = FeedItem | FeedItem[];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { FeedItem } from "./interfaces";
|
|
2
|
+
|
|
3
|
+
export function deduplicateItems(items: FeedItem[]): FeedItem[] {
|
|
4
|
+
const seen: Record<string, boolean> = {};
|
|
5
|
+
const values: FeedItem[] = [];
|
|
6
|
+
|
|
7
|
+
return items.reduce((acc, item) => {
|
|
8
|
+
if (seen[item.id]) {
|
|
9
|
+
return acc;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
seen[item.id] = true;
|
|
13
|
+
return [...acc, item];
|
|
14
|
+
}, values);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function sortItems(items: FeedItem[]) {
|
|
18
|
+
return items.sort((a, b) => {
|
|
19
|
+
return (
|
|
20
|
+
new Date(b.inserted_at).getTime() - new Date(a.inserted_at).getTime()
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const TENANT_OBJECT_COLLECTION = "$tenants";
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { ApiResponse } from "../../api";
|
|
2
|
+
import { ChannelData } from "../../interfaces";
|
|
3
|
+
import Knock from "../../knock";
|
|
4
|
+
|
|
5
|
+
type GetChannelDataInput = {
|
|
6
|
+
objectId: string;
|
|
7
|
+
collection: string;
|
|
8
|
+
channelId: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type SetChannelDataInput = {
|
|
12
|
+
objectId: string;
|
|
13
|
+
collection: string;
|
|
14
|
+
channelId: string;
|
|
15
|
+
data: any;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
class ObjectClient {
|
|
19
|
+
private instance: Knock;
|
|
20
|
+
|
|
21
|
+
constructor(instance: Knock) {
|
|
22
|
+
this.instance = instance;
|
|
23
|
+
}
|
|
24
|
+
async getChannelData<T = any>({
|
|
25
|
+
collection,
|
|
26
|
+
objectId,
|
|
27
|
+
channelId,
|
|
28
|
+
}: GetChannelDataInput) {
|
|
29
|
+
const result = await this.instance.client().makeRequest({
|
|
30
|
+
method: "GET",
|
|
31
|
+
url: `/v1/objects/${collection}/${objectId}/channel_data/${channelId}`,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return this.handleResponse<ChannelData<T>>(result);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async setChannelData({
|
|
38
|
+
objectId,
|
|
39
|
+
collection,
|
|
40
|
+
channelId,
|
|
41
|
+
data,
|
|
42
|
+
}: SetChannelDataInput) {
|
|
43
|
+
const result = await this.instance.client().makeRequest({
|
|
44
|
+
method: "PUT",
|
|
45
|
+
url: `v1/objects/${collection}/${objectId}/channel_data/${channelId}`,
|
|
46
|
+
data: { data },
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return this.handleResponse(result);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private handleResponse<T>(response: ApiResponse) {
|
|
53
|
+
if (response.statusCode === "error") {
|
|
54
|
+
throw new Error(response.error || response.body);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return response.body as T;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default ObjectClient;
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { ChannelType } from "@knocklabs/types";
|
|
2
|
+
import { ApiResponse } from "../../api";
|
|
3
|
+
import Knock from "../../knock";
|
|
4
|
+
import {
|
|
5
|
+
ChannelTypePreferences,
|
|
6
|
+
PreferenceOptions,
|
|
7
|
+
SetPreferencesProperties,
|
|
8
|
+
WorkflowPreferenceSetting,
|
|
9
|
+
WorkflowPreferences,
|
|
10
|
+
PreferenceSet,
|
|
11
|
+
} from "./interfaces";
|
|
12
|
+
|
|
13
|
+
const DEFAULT_PREFERENCE_SET_ID = "default";
|
|
14
|
+
|
|
15
|
+
function buildUpdateParam(param: WorkflowPreferenceSetting) {
|
|
16
|
+
if (typeof param === "object") {
|
|
17
|
+
return param;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return { subscribed: param };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class Preferences {
|
|
24
|
+
private instance: Knock;
|
|
25
|
+
|
|
26
|
+
constructor(instance: Knock) {
|
|
27
|
+
this.instance = instance;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated Use `user.getAllPreferences()` instead
|
|
32
|
+
*/
|
|
33
|
+
async getAll() {
|
|
34
|
+
const result = await this.instance.client().makeRequest({
|
|
35
|
+
method: "GET",
|
|
36
|
+
url: `/v1/users/${this.instance.userId}/preferences`,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return this.handleResponse(result);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @deprecated Use `user.getPreferences()` instead
|
|
44
|
+
*/
|
|
45
|
+
async get(options: PreferenceOptions = {}) {
|
|
46
|
+
const preferenceSetId = options.preferenceSet || DEFAULT_PREFERENCE_SET_ID;
|
|
47
|
+
|
|
48
|
+
const result = await this.instance.client().makeRequest({
|
|
49
|
+
method: "GET",
|
|
50
|
+
url: `/v1/users/${this.instance.userId}/preferences/${preferenceSetId}`,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return this.handleResponse(result);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @deprecated Use `user.setPreferences(preferenceSet, options)` instead
|
|
58
|
+
*/
|
|
59
|
+
async set(
|
|
60
|
+
preferenceSet: SetPreferencesProperties,
|
|
61
|
+
options: PreferenceOptions = {},
|
|
62
|
+
) {
|
|
63
|
+
const preferenceSetId = options.preferenceSet || DEFAULT_PREFERENCE_SET_ID;
|
|
64
|
+
|
|
65
|
+
const result = await this.instance.client().makeRequest({
|
|
66
|
+
method: "PUT",
|
|
67
|
+
url: `/v1/users/${this.instance.userId}/preferences/${preferenceSetId}`,
|
|
68
|
+
data: preferenceSet,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return this.handleResponse(result);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @deprecated Use `user.setPreferences(preferenceSet, options)` instead
|
|
76
|
+
*/
|
|
77
|
+
async setChannelTypes(
|
|
78
|
+
channelTypePreferences: ChannelTypePreferences,
|
|
79
|
+
options: PreferenceOptions = {},
|
|
80
|
+
) {
|
|
81
|
+
const preferenceSetId = options.preferenceSet || DEFAULT_PREFERENCE_SET_ID;
|
|
82
|
+
|
|
83
|
+
const result = await this.instance.client().makeRequest({
|
|
84
|
+
method: "PUT",
|
|
85
|
+
url: `/v1/users/${this.instance.userId}/preferences/${preferenceSetId}/channel_types`,
|
|
86
|
+
data: channelTypePreferences,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return this.handleResponse(result);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @deprecated Use `user.setPreferences(preferenceSet, options)` instead
|
|
94
|
+
*/
|
|
95
|
+
async setChannelType(
|
|
96
|
+
channelType: ChannelType,
|
|
97
|
+
setting: boolean,
|
|
98
|
+
options: PreferenceOptions = {},
|
|
99
|
+
) {
|
|
100
|
+
const preferenceSetId = options.preferenceSet || DEFAULT_PREFERENCE_SET_ID;
|
|
101
|
+
|
|
102
|
+
const result = await this.instance.client().makeRequest({
|
|
103
|
+
method: "PUT",
|
|
104
|
+
url: `/v1/users/${this.instance.userId}/preferences/${preferenceSetId}/channel_types/${channelType}`,
|
|
105
|
+
data: { subscribed: setting },
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
return this.handleResponse(result);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @deprecated Use `user.setPreferences(preferenceSet, options)` instead
|
|
113
|
+
*/
|
|
114
|
+
async setWorkflows(
|
|
115
|
+
workflowPreferences: WorkflowPreferences,
|
|
116
|
+
options: PreferenceOptions = {},
|
|
117
|
+
) {
|
|
118
|
+
const preferenceSetId = options.preferenceSet || DEFAULT_PREFERENCE_SET_ID;
|
|
119
|
+
|
|
120
|
+
const result = await this.instance.client().makeRequest({
|
|
121
|
+
method: "PUT",
|
|
122
|
+
url: `/v1/users/${this.instance.userId}/preferences/${preferenceSetId}/workflows`,
|
|
123
|
+
data: workflowPreferences,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
return this.handleResponse(result);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @deprecated Use `user.setPreferences(preferenceSet, options)` instead
|
|
131
|
+
*/
|
|
132
|
+
async setWorkflow(
|
|
133
|
+
workflowKey: string,
|
|
134
|
+
setting: WorkflowPreferenceSetting,
|
|
135
|
+
options: PreferenceOptions = {},
|
|
136
|
+
) {
|
|
137
|
+
const preferenceSetId = options.preferenceSet || DEFAULT_PREFERENCE_SET_ID;
|
|
138
|
+
const params = buildUpdateParam(setting);
|
|
139
|
+
|
|
140
|
+
const result = await this.instance.client().makeRequest({
|
|
141
|
+
method: "PUT",
|
|
142
|
+
url: `/v1/users/${this.instance.userId}/preferences/${preferenceSetId}/workflows/${workflowKey}`,
|
|
143
|
+
data: params,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
return this.handleResponse(result);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @deprecated Use `user.setPreferences(preferenceSet, options)` instead
|
|
151
|
+
*/
|
|
152
|
+
async setCategories(
|
|
153
|
+
categoryPreferences: WorkflowPreferences,
|
|
154
|
+
options: PreferenceOptions = {},
|
|
155
|
+
) {
|
|
156
|
+
const preferenceSetId = options.preferenceSet || DEFAULT_PREFERENCE_SET_ID;
|
|
157
|
+
|
|
158
|
+
const result = await this.instance.client().makeRequest({
|
|
159
|
+
method: "PUT",
|
|
160
|
+
url: `/v1/users/${this.instance.userId}/preferences/${preferenceSetId}/categories`,
|
|
161
|
+
data: categoryPreferences,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
return this.handleResponse(result);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @deprecated Use `user.setPreferences(preferenceSet, options)` instead
|
|
169
|
+
*/
|
|
170
|
+
async setCategory(
|
|
171
|
+
categoryKey: string,
|
|
172
|
+
setting: WorkflowPreferenceSetting,
|
|
173
|
+
options: PreferenceOptions = {},
|
|
174
|
+
) {
|
|
175
|
+
const preferenceSetId = options.preferenceSet || DEFAULT_PREFERENCE_SET_ID;
|
|
176
|
+
const params = buildUpdateParam(setting);
|
|
177
|
+
|
|
178
|
+
const result = await this.instance.client().makeRequest({
|
|
179
|
+
method: "PUT",
|
|
180
|
+
url: `/v1/users/${this.instance.userId}/preferences/${preferenceSetId}/categories/${categoryKey}`,
|
|
181
|
+
data: params,
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
return this.handleResponse(result);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private handleResponse(response: ApiResponse) {
|
|
188
|
+
if (response.statusCode === "error") {
|
|
189
|
+
throw new Error(response.error || response.body);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return response.body as PreferenceSet;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export default Preferences;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ChannelType } from "@knocklabs/types";
|
|
2
|
+
|
|
3
|
+
export type ChannelTypePreferences = {
|
|
4
|
+
[K in ChannelType]?: boolean;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type WorkflowPreferenceSetting =
|
|
8
|
+
| boolean
|
|
9
|
+
| { channel_types: ChannelTypePreferences };
|
|
10
|
+
|
|
11
|
+
export type WorkflowPreferences = Partial<
|
|
12
|
+
Record<string, WorkflowPreferenceSetting>
|
|
13
|
+
>;
|
|
14
|
+
|
|
15
|
+
export interface SetPreferencesProperties {
|
|
16
|
+
workflows: WorkflowPreferences;
|
|
17
|
+
categories: WorkflowPreferences;
|
|
18
|
+
channel_types: ChannelTypePreferences;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface PreferenceSet {
|
|
22
|
+
id: string;
|
|
23
|
+
categories: WorkflowPreferences;
|
|
24
|
+
workflows: WorkflowPreferences;
|
|
25
|
+
channel_types: ChannelTypePreferences;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface PreferenceOptions {
|
|
29
|
+
preferenceSet?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface GetPreferencesOptions extends PreferenceOptions {
|
|
33
|
+
tenant?: string;
|
|
34
|
+
}
|