@kud/gh 0.11.0 → 0.12.1
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/inbox.d.ts +49 -9
- package/dist/inbox.d.ts.map +1 -1
- package/dist/inbox.js +127 -10
- package/dist/inbox.js.map +1 -1
- package/package.json +1 -1
package/dist/inbox.d.ts
CHANGED
|
@@ -34,6 +34,22 @@
|
|
|
34
34
|
* not showing.
|
|
35
35
|
*/
|
|
36
36
|
export declare const MY_PRS_LIMIT = 30;
|
|
37
|
+
/**
|
|
38
|
+
* How many rows each source asks for — the cap, as DATA rather than a literal
|
|
39
|
+
* buried in eight query strings.
|
|
40
|
+
*
|
|
41
|
+
* It has to be readable from outside, because a cap you cannot compare against
|
|
42
|
+
* `issueCount` is a cap that truncates in silence. Measured 2026-09-07 on a real
|
|
43
|
+
* account: `assigned` 37 rows against 30, `repoIssues` 94 against 30,
|
|
44
|
+
* `authoredIssues` 95 against 30. Two sources showing under a third of what they
|
|
45
|
+
* matched, and nothing anywhere said so.
|
|
46
|
+
*
|
|
47
|
+
* That silence is not merely a display gap. A surface that diffs one fetch
|
|
48
|
+
* against the next reads a row leaving the WINDOW as a row leaving the WORLD, so
|
|
49
|
+
* every update to any of those 95 issues evicted something and was reported as
|
|
50
|
+
* news about the evicted one. See `sourceCoverage`.
|
|
51
|
+
*/
|
|
52
|
+
export declare const SOURCE_LIMITS: Record<InboxSource, number>;
|
|
37
53
|
export type InboxShape = "full" | "minimal";
|
|
38
54
|
/** One search in the inbox, addressable by the alias it answers under. */
|
|
39
55
|
export type InboxSource = "myPRs" | "reviewRequests" | "reviewed" | "assigned" | "repoIssues" | "authoredIssues" | "repoPRs" | "recentlyDone";
|
|
@@ -62,15 +78,6 @@ export type InboxQueryOptions = {
|
|
|
62
78
|
*/
|
|
63
79
|
sources?: readonly InboxSource[];
|
|
64
80
|
};
|
|
65
|
-
/**
|
|
66
|
-
* Build the inbox query. Without `repo`, it is account-wide.
|
|
67
|
-
*
|
|
68
|
-
* The two qualifiers do NOT compose. `user:@me` means "in repos I own", and
|
|
69
|
-
* GitHub ANDs search qualifiers — so `user:@me repo:someone-else/x` matches
|
|
70
|
-
* nothing, and a scoped inbox on a repo you contribute to but do not own would
|
|
71
|
-
* render empty and read as "nothing to do here". So `repo:` REPLACES
|
|
72
|
-
* `user:@me` rather than joining it.
|
|
73
|
-
*/
|
|
74
81
|
export declare const buildInboxQuery: (options?: InboxQueryOptions) => string;
|
|
75
82
|
/**
|
|
76
83
|
* How many sources to put in one request.
|
|
@@ -119,4 +126,37 @@ export declare const buildInboxQueries: (options?: InboxQueryOptions & {
|
|
|
119
126
|
* moment.
|
|
120
127
|
*/
|
|
121
128
|
export declare const mergeInboxData: (parts: any[]) => any;
|
|
129
|
+
/** What a source matched, against what it was allowed to return. */
|
|
130
|
+
export type SourceCoverage = {
|
|
131
|
+
/** Everything the search matched, from GitHub's own `issueCount`. */
|
|
132
|
+
total: number;
|
|
133
|
+
/** What actually came back — at most this source's cap. */
|
|
134
|
+
shown: number;
|
|
135
|
+
/** `total > shown`: the rows are a sample of the set, not the set. */
|
|
136
|
+
truncated: boolean;
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* What each source could see, against what it was allowed to show.
|
|
140
|
+
*
|
|
141
|
+
* The reason this exists is not the display gap, it is what a truncated source
|
|
142
|
+
* does to a DIFF. A surface that marks arrivals and departures by comparing one
|
|
143
|
+
* fetch with the next is asking "what changed in the world?" and reading the
|
|
144
|
+
* answer off a fixed-size window. Where the window is smaller than the world,
|
|
145
|
+
* those are different questions: any update to any of the 95 issues behind a
|
|
146
|
+
* 30-row window reorders it, evicts something, and the eviction is reported as
|
|
147
|
+
* news about the row that left — which never moved at all.
|
|
148
|
+
*
|
|
149
|
+
* So a consumer should treat presence changes on a truncated source as carrying
|
|
150
|
+
* no information, and say what it is not showing instead. Both halves need this
|
|
151
|
+
* number, and until 2026-09-07 it was fetched for exactly one source out of
|
|
152
|
+
* eight and read by nobody — the guarantee lived in a comment and not in the
|
|
153
|
+
* code.
|
|
154
|
+
*
|
|
155
|
+
* A source that answered with no `issueCount` reports `total: shown`, which
|
|
156
|
+
* reads as "not truncated". That is the deliberate direction to fail in: a
|
|
157
|
+
* missing count must never invent a truncation and silence real news.
|
|
158
|
+
*/
|
|
159
|
+
export declare const sourceCoverage: (data: any) => Partial<Record<InboxSource, SourceCoverage>>;
|
|
160
|
+
/** The sources whose rows are a sample rather than the set. */
|
|
161
|
+
export declare const truncatedSources: (data: any) => InboxSource[];
|
|
122
162
|
//# sourceMappingURL=inbox.d.ts.map
|
package/dist/inbox.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../src/inbox.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;GAaG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,YAAY,KAAK,CAAA;AAE9B,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,CAAA;AAE3C,0EAA0E;AAC1E,MAAM,MAAM,WAAW,GACnB,OAAO,GACP,gBAAgB,GAChB,UAAU,GACV,UAAU,GACV,YAAY,GACZ,gBAAgB,GAChB,SAAS,GACT,cAAc,CAAA;AAElB,oEAAoE;AACpE,eAAO,MAAM,aAAa,EAAE,SAAS,WAAW,EAS/C,CAAA;AAED,2CAA2C;AAC3C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;CACjC,CAAA;
|
|
1
|
+
{"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../src/inbox.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;GAaG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,YAAY,KAAK,CAAA;AAE9B;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CASrD,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,CAAA;AAE3C,0EAA0E;AAC1E,MAAM,MAAM,WAAW,GACnB,OAAO,GACP,gBAAgB,GAChB,UAAU,GACV,UAAU,GACV,YAAY,GACZ,gBAAgB,GAChB,SAAS,GACT,cAAc,CAAA;AAElB,oEAAoE;AACpE,eAAO,MAAM,aAAa,EAAE,SAAS,WAAW,EAS/C,CAAA;AAED,2CAA2C;AAC3C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;CACjC,CAAA;AA2SD,eAAO,MAAM,eAAe,GAAI,UAAS,iBAAsB,WAqB9D,CAAA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAS,iBAAiB,GAAG;IAAE,eAAe,CAAC,EAAE,MAAM,CAAA;CAAO,KAC7D,MAAM,EAYR,CAAA;AASD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,GAAG,EAAE,KAAG,GA8B7C,CAAA;AAED,oEAAoE;AACpE,MAAM,MAAM,cAAc,GAAG;IAC3B,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAA;IACb,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAA;IACb,sEAAsE;IACtE,SAAS,EAAE,OAAO,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,GAAG,KACR,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,CAc7C,CAAA;AAED,+DAA+D;AAC/D,eAAO,MAAM,gBAAgB,GAAI,MAAM,GAAG,KAAG,WAAW,EACmB,CAAA"}
|
package/dist/inbox.js
CHANGED
|
@@ -41,6 +41,31 @@
|
|
|
41
41
|
* not showing.
|
|
42
42
|
*/
|
|
43
43
|
export const MY_PRS_LIMIT = 30;
|
|
44
|
+
/**
|
|
45
|
+
* How many rows each source asks for — the cap, as DATA rather than a literal
|
|
46
|
+
* buried in eight query strings.
|
|
47
|
+
*
|
|
48
|
+
* It has to be readable from outside, because a cap you cannot compare against
|
|
49
|
+
* `issueCount` is a cap that truncates in silence. Measured 2026-09-07 on a real
|
|
50
|
+
* account: `assigned` 37 rows against 30, `repoIssues` 94 against 30,
|
|
51
|
+
* `authoredIssues` 95 against 30. Two sources showing under a third of what they
|
|
52
|
+
* matched, and nothing anywhere said so.
|
|
53
|
+
*
|
|
54
|
+
* That silence is not merely a display gap. A surface that diffs one fetch
|
|
55
|
+
* against the next reads a row leaving the WINDOW as a row leaving the WORLD, so
|
|
56
|
+
* every update to any of those 95 issues evicted something and was reported as
|
|
57
|
+
* news about the evicted one. See `sourceCoverage`.
|
|
58
|
+
*/
|
|
59
|
+
export const SOURCE_LIMITS = {
|
|
60
|
+
myPRs: MY_PRS_LIMIT,
|
|
61
|
+
reviewRequests: 20,
|
|
62
|
+
reviewed: 20,
|
|
63
|
+
assigned: 30,
|
|
64
|
+
repoIssues: 30,
|
|
65
|
+
authoredIssues: 30,
|
|
66
|
+
repoPRs: 30,
|
|
67
|
+
recentlyDone: 30,
|
|
68
|
+
};
|
|
44
69
|
/** Every source, in the order a whole-inbox query asks for them. */
|
|
45
70
|
export const INBOX_SOURCES = [
|
|
46
71
|
"myPRs",
|
|
@@ -128,7 +153,7 @@ const sinceDay = (days) => new Date(Date.now() - days * 86400 * 1000).toISOStrin
|
|
|
128
153
|
* appears in the document.
|
|
129
154
|
*/
|
|
130
155
|
const SOURCES = {
|
|
131
|
-
myPRs: ({ scope, health, conversation }) => ` myPRs: search(query: "${scope}is:pr is:open author:@me", type: ISSUE, first: ${
|
|
156
|
+
myPRs: ({ scope, health, conversation, }) => ` myPRs: search(query: "${scope}is:pr is:open author:@me", type: ISSUE, first: ${SOURCE_LIMITS.myPRs}) {
|
|
132
157
|
issueCount
|
|
133
158
|
nodes { __typename ... on PullRequest {
|
|
134
159
|
number title createdAt url headRefName isDraft
|
|
@@ -138,7 +163,8 @@ const SOURCES = {
|
|
|
138
163
|
${conversation}
|
|
139
164
|
}}
|
|
140
165
|
}`,
|
|
141
|
-
reviewRequests: ({ scope, health, conversation }) => ` reviewRequests: search(query: "${scope}is:pr is:open review-requested:@me", type: ISSUE, first:
|
|
166
|
+
reviewRequests: ({ scope, health, conversation, }) => ` reviewRequests: search(query: "${scope}is:pr is:open review-requested:@me", type: ISSUE, first: ${SOURCE_LIMITS.reviewRequests}) {
|
|
167
|
+
issueCount
|
|
142
168
|
nodes { __typename ... on PullRequest {
|
|
143
169
|
number title createdAt url headRefName isDraft
|
|
144
170
|
repository { nameWithOwner }
|
|
@@ -147,7 +173,8 @@ const SOURCES = {
|
|
|
147
173
|
${conversation}
|
|
148
174
|
}}
|
|
149
175
|
}`,
|
|
150
|
-
reviewed: ({ scope, health, conversation }) => ` reviewed: search(query: "${scope}is:pr is:open reviewed-by:@me -author:@me -review-requested:@me", type: ISSUE, first:
|
|
176
|
+
reviewed: ({ scope, health, conversation, }) => ` reviewed: search(query: "${scope}is:pr is:open reviewed-by:@me -author:@me -review-requested:@me", type: ISSUE, first: ${SOURCE_LIMITS.reviewed}) {
|
|
177
|
+
issueCount
|
|
151
178
|
nodes { __typename ... on PullRequest {
|
|
152
179
|
number title createdAt url headRefName isDraft
|
|
153
180
|
repository { nameWithOwner }
|
|
@@ -156,7 +183,8 @@ const SOURCES = {
|
|
|
156
183
|
${conversation}
|
|
157
184
|
}}
|
|
158
185
|
}`,
|
|
159
|
-
assigned: ({ scope, health, conversation, issueConversation, issueLabels, }) => ` assigned: search(query: "${scope}is:open assignee:@me", type: ISSUE, first:
|
|
186
|
+
assigned: ({ scope, health, conversation, issueConversation, issueLabels, }) => ` assigned: search(query: "${scope}is:open assignee:@me", type: ISSUE, first: ${SOURCE_LIMITS.assigned}) {
|
|
187
|
+
issueCount
|
|
160
188
|
nodes {
|
|
161
189
|
__typename
|
|
162
190
|
... on Issue {
|
|
@@ -171,7 +199,8 @@ const SOURCES = {
|
|
|
171
199
|
}
|
|
172
200
|
}
|
|
173
201
|
}`,
|
|
174
|
-
repoIssues: ({ scope, owned, issueConversation, issueLabels, }) => ` repoIssues: search(query: "${scope}${owned}is:issue is:open archived:false", type: ISSUE, first:
|
|
202
|
+
repoIssues: ({ scope, owned, issueConversation, issueLabels, }) => ` repoIssues: search(query: "${scope}${owned}is:issue is:open archived:false", type: ISSUE, first: ${SOURCE_LIMITS.repoIssues}) {
|
|
203
|
+
issueCount
|
|
175
204
|
nodes { __typename ... on Issue {
|
|
176
205
|
number title createdAt url
|
|
177
206
|
repository { nameWithOwner }
|
|
@@ -180,7 +209,36 @@ const SOURCES = {
|
|
|
180
209
|
${issueLabels}
|
|
181
210
|
}}
|
|
182
211
|
}`,
|
|
183
|
-
|
|
212
|
+
/*
|
|
213
|
+
* `-user:@me` is what makes this DISJOINT from `repoIssues`, and it is not an
|
|
214
|
+
* optimisation — it is the thing that makes a merged tab's totals addable.
|
|
215
|
+
*
|
|
216
|
+
* THE INVARIANT, which belongs here and nowhere else: the negations in a
|
|
217
|
+
* merged tab's queries mirror the order `pick` claims rows in. `repoIssues`
|
|
218
|
+
* runs first and takes anything on a repo you own, so this one asks for the
|
|
219
|
+
* remainder — exactly what the host already documents it wants ("issues I
|
|
220
|
+
* filed on repos I don't own") and already achieves at ROW level by deduping.
|
|
221
|
+
* Only `issueCount` never knew, because the query still asked for the superset.
|
|
222
|
+
*
|
|
223
|
+
* `reviewed` has carried the same shape all along (`-review-requested:@me`),
|
|
224
|
+
* which is why `Review` was never wrong and this tab was.
|
|
225
|
+
*
|
|
226
|
+
* Measured 2026-09-07: 94 own-repo issues, 95 authored, 92 of them BOTH — so
|
|
227
|
+
* summing the two `issueCount`s claimed 189 where the truth was 97. Overlap is
|
|
228
|
+
* the normal case, not an edge: a plans repo you own and file into is in both
|
|
229
|
+
* sets by construction. With the negation, 94 + 3 = 97 and the sum is trivially
|
|
230
|
+
* right because the sets cannot intersect.
|
|
231
|
+
*
|
|
232
|
+
* It also fetches BETTER rows for fewer nodes. Without it, 30 rows arrive of
|
|
233
|
+
* which ~27 are duplicates `pick` discards, and the handful of external issues
|
|
234
|
+
* that are this source's entire purpose may not be in that window at all.
|
|
235
|
+
*
|
|
236
|
+
* Add a third source to a merged tab and it takes the negations of every
|
|
237
|
+
* source that claims before it. Measure the overlap instead and you are
|
|
238
|
+
* carrying a second fact that rots silently.
|
|
239
|
+
*/
|
|
240
|
+
authoredIssues: ({ scope, issueConversation, issueLabels, }) => ` authoredIssues: search(query: "${scope}is:issue is:open author:@me -user:@me archived:false", type: ISSUE, first: ${SOURCE_LIMITS.authoredIssues}) {
|
|
241
|
+
issueCount
|
|
184
242
|
nodes { ... on Issue {
|
|
185
243
|
number title createdAt url
|
|
186
244
|
repository { nameWithOwner }
|
|
@@ -189,7 +247,8 @@ const SOURCES = {
|
|
|
189
247
|
${issueLabels}
|
|
190
248
|
}}
|
|
191
249
|
}`,
|
|
192
|
-
repoPRs: ({ scope, owned, health, conversation, }) => ` repoPRs: search(query: "${scope}${owned}is:pr is:open -author:@me archived:false", type: ISSUE, first:
|
|
250
|
+
repoPRs: ({ scope, owned, health, conversation, }) => ` repoPRs: search(query: "${scope}${owned}is:pr is:open -author:@me archived:false", type: ISSUE, first: ${SOURCE_LIMITS.repoPRs}) {
|
|
251
|
+
issueCount
|
|
193
252
|
nodes { __typename ... on PullRequest {
|
|
194
253
|
number title createdAt url headRefName isDraft
|
|
195
254
|
repository { nameWithOwner }
|
|
@@ -198,7 +257,8 @@ const SOURCES = {
|
|
|
198
257
|
${conversation}
|
|
199
258
|
}}
|
|
200
259
|
}`,
|
|
201
|
-
recentlyDone: ({ scope, doneSince, }) => ` recentlyDone: search(query: "${scope}is:pr author:@me -is:open closed:>=${doneSince}", type: ISSUE, first:
|
|
260
|
+
recentlyDone: ({ scope, doneSince, }) => ` recentlyDone: search(query: "${scope}is:pr author:@me -is:open closed:>=${doneSince}", type: ISSUE, first: ${SOURCE_LIMITS.recentlyDone}) {
|
|
261
|
+
issueCount
|
|
202
262
|
nodes { __typename ... on PullRequest {
|
|
203
263
|
number title state isDraft createdAt mergedAt closedAt url
|
|
204
264
|
repository { nameWithOwner }
|
|
@@ -228,9 +288,29 @@ const selectionsFor = ({ repo, doneWithinDays = 14, shape = "full", }) => {
|
|
|
228
288
|
* render empty and read as "nothing to do here". So `repo:` REPLACES
|
|
229
289
|
* `user:@me` rather than joining it.
|
|
230
290
|
*/
|
|
291
|
+
/**
|
|
292
|
+
* Which sources this scope should actually ask for.
|
|
293
|
+
*
|
|
294
|
+
* `authoredIssues` earns its place by asking for issues you filed OUTSIDE the
|
|
295
|
+
* repos you own — `-user:@me`, see SOURCES. Under a `repo:` scope there is no
|
|
296
|
+
* outside: `user:@me` is replaced rather than joined (see below), so the
|
|
297
|
+
* negation has nothing to negate and the search degrades to a strict SUBSET of
|
|
298
|
+
* `repoIssues`. Every row it returns is one `pick` immediately discards, paid
|
|
299
|
+
* for on every scoped fetch.
|
|
300
|
+
*
|
|
301
|
+
* Shared by both builders on purpose. They resolved `options.sources`apiece,
|
|
302
|
+
* which is exactly the shape where a change like this half-lands — the
|
|
303
|
+
* single-document path drops the source and the split path goes on asking.
|
|
304
|
+
*/
|
|
305
|
+
const sourcesFor = (options) => {
|
|
306
|
+
const sources = options.sources ?? INBOX_SOURCES;
|
|
307
|
+
return options.repo
|
|
308
|
+
? sources.filter((source) => source !== "authoredIssues")
|
|
309
|
+
: sources;
|
|
310
|
+
};
|
|
231
311
|
export const buildInboxQuery = (options = {}) => {
|
|
232
312
|
const selections = selectionsFor(options);
|
|
233
|
-
const sources = options
|
|
313
|
+
const sources = sourcesFor(options);
|
|
234
314
|
/*
|
|
235
315
|
* `rateLimit` is free — it does not count against itself — and it is the only
|
|
236
316
|
* authoritative source for what this query costs. Every estimate made about
|
|
@@ -281,7 +361,7 @@ export const INBOX_SOURCES_PER_QUERY = 2;
|
|
|
281
361
|
*/
|
|
282
362
|
export const buildInboxQueries = (options = {}) => {
|
|
283
363
|
const { sourcesPerQuery = INBOX_SOURCES_PER_QUERY, ...queryOptions } = options;
|
|
284
|
-
const sources = options
|
|
364
|
+
const sources = sourcesFor(options);
|
|
285
365
|
const size = Math.max(1, Math.trunc(sourcesPerQuery));
|
|
286
366
|
const chunks = [];
|
|
287
367
|
for (let i = 0; i < sources.length; i += size)
|
|
@@ -323,4 +403,41 @@ export const mergeInboxData = (parts) => {
|
|
|
323
403
|
: {}),
|
|
324
404
|
};
|
|
325
405
|
};
|
|
406
|
+
/**
|
|
407
|
+
* What each source could see, against what it was allowed to show.
|
|
408
|
+
*
|
|
409
|
+
* The reason this exists is not the display gap, it is what a truncated source
|
|
410
|
+
* does to a DIFF. A surface that marks arrivals and departures by comparing one
|
|
411
|
+
* fetch with the next is asking "what changed in the world?" and reading the
|
|
412
|
+
* answer off a fixed-size window. Where the window is smaller than the world,
|
|
413
|
+
* those are different questions: any update to any of the 95 issues behind a
|
|
414
|
+
* 30-row window reorders it, evicts something, and the eviction is reported as
|
|
415
|
+
* news about the row that left — which never moved at all.
|
|
416
|
+
*
|
|
417
|
+
* So a consumer should treat presence changes on a truncated source as carrying
|
|
418
|
+
* no information, and say what it is not showing instead. Both halves need this
|
|
419
|
+
* number, and until 2026-09-07 it was fetched for exactly one source out of
|
|
420
|
+
* eight and read by nobody — the guarantee lived in a comment and not in the
|
|
421
|
+
* code.
|
|
422
|
+
*
|
|
423
|
+
* A source that answered with no `issueCount` reports `total: shown`, which
|
|
424
|
+
* reads as "not truncated". That is the deliberate direction to fail in: a
|
|
425
|
+
* missing count must never invent a truncation and silence real news.
|
|
426
|
+
*/
|
|
427
|
+
export const sourceCoverage = (data) => {
|
|
428
|
+
const out = {};
|
|
429
|
+
if (!data)
|
|
430
|
+
return out;
|
|
431
|
+
for (const source of INBOX_SOURCES) {
|
|
432
|
+
const answered = data[source];
|
|
433
|
+
if (!answered)
|
|
434
|
+
continue;
|
|
435
|
+
const shown = answered.nodes?.length ?? 0;
|
|
436
|
+
const total = typeof answered.issueCount === "number" ? answered.issueCount : shown;
|
|
437
|
+
out[source] = { total, shown, truncated: total > shown };
|
|
438
|
+
}
|
|
439
|
+
return out;
|
|
440
|
+
};
|
|
441
|
+
/** The sources whose rows are a sample rather than the set. */
|
|
442
|
+
export const truncatedSources = (data) => INBOX_SOURCES.filter((source) => sourceCoverage(data)[source]?.truncated);
|
|
326
443
|
//# sourceMappingURL=inbox.js.map
|
package/dist/inbox.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inbox.js","sourceRoot":"","sources":["../src/inbox.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2EAA2E;AAC3E,YAAY;AACZ,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAC/E,uDAAuD;AAEvD;;;;;;;;;;;;;GAaG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"inbox.js","sourceRoot":"","sources":["../src/inbox.ts"],"names":[],"mappings":"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"}
|