@wirecat/cli-core 0.509.0 → 0.510.0
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/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,16 @@ shape of this file.
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## 0.510.0 — 31.10.2026
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **`search events --backend both` marks a repeating event the provider also found.** The stored search shows a series
|
|
15
|
+
as one hit, while a provider such as Google answers the series and each moved occurrence apart, so 0.508.0 left the
|
|
16
|
+
stored hit without `server` and listed the provider's copies again below it. A provider hit is now matched through
|
|
17
|
+
its stored copy's series, and the stored hit takes `server` once.
|
|
18
|
+
- **`search events --help`** says what `--backend both` does in words ("ask both").
|
|
19
|
+
|
|
10
20
|
## 0.509.0 — 31.10.2026
|
|
11
21
|
|
|
12
22
|
### Changed — may break callers
|
|
@@ -226,7 +226,7 @@ const addCalendarCommandsDefinition = (program, deps) => {
|
|
|
226
226
|
const search = example(annotate(searches.command("events"), { effects: deps.serverSearch ? LOCAL_OR_REMOTE_READ : LOCAL_READ })
|
|
227
227
|
.description(deps.serverSearch
|
|
228
228
|
? "find stored events by words, and by meaning when its model is downloaded; with --backend server, ask " +
|
|
229
|
-
"the provider instead, with --backend both, both"
|
|
229
|
+
"the provider instead, or with --backend both, ask both"
|
|
230
230
|
: "find stored events by words, and by meaning when its model is downloaded")
|
|
231
231
|
.argument("<query...>", "what to find in titles, descriptions, places and attendees"), "search events roadmap planning --json", ...(deps.serverSearch
|
|
232
232
|
? ["search events --backend server quarterly review", "search events --backend both quarterly review"]
|
|
@@ -35,7 +35,8 @@ type ServerFound = Awaited<ReturnType<typeof serverSearchAnswer>>;
|
|
|
35
35
|
/**
|
|
36
36
|
* `--backend both`: the stored search's hits in its own order, each one the provider also found marked `server`, then
|
|
37
37
|
* what only the provider found, earliest first. One page and no cursor: the two sides rank and page differently.
|
|
38
|
-
* A provider hit is matched
|
|
38
|
+
* A provider hit is matched through its stored copy: a series, or any of its occurrences, to the stored hit of that
|
|
39
|
+
* series. A provider hit the store does not hold is listed on its own.
|
|
39
40
|
*/
|
|
40
41
|
export declare const bothSearchAnswer: (store: EventStore, accountId: number, archived: EventsFound, served: ServerFound, limit: number) => Promise<{
|
|
41
42
|
query: string;
|
|
@@ -39,24 +39,34 @@ export const serverSearchAnswer = async (source, store, { accountId, account, qu
|
|
|
39
39
|
hits.sort((a, b) => (a.starts_at ?? "").localeCompare(b.starts_at ?? ""));
|
|
40
40
|
return { query, by: "server", hits: hits.slice(0, limit), has_more: more || hits.length > limit };
|
|
41
41
|
};
|
|
42
|
+
/** As the stored search groups hits: the occurrences of one series are one hit. */
|
|
43
|
+
const groupOf = (eventId, eventSeriesId) => eventSeriesId !== null ? `s${eventSeriesId}` : eventId !== null ? `e${eventId}` : undefined;
|
|
42
44
|
/**
|
|
43
45
|
* `--backend both`: the stored search's hits in its own order, each one the provider also found marked `server`, then
|
|
44
46
|
* what only the provider found, earliest first. One page and no cursor: the two sides rank and page differently.
|
|
45
|
-
* A provider hit is matched
|
|
47
|
+
* A provider hit is matched through its stored copy: a series, or any of its occurrences, to the stored hit of that
|
|
48
|
+
* series. A provider hit the store does not hold is listed on its own.
|
|
46
49
|
*/
|
|
47
50
|
export const bothSearchAnswer = async (store, accountId, archived, served, limit) => {
|
|
48
51
|
const calendars = new Map((await store.calendars(accountId)).map((calendar) => [calendar.externalId, calendar]));
|
|
49
52
|
const hits = archived.hits.map((hit) => ({ ...hit }));
|
|
50
|
-
const
|
|
53
|
+
const byGroup = new Map();
|
|
54
|
+
for (const hit of hits) {
|
|
55
|
+
const details = await store.event(Number(hit.ref.slice("event:".length)));
|
|
56
|
+
const group = details && groupOf(details.event.id, details.event.eventSeriesId);
|
|
57
|
+
if (group)
|
|
58
|
+
byGroup.set(group, hit);
|
|
59
|
+
}
|
|
51
60
|
const onlyServer = [];
|
|
52
61
|
for (const hit of served.hits) {
|
|
53
62
|
const calendar = calendars.get(hit.calendar);
|
|
54
63
|
const entry = calendar ? await store.entry(calendar.id, hit.external_id) : null;
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
else
|
|
64
|
+
const group = entry ? groupOf(entry.eventId, entry.eventSeriesId) : undefined;
|
|
65
|
+
const held = group === undefined ? undefined : byGroup.get(group);
|
|
66
|
+
if (!held)
|
|
59
67
|
onlyServer.push(hit);
|
|
68
|
+
else if (!held.found_by.includes("server"))
|
|
69
|
+
held.found_by = [...held.found_by, "server"];
|
|
60
70
|
}
|
|
61
71
|
const merged = [...hits, ...onlyServer];
|
|
62
72
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.510.0",
|
|
4
4
|
"description": "The messenger-neutral half of a messaging CLI: domain model, message locators, rendering, name resolution, the SQLite seam, the command skeleton and shared read commands, the send guard, run records and the message store",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|