@lhremote/cli 0.5.0 → 0.6.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.
Files changed (66) hide show
  1. package/dist/handlers/add-people-to-collection.d.ts +10 -0
  2. package/dist/handlers/add-people-to-collection.d.ts.map +1 -0
  3. package/dist/handlers/add-people-to-collection.js +79 -0
  4. package/dist/handlers/add-people-to-collection.js.map +1 -0
  5. package/dist/handlers/add-people-to-collection.test.d.ts +2 -0
  6. package/dist/handlers/add-people-to-collection.test.d.ts.map +1 -0
  7. package/dist/handlers/add-people-to-collection.test.js +107 -0
  8. package/dist/handlers/add-people-to-collection.test.js.map +1 -0
  9. package/dist/handlers/collect-people.d.ts +12 -0
  10. package/dist/handlers/collect-people.d.ts.map +1 -0
  11. package/dist/handlers/collect-people.js +39 -0
  12. package/dist/handlers/collect-people.js.map +1 -0
  13. package/dist/handlers/collect-people.test.d.ts +2 -0
  14. package/dist/handlers/collect-people.test.d.ts.map +1 -0
  15. package/dist/handlers/collect-people.test.js +92 -0
  16. package/dist/handlers/collect-people.test.js.map +1 -0
  17. package/dist/handlers/create-collection.d.ts +8 -0
  18. package/dist/handlers/create-collection.d.ts.map +1 -0
  19. package/dist/handlers/create-collection.js +26 -0
  20. package/dist/handlers/create-collection.js.map +1 -0
  21. package/dist/handlers/create-collection.test.d.ts +2 -0
  22. package/dist/handlers/create-collection.test.d.ts.map +1 -0
  23. package/dist/handlers/create-collection.test.js +55 -0
  24. package/dist/handlers/create-collection.test.js.map +1 -0
  25. package/dist/handlers/delete-collection.d.ts +8 -0
  26. package/dist/handlers/delete-collection.d.ts.map +1 -0
  27. package/dist/handlers/delete-collection.js +31 -0
  28. package/dist/handlers/delete-collection.js.map +1 -0
  29. package/dist/handlers/delete-collection.test.d.ts +2 -0
  30. package/dist/handlers/delete-collection.test.d.ts.map +1 -0
  31. package/dist/handlers/delete-collection.test.js +74 -0
  32. package/dist/handlers/delete-collection.test.js.map +1 -0
  33. package/dist/handlers/import-people-from-collection.d.ts +8 -0
  34. package/dist/handlers/import-people-from-collection.d.ts.map +1 -0
  35. package/dist/handlers/import-people-from-collection.js +55 -0
  36. package/dist/handlers/import-people-from-collection.js.map +1 -0
  37. package/dist/handlers/import-people-from-collection.test.d.ts +2 -0
  38. package/dist/handlers/import-people-from-collection.test.d.ts.map +1 -0
  39. package/dist/handlers/import-people-from-collection.test.js +121 -0
  40. package/dist/handlers/import-people-from-collection.test.js.map +1 -0
  41. package/dist/handlers/index.d.ts +7 -0
  42. package/dist/handlers/index.d.ts.map +1 -1
  43. package/dist/handlers/index.js +7 -0
  44. package/dist/handlers/index.js.map +1 -1
  45. package/dist/handlers/list-collections.d.ts +5 -0
  46. package/dist/handlers/list-collections.d.ts.map +1 -0
  47. package/dist/handlers/list-collections.js +48 -0
  48. package/dist/handlers/list-collections.js.map +1 -0
  49. package/dist/handlers/list-collections.test.d.ts +2 -0
  50. package/dist/handlers/list-collections.test.d.ts.map +1 -0
  51. package/dist/handlers/list-collections.test.js +111 -0
  52. package/dist/handlers/list-collections.test.js.map +1 -0
  53. package/dist/handlers/remove-people-from-collection.d.ts +10 -0
  54. package/dist/handlers/remove-people-from-collection.d.ts.map +1 -0
  55. package/dist/handlers/remove-people-from-collection.js +75 -0
  56. package/dist/handlers/remove-people-from-collection.js.map +1 -0
  57. package/dist/handlers/remove-people-from-collection.test.d.ts +2 -0
  58. package/dist/handlers/remove-people-from-collection.test.d.ts.map +1 -0
  59. package/dist/handlers/remove-people-from-collection.test.js +100 -0
  60. package/dist/handlers/remove-people-from-collection.test.js.map +1 -0
  61. package/dist/program.d.ts.map +1 -1
  62. package/dist/program.js +70 -1
  63. package/dist/program.js.map +1 -1
  64. package/dist/program.test.js +8 -1
  65. package/dist/program.test.js.map +1 -1
  66. package/package.json +2 -2
