@remit/web-client 0.0.148 → 0.0.149
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remit/web-client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.149",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Remit web client, published as composable primitives — the app shell, auth shells, and runtime config. A distributor imports what it composes and bundles it.",
|
|
6
6
|
"exports": {
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
} from "@remit/api-http-client/types.gen.ts";
|
|
7
7
|
import {
|
|
8
8
|
buildAuthenticityIntel,
|
|
9
|
+
buildCategoryIntel,
|
|
9
10
|
buildSenderIntel,
|
|
10
11
|
} from "./useIntelligenceData.js";
|
|
11
12
|
|
|
@@ -49,6 +50,45 @@ function makeAddress(
|
|
|
49
50
|
} as RemitImapAddressResponse;
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
// The generated union has a member for every category this build knows, so a
|
|
54
|
+
// value outside it cannot be written as one — which is the whole point: it
|
|
55
|
+
// arrives as JSON from a server that classifies into more than this client can.
|
|
56
|
+
function threadCategorizedAs(category: string): RemitImapThreadMessageResponse {
|
|
57
|
+
return { ...makeThread(), category } as RemitImapThreadMessageResponse;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
describe("buildCategoryIntel", () => {
|
|
61
|
+
test("carries a category the client knows through unchanged", () => {
|
|
62
|
+
const result = buildCategoryIntel(
|
|
63
|
+
makeThread({ category: "newsletter" }),
|
|
64
|
+
undefined,
|
|
65
|
+
);
|
|
66
|
+
assert.equal(result.value, "newsletter");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("falls back to personal when the row carries no category", () => {
|
|
70
|
+
const result = buildCategoryIntel(makeThread(), undefined);
|
|
71
|
+
assert.equal(result.value, "personal");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("resolves a category the client does not know to uncategorized", () => {
|
|
75
|
+
const result = buildCategoryIntel(
|
|
76
|
+
threadCategorizedAs("invoice"),
|
|
77
|
+
undefined,
|
|
78
|
+
);
|
|
79
|
+
assert.equal(result.value, "uncategorized");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("marks the category overridden when the sender carries a different one", () => {
|
|
83
|
+
const thread = makeThread({ category: "personal" });
|
|
84
|
+
const address = makeAddress({
|
|
85
|
+
flags: { category: { value: "newsletter" } },
|
|
86
|
+
} as Partial<RemitImapAddressResponse>);
|
|
87
|
+
assert.equal(buildCategoryIntel(thread, address).overridden, true);
|
|
88
|
+
assert.equal(buildCategoryIntel(thread, undefined).overridden, false);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
52
92
|
describe("buildSenderIntel", () => {
|
|
53
93
|
describe("counter wiring — counters present", () => {
|
|
54
94
|
test("surfaces inboundCount from address", () => {
|
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
SenderIntel,
|
|
16
16
|
SimilarMessageIntel,
|
|
17
17
|
} from "@remit/ui";
|
|
18
|
+
import { isThreadCategory } from "@remit/ui";
|
|
18
19
|
import { useQuery } from "@tanstack/react-query";
|
|
19
20
|
import { useMemo } from "react";
|
|
20
21
|
import { isServerError } from "@/lib/error-classifier";
|
|
@@ -56,6 +57,28 @@ const NO_SIGNAL_SUMMARY =
|
|
|
56
57
|
const UNREADABLE_SENDER_SUMMARY =
|
|
57
58
|
"We couldn't read this sender's address, so we can't confirm who really sent this message.";
|
|
58
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Build category intel from the thread message and address lookup.
|
|
62
|
+
*
|
|
63
|
+
* The row's category is a string the API chose, so it is narrowed rather than
|
|
64
|
+
* asserted: a value this build has no entry for — a category a newer server
|
|
65
|
+
* classifies into — resolves to `uncategorized`, which is the taxonomy's own
|
|
66
|
+
* name for "no classification this client can act on" and renders a readable
|
|
67
|
+
* neutral chip. Asserting instead would leave the chip with no tone at all.
|
|
68
|
+
*/
|
|
69
|
+
export function buildCategoryIntel(
|
|
70
|
+
thread: RemitImapThreadMessageResponse,
|
|
71
|
+
address: RemitImapAddressResponse | undefined,
|
|
72
|
+
): IntelligenceData["category"] {
|
|
73
|
+
const served = thread.category ?? "personal";
|
|
74
|
+
return {
|
|
75
|
+
value: isThreadCategory(served) ? served : "uncategorized",
|
|
76
|
+
overridden:
|
|
77
|
+
address?.flags?.category?.value != null &&
|
|
78
|
+
address.flags.category.value !== thread.category,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
59
82
|
/**
|
|
60
83
|
* Build sender intel from the thread message and address lookup.
|
|
61
84
|
*
|
|
@@ -357,12 +380,7 @@ export function useIntelligenceData(
|
|
|
357
380
|
|
|
358
381
|
const authenticity = buildAuthenticityIntel(thread, similar.length);
|
|
359
382
|
|
|
360
|
-
const category =
|
|
361
|
-
value: thread.category ?? "personal",
|
|
362
|
-
overridden:
|
|
363
|
-
address?.flags?.category?.value != null &&
|
|
364
|
-
address.flags.category.value !== thread.category,
|
|
365
|
-
};
|
|
383
|
+
const category = buildCategoryIntel(thread, address);
|
|
366
384
|
|
|
367
385
|
const flags = buildSenderFlags(address);
|
|
368
386
|
|