@remit/web-client 0.0.283 → 0.0.285
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 +1 -1
- package/src/components/settings/QuarantinePanel.render.test.ts +1 -1
- package/src/components/settings/QuarantinePanel.tsx +2 -2
- package/src/hooks/useResultFolderIndex.ts +7 -3
- package/src/hooks/useRulePreview.ts +1 -0
- package/src/hooks/useTriggerSync.ts +7 -1
- package/src/lib/organize/rule-model.test.ts +30 -0
- package/src/lib/organize/rule-model.ts +5 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remit/web-client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.285",
|
|
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": {
|
|
@@ -17,7 +17,7 @@ import { QuarantinePanelView } from "./QuarantinePanel";
|
|
|
17
17
|
const render = (props: {
|
|
18
18
|
entries: readonly QuarantineEntry[];
|
|
19
19
|
isPending: boolean;
|
|
20
|
-
error:
|
|
20
|
+
error: unknown;
|
|
21
21
|
}): string =>
|
|
22
22
|
renderToString(createElement(QuarantinePanelView, props) as never);
|
|
23
23
|
|
|
@@ -44,7 +44,7 @@ function issueUrlFor(entry: QuarantineEntry): string {
|
|
|
44
44
|
);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
function QuarantineReadFailure({ error }: { error:
|
|
47
|
+
function QuarantineReadFailure({ error }: { error: unknown }) {
|
|
48
48
|
return (
|
|
49
49
|
<section role="alert" className="space-y-3">
|
|
50
50
|
<h2 className="text-sm font-semibold text-fg">Messages set aside</h2>
|
|
@@ -77,7 +77,7 @@ function QuarantineReadFailure({ error }: { error: Error }) {
|
|
|
77
77
|
export interface QuarantinePanelViewProps {
|
|
78
78
|
entries: readonly QuarantineEntry[];
|
|
79
79
|
isPending: boolean;
|
|
80
|
-
error:
|
|
80
|
+
error: unknown;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
export function QuarantinePanelView({
|
|
@@ -25,13 +25,17 @@ type MailboxItems = RemitImapMailboxResponse[];
|
|
|
25
25
|
interface MailboxListsState {
|
|
26
26
|
items: MailboxItems[];
|
|
27
27
|
isPending: boolean;
|
|
28
|
-
|
|
28
|
+
// Typed as the generated wire body by TanStack now that the operation
|
|
29
|
+
// declares its failures, but always an `ApiError` or a `NetworkError` by the
|
|
30
|
+
// time it arrives — `client.ts` re-wraps every HTTP failure.
|
|
31
|
+
// `formatErrorMessage` reads a message off any of them.
|
|
32
|
+
error: unknown;
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
export interface ResultFolderIndexState {
|
|
32
36
|
index: ResultFolderIndex;
|
|
33
37
|
isPending: boolean;
|
|
34
|
-
error:
|
|
38
|
+
error: unknown;
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
/**
|
|
@@ -44,7 +48,7 @@ const combineMailboxLists = (
|
|
|
44
48
|
results: {
|
|
45
49
|
data?: { items: MailboxItems };
|
|
46
50
|
isPending: boolean;
|
|
47
|
-
error:
|
|
51
|
+
error: unknown;
|
|
48
52
|
}[],
|
|
49
53
|
): MailboxListsState => ({
|
|
50
54
|
items: results.map((result) => result.data?.items ?? []),
|
|
@@ -9,7 +9,13 @@ interface UseTriggerSyncResult {
|
|
|
9
9
|
trigger: () => void;
|
|
10
10
|
triggerAsync: () => Promise<unknown>;
|
|
11
11
|
isPending: boolean;
|
|
12
|
-
|
|
12
|
+
// TanStack types this as the generated wire body now that the operation
|
|
13
|
+
// declares its failures; by the time it arrives, `client.ts`'s error
|
|
14
|
+
// interceptor has re-wrapped it as an `ApiError` and `taggedFetch` a
|
|
15
|
+
// transport failure as a `NetworkError`. `unknown` is what the declared type
|
|
16
|
+
// and the real one agree on, and every reader goes through
|
|
17
|
+
// `formatErrorMessage`.
|
|
18
|
+
error: unknown;
|
|
13
19
|
reset: () => void;
|
|
14
20
|
}
|
|
15
21
|
|
|
@@ -276,6 +276,36 @@ describe("derivePreview", () => {
|
|
|
276
276
|
);
|
|
277
277
|
});
|
|
278
278
|
|
|
279
|
+
it("carries the empty-index answer through, so a zero can say why (#452)", () => {
|
|
280
|
+
assert.deepEqual(
|
|
281
|
+
derivePreview(
|
|
282
|
+
{ count: 0, indexEmpty: true, previewedSignature: signature },
|
|
283
|
+
signature,
|
|
284
|
+
),
|
|
285
|
+
{ status: "ready", count: 0, indexEmpty: true },
|
|
286
|
+
);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it("keeps the empty-index answer on a stale count", () => {
|
|
290
|
+
assert.deepEqual(
|
|
291
|
+
derivePreview(
|
|
292
|
+
{ count: 0, indexEmpty: true, previewedSignature: "sig-old" },
|
|
293
|
+
signature,
|
|
294
|
+
),
|
|
295
|
+
{ status: "ready", count: 0, stale: true, indexEmpty: true },
|
|
296
|
+
);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it("leaves the flag off when the index answered", () => {
|
|
300
|
+
assert.deepEqual(
|
|
301
|
+
derivePreview(
|
|
302
|
+
{ count: 0, indexEmpty: false, previewedSignature: signature },
|
|
303
|
+
signature,
|
|
304
|
+
),
|
|
305
|
+
{ status: "ready", count: 0 },
|
|
306
|
+
);
|
|
307
|
+
});
|
|
308
|
+
|
|
279
309
|
it("surfaces an error raised for the current predicate", () => {
|
|
280
310
|
assert.deepEqual(
|
|
281
311
|
derivePreview(
|
|
@@ -253,6 +253,8 @@ export interface PreviewState {
|
|
|
253
253
|
count?: number;
|
|
254
254
|
/** The ids that count was counted over, as the server bounded them. */
|
|
255
255
|
matchedIds?: readonly string[];
|
|
256
|
+
/** The server said the semantic index had nothing to answer with (#452). */
|
|
257
|
+
indexEmpty?: boolean;
|
|
256
258
|
/** The signature the {@link count} was counted for. */
|
|
257
259
|
previewedSignature?: string;
|
|
258
260
|
/** The signature the last error was raised for. */
|
|
@@ -274,10 +276,11 @@ export const derivePreview = (
|
|
|
274
276
|
return { status: "error", reason: state.error };
|
|
275
277
|
}
|
|
276
278
|
if (state.count === undefined) return { status: "loading" };
|
|
279
|
+
const indexEmpty = state.indexEmpty === true ? { indexEmpty: true } : {};
|
|
277
280
|
if (state.previewedSignature === currentSignature) {
|
|
278
|
-
return { status: "ready", count: state.count };
|
|
281
|
+
return { status: "ready", count: state.count, ...indexEmpty };
|
|
279
282
|
}
|
|
280
|
-
return { status: "ready", count: state.count, stale: true };
|
|
283
|
+
return { status: "ready", count: state.count, stale: true, ...indexEmpty };
|
|
281
284
|
};
|
|
282
285
|
|
|
283
286
|
/** How long a rule change settles before the next preview fires. */
|