@@ -0,0 +1,74 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
+ vi.mock("@lhremote/core", async (importOriginal) => {
5
+ const actual = await importOriginal();
6
+ return {
7
+ ...actual,
8
+ deleteCollection: vi.fn(),
9
+ };
10
+ });
11
+ import { deleteCollection, } from "@lhremote/core";
12
+ import { handleDeleteCollection } from "./delete-collection.js";
13
+ import { getStdout } from "./testing/mock-helpers.js";
14
+ const MOCK_DELETED = {
15
+ success: true,
16
+ collectionId: 5,
17
+ deleted: true,
18
+ };
19
+ const MOCK_NOT_FOUND = {
20
+ success: true,
21
+ collectionId: 999,
22
+ deleted: false,
23
+ };
24
+ describe("handleDeleteCollection", () => {
25
+ const originalExitCode = process.exitCode;
26
+ let stdoutSpy;
27
+ let stderrSpy;
28
+ beforeEach(() => {
29
+ process.exitCode = undefined;
30
+ vi.clearAllMocks();
31
+ stdoutSpy = vi.spyOn(process.stdout, "write").mockReturnValue(true);
32
+ stderrSpy = vi.spyOn(process.stderr, "write").mockReturnValue(true);
33
+ });
34
+ afterEach(() => {
35
+ process.exitCode = originalExitCode;
36
+ vi.restoreAllMocks();
37
+ });
38
+ it("deletes collection and prints confirmation", async () => {
39
+ vi.mocked(deleteCollection).mockResolvedValue(MOCK_DELETED);
40
+ await handleDeleteCollection(5, {});
41
+ expect(process.exitCode).toBeUndefined();
42
+ expect(getStdout(stdoutSpy)).toContain("Deleted collection #5.");
43
+ });
44
+ it("prints not-found message when collection does not exist", async () => {
45
+ vi.mocked(deleteCollection).mockResolvedValue(MOCK_NOT_FOUND);
46
+ await handleDeleteCollection(999, {});
47
+ expect(process.exitCode).toBeUndefined();
48
+ expect(getStdout(stdoutSpy)).toContain("Collection #999 not found.");
49
+ });
50
+ it("prints JSON with --json when deleted", async () => {
51
+ vi.mocked(deleteCollection).mockResolvedValue(MOCK_DELETED);
52
+ await handleDeleteCollection(5, { json: true });
53
+ expect(process.exitCode).toBeUndefined();
54
+ const parsed = JSON.parse(getStdout(stdoutSpy));
55
+ expect(parsed.success).toBe(true);
56
+ expect(parsed.collectionId).toBe(5);
57
+ expect(parsed.deleted).toBe(true);
58
+ });
59
+ it("prints JSON with --json when not found", async () => {
60
+ vi.mocked(deleteCollection).mockResolvedValue(MOCK_NOT_FOUND);
61
+ await handleDeleteCollection(999, { json: true });
62
+ expect(process.exitCode).toBeUndefined();
63
+ const parsed = JSON.parse(getStdout(stdoutSpy));
64
+ expect(parsed.success).toBe(true);
65
+ expect(parsed.deleted).toBe(false);
66
+ });
67
+ it("sets exitCode 1 on error", async () => {
68
+ vi.mocked(deleteCollection).mockRejectedValue(new Error("connection error"));
69
+ await handleDeleteCollection(5, {});
70
+ expect(process.exitCode).toBe(1);
71
+ expect(stderrSpy).toHaveBeenCalledWith("connection error\n");
72
+ });
73
+ });
74
+ //# sourceMappingURL=delete-collection.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete-collection.test.js","sourceRoot":"","sources":["../../src/handlers/delete-collection.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /** Handle the {@link https://github.com/alexey-pelykh/lhremote#import-people-from-collection | import-people-from-collection} CLI command. */
2
+ export declare function handleImportPeopleFromCollection(collectionId: number, campaignId: number, options: {
3
+ cdpPort?: number;
4
+ cdpHost?: string;
5
+ allowRemote?: boolean;
6
+ json?: boolean;
7
+ }): Promise<void>;
8
+ //# sourceMappingURL=import-people-from-collection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-people-from-collection.d.ts","sourceRoot":"","sources":["../../src/handlers/import-people-from-collection.ts"],"names":[],"mappings":"AAaA,8IAA8I;AAC9I,wBAAsB,gCAAgC,CACpD,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GACA,OAAO,CAAC,IAAI,CAAC,CAkDf"}
@@ -0,0 +1,55 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { CampaignExecutionError, CampaignNotFoundError, DEFAULT_CDP_PORT, InstanceNotRunningError, errorMessage, importPeopleFromCollection, } from "@lhremote/core";
4
+ /** Handle the {@link https://github.com/alexey-pelykh/lhremote#import-people-from-collection | import-people-from-collection} CLI command. */
5
+ export async function handleImportPeopleFromCollection(collectionId, campaignId, options) {
6
+ let result;
7
+ try {
8
+ result = await importPeopleFromCollection({
9
+ collectionId,
10
+ campaignId,
11
+ cdpPort: options.cdpPort ?? DEFAULT_CDP_PORT,
12
+ cdpHost: options.cdpHost,
13
+ allowRemote: options.allowRemote,
14
+ });
15
+ }
16
+ catch (error) {
17
+ if (error instanceof CampaignNotFoundError) {
18
+ process.stderr.write(`Campaign ${String(campaignId)} not found.\n`);
19
+ }
20
+ else if (error instanceof CampaignExecutionError) {
21
+ process.stderr.write(`Failed to import people: ${error.message}\n`);
22
+ }
23
+ else if (error instanceof InstanceNotRunningError) {
24
+ process.stderr.write(`${error.message}\n`);
25
+ }
26
+ else {
27
+ const message = errorMessage(error);
28
+ process.stderr.write(`${message}\n`);
29
+ }
30
+ process.exitCode = 1;
31
+ return;
32
+ }
33
+ if (options.json) {
34
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
35
+ }
36
+ else {
37
+ if (result.totalUrls === 0) {
38
+ process.stdout.write(`Collection #${String(collectionId)} has no people with LinkedIn profiles.\n`);
39
+ }
40
+ else {
41
+ process.stdout.write(`Imported ${String(result.imported)} people from collection #${String(collectionId)} into campaign ${String(campaignId)} action ${String(result.actionId)}.` +
42
+ (result.alreadyInQueue > 0
43
+ ? ` ${String(result.alreadyInQueue)} already in queue.`
44
+ : "") +
45
+ (result.alreadyProcessed > 0
46
+ ? ` ${String(result.alreadyProcessed)} already processed.`
47
+ : "") +
48
+ (result.failed > 0
49
+ ? ` ${String(result.failed)} failed.`
50
+ : "") +
51
+ "\n");
52
+ }
53
+ }
54
+ }
55
+ //# sourceMappingURL=import-people-from-collection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-people-from-collection.js","sourceRoot":"","sources":["../../src/handlers/import-people-from-collection.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,uBAAuB,EACvB,YAAY,EACZ,0BAA0B,GAE3B,MAAM,gBAAgB,CAAC;AAExB,8IAA8I;AAC9I,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,YAAoB,EACpB,UAAkB,EAClB,OAKC;IAED,IAAI,MAAwC,CAAC;IAC7C,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,0BAA0B,CAAC;YACxC,YAAY;YACZ,UAAU;YACV,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,gBAAgB;YAC5C,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,WAAW,EAAE,OAAO,CAAC,WAAW;SACjC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,qBAAqB,EAAE,CAAC;YAC3C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,MAAM,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;QACtE,CAAC;aAAM,IAAI,KAAK,YAAY,sBAAsB,EAAE,CAAC;YACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,4BAA4B,KAAK,CAAC,OAAO,IAAI,CAC9C,CAAC;QACJ,CAAC;aAAM,IAAI,KAAK,YAAY,uBAAuB,EAAE,CAAC;YACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;YACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC/D,CAAC;SAAM,CAAC;QACN,IAAI,MAAM,CAAC,SAAS,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,eAAe,MAAM,CAAC,YAAY,CAAC,0CAA0C,CAC9E,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,YAAY,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,4BAA4B,MAAM,CAAC,YAAY,CAAC,kBAAkB,MAAM,CAAC,UAAU,CAAC,WAAW,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG;gBAC1J,CAAC,MAAM,CAAC,cAAc,GAAG,CAAC;oBACxB,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,oBAAoB;oBACvD,CAAC,CAAC,EAAE,CAAC;gBACP,CAAC,MAAM,CAAC,gBAAgB,GAAG,CAAC;oBAC1B,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,qBAAqB;oBAC1D,CAAC,CAAC,EAAE,CAAC;gBACP,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;oBAChB,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;oBACrC,CAAC,CAAC,EAAE,CAAC;gBACP,IAAI,CACP,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=import-people-from-collection.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-people-from-collection.test.d.ts","sourceRoot":"","sources":["../../src/handlers/import-people-from-collection.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,121 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
+ vi.mock("@lhremote/core", async (importOriginal) => {
5
+ const actual = await importOriginal();
6
+ return {
7
+ ...actual,
8
+ importPeopleFromCollection: vi.fn(),
9
+ };
10
+ });
11
+ import { CampaignExecutionError, CampaignNotFoundError, InstanceNotRunningError, importPeopleFromCollection, } from "@lhremote/core";
12
+ import { handleImportPeopleFromCollection } from "./import-people-from-collection.js";
13
+ import { getStdout } from "./testing/mock-helpers.js";
14
+ const MOCK_RESULT = {
15
+ success: true,
16
+ collectionId: 10,
17
+ campaignId: 1,
18
+ actionId: 5,
19
+ totalUrls: 3,
20
+ imported: 3,
21
+ alreadyInQueue: 1,
22
+ alreadyProcessed: 0,
23
+ failed: 0,
24
+ };
25
+ describe("handleImportPeopleFromCollection", () => {
26
+ const originalExitCode = process.exitCode;
27
+ let stdoutSpy;
28
+ let stderrSpy;
29
+ beforeEach(() => {
30
+ process.exitCode = undefined;
31
+ vi.clearAllMocks();
32
+ stdoutSpy = vi.spyOn(process.stdout, "write").mockReturnValue(true);
33
+ stderrSpy = vi.spyOn(process.stderr, "write").mockReturnValue(true);
34
+ });
35
+ afterEach(() => {
36
+ process.exitCode = originalExitCode;
37
+ vi.restoreAllMocks();
38
+ });
39
+ it("imports people and prints result", async () => {
40
+ vi.mocked(importPeopleFromCollection).mockResolvedValue(MOCK_RESULT);
41
+ await handleImportPeopleFromCollection(10, 1, {});
42
+ expect(process.exitCode).toBeUndefined();
43
+ const output = getStdout(stdoutSpy);
44
+ expect(output).toContain("Imported 3 people from collection #10 into campaign 1 action 5.");
45
+ expect(output).toContain("1 already in queue.");
46
+ });
47
+ it("prints JSON with --json", async () => {
48
+ vi.mocked(importPeopleFromCollection).mockResolvedValue(MOCK_RESULT);
49
+ await handleImportPeopleFromCollection(10, 1, { json: true });
50
+ expect(process.exitCode).toBeUndefined();
51
+ const parsed = JSON.parse(getStdout(stdoutSpy));
52
+ expect(parsed.success).toBe(true);
53
+ expect(parsed.collectionId).toBe(10);
54
+ expect(parsed.campaignId).toBe(1);
55
+ expect(parsed.actionId).toBe(5);
56
+ expect(parsed.imported).toBe(3);
57
+ expect(parsed.alreadyInQueue).toBe(1);
58
+ });
59
+ it("prints empty-collection message when totalUrls is 0", async () => {
60
+ vi.mocked(importPeopleFromCollection).mockResolvedValue({
61
+ ...MOCK_RESULT,
62
+ totalUrls: 0,
63
+ imported: 0,
64
+ alreadyInQueue: 0,
65
+ });
66
+ await handleImportPeopleFromCollection(10, 1, {});
67
+ expect(process.exitCode).toBeUndefined();
68
+ expect(getStdout(stdoutSpy)).toContain("Collection #10 has no people with LinkedIn profiles.");
69
+ });
70
+ it("shows already-processed and failed counts when non-zero", async () => {
71
+ vi.mocked(importPeopleFromCollection).mockResolvedValue({
72
+ ...MOCK_RESULT,
73
+ imported: 1,
74
+ alreadyInQueue: 0,
75
+ alreadyProcessed: 2,
76
+ failed: 1,
77
+ });
78
+ await handleImportPeopleFromCollection(10, 1, {});
79
+ const output = getStdout(stdoutSpy);
80
+ expect(output).toContain("2 already processed.");
81
+ expect(output).toContain("1 failed.");
82
+ });
83
+ it("omits zero counts from human output", async () => {
84
+ vi.mocked(importPeopleFromCollection).mockResolvedValue({
85
+ ...MOCK_RESULT,
86
+ alreadyInQueue: 0,
87
+ alreadyProcessed: 0,
88
+ failed: 0,
89
+ });
90
+ await handleImportPeopleFromCollection(10, 1, {});
91
+ const output = getStdout(stdoutSpy);
92
+ expect(output).not.toContain("already in queue");
93
+ expect(output).not.toContain("already processed");
94
+ expect(output).not.toContain("failed");
95
+ });
96
+ it("sets exitCode 1 when campaign not found", async () => {
97
+ vi.mocked(importPeopleFromCollection).mockRejectedValue(new CampaignNotFoundError(999));
98
+ await handleImportPeopleFromCollection(10, 999, {});
99
+ expect(process.exitCode).toBe(1);
100
+ expect(stderrSpy).toHaveBeenCalledWith("Campaign 999 not found.\n");
101
+ });
102
+ it("sets exitCode 1 on CampaignExecutionError", async () => {
103
+ vi.mocked(importPeopleFromCollection).mockRejectedValue(new CampaignExecutionError("import failed"));
104
+ await handleImportPeopleFromCollection(10, 1, {});
105
+ expect(process.exitCode).toBe(1);
106
+ expect(stderrSpy).toHaveBeenCalledWith("Failed to import people: import failed\n");
107
+ });
108
+ it("sets exitCode 1 on InstanceNotRunningError", async () => {
109
+ vi.mocked(importPeopleFromCollection).mockRejectedValue(new InstanceNotRunningError("No LinkedHelper instance is running."));
110
+ await handleImportPeopleFromCollection(10, 1, {});
111
+ expect(process.exitCode).toBe(1);
112
+ expect(stderrSpy).toHaveBeenCalledWith("No LinkedHelper instance is running.\n");
113
+ });
114
+ it("sets exitCode 1 on generic error", async () => {
115
+ vi.mocked(importPeopleFromCollection).mockRejectedValue(new Error("timeout"));
116
+ await handleImportPeopleFromCollection(10, 1, {});
117
+ expect(process.exitCode).toBe(1);
118
+ expect(stderrSpy).toHaveBeenCalledWith("timeout\n");
119
+ });
120
+ });
121
+ //# sourceMappingURL=import-people-from-collection.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-people-from-collection.test.js","sourceRoot":"","sources":["../../src/handlers/import-people-from-collection.test.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ export { handleAddPeopleToCollection } from "./add-people-to-collection.js";
1
2
  export { handleCampaignAddAction } from "./campaign-add-action.js";
