microsoft-graph-client 1.0.33 → 1.0.34
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/dist/api/chats.d.ts +134 -3
- package/dist/api/chats.d.ts.map +1 -1
- package/dist/api/chats.js +181 -15
- package/dist/api/chats.js.map +1 -1
- package/dist/api/messages.d.ts +122 -3
- package/dist/api/messages.d.ts.map +1 -1
- package/dist/api/messages.js +209 -44
- package/dist/api/messages.js.map +1 -1
- package/dist/types/chat.d.ts +37 -0
- package/dist/types/chat.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/message.d.ts +113 -8
- package/dist/types/message.d.ts.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/odata.d.ts +59 -8
- package/dist/utils/odata.d.ts.map +1 -1
- package/dist/utils/odata.js +64 -9
- package/dist/utils/odata.js.map +1 -1
- package/package.json +1 -1
package/dist/api/chats.d.ts
CHANGED
|
@@ -1,21 +1,152 @@
|
|
|
1
1
|
import { BaseApi } from './base.js';
|
|
2
|
-
import type { AddChatMemberParams, Chat, CreateChatParams, GetChatParams, ListChatsParams, ListChatsResult, RemoveChatMemberParams, UpdateChatParams } from '../types/index.js';
|
|
2
|
+
import type { AddChatMemberParams, Chat, CreateChatParams, FindDmParams, GetChatParams, ListChatsParams, ListChatsResult, RemoveChatMemberParams, UpdateChatParams } from '../types/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* API for chat operations.
|
|
5
|
+
*
|
|
6
|
+
* Microsoft Graph's `/me/chats` is unusually limited compared to other Graph
|
|
7
|
+
* resources. Several quirks documented below shape every method here:
|
|
8
|
+
*
|
|
9
|
+
* - **`$top` is hard-capped at 50.** Values above 50 return HTTP 400.
|
|
10
|
+
* Source: https://learn.microsoft.com/en-us/graph/api/chat-list (Optional
|
|
11
|
+
* query parameters table).
|
|
12
|
+
*
|
|
13
|
+
* - **All `$filter` predicates are post-filtered, not indexed lookups.**
|
|
14
|
+
* Graph applies `$filter` AFTER taking the next `$top` chats from the
|
|
15
|
+
* recency-ordered chat list. So a single page returns "matches found
|
|
16
|
+
* within the next 50 chats by recency", and `@odata.nextLink` advances
|
|
17
|
+
* the scan window. Even `chatType eq 'oneOnOne'` behaves this way:
|
|
18
|
+
* measured `$top=5 → 2 matches`, `$top=50 → 13 matches`. This means you
|
|
19
|
+
* cannot rely on `$filter` to find old chats without paginating.
|
|
20
|
+
* Confirmed by Microsoft on
|
|
21
|
+
* https://learn.microsoft.com/en-us/answers/questions/1660492 :
|
|
22
|
+
* "the API selects top records first and then applies the given filter".
|
|
23
|
+
*
|
|
24
|
+
* - **`$orderby` only accepts ONE value:**
|
|
25
|
+
* `lastMessagePreview/createdDateTime desc`. Ascending order is rejected,
|
|
26
|
+
* every other field (`lastUpdatedDateTime`, `createdDateTime`, `topic`,
|
|
27
|
+
* `chatType`, `id`) is rejected. WITHOUT explicit `$orderby` the default
|
|
28
|
+
* order is approximately recency-based but has many monotonicity
|
|
29
|
+
* violations (verified empirically). Always pass `$orderby` if you care
|
|
30
|
+
* about ordering.
|
|
31
|
+
*
|
|
32
|
+
* - **`members/any(o: contains(tolower(o/displayname), 'X')) + chatType eq
|
|
33
|
+
* 'oneOnOne'` returns 0 results.** This is a Graph bug specific to the
|
|
34
|
+
* displayName predicate. Combining `memberUserId` (the `userId eq …` form)
|
|
35
|
+
* with `chatType eq 'oneOnOne'` works correctly. Use `memberUserId` if
|
|
36
|
+
* you have an AAD ID; resolve names to IDs first.
|
|
37
|
+
*
|
|
38
|
+
* - **`$expand=members` silently truncates at 25 members per chat,**
|
|
39
|
+
* regardless of `$top`. The server still evaluates `members/any()` against
|
|
40
|
+
* the full membership list, but the returned `members` array is capped.
|
|
41
|
+
* Documented as a "known issue" on the official chat-list page.
|
|
42
|
+
*
|
|
43
|
+
* - **`$search` is not allowed** on `/me/chats`.
|
|
44
|
+
* - **`$count=true` is not allowed** on `/me/chats`.
|
|
45
|
+
*
|
|
46
|
+
* For deep background and all the empirical measurements, see
|
|
47
|
+
* `packages/clis/msgraph-cli/CHAT_SEARCH_INVESTIGATION.md` in this repo.
|
|
5
48
|
*/
|
|
6
49
|
export declare class ChatsApi extends BaseApi {
|
|
7
50
|
/**
|
|
8
51
|
* Get a chat by ID with members expanded.
|
|
52
|
+
*
|
|
53
|
+
* Note: due to the documented `$expand=members` 25-cap, the `members` array
|
|
54
|
+
* may be incomplete for chats with more than 25 members. The server
|
|
55
|
+
* correctly counts all members for filter evaluation, but the response is
|
|
56
|
+
* truncated.
|
|
9
57
|
*/
|
|
10
58
|
get(params: GetChatParams): Promise<Chat>;
|
|
59
|
+
/**
|
|
60
|
+
* Find the 1:1 chat between the signed-in user and another user.
|
|
61
|
+
*
|
|
62
|
+
* Why this exists as a primitive: Microsoft Graph has no `/me/chats/with/
|
|
63
|
+
* {userId}` endpoint, and the obvious workaround
|
|
64
|
+
* (`/me/chats?$filter=members/any(...) and chatType eq 'oneOnOne'`) is
|
|
65
|
+
* subject to the recency-window post-filter described in the class doc —
|
|
66
|
+
* older 1:1 chats are unreachable without paginating the entire chat list.
|
|
67
|
+
*
|
|
68
|
+
* Workaround: 1:1 chat IDs follow the deterministic format
|
|
69
|
+
*
|
|
70
|
+
* 19:{userA-guid}_{userB-guid}@unq.gbl.spaces
|
|
71
|
+
*
|
|
72
|
+
* but the order of the two GUIDs is **not** deterministic. Verified
|
|
73
|
+
* empirically against ~12 1:1 chats in an active account: about 75% have
|
|
74
|
+
* the signed-in user's GUID first, the rest have the other user's GUID
|
|
75
|
+
* first. The order likely depends on who initiated the conversation, but
|
|
76
|
+
* we can't tell without trying.
|
|
77
|
+
*
|
|
78
|
+
* So we issue both candidate URLs in parallel. Exactly one returns 200,
|
|
79
|
+
* the other returns 404. Round-trip latency is ~250-700ms total because
|
|
80
|
+
* the calls go in parallel.
|
|
81
|
+
*
|
|
82
|
+
* **This sidesteps `/me/chats` entirely.** It works for any 1:1 chat
|
|
83
|
+
* regardless of how long ago the last message was sent — there is no
|
|
84
|
+
* recency window. It is also strictly read-only with no side effects on
|
|
85
|
+
* Teams (unlike `POST /chats` which would create a new thread if the
|
|
86
|
+
* chat didn't already exist).
|
|
87
|
+
*
|
|
88
|
+
* Returns the existing 1:1 chat, or `null` if no DM exists between the
|
|
89
|
+
* signed-in user and the target user.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* const chat = await client.chats.findDmByUserId({ userId: 'de720d1a-...' });
|
|
93
|
+
* if (chat) console.log(`DM exists: ${chat.id}`);
|
|
94
|
+
* else console.log('No DM with this user yet');
|
|
95
|
+
*/
|
|
96
|
+
findDmByUserId(params: FindDmParams): Promise<Chat | null>;
|
|
11
97
|
/**
|
|
12
98
|
* List chats for the current user.
|
|
13
|
-
*
|
|
14
|
-
* Returns a single page of
|
|
99
|
+
*
|
|
100
|
+
* Builds an OData query from the typed params. Returns a single page of
|
|
101
|
+
* results with `nextLink` for caller-driven pagination — this method does
|
|
102
|
+
* NOT loop through pages.
|
|
103
|
+
*
|
|
104
|
+
* **Important caveats** (see also the class-level doc above):
|
|
105
|
+
*
|
|
106
|
+
* - Filters are post-filtered by Graph against a recency window of
|
|
107
|
+
* `$top` chats. Pagination via `nextLink` advances the window forward.
|
|
108
|
+
* A single page returns `0..top` matches. Pagination ends only when
|
|
109
|
+
* the window has scanned every chat the user has — for power users
|
|
110
|
+
* that may be 50+ pages.
|
|
111
|
+
*
|
|
112
|
+
* - Always pass `orderByLastMessage: true` for monotonic recency order.
|
|
113
|
+
* The default order has gaps and violations.
|
|
114
|
+
*
|
|
115
|
+
* - For finding 1:1 chats with a specific person, prefer
|
|
116
|
+
* {@link findDmByUserId} which sidesteps this whole mess.
|
|
117
|
+
*
|
|
118
|
+
* - For combining a member predicate with `chatType eq 'oneOnOne'`, use
|
|
119
|
+
* the `memberUserId` param (not `memberName` / `memberEmail`) — the
|
|
120
|
+
* displayName form hits a known Graph bug.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* // Active named chats with "morning" in the topic, recency-sorted:
|
|
124
|
+
* const result = await client.chats.list({
|
|
125
|
+
* searchTerm: 'morning',
|
|
126
|
+
* orderByLastMessage: true,
|
|
127
|
+
* top: 50,
|
|
128
|
+
* });
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* // Group/meeting chats containing a specific user, recency-sorted:
|
|
132
|
+
* const result = await client.chats.list({
|
|
133
|
+
* memberUserId: '0379926e-96c3-4c2a-800e-45d1b2a9b06c',
|
|
134
|
+
* chatTypes: ['group', 'meeting'],
|
|
135
|
+
* orderByLastMessage: true,
|
|
136
|
+
* top: 50,
|
|
137
|
+
* });
|
|
15
138
|
*/
|
|
16
139
|
list(params?: ListChatsParams): Promise<ListChatsResult>;
|
|
17
140
|
/**
|
|
18
141
|
* Create a new chat (1:1 or group).
|
|
142
|
+
*
|
|
143
|
+
* For 1:1 chats, Microsoft documents that "if a one-on-one chat already
|
|
144
|
+
* exists between the specified members, the existing chat is returned
|
|
145
|
+
* instead of creating a new one." However we still treat this as a
|
|
146
|
+
* write operation because (a) it has visible side effects on the Teams
|
|
147
|
+
* UI when the chat doesn't exist, and (b) the dedup behavior isn't
|
|
148
|
+
* something we want to rely on for read paths. For "find an existing
|
|
149
|
+
* 1:1", use {@link findDmByUserId} instead.
|
|
19
150
|
*/
|
|
20
151
|
create(params: CreateChatParams): Promise<Chat>;
|
|
21
152
|
/**
|
package/dist/api/chats.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chats.d.ts","sourceRoot":"","sources":["../../src/api/chats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EACV,mBAAmB,EACnB,IAAI,EACJ,gBAAgB,EAChB,aAAa,EAEb,eAAe,EACf,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAE3B
|
|
1
|
+
{"version":3,"file":"chats.d.ts","sourceRoot":"","sources":["../../src/api/chats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EACV,mBAAmB,EACnB,IAAI,EACJ,gBAAgB,EAChB,YAAY,EACZ,aAAa,EAEb,eAAe,EACf,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,qBAAa,QAAS,SAAQ,OAAO;IACnC;;;;;;;OAOG;IACU,GAAG,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoCG;IACU,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAoBvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAyCG;IACU,IAAI,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IA6ErE;;;;;;;;;;OAUG;IACU,MAAM,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5D;;OAEG;IACU,WAAW,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE;;OAEG;IACU,SAAS,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUlE;;OAEG;IACU,YAAY,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;CAGzE"}
|
package/dist/api/chats.js
CHANGED
|
@@ -1,53 +1,211 @@
|
|
|
1
1
|
import { BaseApi } from './base.js';
|
|
2
|
-
import {
|
|
2
|
+
import { odataFilterValue } from '../utils/odata.js';
|
|
3
3
|
/**
|
|
4
4
|
* API for chat operations.
|
|
5
|
+
*
|
|
6
|
+
* Microsoft Graph's `/me/chats` is unusually limited compared to other Graph
|
|
7
|
+
* resources. Several quirks documented below shape every method here:
|
|
8
|
+
*
|
|
9
|
+
* - **`$top` is hard-capped at 50.** Values above 50 return HTTP 400.
|
|
10
|
+
* Source: https://learn.microsoft.com/en-us/graph/api/chat-list (Optional
|
|
11
|
+
* query parameters table).
|
|
12
|
+
*
|
|
13
|
+
* - **All `$filter` predicates are post-filtered, not indexed lookups.**
|
|
14
|
+
* Graph applies `$filter` AFTER taking the next `$top` chats from the
|
|
15
|
+
* recency-ordered chat list. So a single page returns "matches found
|
|
16
|
+
* within the next 50 chats by recency", and `@odata.nextLink` advances
|
|
17
|
+
* the scan window. Even `chatType eq 'oneOnOne'` behaves this way:
|
|
18
|
+
* measured `$top=5 → 2 matches`, `$top=50 → 13 matches`. This means you
|
|
19
|
+
* cannot rely on `$filter` to find old chats without paginating.
|
|
20
|
+
* Confirmed by Microsoft on
|
|
21
|
+
* https://learn.microsoft.com/en-us/answers/questions/1660492 :
|
|
22
|
+
* "the API selects top records first and then applies the given filter".
|
|
23
|
+
*
|
|
24
|
+
* - **`$orderby` only accepts ONE value:**
|
|
25
|
+
* `lastMessagePreview/createdDateTime desc`. Ascending order is rejected,
|
|
26
|
+
* every other field (`lastUpdatedDateTime`, `createdDateTime`, `topic`,
|
|
27
|
+
* `chatType`, `id`) is rejected. WITHOUT explicit `$orderby` the default
|
|
28
|
+
* order is approximately recency-based but has many monotonicity
|
|
29
|
+
* violations (verified empirically). Always pass `$orderby` if you care
|
|
30
|
+
* about ordering.
|
|
31
|
+
*
|
|
32
|
+
* - **`members/any(o: contains(tolower(o/displayname), 'X')) + chatType eq
|
|
33
|
+
* 'oneOnOne'` returns 0 results.** This is a Graph bug specific to the
|
|
34
|
+
* displayName predicate. Combining `memberUserId` (the `userId eq …` form)
|
|
35
|
+
* with `chatType eq 'oneOnOne'` works correctly. Use `memberUserId` if
|
|
36
|
+
* you have an AAD ID; resolve names to IDs first.
|
|
37
|
+
*
|
|
38
|
+
* - **`$expand=members` silently truncates at 25 members per chat,**
|
|
39
|
+
* regardless of `$top`. The server still evaluates `members/any()` against
|
|
40
|
+
* the full membership list, but the returned `members` array is capped.
|
|
41
|
+
* Documented as a "known issue" on the official chat-list page.
|
|
42
|
+
*
|
|
43
|
+
* - **`$search` is not allowed** on `/me/chats`.
|
|
44
|
+
* - **`$count=true` is not allowed** on `/me/chats`.
|
|
45
|
+
*
|
|
46
|
+
* For deep background and all the empirical measurements, see
|
|
47
|
+
* `packages/clis/msgraph-cli/CHAT_SEARCH_INVESTIGATION.md` in this repo.
|
|
5
48
|
*/
|
|
6
49
|
export class ChatsApi extends BaseApi {
|
|
7
50
|
/**
|
|
8
51
|
* Get a chat by ID with members expanded.
|
|
52
|
+
*
|
|
53
|
+
* Note: due to the documented `$expand=members` 25-cap, the `members` array
|
|
54
|
+
* may be incomplete for chats with more than 25 members. The server
|
|
55
|
+
* correctly counts all members for filter evaluation, but the response is
|
|
56
|
+
* truncated.
|
|
9
57
|
*/
|
|
10
58
|
async get(params) {
|
|
11
59
|
return this.client.api(`/chats/${params.chatId}`).expand('members').get();
|
|
12
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Find the 1:1 chat between the signed-in user and another user.
|
|
63
|
+
*
|
|
64
|
+
* Why this exists as a primitive: Microsoft Graph has no `/me/chats/with/
|
|
65
|
+
* {userId}` endpoint, and the obvious workaround
|
|
66
|
+
* (`/me/chats?$filter=members/any(...) and chatType eq 'oneOnOne'`) is
|
|
67
|
+
* subject to the recency-window post-filter described in the class doc —
|
|
68
|
+
* older 1:1 chats are unreachable without paginating the entire chat list.
|
|
69
|
+
*
|
|
70
|
+
* Workaround: 1:1 chat IDs follow the deterministic format
|
|
71
|
+
*
|
|
72
|
+
* 19:{userA-guid}_{userB-guid}@unq.gbl.spaces
|
|
73
|
+
*
|
|
74
|
+
* but the order of the two GUIDs is **not** deterministic. Verified
|
|
75
|
+
* empirically against ~12 1:1 chats in an active account: about 75% have
|
|
76
|
+
* the signed-in user's GUID first, the rest have the other user's GUID
|
|
77
|
+
* first. The order likely depends on who initiated the conversation, but
|
|
78
|
+
* we can't tell without trying.
|
|
79
|
+
*
|
|
80
|
+
* So we issue both candidate URLs in parallel. Exactly one returns 200,
|
|
81
|
+
* the other returns 404. Round-trip latency is ~250-700ms total because
|
|
82
|
+
* the calls go in parallel.
|
|
83
|
+
*
|
|
84
|
+
* **This sidesteps `/me/chats` entirely.** It works for any 1:1 chat
|
|
85
|
+
* regardless of how long ago the last message was sent — there is no
|
|
86
|
+
* recency window. It is also strictly read-only with no side effects on
|
|
87
|
+
* Teams (unlike `POST /chats` which would create a new thread if the
|
|
88
|
+
* chat didn't already exist).
|
|
89
|
+
*
|
|
90
|
+
* Returns the existing 1:1 chat, or `null` if no DM exists between the
|
|
91
|
+
* signed-in user and the target user.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* const chat = await client.chats.findDmByUserId({ userId: 'de720d1a-...' });
|
|
95
|
+
* if (chat) console.log(`DM exists: ${chat.id}`);
|
|
96
|
+
* else console.log('No DM with this user yet');
|
|
97
|
+
*/
|
|
98
|
+
async findDmByUserId(params) {
|
|
99
|
+
// We need the signed-in user's id to construct the candidates.
|
|
100
|
+
const me = (await this.client.api('/me').select('id').get());
|
|
101
|
+
const candidates = [`19:${me.id}_${params.userId}@unq.gbl.spaces`, `19:${params.userId}_${me.id}@unq.gbl.spaces`];
|
|
102
|
+
// Issue both GETs in parallel. Exactly one will succeed (or zero, if no
|
|
103
|
+
// DM exists). We don't care which order — the first fulfilled wins.
|
|
104
|
+
// Expand `lastMessagePreview` so callers get recency info without an
|
|
105
|
+
// extra round trip.
|
|
106
|
+
const results = await Promise.allSettled(candidates.map((cid) => this.client.api(`/chats/${cid}`).expand('members,lastMessagePreview').get()));
|
|
107
|
+
const winner = results.find((r) => r.status === 'fulfilled');
|
|
108
|
+
return winner ? winner.value : null;
|
|
109
|
+
}
|
|
13
110
|
/**
|
|
14
111
|
* List chats for the current user.
|
|
15
|
-
*
|
|
16
|
-
* Returns a single page of
|
|
112
|
+
*
|
|
113
|
+
* Builds an OData query from the typed params. Returns a single page of
|
|
114
|
+
* results with `nextLink` for caller-driven pagination — this method does
|
|
115
|
+
* NOT loop through pages.
|
|
116
|
+
*
|
|
117
|
+
* **Important caveats** (see also the class-level doc above):
|
|
118
|
+
*
|
|
119
|
+
* - Filters are post-filtered by Graph against a recency window of
|
|
120
|
+
* `$top` chats. Pagination via `nextLink` advances the window forward.
|
|
121
|
+
* A single page returns `0..top` matches. Pagination ends only when
|
|
122
|
+
* the window has scanned every chat the user has — for power users
|
|
123
|
+
* that may be 50+ pages.
|
|
124
|
+
*
|
|
125
|
+
* - Always pass `orderByLastMessage: true` for monotonic recency order.
|
|
126
|
+
* The default order has gaps and violations.
|
|
127
|
+
*
|
|
128
|
+
* - For finding 1:1 chats with a specific person, prefer
|
|
129
|
+
* {@link findDmByUserId} which sidesteps this whole mess.
|
|
130
|
+
*
|
|
131
|
+
* - For combining a member predicate with `chatType eq 'oneOnOne'`, use
|
|
132
|
+
* the `memberUserId` param (not `memberName` / `memberEmail`) — the
|
|
133
|
+
* displayName form hits a known Graph bug.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* // Active named chats with "morning" in the topic, recency-sorted:
|
|
137
|
+
* const result = await client.chats.list({
|
|
138
|
+
* searchTerm: 'morning',
|
|
139
|
+
* orderByLastMessage: true,
|
|
140
|
+
* top: 50,
|
|
141
|
+
* });
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* // Group/meeting chats containing a specific user, recency-sorted:
|
|
145
|
+
* const result = await client.chats.list({
|
|
146
|
+
* memberUserId: '0379926e-96c3-4c2a-800e-45d1b2a9b06c',
|
|
147
|
+
* chatTypes: ['group', 'meeting'],
|
|
148
|
+
* orderByLastMessage: true,
|
|
149
|
+
* top: 50,
|
|
150
|
+
* });
|
|
17
151
|
*/
|
|
18
152
|
async list(params) {
|
|
19
153
|
let query;
|
|
20
154
|
if (params?.nextLink) {
|
|
155
|
+
// When following a nextLink, all query params are already baked in.
|
|
156
|
+
// Just GET it directly.
|
|
21
157
|
query = this.client.api(params.nextLink);
|
|
22
158
|
}
|
|
23
159
|
else {
|
|
24
160
|
const top = params?.top ?? 50;
|
|
25
161
|
query = this.client.api('/me/chats').top(top);
|
|
26
162
|
const filters = [];
|
|
163
|
+
const expand = new Set(params?.expand ?? []);
|
|
27
164
|
if (params?.searchTerm) {
|
|
28
|
-
|
|
165
|
+
// We must URL-encode the value here because the SDK's `.filter()` builder
|
|
166
|
+
// URL-encodes the parameter NAME but not the VALUE. Reserved characters
|
|
167
|
+
// in topics like "FM & FD" would otherwise be parsed as query param
|
|
168
|
+
// separators on the server. odataFilterValue() does both layers:
|
|
169
|
+
// OData literal escape (' → '') AND URL encode. The OData syntax around
|
|
170
|
+
// the value (`contains(...)`, the surrounding quotes) is NOT encoded —
|
|
171
|
+
// it's part of the filter expression that the SDK passes through.
|
|
172
|
+
// Verified empirically with `test/probe-encoding.mts`.
|
|
173
|
+
const value = odataFilterValue(params.searchTerm.toLowerCase());
|
|
174
|
+
filters.push(`contains(tolower(topic), '${value}')`);
|
|
29
175
|
}
|
|
30
176
|
if (params?.chatTypes && params.chatTypes.length > 0) {
|
|
31
177
|
const typeFilters = params.chatTypes.map((t) => `chatType eq '${t}'`);
|
|
32
|
-
filters.push(`(${typeFilters.join(' or ')})`);
|
|
178
|
+
filters.push(typeFilters.length === 1 ? typeFilters[0] : `(${typeFilters.join(' or ')})`);
|
|
33
179
|
}
|
|
34
180
|
if (params?.memberName) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
181
|
+
// KNOWN GRAPH BUG: this combined with `chatType eq 'oneOnOne'` returns
|
|
182
|
+
// 0. Caller is responsible for not passing that combination, OR for
|
|
183
|
+
// using `memberUserId` instead (which is bug-free).
|
|
184
|
+
const value = odataFilterValue(params.memberName.toLowerCase());
|
|
185
|
+
filters.push(`members/any(o: contains(tolower(o/displayname), '${value}'))`);
|
|
186
|
+
// members/any() silently returns false unless members are expanded.
|
|
187
|
+
// Documented in this package's CLAUDE.md.
|
|
188
|
+
expand.add('members');
|
|
39
189
|
}
|
|
40
190
|
if (params?.memberEmail) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
191
|
+
const value = odataFilterValue(params.memberEmail);
|
|
192
|
+
filters.push(`members/any(o: o/microsoft.graph.aadUserConversationMember/email eq '${value}')`);
|
|
193
|
+
expand.add('members');
|
|
194
|
+
}
|
|
195
|
+
if (params?.memberUserId) {
|
|
196
|
+
// Equality on userId is the bug-free form. Combining this with
|
|
197
|
+
// `chatType eq 'oneOnOne'` works correctly server-side.
|
|
198
|
+
filters.push(`members/any(o: o/microsoft.graph.aadUserConversationMember/userId eq '${params.memberUserId}')`);
|
|
199
|
+
expand.add('members');
|
|
45
200
|
}
|
|
46
201
|
if (filters.length > 0) {
|
|
47
202
|
query = query.filter(filters.join(' and '));
|
|
48
203
|
}
|
|
49
|
-
if (
|
|
50
|
-
query = query.expand(
|
|
204
|
+
if (expand.size > 0) {
|
|
205
|
+
query = query.expand([...expand].join(','));
|
|
206
|
+
}
|
|
207
|
+
if (params?.orderByLastMessage) {
|
|
208
|
+
query = query.orderby('lastMessagePreview/createdDateTime desc');
|
|
51
209
|
}
|
|
52
210
|
}
|
|
53
211
|
const response = (await query.get());
|
|
@@ -58,6 +216,14 @@ export class ChatsApi extends BaseApi {
|
|
|
58
216
|
}
|
|
59
217
|
/**
|
|
60
218
|
* Create a new chat (1:1 or group).
|
|
219
|
+
*
|
|
220
|
+
* For 1:1 chats, Microsoft documents that "if a one-on-one chat already
|
|
221
|
+
* exists between the specified members, the existing chat is returned
|
|
222
|
+
* instead of creating a new one." However we still treat this as a
|
|
223
|
+
* write operation because (a) it has visible side effects on the Teams
|
|
224
|
+
* UI when the chat doesn't exist, and (b) the dedup behavior isn't
|
|
225
|
+
* something we want to rely on for read paths. For "find an existing
|
|
226
|
+
* 1:1", use {@link findDmByUserId} instead.
|
|
61
227
|
*/
|
|
62
228
|
async create(params) {
|
|
63
229
|
const payload = {
|
package/dist/api/chats.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chats.js","sourceRoot":"","sources":["../../src/api/chats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"chats.js","sourceRoot":"","sources":["../../src/api/chats.ts"],"names":[],"mappings":"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"}
|
package/dist/api/messages.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseApi } from './base.js';
|
|
2
|
-
import type { ChatMessage, DeleteChatMessageParams, DownloadHostedContentParams, DownloadHostedContentResult, GetChatMessagesParams, GetMessageParams, SearchMessagesParams, SearchResponse, SendChatMessageParams, SetMessageReactionParams, UnsetMessageReactionParams, UpdateChatMessageParams } from '../types/index.js';
|
|
2
|
+
import type { ChatMessage, DeleteChatMessageParams, DownloadHostedContentParams, DownloadHostedContentResult, GetChatMessagesParams, GetMessageParams, ListMessagesParams, ListMessagesResult, SearchMessagesParams, SearchResponse, SendChatMessageParams, SetMessageReactionParams, UnsetMessageReactionParams, UpdateChatMessageParams } from '../types/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* API for message operations.
|
|
5
5
|
*/
|
|
@@ -14,9 +14,69 @@ export declare class MessagesApi extends BaseApi {
|
|
|
14
14
|
*/
|
|
15
15
|
get(params: GetMessageParams): Promise<ChatMessage>;
|
|
16
16
|
/**
|
|
17
|
-
* Get messages from a chat.
|
|
17
|
+
* Get messages from a chat. Returns a flat array of `ChatMessage`.
|
|
18
|
+
*
|
|
19
|
+
* Backward-compat method: prefer `listMessages` for new code, which exposes
|
|
20
|
+
* pagination metadata and a richer return shape.
|
|
21
|
+
*
|
|
22
|
+
* **Bug fix history**: this method previously built the OData filter
|
|
23
|
+
* `from/user/id eq '<id>'` for the `fromUser` param. Graph rejects this
|
|
24
|
+
* with "The entity property 'user/id' and operationKind 'Equal' is not
|
|
25
|
+
* allowed in $filter query." (HTTP 400). The filter is now applied
|
|
26
|
+
* client-side after fetching the page — see the doc on `listMessages`
|
|
27
|
+
* for the full reasoning.
|
|
18
28
|
*/
|
|
19
29
|
getChatMessages(params: GetChatMessagesParams): Promise<ChatMessage[]>;
|
|
30
|
+
/**
|
|
31
|
+
* List messages in a chat with caller-driven pagination.
|
|
32
|
+
*
|
|
33
|
+
* Returns one page plus a `nextLink` token. The caller passes the token
|
|
34
|
+
* back as `nextLink` on a follow-up call to fetch the next page. This
|
|
35
|
+
* method does NOT loop through pages.
|
|
36
|
+
*
|
|
37
|
+
* **Server-side capabilities of `/chats/{id}/messages`** (verified
|
|
38
|
+
* empirically — Microsoft's docs are vague on most of this):
|
|
39
|
+
*
|
|
40
|
+
* - `$top` ✓ (works, max ~50)
|
|
41
|
+
* - `$orderby=createdDateTime desc` ✓ (default)
|
|
42
|
+
* - `$filter=lastModifiedDateTime gt|lt <iso>` ✓ — the only content-ish
|
|
43
|
+
* filter that works
|
|
44
|
+
* - `$search` ✗ — "Query option 'Search' is not allowed"
|
|
45
|
+
* - `$filter=contains(body/content, 'X')` ✗ — "Only binary operation
|
|
46
|
+
* expressions are allowed"
|
|
47
|
+
* - `$filter=from/user/id eq 'X'` ✗ — "operationKind 'Equal' is not
|
|
48
|
+
* allowed"
|
|
49
|
+
*
|
|
50
|
+
* Microsoft's recommended approach for keyword search within a chat is:
|
|
51
|
+
* use the global `/search/query` endpoint and filter `chatId` client-side.
|
|
52
|
+
* That global path is implemented in `messages.search()`. This local path
|
|
53
|
+
* is for chronological reading of a chat with optional date filter.
|
|
54
|
+
*
|
|
55
|
+
* **The `containing` and `fromUser` params are client-side filters** —
|
|
56
|
+
* they keep only messages from the returned page that match. The
|
|
57
|
+
* `scanned` and `matched` fields in the result tell the caller how many
|
|
58
|
+
* messages were inspected vs how many matched, so the agent can paginate
|
|
59
|
+
* forward if it wants more.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // Read the most recent 50 messages from a chat:
|
|
63
|
+
* const r = await client.messages.listMessages({ chatId, limit: 50 });
|
|
64
|
+
* console.log(r.messages, r.nextLink);
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* // Find messages containing "ticket" in the most recent 50:
|
|
68
|
+
* const r = await client.messages.listMessages({
|
|
69
|
+
* chatId, limit: 50, containing: 'ticket'
|
|
70
|
+
* });
|
|
71
|
+
* // r.scanned === 50, r.matched === r.messages.length
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* // Page forward:
|
|
75
|
+
* const r2 = await client.messages.listMessages({
|
|
76
|
+
* chatId, nextLink: r.nextLink
|
|
77
|
+
* });
|
|
78
|
+
*/
|
|
79
|
+
listMessages(params: ListMessagesParams): Promise<ListMessagesResult>;
|
|
20
80
|
/**
|
|
21
81
|
* Send a message to a chat.
|
|
22
82
|
*/
|
|
@@ -26,7 +86,66 @@ export declare class MessagesApi extends BaseApi {
|
|
|
26
86
|
*/
|
|
27
87
|
updateChatMessage(params: UpdateChatMessageParams): Promise<void>;
|
|
28
88
|
/**
|
|
29
|
-
* Search messages across chats and channels.
|
|
89
|
+
* Search chat messages across the signed-in user's chats and channels.
|
|
90
|
+
*
|
|
91
|
+
* Uses the BETA `/search/query` endpoint with `entityTypes: ['chatMessage']`.
|
|
92
|
+
* Beta is the canonical example in Microsoft's docs and is functionally
|
|
93
|
+
* equivalent to v1.0 (verified empirically — same results, same latency)
|
|
94
|
+
* but is the documented forward path. See:
|
|
95
|
+
* https://learn.microsoft.com/en-us/graph/search-concept-chat-messages
|
|
96
|
+
*
|
|
97
|
+
* **What this method DOES support:**
|
|
98
|
+
*
|
|
99
|
+
* - Free-text full-text search across message body and attachments.
|
|
100
|
+
* Microsoft Search indexes all messages the user has access to —
|
|
101
|
+
* NOT recency-windowed, unlike `/me/chats` filters.
|
|
102
|
+
* - The full set of documented KQL operators (`from:`, `to:`, `mentions:`,
|
|
103
|
+
* `IsRead:`, `hasAttachment:`, `sent>`, `sent<`) via typed params.
|
|
104
|
+
* - Real pagination via `from_offset` (skip N hits) and `size` (page size).
|
|
105
|
+
* Caller drives pagination — this method does NOT loop.
|
|
106
|
+
* - Up to 500 hits per call (Graph hard cap is 501).
|
|
107
|
+
*
|
|
108
|
+
* **What this method does NOT support, and why:**
|
|
109
|
+
*
|
|
110
|
+
* - **No `chatId` / `channelId` / `scope` filter.** Microsoft has not built
|
|
111
|
+
* server-side filtering by chat or channel for `chatMessage` search.
|
|
112
|
+
* Verified exhaustively against ~12 KQL operator variants and request
|
|
113
|
+
* body shapes (`stringInputs`, `sourceFilters`, etc.) — none filter.
|
|
114
|
+
* Confirmed by Microsoft on
|
|
115
|
+
* https://learn.microsoft.com/en-us/answers/questions/5510799 :
|
|
116
|
+
* "All scoping beyond keyword/KQL must be done client-side."
|
|
117
|
+
*
|
|
118
|
+
* - **`from:` does NOT accept user IDs.** Per docs and verified empirically,
|
|
119
|
+
* `from:` accepts a display name (`from:Bob`, `from:"Bob Smith"`) or an
|
|
120
|
+
* email (`from:bob@contoso.com`). Passing a GUID returns 0 hits silently.
|
|
121
|
+
* Resolve a user ID to a name/email before passing it here.
|
|
122
|
+
*
|
|
123
|
+
* - **`mentions:` is the inverse:** it ONLY accepts the user ID, and the
|
|
124
|
+
* GUID must have dashes stripped. Per docs.
|
|
125
|
+
*
|
|
126
|
+
* **About `total` in the response:** Microsoft's docs say total is "the
|
|
127
|
+
* number of results on the page, not the total number of matching results."
|
|
128
|
+
* That documentation is wrong (or outdated). Verified empirically: `total`
|
|
129
|
+
* IS the grand total of matching messages across all pages, regardless of
|
|
130
|
+
* `size`. For very common terms total can be in the thousands.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* // Find messages I sent containing "delivery", page 1:
|
|
134
|
+
* const r = await client.messages.search({
|
|
135
|
+
* query: 'delivery',
|
|
136
|
+
* from: 'evrim.a@first.bet',
|
|
137
|
+
* size: 25,
|
|
138
|
+
* });
|
|
139
|
+
* // r.value[0].hitsContainers[0]: { total, moreResultsAvailable, hits[] }
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* // Page 2:
|
|
143
|
+
* const r2 = await client.messages.search({
|
|
144
|
+
* query: 'delivery',
|
|
145
|
+
* from: 'evrim.a@first.bet',
|
|
146
|
+
* size: 25,
|
|
147
|
+
* from_offset: 25,
|
|
148
|
+
* });
|
|
30
149
|
*/
|
|
31
150
|
search(params: SearchMessagesParams): Promise<SearchResponse>;
|
|
32
151
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/api/messages.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EACV,WAAW,EAGX,uBAAuB,EACvB,2BAA2B,EAC3B,2BAA2B,EAC3B,qBAAqB,EACrB,gBAAgB,EAGhB,oBAAoB,EAEpB,cAAc,EACd,qBAAqB,EACrB,wBAAwB,EACxB,0BAA0B,EAC1B,uBAAuB,EACxB,MAAM,mBAAmB,CAAC;AAG3B;;GAEG;AACH,qBAAa,WAAY,SAAQ,OAAO;IACtC;;;OAGG;IACU,qBAAqB,CAAC,MAAM,EAAE,2BAA2B,GAAG,OAAO,CAAC,2BAA2B,CAAC;IAW7G;;OAEG;IACU,GAAG,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;IAIhE
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/api/messages.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,KAAK,EACV,WAAW,EAGX,uBAAuB,EACvB,2BAA2B,EAC3B,2BAA2B,EAC3B,qBAAqB,EACrB,gBAAgB,EAGhB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EAEpB,cAAc,EACd,qBAAqB,EACrB,wBAAwB,EACxB,0BAA0B,EAC1B,uBAAuB,EACxB,MAAM,mBAAmB,CAAC;AAG3B;;GAEG;AACH,qBAAa,WAAY,SAAQ,OAAO;IACtC;;;OAGG;IACU,qBAAqB,CAAC,MAAM,EAAE,2BAA2B,GAAG,OAAO,CAAC,2BAA2B,CAAC;IAW7G;;OAEG;IACU,GAAG,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;IAIhE;;;;;;;;;;;;OAYG;IACU,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAyBnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgDG;IACU,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAgDlF;;OAEG;IACU,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,WAAW,CAAC;IA6DjF;;OAEG;IACU,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgC9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6DG;IACU,MAAM,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC;IAoD1E;;OAEG;IACU,WAAW,CAAC,MAAM,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOzE;;OAEG;IACU,UAAU,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvE;;OAEG;IACU,cAAc,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3E;;OAEG;IACU,aAAa,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;IAO7E;;OAEG;YACW,qBAAqB;CAgEpC"}
|