linkedin-secret-sauce 0.3.26 → 0.3.28
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/dist/linkedin-api.js
CHANGED
|
@@ -289,9 +289,9 @@ async function searchSalesLeads(keywords, options) {
|
|
|
289
289
|
// Extract metadata.totalDisplayCount (LinkedIn's display string like "500K+")
|
|
290
290
|
const metadataVal = rrec && 'metadata' in rrec ? rrec.metadata : undefined;
|
|
291
291
|
const metadata = (metadataVal && typeof metadataVal === 'object') ? metadataVal : undefined;
|
|
292
|
-
// Calculate hasMore
|
|
293
|
-
//
|
|
294
|
-
const hasMore = items.length === count;
|
|
292
|
+
// Calculate hasMore using LinkedIn's total count (primary) or result length (fallback)
|
|
293
|
+
// LinkedIn API always returns paging.total, so we use it for accurate pagination
|
|
294
|
+
const hasMore = paging?.total ? (start + count) < paging.total : items.length === count;
|
|
295
295
|
const result = options
|
|
296
296
|
? {
|
|
297
297
|
items,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseSalesSearchResults = parseSalesSearchResults;
|
|
4
|
+
const json_sanitizer_1 = require("../utils/json-sanitizer");
|
|
4
5
|
function parseSalesSearchResults(rawResponse) {
|
|
5
6
|
const rr = rawResponse;
|
|
6
7
|
const elements = Array.isArray(rr?.elements) ? rr?.elements : [];
|
|
@@ -8,13 +9,13 @@ function parseSalesSearchResults(rawResponse) {
|
|
|
8
9
|
for (const el of elements) {
|
|
9
10
|
const name = [el?.firstName, el?.lastName].filter(Boolean).join(' ').trim() || undefined;
|
|
10
11
|
const res = {
|
|
11
|
-
name,
|
|
12
|
-
headline: (el?.summary || '').split('\n')[0]?.slice(0, 180),
|
|
12
|
+
name: (0, json_sanitizer_1.sanitizeForJson)(name),
|
|
13
|
+
headline: (0, json_sanitizer_1.sanitizeForJson)((el?.summary || '').split('\n')[0]?.slice(0, 180)),
|
|
13
14
|
salesProfileUrn: el?.entityUrn,
|
|
14
15
|
objectUrn: el?.objectUrn,
|
|
15
|
-
geoRegion: el?.geoRegion,
|
|
16
|
-
locationText: el?.geoRegion,
|
|
17
|
-
summary: el?.summary,
|
|
16
|
+
geoRegion: (0, json_sanitizer_1.sanitizeForJson)(el?.geoRegion),
|
|
17
|
+
locationText: (0, json_sanitizer_1.sanitizeForJson)(el?.geoRegion),
|
|
18
|
+
summary: (0, json_sanitizer_1.sanitizeForJson)(el?.summary),
|
|
18
19
|
};
|
|
19
20
|
// fsdKey from URN patterns
|
|
20
21
|
const urn = String(el?.entityUrn || '');
|
|
@@ -39,8 +40,8 @@ function parseSalesSearchResults(rawResponse) {
|
|
|
39
40
|
// Current position (backward compatible - extract from first position)
|
|
40
41
|
const pos = Array.isArray(el?.currentPositions) && el.currentPositions.length > 0 ? el.currentPositions[0] : undefined;
|
|
41
42
|
if (pos) {
|
|
42
|
-
res.currentRole = pos?.title;
|
|
43
|
-
res.currentCompany = pos?.companyName;
|
|
43
|
+
res.currentRole = (0, json_sanitizer_1.sanitizeForJson)(pos?.title);
|
|
44
|
+
res.currentCompany = (0, json_sanitizer_1.sanitizeForJson)(pos?.companyName);
|
|
44
45
|
// Extract company logo from companyUrnResolutionResult if available
|
|
45
46
|
const companyData = pos?.companyUrnResolutionResult;
|
|
46
47
|
if (companyData?.companyPictureDisplayImage) {
|
|
@@ -56,7 +57,7 @@ function parseSalesSearchResults(rawResponse) {
|
|
|
56
57
|
res.premium = el?.premium;
|
|
57
58
|
res.openLink = el?.openLink;
|
|
58
59
|
res.degree = el?.degree;
|
|
59
|
-
res.industry = el?.industry;
|
|
60
|
+
res.industry = (0, json_sanitizer_1.sanitizeForJson)(el?.industry);
|
|
60
61
|
res.isOpenProfile = el?.isOpenProfile;
|
|
61
62
|
res.memorialized = el?.memorialized;
|
|
62
63
|
res.saved = el?.saved;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitizes string values to ensure they can be safely JSON serialized
|
|
3
|
+
*
|
|
4
|
+
* Removes control characters (0x00-0x1F, 0x7F-0x9F) that can break JSON parsing
|
|
5
|
+
* when consumers try to stringify the response data.
|
|
6
|
+
*
|
|
7
|
+
* This fixes the "Unterminated string in JSON" error that occurs when LinkedIn
|
|
8
|
+
* returns profile/company data containing unescaped control characters.
|
|
9
|
+
*/
|
|
10
|
+
export declare function sanitizeForJson(value: unknown): string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Sanitizes all string fields in an object recursively
|
|
13
|
+
*/
|
|
14
|
+
export declare function sanitizeObject<T>(obj: T): T;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sanitizeForJson = sanitizeForJson;
|
|
4
|
+
exports.sanitizeObject = sanitizeObject;
|
|
5
|
+
/**
|
|
6
|
+
* Sanitizes string values to ensure they can be safely JSON serialized
|
|
7
|
+
*
|
|
8
|
+
* Removes control characters (0x00-0x1F, 0x7F-0x9F) that can break JSON parsing
|
|
9
|
+
* when consumers try to stringify the response data.
|
|
10
|
+
*
|
|
11
|
+
* This fixes the "Unterminated string in JSON" error that occurs when LinkedIn
|
|
12
|
+
* returns profile/company data containing unescaped control characters.
|
|
13
|
+
*/
|
|
14
|
+
function sanitizeForJson(value) {
|
|
15
|
+
if (value === null || value === undefined)
|
|
16
|
+
return undefined;
|
|
17
|
+
if (typeof value !== 'string')
|
|
18
|
+
return String(value);
|
|
19
|
+
// Remove ASCII control characters (0x00-0x1F) and DEL (0x7F)
|
|
20
|
+
// Also remove C1 control codes (0x80-0x9F)
|
|
21
|
+
// These characters can break JSON serialization even though JSON.stringify
|
|
22
|
+
// should escape them - LinkedIn sometimes returns malformed strings
|
|
23
|
+
return String(value)
|
|
24
|
+
.replace(/[\u0000-\u001F\u007F-\u009F]/g, '')
|
|
25
|
+
.trim();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Sanitizes all string fields in an object recursively
|
|
29
|
+
*/
|
|
30
|
+
function sanitizeObject(obj) {
|
|
31
|
+
if (obj === null || obj === undefined)
|
|
32
|
+
return obj;
|
|
33
|
+
if (typeof obj === 'string') {
|
|
34
|
+
return sanitizeForJson(obj);
|
|
35
|
+
}
|
|
36
|
+
if (Array.isArray(obj)) {
|
|
37
|
+
return obj.map(item => sanitizeObject(item));
|
|
38
|
+
}
|
|
39
|
+
if (typeof obj === 'object') {
|
|
40
|
+
const result = {};
|
|
41
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
42
|
+
result[key] = sanitizeObject(value);
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
return obj;
|
|
47
|
+
}
|