2
3
  export { handleCampaignCreate } from "./campaign-create.js";
3
4
  export { handleCampaignDelete } from "./campaign-delete.js";
@@ -20,18 +21,24 @@ export { handleImportPeopleFromUrls } from "./import-people-from-urls.js";
20
21
  export { handleCampaignStop } from "./campaign-stop.js";
21
22
  export { handleCampaignUpdate } from "./campaign-update.js";
22
23
  export { handleCampaignUpdateAction } from "./campaign-update-action.js";
24
+ export { handleCreateCollection } from "./create-collection.js";
25
+ export { handleDeleteCollection } from "./delete-collection.js";
23
26
  export { handleCheckReplies } from "./check-replies.js";
27
+ export { handleCollectPeople } from "./collect-people.js";
24
28
  export { handleDescribeActions } from "./describe-actions.js";
25
29
  export { handleCheckStatus } from "./check-status.js";
26
30
  export { handleFindApp } from "./find-app.js";
27
31
  export { handleGetErrors } from "./get-errors.js";
32
+ export { handleImportPeopleFromCollection } from "./import-people-from-collection.js";
28
33
  export { handleQueryMessages } from "./query-messages.js";
29
34
  export { handleQueryProfile } from "./query-profile.js";
30
35
  export { handleQueryProfiles } from "./query-profiles.js";
