-
Notifications
You must be signed in to change notification settings - Fork 24
/
messages-uri.ts
290 lines (242 loc) · 8.93 KB
/
messages-uri.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
import { Incident } from "incident";
import { posix } from "path";
import { parse as parseUri, resolve as resolveUri, Url } from "url";
export const DEFAULT_USER: string = "ME";
export const DEFAULT_ENDPOINT: string = "SELF";
const CONVERSATION_PATTERN: RegExp = /^\/v1\/users\/([^/]+)\/conversations\/([^/]+)$/;
const CONTACT_PATTERN: RegExp = /^\/v1\/users\/([^/]+)\/contacts\/([^/]+)$/;
const MESSAGES_PATTERN: RegExp = /^\/v1\/users\/([^/]+)\/conversations\/([^/]+)\/messages$/;
const MESSAGE_PATTERN: RegExp = /^\/v1\/users\/([^/]+)\/conversations\/([^/]+)\/messages\/([^/]+)$/;
function joinPath(parts: string[]): string {
return posix.join.apply(null, parts);
}
// The following functions build an array of parts to build the path
// /v1
function buildV1(): string[] {
return ["v1"];
}
// /v1/threads
function buildThreads(): string[] {
return buildV1().concat("threads");
}
// /v1/threads/{thread}
function buildThread(thread: string): string[] {
return buildThreads().concat(thread);
}
// /v1/users
function buildUsers(): string[] {
return buildV1().concat("users");
}
// /v1/users/{user}
function buildUser(user: string): string[] {
return buildUsers().concat(user);
}
// /v1/users/{user}/endpoints
function buildEndpoints(user: string): string[] {
return buildUser(user).concat("endpoints");
}
// /v1/users/{user}/endpoints/{endpoint}
function buildEndpoint(user: string, endpoint: string): string[] {
return buildEndpoints(user).concat(endpoint);
}
// /v1/users/{user}/endpoints/{endpoint}/subscriptions
function buildSubscriptions(user: string, endpoint: string): string[] {
return buildEndpoint(user, endpoint).concat("subscriptions");
}
// /v1/users/{user}/endpoints/{endpoint}/subscriptions/{subscription}
function buildSubscription(user: string, endpoint: string, subscription: number): string[] {
return buildSubscriptions(user, endpoint).concat(String(subscription));
}
// /v1/users/{user}/endpoints/{endpoint}/subscriptions/{subscription}/poll
function buildPoll(user: string, endpoint: string, subscription: number): string[] {
return buildSubscription(user, endpoint, subscription).concat("poll");
}
// /v1/users/{user}/endpoints/{endpoint}/presenceDocs
function buildEndpointPresenceDocs(user: string, endpoint: string): string[] {
return buildEndpoint(user, endpoint).concat("presenceDocs");
}
// /v1/users/{user}/endpoints/{endpoint}/presenceDocs/endpointMessagingService
function buildEndpointMessagingService(user: string, endpoint: string): string[] {
return buildEndpointPresenceDocs(user, endpoint).concat("endpointMessagingService");
}
// /v1/users/{user}/conversations
function buildConversations(user: string): string[] {
return buildUser(user).concat("conversations");
}
// /v1/users/{user}/conversations/{conversation}
function buildConversation(user: string, conversation: string): string[] {
return buildConversations(user).concat(conversation);
}
// /v1/users/{user}/conversations/{conversation}/messages
function buildMessages(user: string, conversation: string): string[] {
return buildConversation(user, conversation).concat("messages");
}
// /v1/users/{user}/presenceDocs
function buildUserPresenceDocs(user: string): string[] {
return buildUser(user).concat("presenceDocs");
}
// /v1/users/{user}/presenceDocs/endpointMessagingService
function buildUserMessagingService(user: string): string[] {
return buildUserPresenceDocs(user).concat("endpointMessagingService");
}
// /v1/objects
function buildObjects(): string[] {
return buildV1().concat("objects");
}
// /v1/objects/{objectId}
function buildObject(objectId: string) {
return buildObjects().concat(objectId);
}
// /v1/objects/{objectId}/content/{content}
function buildObjectContent(objectId: string, content: string) {
return buildObject(objectId).concat("content").concat(content);
}
// /v1/objects/{objectId}/view/{content}
function buildObjectView(objectId: string, view: string) {
return buildObject(objectId).concat("view").concat(view);
}
/**
* Returns an URI origin like: "https://host.com"
* If host is `null`, returns an empty string
*/
function getOrigin(host: string): string {
return host === null ? "" : "https://" + host;
}
function get(host: string, path: string) {
return resolveUri(getOrigin(host), path);
}
export function thread(host: string, threadId: string): string {
return get(host, joinPath(buildThread(threadId)));
}
export function users(host: string): string {
return get(host, joinPath(buildUsers()));
}
export function user(host: string, userId: string = DEFAULT_USER): string {
return get(host, joinPath(buildUser(userId)));
}
/**
* Build the URI for the endpoints of a user.
*
* Template: `https://{host}/v1/users/{userId}/endpoints`
*
* @param host Hostname of the messages server.
* @param userId Id of the user. Default: `"ME"`.
* @return Formatted URI.
*/
export function endpoints(host: string, userId: string = DEFAULT_USER): string {
return get(host, joinPath(buildEndpoints(userId)));
}
export function endpoint(host: string, userId: string = DEFAULT_USER,
endpointId: string = DEFAULT_ENDPOINT): string {
return get(host, joinPath(buildEndpoint(userId, endpointId)));
}
export function poll(host: string, userId: string = DEFAULT_USER,
endpointId: string = DEFAULT_ENDPOINT, subscriptionId: number = 0): string {
return get(host, joinPath(buildPoll(userId, endpointId, subscriptionId)));
}
/**
* Returns https://{host}/v1/users/{userId}/endpoints/{endpointId}/subscriptions
* @param host
* @param userId
* @param endpointId
*/
export function subscriptions(host: string, userId: string = DEFAULT_USER,
endpointId: string = DEFAULT_ENDPOINT): string {
return get(host, joinPath(buildSubscriptions(userId, endpointId)));
}
export function conversations(host: string, user: string): string {
return get(host, joinPath(buildConversations(user)));
}
export function conversation(host: string, user: string, conversationId: string): string {
return get(host, joinPath(buildConversation(user, conversationId)));
}
/**
* Returns https://{host}/v1/users/{user}/conversations/{conversationId}/messages
* @param host
* @param user
* @param conversationId
*/
export function messages(host: string, user: string, conversationId: string): string {
return get(host, joinPath(buildMessages(user, conversationId)));
}
export function objects(host: string): string {
return get(host, joinPath(buildObjects()));
}
export function object(host: string, objectId: string): string {
return get(host, joinPath(buildObject(objectId)));
}
export function objectContent(host: string, objectId: string, content: string): string {
return get(host, joinPath(buildObjectContent(objectId, content)));
}
export function objectView(host: string, objectId: string, view: string): string {
return get(host, joinPath(buildObjectView(objectId, view)));
}
export function userMessagingService(host: string, user: string = DEFAULT_USER): string {
return get(host, joinPath(buildUserMessagingService(user)));
}
export function endpointMessagingService(host: string, user: string = DEFAULT_USER,
endpoint: string = DEFAULT_ENDPOINT): string {
return get(host, joinPath(buildEndpointMessagingService(user, endpoint)));
}
export interface MessageUri {
host: string;
user: string;
conversation: string;
message: string;
}
export function parseMessage(uri: string): MessageUri {
const parsed: Url = parseUri(uri);
if (parsed.host === undefined || parsed.pathname === undefined) {
throw new Incident("parse-error", "Expected URI to have a host and path");
}
const match: RegExpExecArray | null = MESSAGE_PATTERN.exec(parsed.pathname);
if (match === null) {
throw new Incident("parse-error", "Expected URI to be a message uri");
}
return {
host: parsed.host,
user: match[1],
conversation: match[2],
message: match[3],
};
}
export interface ContactUri {
host: string;
user: string;
contact: string;
}
export function parseContact(uri: string): ContactUri {
const parsed: Url = parseUri(uri);
if (parsed.host === undefined || parsed.pathname === undefined) {
throw new Incident("parse-error", "Expected URI to have a host and path");
}
const match: RegExpExecArray | null = CONTACT_PATTERN.exec(parsed.pathname);
if (match === null) {
throw new Incident("parse-error", "Expected URI to be a conversation uri");
}
return {
host: parsed.host,
user: match[1],
contact: match[2],
};
}
export interface ConversationUri {
host: string;
user: string;
conversation: string;
}
export function parseConversation(uri: string): ConversationUri {
const parsed: Url = parseUri(uri);
if (parsed.host === undefined || parsed.pathname === undefined) {
throw new Incident("parse-error", "Expected URI to have a host and path");
}
const match: RegExpExecArray | null = CONVERSATION_PATTERN.exec(parsed.pathname);
if (match === null) {
throw new Incident("parse-error", "Expected URI to be a conversation uri");
}
return {
host: parsed.host,
user: match[1],
conversation: match[2],
};
}