@lhremote/core 0.5.0 → 0.7.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/README.md +39 -0
- package/dist/cdp/client.d.ts +5 -1
- package/dist/cdp/client.d.ts.map +1 -1
- package/dist/cdp/client.js +11 -3
- package/dist/cdp/client.js.map +1 -1
- package/dist/data/index.d.ts +1 -0
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/index.js +1 -0
- package/dist/data/index.js.map +1 -1
- package/dist/data/linkedin-reference.d.ts +44 -0
- package/dist/data/linkedin-reference.d.ts.map +1 -0
- package/dist/data/linkedin-reference.js +316 -0
- package/dist/data/linkedin-reference.js.map +1 -0
- package/dist/data/linkedin-reference.test.d.ts +2 -0
- package/dist/data/linkedin-reference.test.d.ts.map +1 -0
- package/dist/data/linkedin-reference.test.js +124 -0
- package/dist/data/linkedin-reference.test.js.map +1 -0
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/repositories/collection-list.d.ts +69 -0
- package/dist/db/repositories/collection-list.d.ts.map +1 -0
- package/dist/db/repositories/collection-list.integration.test.d.ts +2 -0
- package/dist/db/repositories/collection-list.integration.test.d.ts.map +1 -0
- package/dist/db/repositories/collection-list.integration.test.js +124 -0
- package/dist/db/repositories/collection-list.integration.test.js.map +1 -0
- package/dist/db/repositories/collection-list.js +161 -0
- package/dist/db/repositories/collection-list.js.map +1 -0
- package/dist/db/repositories/index.d.ts +1 -0
- package/dist/db/repositories/index.d.ts.map +1 -1
- package/dist/db/repositories/index.js +1 -0
- package/dist/db/repositories/index.js.map +1 -1
- package/dist/db/testing/create-fixture.js +17 -0
- package/dist/db/testing/create-fixture.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/operations/add-people-to-collection.d.ts +22 -0
- package/dist/operations/add-people-to-collection.d.ts.map +1 -0
- package/dist/operations/add-people-to-collection.js +27 -0
- package/dist/operations/add-people-to-collection.js.map +1 -0
- package/dist/operations/add-people-to-collection.test.d.ts +2 -0
- package/dist/operations/add-people-to-collection.test.d.ts.map +1 -0
- package/dist/operations/add-people-to-collection.test.js +69 -0
- package/dist/operations/add-people-to-collection.test.js.map +1 -0
- package/dist/operations/build-linkedin-url.d.ts +39 -0
- package/dist/operations/build-linkedin-url.d.ts.map +1 -0
- package/dist/operations/build-linkedin-url.js +72 -0
- package/dist/operations/build-linkedin-url.js.map +1 -0
- package/dist/operations/collect-people.d.ts +40 -0
- package/dist/operations/collect-people.d.ts.map +1 -0
- package/dist/operations/collect-people.js +55 -0
- package/dist/operations/collect-people.js.map +1 -0
- package/dist/operations/collect-people.test.d.ts +2 -0
- package/dist/operations/collect-people.test.d.ts.map +1 -0
- package/dist/operations/collect-people.test.js +156 -0
- package/dist/operations/collect-people.test.js.map +1 -0
- package/dist/operations/create-collection.d.ts +20 -0
- package/dist/operations/create-collection.d.ts.map +1 -0
- package/dist/operations/create-collection.js +26 -0
- package/dist/operations/create-collection.js.map +1 -0
- package/dist/operations/create-collection.test.d.ts +2 -0
- package/dist/operations/create-collection.test.d.ts.map +1 -0
- package/dist/operations/create-collection.test.js +72 -0
- package/dist/operations/create-collection.test.js.map +1 -0
- package/dist/operations/delete-collection.d.ts +20 -0
- package/dist/operations/delete-collection.d.ts.map +1 -0
- package/dist/operations/delete-collection.js +26 -0
- package/dist/operations/delete-collection.js.map +1 -0
- package/dist/operations/delete-collection.test.d.ts +2 -0
- package/dist/operations/delete-collection.test.d.ts.map +1 -0
- package/dist/operations/delete-collection.test.js +61 -0
- package/dist/operations/delete-collection.test.js.map +1 -0
- package/dist/operations/import-people-from-collection.d.ts +30 -0
- package/dist/operations/import-people-from-collection.d.ts.map +1 -0
- package/dist/operations/import-people-from-collection.js +65 -0
- package/dist/operations/import-people-from-collection.js.map +1 -0
- package/dist/operations/import-people-from-collection.test.d.ts +2 -0
- package/dist/operations/import-people-from-collection.test.d.ts.map +1 -0
- package/dist/operations/import-people-from-collection.test.js +170 -0
- package/dist/operations/import-people-from-collection.test.js.map +1 -0
- package/dist/operations/index.d.ts +9 -0
- package/dist/operations/index.d.ts.map +1 -1
- package/dist/operations/index.js +12 -0
- package/dist/operations/index.js.map +1 -1
- package/dist/operations/list-collections.d.ts +18 -0
- package/dist/operations/list-collections.d.ts.map +1 -0
- package/dist/operations/list-collections.js +22 -0
- package/dist/operations/list-collections.js.map +1 -0
- package/dist/operations/list-collections.test.d.ts +2 -0
- package/dist/operations/list-collections.test.d.ts.map +1 -0
- package/dist/operations/list-collections.test.js +73 -0
- package/dist/operations/list-collections.test.js.map +1 -0
- package/dist/operations/remove-people-from-collection.d.ts +21 -0
- package/dist/operations/remove-people-from-collection.d.ts.map +1 -0
- package/dist/operations/remove-people-from-collection.js +26 -0
- package/dist/operations/remove-people-from-collection.js.map +1 -0
- package/dist/operations/remove-people-from-collection.test.d.ts +2 -0
- package/dist/operations/remove-people-from-collection.test.d.ts.map +1 -0
- package/dist/operations/remove-people-from-collection.test.js +68 -0
- package/dist/operations/remove-people-from-collection.test.js.map +1 -0
- package/dist/operations/resolve-linkedin-entity.d.ts +33 -0
- package/dist/operations/resolve-linkedin-entity.d.ts.map +1 -0
- package/dist/operations/resolve-linkedin-entity.js +198 -0
- package/dist/operations/resolve-linkedin-entity.js.map +1 -0
- package/dist/services/app.d.ts.map +1 -1
- package/dist/services/app.js +37 -12
- package/dist/services/app.js.map +1 -1
- package/dist/services/app.test.js +57 -0
- package/dist/services/app.test.js.map +1 -1
- package/dist/services/boolean-expression.d.ts +29 -0
- package/dist/services/boolean-expression.d.ts.map +1 -0
- package/dist/services/boolean-expression.js +79 -0
- package/dist/services/boolean-expression.js.map +1 -0
- package/dist/services/boolean-expression.test.d.ts +2 -0
- package/dist/services/boolean-expression.test.d.ts.map +1 -0
- package/dist/services/boolean-expression.test.js +64 -0
- package/dist/services/boolean-expression.test.js.map +1 -0
- package/dist/services/collection.d.ts +84 -0
- package/dist/services/collection.d.ts.map +1 -0
- package/dist/services/collection.js +154 -0
- package/dist/services/collection.js.map +1 -0
- package/dist/services/collection.test.d.ts +2 -0
- package/dist/services/collection.test.d.ts.map +1 -0
- package/dist/services/collection.test.js +219 -0
- package/dist/services/collection.test.js.map +1 -0
- package/dist/services/errors.d.ts +27 -0
- package/dist/services/errors.d.ts.map +1 -1
- package/dist/services/errors.js +38 -0
- package/dist/services/errors.js.map +1 -1
- package/dist/services/index.d.ts +7 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +7 -1
- package/dist/services/index.js.map +1 -1
- package/dist/services/instance.d.ts +12 -0
- package/dist/services/instance.d.ts.map +1 -1
- package/dist/services/instance.js +28 -0
- package/dist/services/instance.js.map +1 -1
- package/dist/services/instance.test.js +31 -0
- package/dist/services/instance.test.js.map +1 -1
- package/dist/services/launcher.d.ts +16 -0
- package/dist/services/launcher.d.ts.map +1 -1
- package/dist/services/launcher.js +63 -10
- package/dist/services/launcher.js.map +1 -1
- package/dist/services/launcher.test.js +109 -42
- package/dist/services/launcher.test.js.map +1 -1
- package/dist/services/sn-url-builder.d.ts +21 -0
- package/dist/services/sn-url-builder.d.ts.map +1 -0
- package/dist/services/sn-url-builder.js +132 -0
- package/dist/services/sn-url-builder.js.map +1 -0
- package/dist/services/sn-url-builder.test.d.ts +2 -0
- package/dist/services/sn-url-builder.test.d.ts.map +1 -0
- package/dist/services/sn-url-builder.test.js +130 -0
- package/dist/services/sn-url-builder.test.js.map +1 -0
- package/dist/services/source-type-registry.d.ts +19 -0
- package/dist/services/source-type-registry.d.ts.map +1 -0
- package/dist/services/source-type-registry.js +66 -0
- package/dist/services/source-type-registry.js.map +1 -0
- package/dist/services/source-type-registry.test.d.ts +2 -0
- package/dist/services/source-type-registry.test.d.ts.map +1 -0
- package/dist/services/source-type-registry.test.js +124 -0
- package/dist/services/source-type-registry.test.js.map +1 -0
- package/dist/services/url-builder.d.ts +12 -0
- package/dist/services/url-builder.d.ts.map +1 -0
- package/dist/services/url-builder.js +100 -0
- package/dist/services/url-builder.js.map +1 -0
- package/dist/services/url-builder.test.d.ts +2 -0
- package/dist/services/url-builder.test.d.ts.map +1 -0
- package/dist/services/url-builder.test.js +79 -0
- package/dist/services/url-builder.test.js.map +1 -0
- package/dist/services/url-templates.d.ts +41 -0
- package/dist/services/url-templates.d.ts.map +1 -0
- package/dist/services/url-templates.js +118 -0
- package/dist/services/url-templates.js.map +1 -0
- package/dist/services/url-templates.test.d.ts +2 -0
- package/dist/services/url-templates.test.d.ts.map +1 -0
- package/dist/services/url-templates.test.js +159 -0
- package/dist/services/url-templates.test.js.map +1 -0
- package/dist/types/collection.d.ts +12 -0
- package/dist/types/collection.d.ts.map +1 -0
- package/dist/types/collection.js +4 -0
- package/dist/types/collection.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/linkedin-url.d.ts +109 -0
- package/dist/types/linkedin-url.d.ts.map +1 -0
- package/dist/types/linkedin-url.js +4 -0
- package/dist/types/linkedin-url.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
2
|
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
3
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
-
import { LinkedHelperNotRunningError, ServiceError, StartInstanceError, WrongPortError, } from "./errors.js";
|
|
4
|
+
import { LinkedHelperNotRunningError, NodeIntegrationUnavailableError, ServiceError, StartInstanceError, WrongPortError, } from "./errors.js";
|
|
5
5
|
import { LauncherService } from "./launcher.js";
|
|
6
6
|
/**
|
|
7
7
|
* Shared CDPClient mocks — LauncherService creates exactly one CDPClient,
|
|
@@ -10,6 +10,9 @@ import { LauncherService } from "./launcher.js";
|
|
|
10
10
|
const mockConnect = vi.fn();
|
|
11
11
|
const mockDisconnect = vi.fn();
|
|
12
12
|
const mockEvaluate = vi.fn();
|
|
13
|
+
const mockSend = vi.fn();
|
|
14
|
+
const mockOn = vi.fn();
|
|
15
|
+
const mockOff = vi.fn();
|
|
13
16
|
const mockIsConnected = vi.fn().mockReturnValue(true);
|
|
14
17
|
vi.mock("../cdp/index.js", async (importOriginal) => {
|
|
15
18
|
const original = await importOriginal();
|
|
@@ -18,6 +21,9 @@ vi.mock("../cdp/index.js", async (importOriginal) => {
|
|
|
18
21
|
this.connect = mockConnect;
|
|
19
22
|
this.disconnect = mockDisconnect;
|
|
20
23
|
this.evaluate = mockEvaluate;
|
|
24
|
+
this.send = mockSend;
|
|
25
|
+
this.on = mockOn;
|
|
26
|
+
this.off = mockOff;
|
|
21
27
|
Object.defineProperty(this, "isConnected", {
|
|
22
28
|
get: mockIsConnected,
|
|
23
29
|
});
|
|
@@ -34,16 +40,30 @@ afterEach(() => {
|
|
|
34
40
|
});
|
|
35
41
|
describe("LauncherService", () => {
|
|
36
42
|
let service;
|
|
43
|
+
/** Value returned by the next non-probe evaluate call. */
|
|
44
|
+
let nextEvaluateResult = undefined;
|
|
37
45
|
beforeEach(() => {
|
|
38
46
|
service = new LauncherService(9222);
|
|
39
47
|
mockConnect.mockResolvedValue(undefined);
|
|
40
|
-
|
|
48
|
+
nextEvaluateResult = undefined;
|
|
49
|
+
// Default: require is available in the default context.
|
|
50
|
+
// The probe call returns true; all other calls return nextEvaluateResult.
|
|
51
|
+
mockEvaluate.mockImplementation((expression) => {
|
|
52
|
+
if (expression === "typeof require === 'function'") {
|
|
53
|
+
return Promise.resolve(true);
|
|
54
|
+
}
|
|
55
|
+
return Promise.resolve(nextEvaluateResult);
|
|
56
|
+
});
|
|
41
57
|
});
|
|
42
58
|
describe("connect", () => {
|
|
43
59
|
it("creates a CDPClient and connects", async () => {
|
|
44
60
|
await service.connect();
|
|
45
61
|
expect(service.isConnected).toBe(true);
|
|
46
62
|
});
|
|
63
|
+
it("probes for require availability during connect", async () => {
|
|
64
|
+
await service.connect();
|
|
65
|
+
expect(mockEvaluate).toHaveBeenCalledWith("typeof require === 'function'");
|
|
66
|
+
});
|
|
47
67
|
it("wraps CDPConnectionError into LinkedHelperNotRunningError", async () => {
|
|
48
68
|
mockConnect.mockRejectedValue(new CDPConnectionError("connection refused"));
|
|
49
69
|
mockFindApp.mockResolvedValue([]);
|
|
@@ -54,6 +74,72 @@ describe("LauncherService", () => {
|
|
|
54
74
|
await expect(service.connect()).rejects.toThrow(TypeError);
|
|
55
75
|
});
|
|
56
76
|
});
|
|
77
|
+
describe("connect with context fallback", () => {
|
|
78
|
+
it("falls back to preload context when default lacks require", async () => {
|
|
79
|
+
let probeCount = 0;
|
|
80
|
+
mockEvaluate.mockImplementation((expression, _await, contextId) => {
|
|
81
|
+
if (expression === "typeof require === 'function'") {
|
|
82
|
+
probeCount++;
|
|
83
|
+
// First probe (default context): no require
|
|
84
|
+
// Second probe (preload context id=2): has require
|
|
85
|
+
return Promise.resolve(probeCount >= 2 && contextId === 2);
|
|
86
|
+
}
|
|
87
|
+
return Promise.resolve(undefined);
|
|
88
|
+
});
|
|
89
|
+
mockOn.mockImplementation((event, handler) => {
|
|
90
|
+
if (event === "Runtime.executionContextCreated") {
|
|
91
|
+
handler({ context: { id: 1, auxData: { isDefault: true } } });
|
|
92
|
+
handler({ context: { id: 2, auxData: { isDefault: false } } });
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
mockSend.mockResolvedValue(undefined);
|
|
96
|
+
await service.connect();
|
|
97
|
+
expect(service.isConnected).toBe(true);
|
|
98
|
+
expect(mockSend).toHaveBeenCalledWith("Runtime.enable");
|
|
99
|
+
expect(mockSend).toHaveBeenCalledWith("Runtime.disable");
|
|
100
|
+
});
|
|
101
|
+
it("throws NodeIntegrationUnavailableError when no context has require", async () => {
|
|
102
|
+
mockEvaluate.mockImplementation((expression) => {
|
|
103
|
+
if (expression === "typeof require === 'function'") {
|
|
104
|
+
return Promise.resolve(false);
|
|
105
|
+
}
|
|
106
|
+
return Promise.resolve(undefined);
|
|
107
|
+
});
|
|
108
|
+
mockOn.mockImplementation((event, handler) => {
|
|
109
|
+
if (event === "Runtime.executionContextCreated") {
|
|
110
|
+
handler({ context: { id: 1, auxData: { isDefault: true } } });
|
|
111
|
+
handler({ context: { id: 2, auxData: { isDefault: false } } });
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
mockSend.mockResolvedValue(undefined);
|
|
115
|
+
await expect(service.connect()).rejects.toThrow(NodeIntegrationUnavailableError);
|
|
116
|
+
});
|
|
117
|
+
it("uses preload context for subsequent evaluations", async () => {
|
|
118
|
+
const PRELOAD_CONTEXT_ID = 42;
|
|
119
|
+
let probeCount = 0;
|
|
120
|
+
mockEvaluate.mockImplementation((expression, _await, contextId) => {
|
|
121
|
+
if (expression === "typeof require === 'function'") {
|
|
122
|
+
probeCount++;
|
|
123
|
+
return Promise.resolve(probeCount >= 2 && contextId === PRELOAD_CONTEXT_ID);
|
|
124
|
+
}
|
|
125
|
+
return Promise.resolve(nextEvaluateResult);
|
|
126
|
+
});
|
|
127
|
+
mockOn.mockImplementation((event, handler) => {
|
|
128
|
+
if (event === "Runtime.executionContextCreated") {
|
|
129
|
+
handler({ context: { id: 1, auxData: { isDefault: true } } });
|
|
130
|
+
handler({ context: { id: PRELOAD_CONTEXT_ID, auxData: { isDefault: false } } });
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
mockSend.mockResolvedValue(undefined);
|
|
134
|
+
await service.connect();
|
|
135
|
+
nextEvaluateResult = [];
|
|
136
|
+
await service.listAccounts();
|
|
137
|
+
const calls = mockEvaluate.mock.calls;
|
|
138
|
+
const lastCall = calls[calls.length - 1];
|
|
139
|
+
expect(lastCall).toBeDefined();
|
|
140
|
+
expect(lastCall?.[2]).toBe(PRELOAD_CONTEXT_ID);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
57
143
|
describe("disconnect", () => {
|
|
58
144
|
it("disconnects the CDPClient", async () => {
|
|
59
145
|
await service.connect();
|
|
@@ -67,17 +153,17 @@ describe("LauncherService", () => {
|
|
|
67
153
|
describe("startInstance", () => {
|
|
68
154
|
it("evaluates the startInstance expression", async () => {
|
|
69
155
|
await service.connect();
|
|
70
|
-
|
|
156
|
+
nextEvaluateResult = { success: true };
|
|
71
157
|
await service.startInstance(42);
|
|
72
|
-
expect(mockEvaluate).toHaveBeenCalledWith(expect.stringContaining("startInstance"), true);
|
|
73
|
-
expect(mockEvaluate).toHaveBeenCalledWith(expect.stringContaining("42"), true);
|
|
158
|
+
expect(mockEvaluate).toHaveBeenCalledWith(expect.stringContaining("startInstance"), true, undefined);
|
|
159
|
+
expect(mockEvaluate).toHaveBeenCalledWith(expect.stringContaining("42"), true, undefined);
|
|
74
160
|
});
|
|
75
161
|
it("throws StartInstanceError on failure", async () => {
|
|
76
162
|
await service.connect();
|
|
77
|
-
|
|
163
|
+
nextEvaluateResult = {
|
|
78
164
|
success: false,
|
|
79
165
|
error: "account is already running",
|
|
80
|
-
}
|
|
166
|
+
};
|
|
81
167
|
await expect(service.startInstance(42)).rejects.toThrow(StartInstanceError);
|
|
82
168
|
await expect(service.startInstance(42)).rejects.toThrow(/account is already running/);
|
|
83
169
|
});
|
|
@@ -89,7 +175,7 @@ describe("LauncherService", () => {
|
|
|
89
175
|
it("evaluates the stopInstance expression", async () => {
|
|
90
176
|
await service.connect();
|
|
91
177
|
await service.stopInstance(42);
|
|
92
|
-
expect(mockEvaluate).toHaveBeenCalledWith(expect.stringContaining("stopInstance"), true);
|
|
178
|
+
expect(mockEvaluate).toHaveBeenCalledWith(expect.stringContaining("stopInstance"), true, undefined);
|
|
93
179
|
});
|
|
94
180
|
it("throws ServiceError when not connected", async () => {
|
|
95
181
|
await expect(service.stopInstance(42)).rejects.toThrow(ServiceError);
|
|
@@ -98,13 +184,13 @@ describe("LauncherService", () => {
|
|
|
98
184
|
describe("getInstanceStatus", () => {
|
|
99
185
|
it("returns the instance status", async () => {
|
|
100
186
|
await service.connect();
|
|
101
|
-
|
|
187
|
+
nextEvaluateResult = "running";
|
|
102
188
|
const status = await service.getInstanceStatus(42);
|
|
103
189
|
expect(status).toBe("running");
|
|
104
190
|
});
|
|
105
191
|
it("returns stopped when status is null", async () => {
|
|
106
192
|
await service.connect();
|
|
107
|
-
|
|
193
|
+
nextEvaluateResult = "stopped";
|
|
108
194
|
const status = await service.getInstanceStatus(42);
|
|
109
195
|
expect(status).toBe("stopped");
|
|
110
196
|
});
|
|
@@ -112,10 +198,10 @@ describe("LauncherService", () => {
|
|
|
112
198
|
describe("listAccounts", () => {
|
|
113
199
|
it("returns parsed accounts", async () => {
|
|
114
200
|
await service.connect();
|
|
115
|
-
|
|
201
|
+
nextEvaluateResult = [
|
|
116
202
|
{ id: 1, liId: 100, name: "Alice", email: "alice@test.com" },
|
|
117
203
|
{ id: 2, liId: 200, name: "Bob" },
|
|
118
|
-
]
|
|
204
|
+
];
|
|
119
205
|
const accounts = await service.listAccounts();
|
|
120
206
|
expect(accounts).toHaveLength(2);
|
|
121
207
|
expect(accounts).toContainEqual(expect.objectContaining({ name: "Alice" }));
|
|
@@ -123,43 +209,24 @@ describe("LauncherService", () => {
|
|
|
123
209
|
});
|
|
124
210
|
it("returns empty array when no accounts", async () => {
|
|
125
211
|
await service.connect();
|
|
126
|
-
|
|
212
|
+
nextEvaluateResult = [];
|
|
127
213
|
const accounts = await service.listAccounts();
|
|
128
214
|
expect(accounts).toEqual([]);
|
|
129
215
|
});
|
|
130
|
-
it("
|
|
131
|
-
await service.connect();
|
|
132
|
-
mockEvaluate.mockRejectedValue(new CDPEvaluationError("ReferenceError: require is not defined"));
|
|
133
|
-
await expect(service.listAccounts()).rejects.toThrow(WrongPortError);
|
|
134
|
-
await expect(service.listAccounts()).rejects.toThrow(/appears to be a LinkedHelper instance/);
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
describe("wrong port detection", () => {
|
|
138
|
-
it("throws WrongPortError from startInstance", async () => {
|
|
139
|
-
await service.connect();
|
|
140
|
-
mockEvaluate.mockRejectedValue(new CDPEvaluationError("ReferenceError: require is not defined"));
|
|
141
|
-
await expect(service.startInstance(42)).rejects.toThrow(WrongPortError);
|
|
142
|
-
});
|
|
143
|
-
it("throws WrongPortError from stopInstance", async () => {
|
|
216
|
+
it("propagates CDPEvaluationErrors directly", async () => {
|
|
144
217
|
await service.connect();
|
|
145
|
-
mockEvaluate.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
await expect(service.getInstanceStatus(42)).rejects.toThrow(WrongPortError);
|
|
152
|
-
});
|
|
153
|
-
it("does not catch unrelated CDPEvaluationErrors", async () => {
|
|
154
|
-
await service.connect();
|
|
155
|
-
mockEvaluate.mockRejectedValue(new CDPEvaluationError("TypeError: Cannot read property 'get' of undefined"));
|
|
218
|
+
mockEvaluate.mockImplementation((expression) => {
|
|
219
|
+
if (expression === "typeof require === 'function'") {
|
|
220
|
+
return Promise.resolve(true);
|
|
221
|
+
}
|
|
222
|
+
return Promise.reject(new CDPEvaluationError("ReferenceError: remote is not defined"));
|
|
223
|
+
});
|
|
156
224
|
await expect(service.listAccounts()).rejects.toThrow(CDPEvaluationError);
|
|
157
|
-
await expect(service.listAccounts()).rejects.not.toThrow(WrongPortError);
|
|
158
225
|
});
|
|
159
|
-
it("
|
|
226
|
+
it("throws WrongPortError when electronStore is not available", async () => {
|
|
160
227
|
await service.connect();
|
|
161
|
-
|
|
162
|
-
await expect(service.listAccounts()).rejects.toThrow(
|
|
228
|
+
nextEvaluateResult = null;
|
|
229
|
+
await expect(service.listAccounts()).rejects.toThrow(WrongPortError);
|
|
163
230
|
});
|
|
164
231
|
});
|
|
165
232
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launcher.test.js","sourceRoot":"","sources":["../../src/services/launcher.test.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEzE,OAAO,EACL,2BAA2B,EAC3B,YAAY,EACZ,kBAAkB,EAClB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD;;;GAGG;AACH,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;AAC5B,MAAM,cAAc,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;AAC/B,MAAM,YAAY,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;AAC7B,MAAM,eAAe,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;AAEtD,EAAE,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IAClD,MAAM,QAAQ,GAAG,MAAM,cAAc,EAAoC,CAAC;IAC1E,OAAO;QACL,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC;YACpC,IAAI,CAAC,OAAO,GAAG,WAAW,CAAC;YAC3B,IAAI,CAAC,UAAU,GAAG,cAAc,CAAC;YACjC,IAAI,CAAC,QAAQ,GAAG,YAAY,CAAC;YAC7B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE;gBACzC,GAAG,EAAE,eAAe;aACrB,CAAC,CAAC;QACL,CAAC,CAAC;QACF,kBAAkB,EAAE,QAAQ,CAAC,kBAAkB;QAC/C,kBAAkB,EAAE,QAAQ,CAAC,kBAAkB;QAC/C,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE;KACjB,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAElF,MAAM,WAAW,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAEvC,SAAS,CAAC,GAAG,EAAE;IACb,EAAE,CAAC,eAAe,EAAE,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,IAAI,OAAwB,CAAC;IAE7B,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;QACpC,WAAW,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QACzC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"launcher.test.js","sourceRoot":"","sources":["../../src/services/launcher.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { SNSearchParams, UrlBuilderResult } from "../types/linkedin-url.js";
|
|
2
|
+
/**
|
|
3
|
+
* Build a Sales Navigator search (`/sales/search/people`) URL
|
|
4
|
+
* with Rest.li protocol encoding.
|
|
5
|
+
*
|
|
6
|
+
* @param params - SN search parameters
|
|
7
|
+
* @returns URL and any warnings
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* buildSNSearchUrl({
|
|
12
|
+
* keywords: "software engineer",
|
|
13
|
+
* filters: [{
|
|
14
|
+
* type: "CURRENT_COMPANY",
|
|
15
|
+
* values: [{ id: "urn:li:organization:1441", text: "Google", selectionType: "INCLUDED" }],
|
|
16
|
+
* }],
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildSNSearchUrl(params: SNSearchParams): UrlBuilderResult;
|
|
21
|
+
//# sourceMappingURL=sn-url-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sn-url-builder.d.ts","sourceRoot":"","sources":["../../src/services/sn-url-builder.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGV,cAAc,EACd,gBAAgB,EACjB,MAAM,0BAA0B,CAAC;AAsFlC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,cAAc,GACrB,gBAAgB,CA+ClB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
|
+
import { buildBooleanExpression } from "./boolean-expression.js";
|
|
4
|
+
const BASE_URL = "https://www.linkedin.com/sales/search/people";
|
|
5
|
+
/**
|
|
6
|
+
* Valid Sales Navigator filter types.
|
|
7
|
+
*/
|
|
8
|
+
const VALID_SN_FILTER_TYPES = new Set([
|
|
9
|
+
"CURRENT_COMPANY",
|
|
10
|
+
"PAST_COMPANY",
|
|
11
|
+
"REGION",
|
|
12
|
+
"SENIORITY_LEVEL",
|
|
13
|
+
"FUNCTION",
|
|
14
|
+
"INDUSTRY",
|
|
15
|
+
"COMPANY_HEADCOUNT",
|
|
16
|
+
"COMPANY_TYPE",
|
|
17
|
+
"CURRENT_TITLE",
|
|
18
|
+
"PAST_TITLE",
|
|
19
|
+
"YEARS_AT_CURRENT_COMPANY",
|
|
20
|
+
"YEARS_AT_CURRENT_POSITION",
|
|
21
|
+
"YEARS_OF_EXPERIENCE",
|
|
22
|
+
"SCHOOL",
|
|
23
|
+
"PROFILE_LANGUAGE",
|
|
24
|
+
"GROUP",
|
|
25
|
+
"CONNECTION",
|
|
26
|
+
]);
|
|
27
|
+
/**
|
|
28
|
+
* Filter types only valid for basic search, not Sales Navigator.
|
|
29
|
+
*/
|
|
30
|
+
const BASIC_SEARCH_ONLY_FILTER_TYPES = new Set([
|
|
31
|
+
"serviceCategory",
|
|
32
|
+
]);
|
|
33
|
+
/**
|
|
34
|
+
* Resolve keywords to a string.
|
|
35
|
+
*/
|
|
36
|
+
function resolveKeywords(keywords) {
|
|
37
|
+
if (typeof keywords === "string")
|
|
38
|
+
return keywords;
|
|
39
|
+
return buildBooleanExpression(keywords);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Encode a single filter value in Rest.li format.
|
|
43
|
+
*
|
|
44
|
+
* Output: `(id:value,text:value,selectionType:INCLUDED)`
|
|
45
|
+
*/
|
|
46
|
+
function encodeFilterValue(value) {
|
|
47
|
+
const parts = [
|
|
48
|
+
`id:${encodeRestLiValue(value.id)}`,
|
|
49
|
+
];
|
|
50
|
+
if (value.text !== undefined) {
|
|
51
|
+
parts.push(`text:${encodeRestLiValue(value.text)}`);
|
|
52
|
+
}
|
|
53
|
+
parts.push(`selectionType:${value.selectionType}`);
|
|
54
|
+
return `(${parts.join(",")})`;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Encode a filter in Rest.li format.
|
|
58
|
+
*
|
|
59
|
+
* Output: `(type:CURRENT_COMPANY,values:List((id:...,selectionType:INCLUDED)))`
|
|
60
|
+
*/
|
|
61
|
+
function encodeFilter(filter) {
|
|
62
|
+
const values = filter.values.map(encodeFilterValue).join(",");
|
|
63
|
+
return `(type:${filter.type},values:List(${values}))`;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Percent-encode a value for Rest.li URI format.
|
|
67
|
+
*
|
|
68
|
+
* Rest.li uses standard percent-encoding. Structural characters like
|
|
69
|
+
* parentheses and commas are added by the surrounding syntax, not as part
|
|
70
|
+
* of the encoded value, so we keep the `encodeURIComponent` output as-is.
|
|
71
|
+
*/
|
|
72
|
+
function encodeRestLiValue(value) {
|
|
73
|
+
return encodeURIComponent(value);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Build a Sales Navigator search (`/sales/search/people`) URL
|
|
77
|
+
* with Rest.li protocol encoding.
|
|
78
|
+
*
|
|
79
|
+
* @param params - SN search parameters
|
|
80
|
+
* @returns URL and any warnings
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* buildSNSearchUrl({
|
|
85
|
+
* keywords: "software engineer",
|
|
86
|
+
* filters: [{
|
|
87
|
+
* type: "CURRENT_COMPANY",
|
|
88
|
+
* values: [{ id: "urn:li:organization:1441", text: "Google", selectionType: "INCLUDED" }],
|
|
89
|
+
* }],
|
|
90
|
+
* });
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export function buildSNSearchUrl(params) {
|
|
94
|
+
const warnings = [];
|
|
95
|
+
const queryParts = [];
|
|
96
|
+
queryParts.push("spellCorrectionEnabled:true");
|
|
97
|
+
queryParts.push("recentSearchParam:(doLogHistory:true)");
|
|
98
|
+
// Filters
|
|
99
|
+
if (params.filters !== undefined && params.filters.length > 0) {
|
|
100
|
+
const validFilters = [];
|
|
101
|
+
for (const filter of params.filters) {
|
|
102
|
+
if (BASIC_SEARCH_ONLY_FILTER_TYPES.has(filter.type)) {
|
|
103
|
+
warnings.push(`"${filter.type}" is a basic search filter — not applicable to Sales Navigator`);
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (!VALID_SN_FILTER_TYPES.has(filter.type)) {
|
|
107
|
+
warnings.push(`Unknown Sales Navigator filter type: "${filter.type}"`);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (filter.values.length === 0) {
|
|
111
|
+
warnings.push(`Empty values for filter "${filter.type}" — ignored`);
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
validFilters.push(filter);
|
|
115
|
+
}
|
|
116
|
+
if (validFilters.length > 0) {
|
|
117
|
+
const filtersList = validFilters.map(encodeFilter).join(",");
|
|
118
|
+
queryParts.push(`filters:List(${filtersList})`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Keywords
|
|
122
|
+
if (params.keywords !== undefined) {
|
|
123
|
+
const keywordsStr = resolveKeywords(params.keywords);
|
|
124
|
+
if (keywordsStr.length > 0) {
|
|
125
|
+
queryParts.push(`keywords:${encodeRestLiValue(keywordsStr)}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const query = `(${queryParts.join(",")})`;
|
|
129
|
+
const url = `${BASE_URL}?query=${query}`;
|
|
130
|
+
return { url, sourceType: "SNSearchPage", warnings };
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=sn-url-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sn-url-builder.js","sourceRoot":"","sources":["../../src/services/sn-url-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sn-url-builder.test.d.ts","sourceRoot":"","sources":["../../src/services/sn-url-builder.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
import { detectSourceType } from "./source-type-registry.js";
|
|
5
|
+
import { buildSNSearchUrl } from "./sn-url-builder.js";
|
|
6
|
+
describe("buildSNSearchUrl", () => {
|
|
7
|
+
it("builds base URL with default query structure", () => {
|
|
8
|
+
const result = buildSNSearchUrl({});
|
|
9
|
+
expect(result.url).toContain("https://www.linkedin.com/sales/search/people?query=(");
|
|
10
|
+
expect(result.url).toContain("spellCorrectionEnabled:true");
|
|
11
|
+
expect(result.url).toContain("recentSearchParam:(doLogHistory:true)");
|
|
12
|
+
expect(result.sourceType).toBe("SNSearchPage");
|
|
13
|
+
expect(result.warnings).toHaveLength(0);
|
|
14
|
+
});
|
|
15
|
+
it("includes keywords in query", () => {
|
|
16
|
+
const result = buildSNSearchUrl({
|
|
17
|
+
keywords: "software engineer",
|
|
18
|
+
});
|
|
19
|
+
expect(result.url).toContain("keywords:software%20engineer");
|
|
20
|
+
});
|
|
21
|
+
it("accepts boolean expression as keywords", () => {
|
|
22
|
+
const result = buildSNSearchUrl({
|
|
23
|
+
keywords: { and: ["SaaS", "B2B"] },
|
|
24
|
+
});
|
|
25
|
+
expect(result.url).toContain("keywords:SaaS%20AND%20B2B");
|
|
26
|
+
});
|
|
27
|
+
it("encodes CURRENT_COMPANY filter in Rest.li format", () => {
|
|
28
|
+
const result = buildSNSearchUrl({
|
|
29
|
+
filters: [
|
|
30
|
+
{
|
|
31
|
+
type: "CURRENT_COMPANY",
|
|
32
|
+
values: [
|
|
33
|
+
{
|
|
34
|
+
id: "urn:li:organization:1441",
|
|
35
|
+
text: "Google",
|
|
36
|
+
selectionType: "INCLUDED",
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
});
|
|
42
|
+
expect(result.url).toContain("filters:List(");
|
|
43
|
+
expect(result.url).toContain("type:CURRENT_COMPANY");
|
|
44
|
+
expect(result.url).toContain("selectionType:INCLUDED");
|
|
45
|
+
expect(result.url).toContain("text:Google");
|
|
46
|
+
});
|
|
47
|
+
it("encodes multiple filters", () => {
|
|
48
|
+
const result = buildSNSearchUrl({
|
|
49
|
+
filters: [
|
|
50
|
+
{
|
|
51
|
+
type: "CURRENT_COMPANY",
|
|
52
|
+
values: [
|
|
53
|
+
{
|
|
54
|
+
id: "urn:li:organization:1441",
|
|
55
|
+
text: "Google",
|
|
56
|
+
selectionType: "INCLUDED",
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
type: "REGION",
|
|
62
|
+
values: [
|
|
63
|
+
{
|
|
64
|
+
id: "102277331",
|
|
65
|
+
text: "San Francisco",
|
|
66
|
+
selectionType: "INCLUDED",
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
});
|
|
72
|
+
expect(result.url).toContain("type:CURRENT_COMPANY");
|
|
73
|
+
expect(result.url).toContain("type:REGION");
|
|
74
|
+
});
|
|
75
|
+
it("encodes EXCLUDED selectionType", () => {
|
|
76
|
+
const result = buildSNSearchUrl({
|
|
77
|
+
filters: [
|
|
78
|
+
{
|
|
79
|
+
type: "CURRENT_TITLE",
|
|
80
|
+
values: [
|
|
81
|
+
{
|
|
82
|
+
id: "intern",
|
|
83
|
+
text: "Intern",
|
|
84
|
+
selectionType: "EXCLUDED",
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
});
|
|
90
|
+
expect(result.url).toContain("selectionType:EXCLUDED");
|
|
91
|
+
});
|
|
92
|
+
it("warns on basic-search-only filter types", () => {
|
|
93
|
+
const result = buildSNSearchUrl({
|
|
94
|
+
filters: [
|
|
95
|
+
{
|
|
96
|
+
type: "serviceCategory",
|
|
97
|
+
values: [{ id: "1", selectionType: "INCLUDED" }],
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
});
|
|
101
|
+
expect(result.warnings).toHaveLength(1);
|
|
102
|
+
expect(result.warnings[0]).toContain("basic search filter");
|
|
103
|
+
});
|
|
104
|
+
it("warns on unknown filter types", () => {
|
|
105
|
+
const result = buildSNSearchUrl({
|
|
106
|
+
filters: [
|
|
107
|
+
{
|
|
108
|
+
type: "UNKNOWN_FILTER",
|
|
109
|
+
values: [{ id: "1", selectionType: "INCLUDED" }],
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
});
|
|
113
|
+
expect(result.warnings).toHaveLength(1);
|
|
114
|
+
expect(result.warnings[0]).toContain("Unknown Sales Navigator filter");
|
|
115
|
+
});
|
|
116
|
+
it("warns on empty filter values", () => {
|
|
117
|
+
const result = buildSNSearchUrl({
|
|
118
|
+
filters: [{ type: "CURRENT_COMPANY", values: [] }],
|
|
119
|
+
});
|
|
120
|
+
expect(result.warnings).toHaveLength(1);
|
|
121
|
+
expect(result.warnings[0]).toContain("Empty values");
|
|
122
|
+
});
|
|
123
|
+
it("output URL is detected as SNSearchPage", () => {
|
|
124
|
+
const result = buildSNSearchUrl({
|
|
125
|
+
keywords: "test",
|
|
126
|
+
});
|
|
127
|
+
expect(detectSourceType(result.url)).toBe("SNSearchPage");
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
//# sourceMappingURL=sn-url-builder.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sn-url-builder.test.js","sourceRoot":"","sources":["../../src/services/sn-url-builder.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { SourceType } from "../types/collection.js";
|
|
2
|
+
/**
|
|
3
|
+
* Detect the LinkedIn source type from a URL.
|
|
4
|
+
*
|
|
5
|
+
* Tests the URL pathname against known LinkedIn page patterns and
|
|
6
|
+
* returns the matching source type, or `undefined` if no pattern matches.
|
|
7
|
+
*
|
|
8
|
+
* @param url - Full LinkedIn URL or pathname
|
|
9
|
+
* @returns The detected source type, or `undefined` for unknown URLs
|
|
10
|
+
*/
|
|
11
|
+
export declare function detectSourceType(url: string): SourceType | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Validate whether a string is a known source type.
|
|
14
|
+
*
|
|
15
|
+
* @param type - String to validate
|
|
16
|
+
* @returns `true` if `type` is a valid {@link SourceType}
|
|
17
|
+
*/
|
|
18
|
+
export declare function validateSourceType(type: string): type is SourceType;
|
|
19
|
+
//# sourceMappingURL=source-type-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-type-registry.d.ts","sourceRoot":"","sources":["../../src/services/source-type-registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AA2CzD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAgBpE;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,UAAU,CAEnE"}
|