31
36
  export { handleQueryProfilesBulk } from "./query-profiles-bulk.js";
32
37
  export { handleScrapeMessagingHistory } from "./scrape-messaging-history.js";
38
+ export { handleListCollections } from "./list-collections.js";
33
39
  export { handleLaunchApp } from "./launch-app.js";
34
40
  export { handleListAccounts } from "./list-accounts.js";
41
+ export { handleRemovePeopleFromCollection } from "./remove-people-from-collection.js";
35
42
  export { handleQuitApp } from "./quit-app.js";
36
43
  export { handleStartInstance } from "./start-instance.js";
37
44
  export { handleStopInstance } from "./stop-instance.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-only
2
2
  // Copyright (C) 2026 Oleksii PELYKH
3
+ export { handleAddPeopleToCollection } from "./add-people-to-collection.js";
3
4
  export { handleCampaignAddAction } from "./campaign-add-action.js";
4
5
  export { handleCampaignCreate } from "./campaign-create.js";
5
6
  export { handleCampaignDelete } from "./campaign-delete.js";
@@ -22,18 +23,24 @@ export { handleImportPeopleFromUrls } from "./import-people-from-urls.js";
22
23
  export { handleCampaignStop } from "./campaign-stop.js";
23
24
  export { handleCampaignUpdate } from "./campaign-update.js";
