@wirecat/cli-memo 0.0.0-stage → 0.5.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/LICENSE +21 -0
- package/README.md +314 -2
- package/dist/answers/command.d.ts +35 -0
- package/dist/answers/command.d.ts.map +1 -0
- package/dist/answers/command.js +117 -0
- package/dist/answers/command.js.map +1 -0
- package/dist/app.d.ts +9 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +10 -0
- package/dist/app.js.map +1 -0
- package/dist/bin/memo.d.ts +3 -0
- package/dist/bin/memo.d.ts.map +1 -0
- package/dist/bin/memo.js +14 -0
- package/dist/bin/memo.js.map +1 -0
- package/dist/config.d.ts +39 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +40 -0
- package/dist/config.js.map +1 -0
- package/dist/context/command.d.ts +6 -0
- package/dist/context/command.d.ts.map +1 -0
- package/dist/context/command.js +73 -0
- package/dist/context/command.js.map +1 -0
- package/dist/context/context.d.ts +28 -0
- package/dist/context/context.d.ts.map +1 -0
- package/dist/context/context.js +49 -0
- package/dist/context/context.js.map +1 -0
- package/dist/knowledge/command.d.ts +4 -0
- package/dist/knowledge/command.d.ts.map +1 -0
- package/dist/knowledge/command.js +158 -0
- package/dist/knowledge/command.js.map +1 -0
- package/dist/mail/command.d.ts +4 -0
- package/dist/mail/command.d.ts.map +1 -0
- package/dist/mail/command.js +61 -0
- package/dist/mail/command.js.map +1 -0
- package/dist/mail/gmail.d.ts +18 -0
- package/dist/mail/gmail.d.ts.map +1 -0
- package/dist/mail/gmail.js +103 -0
- package/dist/mail/gmail.js.map +1 -0
- package/dist/mail/himalaya.d.ts +4 -0
- package/dist/mail/himalaya.d.ts.map +1 -0
- package/dist/mail/himalaya.js +13 -0
- package/dist/mail/himalaya.js.map +1 -0
- package/dist/mail/import.d.ts +53 -0
- package/dist/mail/import.d.ts.map +1 -0
- package/dist/mail/import.js +170 -0
- package/dist/mail/import.js.map +1 -0
- package/dist/mail/parse.d.ts +21 -0
- package/dist/mail/parse.d.ts.map +1 -0
- package/dist/mail/parse.js +86 -0
- package/dist/mail/parse.js.map +1 -0
- package/dist/notes/about.d.ts +31 -0
- package/dist/notes/about.d.ts.map +1 -0
- package/dist/notes/about.js +69 -0
- package/dist/notes/about.js.map +1 -0
- package/dist/notes/bound.d.ts +24 -0
- package/dist/notes/bound.d.ts.map +1 -0
- package/dist/notes/bound.js +57 -0
- package/dist/notes/bound.js.map +1 -0
- package/dist/notes/command.d.ts +4 -0
- package/dist/notes/command.d.ts.map +1 -0
- package/dist/notes/command.js +222 -0
- package/dist/notes/command.js.map +1 -0
- package/dist/notes/dialects/common.d.ts +18 -0
- package/dist/notes/dialects/common.d.ts.map +1 -0
- package/dist/notes/dialects/common.js +79 -0
- package/dist/notes/dialects/common.js.map +1 -0
- package/dist/notes/dialects/index.d.ts +5 -0
- package/dist/notes/dialects/index.d.ts.map +1 -0
- package/dist/notes/dialects/index.js +6 -0
- package/dist/notes/dialects/index.js.map +1 -0
- package/dist/notes/dialects/markdown.d.ts +7 -0
- package/dist/notes/dialects/markdown.d.ts.map +1 -0
- package/dist/notes/dialects/markdown.js +51 -0
- package/dist/notes/dialects/markdown.js.map +1 -0
- package/dist/notes/dialects/obsidian.d.ts +6 -0
- package/dist/notes/dialects/obsidian.d.ts.map +1 -0
- package/dist/notes/dialects/obsidian.js +33 -0
- package/dist/notes/dialects/obsidian.js.map +1 -0
- package/dist/notes/dialects/types.d.ts +39 -0
- package/dist/notes/dialects/types.d.ts.map +1 -0
- package/dist/notes/dialects/types.js +2 -0
- package/dist/notes/dialects/types.js.map +1 -0
- package/dist/notes/embed.d.ts +51 -0
- package/dist/notes/embed.d.ts.map +1 -0
- package/dist/notes/embed.js +109 -0
- package/dist/notes/embed.js.map +1 -0
- package/dist/notes/export.d.ts +27 -0
- package/dist/notes/export.d.ts.map +1 -0
- package/dist/notes/export.js +76 -0
- package/dist/notes/export.js.map +1 -0
- package/dist/notes/files.d.ts +14 -0
- package/dist/notes/files.d.ts.map +1 -0
- package/dist/notes/files.js +77 -0
- package/dist/notes/files.js.map +1 -0
- package/dist/notes/folders-command.d.ts +4 -0
- package/dist/notes/folders-command.d.ts.map +1 -0
- package/dist/notes/folders-command.js +113 -0
- package/dist/notes/folders-command.js.map +1 -0
- package/dist/notes/folders.d.ts +27 -0
- package/dist/notes/folders.d.ts.map +1 -0
- package/dist/notes/folders.js +46 -0
- package/dist/notes/folders.js.map +1 -0
- package/dist/notes/import.d.ts +33 -0
- package/dist/notes/import.d.ts.map +1 -0
- package/dist/notes/import.js +183 -0
- package/dist/notes/import.js.map +1 -0
- package/dist/notes/internal.d.ts +17 -0
- package/dist/notes/internal.d.ts.map +1 -0
- package/dist/notes/internal.js +47 -0
- package/dist/notes/internal.js.map +1 -0
- package/dist/notes/links.d.ts +18 -0
- package/dist/notes/links.d.ts.map +1 -0
- package/dist/notes/links.js +44 -0
- package/dist/notes/links.js.map +1 -0
- package/dist/notes/renames.d.ts +11 -0
- package/dist/notes/renames.d.ts.map +1 -0
- package/dist/notes/renames.js +24 -0
- package/dist/notes/renames.js.map +1 -0
- package/dist/notes/search.d.ts +5 -0
- package/dist/notes/search.d.ts.map +1 -0
- package/dist/notes/search.js +20 -0
- package/dist/notes/search.js.map +1 -0
- package/dist/notes/state.d.ts +14 -0
- package/dist/notes/state.d.ts.map +1 -0
- package/dist/notes/state.js +21 -0
- package/dist/notes/state.js.map +1 -0
- package/dist/options.d.ts +4 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +12 -0
- package/dist/options.js.map +1 -0
- package/dist/people/command.d.ts +5 -0
- package/dist/people/command.d.ts.map +1 -0
- package/dist/people/command.js +57 -0
- package/dist/people/command.js.map +1 -0
- package/dist/people/identity.d.ts +4 -0
- package/dist/people/identity.d.ts.map +1 -0
- package/dist/people/identity.js +13 -0
- package/dist/people/identity.js.map +1 -0
- package/dist/people/notes-map.d.ts +13 -0
- package/dist/people/notes-map.d.ts.map +1 -0
- package/dist/people/notes-map.js +49 -0
- package/dist/people/notes-map.js.map +1 -0
- package/dist/people/subject.d.ts +8 -0
- package/dist/people/subject.d.ts.map +1 -0
- package/dist/people/subject.js +19 -0
- package/dist/people/subject.js.map +1 -0
- package/dist/program.d.ts +7 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +34 -0
- package/dist/program.js.map +1 -0
- package/dist/run/auto.d.ts +20 -0
- package/dist/run/auto.d.ts.map +1 -0
- package/dist/run/auto.js +139 -0
- package/dist/run/auto.js.map +1 -0
- package/dist/run/import.d.ts +18 -0
- package/dist/run/import.d.ts.map +1 -0
- package/dist/run/import.js +114 -0
- package/dist/run/import.js.map +1 -0
- package/dist/search/command.d.ts +38 -0
- package/dist/search/command.d.ts.map +1 -0
- package/dist/search/command.js +269 -0
- package/dist/search/command.js.map +1 -0
- package/dist/store/gone.d.ts +17 -0
- package/dist/store/gone.d.ts.map +1 -0
- package/dist/store/gone.js +52 -0
- package/dist/store/gone.js.map +1 -0
- package/dist/store/scope.d.ts +19 -0
- package/dist/store/scope.d.ts.map +1 -0
- package/dist/store/scope.js +34 -0
- package/dist/store/scope.js.map +1 -0
- package/dist/store/source-target.d.ts +18 -0
- package/dist/store/source-target.d.ts.map +1 -0
- package/dist/store/source-target.js +28 -0
- package/dist/store/source-target.js.map +1 -0
- package/dist/tags/command.d.ts +4 -0
- package/dist/tags/command.d.ts.map +1 -0
- package/dist/tags/command.js +166 -0
- package/dist/tags/command.js.map +1 -0
- package/dist/tasks/command.d.ts +4 -0
- package/dist/tasks/command.d.ts.map +1 -0
- package/dist/tasks/command.js +83 -0
- package/dist/tasks/command.js.map +1 -0
- package/dist/tasks/context.d.ts +16 -0
- package/dist/tasks/context.d.ts.map +1 -0
- package/dist/tasks/context.js +68 -0
- package/dist/tasks/context.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/package.json +53 -4
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { CliError } from "@wirecat/cli-core";
|
|
3
|
+
import { openStore } from "@wirecat/cli-messaging/store";
|
|
4
|
+
import { boundFolders, folderOfFile } from "../notes/bound.js";
|
|
5
|
+
import { folderNotes } from "../notes/import.js";
|
|
6
|
+
import { identityOf } from "./identity.js";
|
|
7
|
+
import { importNotesMap } from "./notes-map.js";
|
|
8
|
+
/** Who is who is linked in messaging (`tg contacts link`); the note about a person is an `about` link. */
|
|
9
|
+
export const noteCommand = (program, streams, env) => {
|
|
10
|
+
program
|
|
11
|
+
.command("note")
|
|
12
|
+
.description("Name the note that is about a person, or show it")
|
|
13
|
+
.argument("<identity>", "<messenger>:<name or id> of any identity of the person")
|
|
14
|
+
.argument("[path]", "the note about them, a file in a configured folder")
|
|
15
|
+
.option("--clear", "forget which file note is about them")
|
|
16
|
+
.action(async (identity, path, options) => {
|
|
17
|
+
const store = await openStore({ env });
|
|
18
|
+
try {
|
|
19
|
+
const folders = await boundFolders(store, env, { strict: false });
|
|
20
|
+
await importNotesMap(store, env, folders);
|
|
21
|
+
const person = await store.personOf(await identityOf(store, identity));
|
|
22
|
+
if (person === undefined)
|
|
23
|
+
throw new CliError("not_found", `the store has no person for "${identity}"`);
|
|
24
|
+
const to = `person:${person.uid}`;
|
|
25
|
+
const files = async () => {
|
|
26
|
+
const found = [];
|
|
27
|
+
for (const link of await store.notes.links({ to })) {
|
|
28
|
+
if (link.kind !== "about" || link.origin !== "owner")
|
|
29
|
+
continue;
|
|
30
|
+
const note = await store.notes.note(link.from.replace(/^note:/, "")).catch(() => undefined);
|
|
31
|
+
if (note?.source === "file" && note.deletedAt === null)
|
|
32
|
+
found.push({ link, note });
|
|
33
|
+
}
|
|
34
|
+
return found;
|
|
35
|
+
};
|
|
36
|
+
if (options.clear)
|
|
37
|
+
for (const { link } of await files())
|
|
38
|
+
await store.notes.removeLink(link.id);
|
|
39
|
+
else if (path !== undefined) {
|
|
40
|
+
const { folder, path: inside } = folderOfFile(folders, path);
|
|
41
|
+
const note = (await folderNotes(store, folder.id)).find((candidate) => candidate.path === inside);
|
|
42
|
+
if (!note)
|
|
43
|
+
throw new CliError("not_found", `${path} is not imported yet — memo notes import`);
|
|
44
|
+
await store.notes.addLink({ from: `note:${note.id}`, to, kind: "about", origin: "owner" });
|
|
45
|
+
}
|
|
46
|
+
const shown = (await files()).map(({ note }) => {
|
|
47
|
+
const folder = folders.find((candidate) => candidate.id === note.folderId);
|
|
48
|
+
return folder ? join(folder.path, note.path) : `note:${note.id}`;
|
|
49
|
+
});
|
|
50
|
+
streams.data(`${person.name ?? person.uid}: ${shown.join(", ") || "no note"}\n`);
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
await store.close();
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/people/command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IdentityRef, MessageStore } from "@wirecat/cli-messaging/store";
|
|
2
|
+
/** `telegram:Ana`, `max:12345`, `email:ana@example.com` — the messenger is always named. */
|
|
3
|
+
export declare const identityOf: (store: MessageStore, reference: string) => Promise<IdentityRef>;
|
|
4
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/people/identity.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAE7E,4FAA4F;AAC5F,eAAO,MAAM,UAAU,UAAiB,YAAY,aAAa,MAAM,KAAG,OAAO,CAAC,WAAW,CAQ5F,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CliError } from "@wirecat/cli-core";
|
|
2
|
+
import { pickPerson } from "@wirecat/cli-messaging";
|
|
3
|
+
/** `telegram:Ana`, `max:12345`, `email:ana@example.com` — the messenger is always named. */
|
|
4
|
+
export const identityOf = async (store, reference) => {
|
|
5
|
+
const match = /^([a-z][a-z0-9-]*):(.+)$/.exec(reference.trim());
|
|
6
|
+
if (match === null)
|
|
7
|
+
throw new CliError("validation_error", `"${reference}" names no messenger — write it as <messenger>:<name or id>`);
|
|
8
|
+
const [, provider = "", who = ""] = match;
|
|
9
|
+
const people = await store.people(provider);
|
|
10
|
+
const exact = people.get(provider === "email" ? who.toLowerCase() : who);
|
|
11
|
+
return { provider, id: exact?.id ?? pickPerson(who, people).id };
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/people/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAGnD,4FAA4F;AAC5F,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,KAAmB,EAAE,SAAiB,EAAwB,EAAE;IAC/F,MAAM,KAAK,GAAG,0BAA0B,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAA;IAC/D,IAAI,KAAK,KAAK,IAAI;QAChB,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,IAAI,SAAS,6DAA6D,CAAC,CAAA;IACpH,MAAM,CAAC,EAAE,QAAQ,GAAG,EAAE,EAAE,GAAG,GAAG,EAAE,CAAC,GAAG,KAAK,CAAA;IACzC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IACxE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,EAAE,CAAA;AAClE,CAAC,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MessageStore } from "@wirecat/cli-messaging/store";
|
|
2
|
+
import * as v from "valibot";
|
|
3
|
+
import { type BoundFolder } from "../notes/bound.js";
|
|
4
|
+
declare const NotesMapSchema: v.RecordSchema<v.StringSchema<undefined>, v.StringSchema<undefined>, undefined>;
|
|
5
|
+
/** Person uid → the note about them, as `memo note` kept it before the store could hold the link. */
|
|
6
|
+
export type NotesMap = v.InferOutput<typeof NotesMapSchema>;
|
|
7
|
+
/**
|
|
8
|
+
* Moves each entry of the old `people-notes.json` into the store as an `about` link, once. An entry whose
|
|
9
|
+
* note is not imported yet waits for a later run; the file itself is left as the owner wrote it.
|
|
10
|
+
*/
|
|
11
|
+
export declare const importNotesMap: (store: MessageStore, env: NodeJS.ProcessEnv, folders: BoundFolder[]) => Promise<number>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=notes-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notes-map.d.ts","sourceRoot":"","sources":["../../src/people/notes-map.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAChE,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAC5B,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,mBAAmB,CAAA;AAGlE,QAAA,MAAM,cAAc,iFAAmC,CAAA;AAEvD,qGAAqG;AACrG,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,cAAc,CAAC,CAAA;AAQ3D;;;GAGG;AACH,eAAO,MAAM,cAAc,UAClB,YAAY,OACd,MAAM,CAAC,UAAU,WACb,WAAW,EAAE,KACrB,OAAO,CAAC,MAAM,CAgChB,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { loadConfigFile, resolvePaths } from "@wirecat/cli-core";
|
|
4
|
+
import * as v from "valibot";
|
|
5
|
+
import { folderOfFile } from "../notes/bound.js";
|
|
6
|
+
import { folderNotes } from "../notes/import.js";
|
|
7
|
+
const NotesMapSchema = v.record(v.string(), v.string());
|
|
8
|
+
const mapPath = (env) => join(resolvePaths({ appName: "cli-memo", prefix: "MEMO", env }).config, "people-notes.json");
|
|
9
|
+
const donePath = (env) => join(resolvePaths({ appName: "cli-memo", prefix: "MEMO", env }).state, "people-notes-imported.json");
|
|
10
|
+
/**
|
|
11
|
+
* Moves each entry of the old `people-notes.json` into the store as an `about` link, once. An entry whose
|
|
12
|
+
* note is not imported yet waits for a later run; the file itself is left as the owner wrote it.
|
|
13
|
+
*/
|
|
14
|
+
export const importNotesMap = async (store, env, folders) => {
|
|
15
|
+
if (!existsSync(mapPath(env)))
|
|
16
|
+
return 0;
|
|
17
|
+
const map = loadConfigFile(mapPath(env), NotesMapSchema, () => ({}));
|
|
18
|
+
let done = [];
|
|
19
|
+
try {
|
|
20
|
+
done = JSON.parse(readFileSync(donePath(env), "utf8"));
|
|
21
|
+
}
|
|
22
|
+
catch { }
|
|
23
|
+
const pending = Object.entries(map).filter(([uid]) => !done.includes(uid));
|
|
24
|
+
if (pending.length === 0)
|
|
25
|
+
return 0;
|
|
26
|
+
const byFolder = new Map();
|
|
27
|
+
let linked = 0;
|
|
28
|
+
for (const [uid, file] of pending) {
|
|
29
|
+
let place;
|
|
30
|
+
try {
|
|
31
|
+
place = folderOfFile(folders, file);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (!byFolder.has(place.folder.id))
|
|
37
|
+
byFolder.set(place.folder.id, new Map((await folderNotes(store, place.folder.id)).map((note) => [note.path, note.id])));
|
|
38
|
+
const id = byFolder.get(place.folder.id)?.get(place.path);
|
|
39
|
+
if (id === undefined)
|
|
40
|
+
continue;
|
|
41
|
+
await store.notes.addLink({ from: `note:${id}`, to: `person:${uid}`, kind: "about", origin: "owner" });
|
|
42
|
+
done.push(uid);
|
|
43
|
+
linked++;
|
|
44
|
+
}
|
|
45
|
+
mkdirSync(join(donePath(env), ".."), { recursive: true });
|
|
46
|
+
writeFileSync(donePath(env), JSON.stringify(done));
|
|
47
|
+
return linked;
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=notes-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notes-map.js","sourceRoot":"","sources":["../../src/people/notes-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MessageStore, PersonRecord } from "@wirecat/cli-messaging/store";
|
|
2
|
+
export interface Subject {
|
|
3
|
+
ref: string;
|
|
4
|
+
person?: PersonRecord;
|
|
5
|
+
}
|
|
6
|
+
/** A typed reference as written, or `<messenger>:<name or id>` turned into the person behind it. */
|
|
7
|
+
export declare const subjectOf: (store: MessageStore, text: string) => Promise<Subject>;
|
|
8
|
+
//# sourceMappingURL=subject.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subject.d.ts","sourceRoot":"","sources":["../../src/people/subject.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAK9E,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,YAAY,CAAA;CACtB;AAED,oGAAoG;AACpG,eAAO,MAAM,SAAS,UAAiB,YAAY,QAAQ,MAAM,KAAG,OAAO,CAAC,OAAO,CAYlF,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { formatReference } from "@wirecat/cli-messaging";
|
|
2
|
+
import { identityOf } from "./identity.js";
|
|
3
|
+
const TYPED = /^(person|entity|note|task|msg|chat|contact|folder):\S+$/;
|
|
4
|
+
/** A typed reference as written, or `<messenger>:<name or id>` turned into the person behind it. */
|
|
5
|
+
export const subjectOf = async (store, text) => {
|
|
6
|
+
const typed = text.trim();
|
|
7
|
+
if (typed.startsWith("person:")) {
|
|
8
|
+
const person = await store.personByUid(typed.slice("person:".length));
|
|
9
|
+
return person === undefined ? { ref: typed } : { ref: typed, person };
|
|
10
|
+
}
|
|
11
|
+
if (TYPED.test(typed))
|
|
12
|
+
return { ref: typed };
|
|
13
|
+
const identity = await identityOf(store, text);
|
|
14
|
+
const person = await store.personOf(identity);
|
|
15
|
+
return person === undefined
|
|
16
|
+
? { ref: formatReference({ type: "contact", provider: identity.provider, id: identity.id }) }
|
|
17
|
+
: { ref: `person:${person.uid}`, person };
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=subject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subject.js","sourceRoot":"","sources":["../../src/people/subject.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAE1C,MAAM,KAAK,GAAG,yDAAyD,CAAA;AAOvE,oGAAoG;AACpG,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,KAAmB,EAAE,IAAY,EAAoB,EAAE;IACrF,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IACzB,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAA;QACrE,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;IACvE,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAA;IAC5C,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IAC9C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC7C,OAAO,MAAM,KAAK,SAAS;QACzB,CAAC,CAAC,EAAE,GAAG,EAAE,eAAe,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,EAAE;QAC7F,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,MAAM,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,CAAA;AAC7C,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAenC,eAAO,MAAM,aAAa,uBAGvB;IACD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CACxB,KAAQ,OAmBR,CAAA"}
|
package/dist/program.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { processStreams } from "@wirecat/cli-core";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { askCommand } from "./answers/command.js";
|
|
4
|
+
import { contextCommand } from "./context/command.js";
|
|
5
|
+
import { knowledgeCommands } from "./knowledge/command.js";
|
|
6
|
+
import { mailCommand } from "./mail/command.js";
|
|
7
|
+
import { notesCommand } from "./notes/command.js";
|
|
8
|
+
import { foldersCommand } from "./notes/folders-command.js";
|
|
9
|
+
import { noteCommand } from "./people/command.js";
|
|
10
|
+
import { autoCommand } from "./run/auto.js";
|
|
11
|
+
import { importCommand } from "./run/import.js";
|
|
12
|
+
import { searchCommand } from "./search/command.js";
|
|
13
|
+
import { tagsCommand } from "./tags/command.js";
|
|
14
|
+
import { tasksCommand } from "./tasks/command.js";
|
|
15
|
+
import { VERSION } from "./version.js";
|
|
16
|
+
export const createProgram = ({ streams = processStreams, env = process.env, } = {}) => {
|
|
17
|
+
const program = new Command("memo")
|
|
18
|
+
.description("Context about people across messengers, notes and mail")
|
|
19
|
+
.version(VERSION);
|
|
20
|
+
contextCommand(program, streams, env);
|
|
21
|
+
notesCommand(program, streams, env);
|
|
22
|
+
foldersCommand(program, streams, env);
|
|
23
|
+
mailCommand(program, streams, env);
|
|
24
|
+
noteCommand(program, streams, env);
|
|
25
|
+
tagsCommand(program, streams, env);
|
|
26
|
+
tasksCommand(program, streams, env);
|
|
27
|
+
knowledgeCommands(program, streams, env);
|
|
28
|
+
searchCommand(program, streams, env);
|
|
29
|
+
askCommand(program, streams, env);
|
|
30
|
+
importCommand(program, streams, env);
|
|
31
|
+
autoCommand(program, streams, env);
|
|
32
|
+
return program;
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=program.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program.js","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAgB,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAC5B,OAAO,GAAG,cAAc,EACxB,GAAG,GAAG,OAAO,CAAC,GAAG,GAClB,GAGG,EAAE,EAAW,EAAE;IACjB,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;SAChC,WAAW,CAAC,wDAAwD,CAAC;SACrE,OAAO,CAAC,OAAO,CAAC,CAAA;IAEnB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IACrC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IACnC,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IACrC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IAClC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IAClC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IAClC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IACnC,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IACxC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IACpC,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IACjC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IACpC,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;IAElC,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Streams } from "@wirecat/cli-core";
|
|
2
|
+
import { type Command } from "commander";
|
|
3
|
+
import { type Config } from "../config.js";
|
|
4
|
+
export declare const DEFAULT_EVERY = "5m";
|
|
5
|
+
/** `5m`, `90s`, `1h` → systemd's `5min`, `90s`, `1h`; under a minute is refused. */
|
|
6
|
+
export declare const interval: (value: string) => string;
|
|
7
|
+
export declare const serviceUnit: (env: NodeJS.ProcessEnv) => string;
|
|
8
|
+
export declare const timerUnit: (every: string) => string;
|
|
9
|
+
export interface AutoState {
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
every: string;
|
|
12
|
+
}
|
|
13
|
+
export declare const autoState: (config: Config) => AutoState;
|
|
14
|
+
/**
|
|
15
|
+
* Makes the timer match the config: on with its interval, or gone. The config is the one source, so a
|
|
16
|
+
* hand edit of `auto` takes effect at the next timer run, which calls this first.
|
|
17
|
+
*/
|
|
18
|
+
export declare const applyAuto: (env: NodeJS.ProcessEnv, state: AutoState) => Promise<void>;
|
|
19
|
+
export declare const autoCommand: (program: Command, streams: Streams, env: NodeJS.ProcessEnv) => void;
|
|
20
|
+
//# sourceMappingURL=auto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto.d.ts","sourceRoot":"","sources":["../../src/run/auto.ts"],"names":[],"mappings":"AAKA,OAAO,EAA4B,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAC1E,OAAO,EAAE,KAAK,OAAO,EAAwB,MAAM,WAAW,CAAA;AAC9D,OAAO,EAAE,KAAK,MAAM,EAA4B,MAAM,cAAc,CAAA;AAEpE,eAAO,MAAM,aAAa,OAAO,CAAA;AAGjC,oFAAoF;AACpF,eAAO,MAAM,QAAQ,UAAW,MAAM,KAAG,MAKxC,CAAA;AAWD,eAAO,MAAM,WAAW,QAAS,MAAM,CAAC,UAAU,KAAG,MAYvC,CAAA;AAEd,eAAO,MAAM,SAAS,UAAW,MAAM,KAAG,MAa5B,CAAA;AAad,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,eAAO,MAAM,SAAS,WAAY,MAAM,KAAG,SAGzC,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,SAAS,QAAe,MAAM,CAAC,UAAU,SAAS,SAAS,KAAG,OAAO,CAAC,IAAI,CAwBtF,CAAA;AAED,eAAO,MAAM,WAAW,YAAa,OAAO,WAAW,OAAO,OAAO,MAAM,CAAC,UAAU,KAAG,IAiExF,CAAA"}
|
package/dist/run/auto.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { CliError, createRenderer } from "@wirecat/cli-core";
|
|
7
|
+
import { InvalidArgumentError } from "commander";
|
|
8
|
+
import { loadConfig, updateConfig } from "../config.js";
|
|
9
|
+
export const DEFAULT_EVERY = "5m";
|
|
10
|
+
const UNIT = "memo-import";
|
|
11
|
+
/** `5m`, `90s`, `1h` → systemd's `5min`, `90s`, `1h`; under a minute is refused. */
|
|
12
|
+
export const interval = (value) => {
|
|
13
|
+
const match = /^(\d+)(s|m|h)$/.exec(value.trim());
|
|
14
|
+
const seconds = match === null ? 0 : Number(match[1]) * { s: 1, m: 60, h: 3600 }[match[2]];
|
|
15
|
+
if (seconds < 60)
|
|
16
|
+
throw new InvalidArgumentError("an interval of a minute or more, like 5m, 90s or 1h");
|
|
17
|
+
return value.trim();
|
|
18
|
+
};
|
|
19
|
+
const systemdSpan = (every) => every.replace(/m$/, "min");
|
|
20
|
+
const unitDir = (env) => join(env.XDG_CONFIG_HOME ?? join(env.HOME ?? homedir(), ".config"), "systemd", "user");
|
|
21
|
+
const quote = (arg) => `"${arg.replace(/(["\\])/g, "\\$1")}"`;
|
|
22
|
+
const memoBin = () => resolve(dirname(fileURLToPath(import.meta.url)), "../bin/memo.js");
|
|
23
|
+
export const serviceUnit = (env) => [
|
|
24
|
+
"[Unit]",
|
|
25
|
+
"Description=memo: import notes and mail into the shared store",
|
|
26
|
+
"",
|
|
27
|
+
"[Service]",
|
|
28
|
+
"Type=oneshot",
|
|
29
|
+
`ExecStart=${[process.execPath, memoBin(), "import"].map(quote).join(" ")}`,
|
|
30
|
+
// Himalaya and the keyring helper it calls are found on the PATH memo was set up with.
|
|
31
|
+
`Environment=${quote(`PATH=${env.PATH ?? ""}`)} MEMO_AUTO=1`,
|
|
32
|
+
"Nice=10",
|
|
33
|
+
"",
|
|
34
|
+
].join("\n");
|
|
35
|
+
export const timerUnit = (every) => [
|
|
36
|
+
"[Unit]",
|
|
37
|
+
`Description=memo: import notes and mail every ${every}`,
|
|
38
|
+
"",
|
|
39
|
+
"[Timer]",
|
|
40
|
+
"OnActiveSec=1min",
|
|
41
|
+
`OnUnitActiveSec=${systemdSpan(every)}`,
|
|
42
|
+
"AccuracySec=30s",
|
|
43
|
+
"",
|
|
44
|
+
"[Install]",
|
|
45
|
+
"WantedBy=timers.target",
|
|
46
|
+
"",
|
|
47
|
+
].join("\n");
|
|
48
|
+
const systemctl = (env) => (...args) => new Promise((done, fail) => execFile(env.MEMO_SYSTEMCTL ?? "systemctl", ["--user", ...args], { env }, (error, stdout, stderr) => error === null
|
|
49
|
+
? done(stdout)
|
|
50
|
+
: fail(new CliError("provider_error", `systemctl ${args.join(" ")}: ${stderr.trim() || error.message}`))));
|
|
51
|
+
export const autoState = (config) => ({
|
|
52
|
+
enabled: config.auto?.enabled ?? false,
|
|
53
|
+
every: config.auto?.every ?? DEFAULT_EVERY,
|
|
54
|
+
});
|
|
55
|
+
/**
|
|
56
|
+
* Makes the timer match the config: on with its interval, or gone. The config is the one source, so a
|
|
57
|
+
* hand edit of `auto` takes effect at the next timer run, which calls this first.
|
|
58
|
+
*/
|
|
59
|
+
export const applyAuto = async (env, state) => {
|
|
60
|
+
const run = systemctl(env);
|
|
61
|
+
const dir = unitDir(env);
|
|
62
|
+
const timerPath = join(dir, `${UNIT}.timer`);
|
|
63
|
+
const servicePath = join(dir, `${UNIT}.service`);
|
|
64
|
+
if (!state.enabled) {
|
|
65
|
+
if (!existsSync(timerPath) && !existsSync(servicePath))
|
|
66
|
+
return;
|
|
67
|
+
await run("disable", "--now", `${UNIT}.timer`).catch(() => "");
|
|
68
|
+
rmSync(timerPath, { force: true });
|
|
69
|
+
rmSync(servicePath, { force: true });
|
|
70
|
+
await run("daemon-reload");
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const wanted = { [servicePath]: serviceUnit(env), [timerPath]: timerUnit(state.every) };
|
|
74
|
+
const stale = Object.entries(wanted).filter(([path, text]) => !existsSync(path) || readFileSync(path, "utf8") !== text);
|
|
75
|
+
if (stale.length === 0)
|
|
76
|
+
return;
|
|
77
|
+
mkdirSync(dir, { recursive: true });
|
|
78
|
+
for (const [path, text] of stale)
|
|
79
|
+
writeFileSync(path, text);
|
|
80
|
+
await run("daemon-reload");
|
|
81
|
+
await run("enable", "--now", `${UNIT}.timer`);
|
|
82
|
+
// A timer already running keeps its old interval until restarted.
|
|
83
|
+
if (stale.some(([path]) => path === timerPath))
|
|
84
|
+
await run("restart", `${UNIT}.timer`);
|
|
85
|
+
};
|
|
86
|
+
export const autoCommand = (program, streams, env) => {
|
|
87
|
+
const run = systemctl(env);
|
|
88
|
+
const auto = program
|
|
89
|
+
.command("auto")
|
|
90
|
+
.description("Run memo import on a timer (systemd user timer); on/off and the interval live in the config");
|
|
91
|
+
auto
|
|
92
|
+
.command("on")
|
|
93
|
+
.description("Import every --every (default: auto.every in the config, else 5m), starting a minute from now")
|
|
94
|
+
.option("--every <interval>", "how often: 5m, 90s, 1h — a minute or more", interval)
|
|
95
|
+
.action(async (options) => {
|
|
96
|
+
const config = updateConfig((current) => ({ ...current, auto: { enabled: true, every: options.every ?? autoState(current).every } }), env);
|
|
97
|
+
await applyAuto(env, autoState(config));
|
|
98
|
+
streams.data(`memo import runs every ${autoState(config).every}.\n`);
|
|
99
|
+
});
|
|
100
|
+
auto
|
|
101
|
+
.command("off")
|
|
102
|
+
.description("Stop importing on a timer and remove the timer")
|
|
103
|
+
.action(async () => {
|
|
104
|
+
const config = updateConfig((current) => ({ ...current, auto: { ...current.auto, enabled: false } }), env);
|
|
105
|
+
await applyAuto(env, autoState(config));
|
|
106
|
+
streams.data("memo import no longer runs on a timer.\n");
|
|
107
|
+
});
|
|
108
|
+
auto
|
|
109
|
+
.command("status")
|
|
110
|
+
.description("Whether the timer is on, its interval, when it runs next and how the last run ended")
|
|
111
|
+
.option("--json", "print JSON")
|
|
112
|
+
.action(async (options) => {
|
|
113
|
+
const state = autoState(loadConfig(env));
|
|
114
|
+
const show = async (unit, properties) => Object.fromEntries((await run("show", unit, "--property", properties).catch(() => ""))
|
|
115
|
+
.split("\n")
|
|
116
|
+
.filter(Boolean)
|
|
117
|
+
.map((line) => [line.slice(0, line.indexOf("=")), line.slice(line.indexOf("=") + 1)]));
|
|
118
|
+
const timer = await show(`${UNIT}.timer`, "ActiveState");
|
|
119
|
+
const service = await show(`${UNIT}.service`, "Result");
|
|
120
|
+
// list-timers gives wall-clock times for every kind of timer; `show` leaves them empty for these.
|
|
121
|
+
const listed = JSON.parse((await run("list-timers", `${UNIT}.timer`, "--output=json").catch(() => "[]")) || "[]")[0];
|
|
122
|
+
const when = (micros) => typeof micros === "number" && micros > 0 ? new Date(micros / 1000).toISOString() : null;
|
|
123
|
+
const status = {
|
|
124
|
+
...state,
|
|
125
|
+
timer: timer.ActiveState ?? "unknown",
|
|
126
|
+
next: when(listed?.next),
|
|
127
|
+
last: when(listed?.last),
|
|
128
|
+
lastResult: service.Result || null,
|
|
129
|
+
};
|
|
130
|
+
if (options.json)
|
|
131
|
+
createRenderer({ format: "json", color: false, streams }).result(status);
|
|
132
|
+
else
|
|
133
|
+
streams.data(`${status.enabled ? `on, every ${status.every}` : "off"} — timer ${status.timer}` +
|
|
134
|
+
(status.next ? `, next ${status.next}` : "") +
|
|
135
|
+
(status.last ? `, last ${status.last} (${status.lastResult ?? "?"})` : "") +
|
|
136
|
+
"\n");
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=auto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto.js","sourceRoot":"","sources":["../../src/run/auto.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Streams } from "@wirecat/cli-core";
|
|
2
|
+
import type { Command } from "commander";
|
|
3
|
+
import { type ImportResult } from "../mail/import.js";
|
|
4
|
+
import { type NoteChunksEmbedded } from "../notes/embed.js";
|
|
5
|
+
import { type NotesImport } from "../notes/import.js";
|
|
6
|
+
export interface ImportRun {
|
|
7
|
+
notes: NotesImport[];
|
|
8
|
+
/** The notes' chunks embedded for search by meaning this run. */
|
|
9
|
+
notesEmbedded?: NoteChunksEmbedded;
|
|
10
|
+
mail: ImportResult[];
|
|
11
|
+
/** A source that failed; the others still ran. */
|
|
12
|
+
failed: {
|
|
13
|
+
source: string;
|
|
14
|
+
reason: string;
|
|
15
|
+
}[];
|
|
16
|
+
}
|
|
17
|
+
export declare const importCommand: (program: Command, streams: Streams, env: NodeJS.ProcessEnv) => void;
|
|
18
|
+
//# sourceMappingURL=import.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../src/run/import.ts"],"names":[],"mappings":"AACA,OAAO,EAA0C,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAGxF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAGxC,OAAO,EAAE,KAAK,YAAY,EAAc,MAAM,mBAAmB,CAAA;AAEjE,OAAO,EAAmB,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAE5E,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAOlE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,WAAW,EAAE,CAAA;IACpB,iEAAiE;IACjE,aAAa,CAAC,EAAE,kBAAkB,CAAA;IAClC,IAAI,EAAE,YAAY,EAAE,CAAA;IACpB,kDAAkD;IAClD,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC7C;AA4BD,eAAO,MAAM,aAAa,YAAa,OAAO,WAAW,OAAO,OAAO,MAAM,CAAC,UAAU,KAAG,IA8E1F,CAAA"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { CliError, createRenderer, resolvePaths } from "@wirecat/cli-core";
|
|
3
|
+
import { releaseLock, takeLock } from "@wirecat/cli-messaging/background";
|
|
4
|
+
import { openStore } from "@wirecat/cli-messaging/store";
|
|
5
|
+
import { loadConfig } from "../config.js";
|
|
6
|
+
import { himalaya } from "../mail/himalaya.js";
|
|
7
|
+
import { importMail } from "../mail/import.js";
|
|
8
|
+
import { boundFolders } from "../notes/bound.js";
|
|
9
|
+
import { embedNoteChunks } from "../notes/embed.js";
|
|
10
|
+
import { noteFolders } from "../notes/folders.js";
|
|
11
|
+
import { importNotes } from "../notes/import.js";
|
|
12
|
+
import { importNotesMap } from "../people/notes-map.js";
|
|
13
|
+
import { applyAuto, autoState } from "./auto.js";
|
|
14
|
+
const DAY = 86_400_000;
|
|
15
|
+
const MAIL_WINDOW_DAYS = 30;
|
|
16
|
+
const text = (run) => [
|
|
17
|
+
...run.notes.map((n) => `notes ${n.folder}: ${n.notes} notes, ${n.changed} changed, ${n.renamed} moved, ${n.deleted} gone` +
|
|
18
|
+
(n.deletionsSkipped === undefined ? "" : ` — deletions skipped: ${n.deletionsSkipped}`)),
|
|
19
|
+
...(run.notesEmbedded === undefined
|
|
20
|
+
? []
|
|
21
|
+
: [
|
|
22
|
+
`notes by meaning: ${run.notesEmbedded.chunks} chunks embedded` +
|
|
23
|
+
(run.notesEmbedded.notEmbedded !== undefined
|
|
24
|
+
? ` — ${run.notesEmbedded.notEmbedded}`
|
|
25
|
+
: run.notesEmbedded.left
|
|
26
|
+
? " — more next run"
|
|
27
|
+
: ""),
|
|
28
|
+
]),
|
|
29
|
+
...run.mail.map((m) => `mail ${m.account}: ${m.listed} listed, ${m.saved} new, ${m.deleted} gone` +
|
|
30
|
+
(m.complete ? "" : " — more to read next run") +
|
|
31
|
+
(m.deletionsSkipped === undefined ? "" : ` — deletions skipped: ${m.deletionsSkipped}`)),
|
|
32
|
+
...run.failed.map(({ source, reason }) => `failed ${source}: ${reason}`),
|
|
33
|
+
].join("\n") || "Nothing to import: set notes.folders or mail.accounts in the config.";
|
|
34
|
+
export const importCommand = (program, streams, env) => {
|
|
35
|
+
program
|
|
36
|
+
.command("import")
|
|
37
|
+
.description("Bring notes and mail up to date in the shared store — only what changed; the timer runs this")
|
|
38
|
+
.option("--notes", "notes only")
|
|
39
|
+
.option("--mail", "mail only")
|
|
40
|
+
.option("--no-embed", "skip embedding notes and mail for search by meaning this run")
|
|
41
|
+
.option("--json", "print JSON")
|
|
42
|
+
.action(async (options) => {
|
|
43
|
+
const both = !options.notes && !options.mail;
|
|
44
|
+
const config = loadConfig(env);
|
|
45
|
+
if (env.MEMO_AUTO === "1") {
|
|
46
|
+
await applyAuto(env, autoState(config));
|
|
47
|
+
if (!autoState(config).enabled)
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const lock = join(resolvePaths({ appName: "cli-memo", prefix: "MEMO", env }).state, "import.lock");
|
|
51
|
+
const holder = takeLock(lock, { pid: process.pid, startedAt: new Date().toISOString() });
|
|
52
|
+
if (holder !== undefined)
|
|
53
|
+
throw new CliError("rate_limited", `an import is already running (process ${holder.pid}); try again when it ends`);
|
|
54
|
+
const store = await openStore({ env });
|
|
55
|
+
const run = { notes: [], mail: [], failed: [] };
|
|
56
|
+
const attempt = async (source, work) => {
|
|
57
|
+
try {
|
|
58
|
+
await work();
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
run.failed.push({ source, reason: error instanceof Error ? error.message : String(error) });
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
try {
|
|
65
|
+
if (both || options.notes) {
|
|
66
|
+
const folders = await boundFolders(store, env, { strict: false });
|
|
67
|
+
for (const folder of noteFolders(config.notes))
|
|
68
|
+
if (!folders.some(({ path }) => path === folder.path))
|
|
69
|
+
run.failed.push({
|
|
70
|
+
source: `notes ${folder.path}`,
|
|
71
|
+
reason: `no folder id — memo folders add ${folder.path}`,
|
|
72
|
+
});
|
|
73
|
+
for (const folder of folders)
|
|
74
|
+
await attempt(`notes ${folder.path}`, async () => {
|
|
75
|
+
run.notes.push(await importNotes(store, folder, { ignore: config.notes?.ignore ?? [], env }));
|
|
76
|
+
});
|
|
77
|
+
if (folders.length > 0)
|
|
78
|
+
await attempt("notes by meaning", async () => {
|
|
79
|
+
run.notesEmbedded = await embedNoteChunks(store, {
|
|
80
|
+
embed: options.embed && config.notes?.embed !== false,
|
|
81
|
+
env,
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
await attempt("people-notes.json", async () => {
|
|
85
|
+
await importNotesMap(store, env, folders);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (both || options.mail) {
|
|
89
|
+
for (const account of config.mail?.accounts ?? [])
|
|
90
|
+
await attempt(`mail ${account.name}`, async () => {
|
|
91
|
+
run.mail.push(await importMail({
|
|
92
|
+
store,
|
|
93
|
+
run: himalaya(env),
|
|
94
|
+
account,
|
|
95
|
+
since: new Date(Date.now() - MAIL_WINDOW_DAYS * DAY),
|
|
96
|
+
env,
|
|
97
|
+
embed: options.embed,
|
|
98
|
+
}));
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
await store.close();
|
|
104
|
+
releaseLock(lock, process.pid);
|
|
105
|
+
}
|
|
106
|
+
if (options.json)
|
|
107
|
+
createRenderer({ format: "json", color: false, streams }).result(run);
|
|
108
|
+
else
|
|
109
|
+
streams.data(`${text(run)}\n`);
|
|
110
|
+
if (run.failed.length > 0)
|
|
111
|
+
process.exitCode = 1;
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/run/import.ts"],"names":[],"mappings":"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"}
|