24
25
  export { handleCampaignUpdateAction } from "./campaign-update-action.js";
26
+ export { handleCreateCollection } from "./create-collection.js";
27
+ export { handleDeleteCollection } from "./delete-collection.js";
25
28
  export { handleCheckReplies } from "./check-replies.js";
29
+ export { handleCollectPeople } from "./collect-people.js";
26
30
  export { handleDescribeActions } from "./describe-actions.js";
27
31
  export { handleCheckStatus } from "./check-status.js";
28
32
  export { handleFindApp } from "./find-app.js";
29
33
  export { handleGetErrors } from "./get-errors.js";
34
+ export { handleImportPeopleFromCollection } from "./import-people-from-collection.js";
30
35
  export { handleQueryMessages } from "./query-messages.js";
31
36
  export { handleQueryProfile } from "./query-profile.js";
32
37
  export { handleQueryProfiles } from "./query-profiles.js";
33
38
  export { handleQueryProfilesBulk } from "./query-profiles-bulk.js";
34
39
  export { handleScrapeMessagingHistory } from "./scrape-messaging-history.js";
40
+ export { handleListCollections } from "./list-collections.js";
35
41
  export { handleLaunchApp } from "./launch-app.js";
36
42
  export { handleListAccounts } from "./list-accounts.js";
43
+ export { handleRemovePeopleFromCollection } from "./remove-people-from-collection.js";
37
44
  export { handleQuitApp } from "./quit-app.js";
38
45
  export { handleStartInstance } from "./start-instance.js";
39
46
  export { handleStopInstance } from "./stop-instance.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** Handle the {@link https://github.com/alexey-pelykh/lhremote#list-collections | list-collections} CLI command. */
2
+ export declare function handleListCollections(options: {
3
+ json?: boolean;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=list-collections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-collections.d.ts","sourceRoot":"","sources":["../../src/handlers/list-collections.ts"],"names":[],"mappings":"AAWA,oHAAoH;AACpH,wBAAsB,qBAAqB,CAAC,OAAO,EAAE;IACnD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDhB"}
@@ -0,0 +1,48 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { CollectionListRepository, DatabaseClient, discoverAllDatabases, errorMessage, } from "@lhremote/core";
4
+ /** Handle the {@link https://github.com/alexey-pelykh/lhremote#list-collections | list-collections} CLI command. */
5
+ export async function handleListCollections(options) {
6
+ const databases = discoverAllDatabases();
7
+ if (databases.size === 0) {
8
+ process.stderr.write("No LinkedHelper databases found.\n");
9
+ process.exitCode = 1;
10
+ return;
11
+ }
12
+ const allCollections = [];
13
+ for (const [, dbPath] of databases) {
14
+ const db = new DatabaseClient(dbPath);
15
+ try {
16
+ const repo = new CollectionListRepository(db);
17
+ const collections = repo.listCollections();
18
+ allCollections.push(...collections);
19
+ }
20
+ catch (error) {
21
+ const message = errorMessage(error);
22
+ process.stderr.write(`Error in database at ${dbPath}: ${message}\n`);
23
+ process.exitCode = 1;
24
+ return;
25
+ }
26
+ finally {
27
+ db.close();
28
+ }
29
+ }
30
+ if (options.json) {
31
+ const response = {
32
+ collections: allCollections,
33
+ total: allCollections.length,
34
+ };
35
+ process.stdout.write(JSON.stringify(response, null, 2) + "\n");
36
+ }
37
+ else {
38
+ if (allCollections.length === 0) {
39
+ process.stdout.write("No collections found.\n");
40
+ return;
41
+ }
42
+ process.stdout.write(`Collections (${String(allCollections.length)} total):\n\n`);
43
+ for (const collection of allCollections) {
44
+ process.stdout.write(`#${collection.id} ${collection.name} — ${String(collection.peopleCount)} people\n`);
45
+ }
46
+ }
47
+ }
48
+ //# sourceMappingURL=list-collections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-collections.js","sourceRoot":"","sources":["../../src/handlers/list-collections.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAEL,wBAAwB,EACxB,cAAc,EACd,oBAAoB,EACpB,YAAY,GACb,MAAM,gBAAgB,CAAC;AAExB,oHAAoH;AACpH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAE3C;IACC,MAAM,SAAS,GAAG,oBAAoB,EAAE,CAAC;IACzC,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC3D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,cAAc,GAAwB,EAAE,CAAC;IAE/C,KAAK,MAAM,CAAC,EAAE,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QACnC,MAAM,EAAE,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,wBAAwB,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YAC3C,cAAc,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;YACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,MAAM,KAAK,OAAO,IAAI,CAAC,CAAC;YACrE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,KAAK,EAAE,CAAC;QACb,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,QAAQ,GAAG;YACf,WAAW,EAAE,cAAc;YAC3B,KAAK,EAAE,cAAc,CAAC,MAAM;SAC7B,CAAC;QACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjE,CAAC;SAAM,CAAC;QACN,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,gBAAgB,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,cAAc,CAC5D,CAAC;QAEF,KAAK,MAAM,UAAU,IAAI,cAAc,EAAE,CAAC;YACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,UAAU,CAAC,EAAE,KAAK,UAAU,CAAC,IAAI,MAAM,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,WAAW,CACrF,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=list-collections.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-collections.test.d.ts","sourceRoot":"","sources":["../../src/handlers/list-collections.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,111 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
+ vi.mock("@lhremote/core", async (importOriginal) => {
5
+ const actual = await importOriginal();
6
+ return {
7
+ ...actual,
8
+ DatabaseClient: vi.fn(),
9
+ CollectionListRepository: vi.fn(),
10
+ discoverAllDatabases: vi.fn(),
11
+ };
12
+ });
13
+ import { CollectionListRepository } from "@lhremote/core";
14
+ import { handleListCollections } from "./list-collections.js";
15
+ import { getStdout, mockDb, mockDiscovery } from "./testing/mock-helpers.js";
16
+ const MOCK_COLLECTIONS = [
17
+ {
18
+ id: 1,
19
+ name: "Prospects Q1",
20
+ peopleCount: 42,
21
+ createdAt: "2025-01-01T00:00:00Z",
22
+ },
23
+ {
24
+ id: 2,
25
+ name: "Follow-Up List",
26
+ peopleCount: 7,
27
+ createdAt: "2025-01-02T00:00:00Z",
28
+ },
29
+ ];
30
+ function mockRepo(collections = MOCK_COLLECTIONS) {
31
+ vi.mocked(CollectionListRepository).mockImplementation(function () {
32
+ return {
33
+ listCollections: vi.fn().mockReturnValue(collections),
34
+ };
35
+ });
36
+ }
37
+ function setupSuccessPath() {
38
+ mockDiscovery();
39
+ mockDb();
40
+ mockRepo();
41
+ }
42
+ describe("handleListCollections", () => {
43
+ const originalExitCode = process.exitCode;
44
+ let stdoutSpy;
45
+ let stderrSpy;
46
+ beforeEach(() => {
47
+ process.exitCode = undefined;
48
+ vi.clearAllMocks();
49
+ stdoutSpy = vi.spyOn(process.stdout, "write").mockReturnValue(true);
50
+ stderrSpy = vi.spyOn(process.stderr, "write").mockReturnValue(true);
51
+ });
52
+ afterEach(() => {
53
+ process.exitCode = originalExitCode;
54
+ vi.restoreAllMocks();
55
+ });
56
+ it("prints JSON with --json", async () => {
57
+ setupSuccessPath();
58
+ await handleListCollections({ json: true });
59
+ expect(process.exitCode).toBeUndefined();
60
+ const parsed = JSON.parse(getStdout(stdoutSpy));
61
+ expect(parsed.collections).toHaveLength(2);
62
+ expect(parsed.total).toBe(2);
63
+ });
64
+ it("prints human-readable output", async () => {
65
+ setupSuccessPath();
66
+ await handleListCollections({});
67
+ expect(process.exitCode).toBeUndefined();
68
+ const output = getStdout(stdoutSpy);
69
+ expect(output).toContain("Collections (2 total):");
70
+ expect(output).toContain("#1 Prospects Q1");
71
+ expect(output).toContain("42 people");
72
+ expect(output).toContain("#2 Follow-Up List");
73
+ expect(output).toContain("7 people");
74
+ });
75
+ it("prints 'No collections found' when empty", async () => {
76
+ mockDiscovery();
77
+ mockDb();
78
+ mockRepo([]);
79
+ await handleListCollections({});
80
+ expect(process.exitCode).toBeUndefined();
81
+ expect(getStdout(stdoutSpy)).toContain("No collections found.");
82
+ });
83
+ it("sets exitCode 1 when no databases found", async () => {
84
+ mockDiscovery(new Map());
85
+ await handleListCollections({});
86
+ expect(process.exitCode).toBe(1);
87
+ expect(stderrSpy).toHaveBeenCalledWith("No LinkedHelper databases found.\n");
88
+ });
89
+ it("closes database after listing", async () => {
90
+ mockDiscovery();
91
+ const { close } = mockDb();
92
+ mockRepo();
93
+ await handleListCollections({});
94
+ expect(close).toHaveBeenCalledOnce();
95
+ });
96
+ it("sets exitCode 1 on database error", async () => {
97
+ mockDiscovery();
98
+ mockDb();
99
+ vi.mocked(CollectionListRepository).mockImplementation(function () {
100
+ return {
101
+ listCollections: vi.fn().mockImplementation(() => {
102
+ throw new Error("database locked");
103
+ }),
104
+ };
105
+ });
106
+ await handleListCollections({});
107
+ expect(process.exitCode).toBe(1);
108
+ expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining("database locked"));
109
+ });
110
+ });
111
+ //# sourceMappingURL=list-collections.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-collections.test.js","sourceRoot":"","sources":["../../src/handlers/list-collections.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /** Handle the {@link https://github.com/alexey-pelykh/lhremote#remove-people-from-collection | remove-people-from-collection} CLI command. */
2
+ export declare function handleRemovePeopleFromCollection(collectionId: number, options: {
3
+ personIds?: string;
4
+ personIdsFile?: string;
5
+ cdpPort?: number;
6
+ cdpHost?: string;
7
+ allowRemote?: boolean;
8
+ json?: boolean;
9
+ }): Promise<void>;
10
+ //# sourceMappingURL=remove-people-from-collection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remove-people-from-collection.d.ts","sourceRoot":"","sources":["../../src/handlers/remove-people-from-collection.ts"],"names":[],"mappings":"AA8BA,8IAA8I;AAC9I,wBAAsB,gCAAgC,CACpD,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GACA,OAAO,CAAC,IAAI,CAAC,CAoDf"}