linkedin-secret-sauce 0.1.2 → 0.2.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/dist/config.js +0 -1
- package/dist/cookie-pool.js +2 -1
- package/dist/cosiall-client.js +20 -5
- package/dist/http-client.d.ts +1 -1
- package/dist/http-client.js +10 -6
- package/dist/linkedin-api.js +19 -9
- package/dist/parsers/company-parser.d.ts +1 -1
- package/dist/parsers/company-parser.js +13 -8
- package/dist/parsers/image-parser.d.ts +10 -1
- package/dist/parsers/image-parser.js +4 -3
- package/dist/parsers/profile-parser.d.ts +1 -1
- package/dist/parsers/profile-parser.js +28 -24
- package/dist/parsers/search-parser.d.ts +1 -1
- package/dist/parsers/search-parser.js +2 -1
- package/dist/utils/logger.d.ts +1 -1
- package/dist/utils/metrics.d.ts +4 -1
- package/dist/utils/metrics.js +0 -1
- package/dist/utils/search-encoder.d.ts +1 -1
- package/dist/utils/search-encoder.js +3 -2
- package/package.json +58 -53
package/dist/config.js
CHANGED
package/dist/cookie-pool.js
CHANGED
|
@@ -89,7 +89,8 @@ async function ensureInitialized() {
|
|
|
89
89
|
(0, logger_1.log)('info', 'cookiePool.refreshed', { count: refreshed.length });
|
|
90
90
|
}
|
|
91
91
|
catch (e) {
|
|
92
|
-
|
|
92
|
+
const err = e;
|
|
93
|
+
(0, logger_1.log)('warn', 'cookiePool.refreshFailed', { error: err?.message });
|
|
93
94
|
}
|
|
94
95
|
}, interval);
|
|
95
96
|
}
|
package/dist/cosiall-client.js
CHANGED
|
@@ -29,9 +29,24 @@ async function fetchCookiesFromCosiall() {
|
|
|
29
29
|
}
|
|
30
30
|
(0, logger_1.log)('info', 'cosiall.fetch.success', { count: data.length });
|
|
31
31
|
(0, metrics_1.incrementMetric)('cosiallSuccess');
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
function isCookie(obj) {
|
|
33
|
+
return !!obj && typeof obj === 'object' && 'name' in obj && 'value' in obj;
|
|
34
|
+
}
|
|
35
|
+
function isItem(obj) {
|
|
36
|
+
if (!obj || typeof obj !== 'object')
|
|
37
|
+
return false;
|
|
38
|
+
const rec = obj;
|
|
39
|
+
if (typeof rec.accountId !== 'string')
|
|
40
|
+
return false;
|
|
41
|
+
if (!Array.isArray(rec.cookies))
|
|
42
|
+
return false;
|
|
43
|
+
if (!rec.cookies.every(isCookie))
|
|
44
|
+
return false;
|
|
45
|
+
if (rec.expiresAt !== undefined && typeof rec.expiresAt !== 'number')
|
|
46
|
+
return false;
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
return data
|
|
50
|
+
.filter(isItem)
|
|
51
|
+
.map((item) => ({ accountId: item.accountId, cookies: item.cookies, expiresAt: item.expiresAt }));
|
|
37
52
|
}
|
package/dist/http-client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export interface LinkedInRequestOptions {
|
|
2
2
|
url: string;
|
|
3
3
|
method?: 'GET' | 'POST';
|
|
4
|
-
body?:
|
|
4
|
+
body?: unknown;
|
|
5
5
|
headers?: Record<string, string>;
|
|
6
6
|
}
|
|
7
7
|
export declare function executeLinkedInRequest<T>(options: LinkedInRequestOptions, _operationName: string): Promise<T>;
|
package/dist/http-client.js
CHANGED
|
@@ -71,18 +71,22 @@ async function executeLinkedInRequest(options, _operationName) {
|
|
|
71
71
|
(0, logger_1.log)('debug', 'http.attempt', { accountId, attempt: attempt + 1, method: options.method ?? 'GET', url: options.url });
|
|
72
72
|
let res;
|
|
73
73
|
try {
|
|
74
|
-
|
|
74
|
+
const init = {
|
|
75
75
|
method: options.method ?? 'GET',
|
|
76
76
|
headers,
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
};
|
|
78
|
+
if (options.body !== undefined) {
|
|
79
|
+
init.body = typeof options.body === 'string' ? options.body : JSON.stringify(options.body);
|
|
80
|
+
}
|
|
81
|
+
res = (await fetch(options.url, init));
|
|
79
82
|
}
|
|
80
83
|
catch (err) {
|
|
81
|
-
const
|
|
82
|
-
|
|
84
|
+
const e = err;
|
|
85
|
+
const code = e?.code || e?.cause?.code || 'FETCH_FAILED';
|
|
86
|
+
(0, logger_1.log)('error', 'http.networkError', { accountId, url: options.url, code, message: String(e?.message || err) });
|
|
83
87
|
(0, metrics_1.incrementMetric)('httpFailures');
|
|
84
88
|
try {
|
|
85
|
-
(0, request_history_1.recordRequest)({ operation: op, selector: options.url, status: 0, durationMs: Date.now() - started, accountId, errorMessage: String(
|
|
89
|
+
(0, request_history_1.recordRequest)({ operation: op, selector: options.url, status: 0, durationMs: Date.now() - started, accountId, errorMessage: String(e?.message || err) });
|
|
86
90
|
}
|
|
87
91
|
catch { }
|
|
88
92
|
lastError = new errors_1.LinkedInClientError('LinkedIn fetch failed', 'REQUEST_FAILED', 0, accountId);
|
package/dist/linkedin-api.js
CHANGED
|
@@ -210,7 +210,10 @@ async function searchSalesLeads(keywords, options) {
|
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
const items = (0, search_parser_1.parseSalesSearchResults)(raw);
|
|
213
|
-
const
|
|
213
|
+
const rrec = (raw && typeof raw === 'object') ? raw : undefined;
|
|
214
|
+
const pagingVal = rrec && 'paging' in rrec ? rrec.paging : undefined;
|
|
215
|
+
const p = (pagingVal && typeof pagingVal === 'object') ? pagingVal : undefined;
|
|
216
|
+
const paging = p ?? { start, count };
|
|
214
217
|
const result = options
|
|
215
218
|
? { items, page: { start: Number(paging.start ?? start), count: Number(paging.count ?? count), total: paging?.total } }
|
|
216
219
|
: items; // backward-compat: old tests expect an array when no options passed
|
|
@@ -223,11 +226,8 @@ async function getProfilesBatch(vanities, concurrency = 4) {
|
|
|
223
226
|
const results = Array.from({ length: vanities.length }, () => null);
|
|
224
227
|
let idx = 0;
|
|
225
228
|
async function worker() {
|
|
226
|
-
|
|
227
|
-
while (true) {
|
|
229
|
+
while (idx < vanities.length) {
|
|
228
230
|
const myIdx = idx++;
|
|
229
|
-
if (myIdx >= vanities.length)
|
|
230
|
-
break;
|
|
231
231
|
const vanity = vanities[myIdx];
|
|
232
232
|
try {
|
|
233
233
|
const prof = await getProfileByVanity(vanity);
|
|
@@ -253,7 +253,10 @@ async function resolveCompanyUniversalName(universalName) {
|
|
|
253
253
|
}
|
|
254
254
|
catch { }
|
|
255
255
|
const raw = await (0, http_client_1.executeLinkedInRequest)({ url }, 'resolveCompanyUniversalName');
|
|
256
|
-
const
|
|
256
|
+
const rec = (raw && typeof raw === 'object') ? raw : undefined;
|
|
257
|
+
const elementsVal = rec && 'elements' in rec ? rec.elements : undefined;
|
|
258
|
+
const first = Array.isArray(elementsVal) ? elementsVal[0] : undefined;
|
|
259
|
+
const id = first?.id ?? first?.entityUrn ?? undefined;
|
|
257
260
|
try {
|
|
258
261
|
(0, logger_1.log)('info', 'api.ok', { operation: 'resolveCompanyUniversalName', selector: universalName, id });
|
|
259
262
|
}
|
|
@@ -372,11 +375,18 @@ async function typeahead(options) {
|
|
|
372
375
|
const items = Array.isArray(raw?.elements)
|
|
373
376
|
? raw.elements.map((it) => ({
|
|
374
377
|
id: String(it?.id ?? it?.backendId ?? ''),
|
|
375
|
-
text: it
|
|
378
|
+
text: it.displayValue ??
|
|
379
|
+
it.headline?.text ??
|
|
380
|
+
it.text ??
|
|
381
|
+
it.name ??
|
|
382
|
+
it.label ??
|
|
383
|
+
''
|
|
376
384
|
}))
|
|
377
385
|
: [];
|
|
378
|
-
const
|
|
379
|
-
const
|
|
386
|
+
const rtype = (raw && typeof raw === 'object') ? raw : undefined;
|
|
387
|
+
const pagingVal2 = rtype && 'paging' in rtype ? rtype.paging : undefined;
|
|
388
|
+
const paging2 = (pagingVal2 && typeof pagingVal2 === 'object') ? pagingVal2 : undefined;
|
|
389
|
+
const result = { items, page: { start: Number(paging2?.start ?? start), count: Number(paging2?.count ?? count), total: paging2?.total } };
|
|
380
390
|
typeaheadCache.set(cacheKey, { data: result, ts: Date.now() });
|
|
381
391
|
try {
|
|
382
392
|
(0, logger_1.log)('info', 'api.ok', { operation: 'typeahead', selector: { type, query }, count: items.length });
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { Company } from '../types';
|
|
2
|
-
export declare function parseCompany(raw:
|
|
2
|
+
export declare function parseCompany(raw: unknown): Company;
|
|
@@ -3,18 +3,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.parseCompany = parseCompany;
|
|
4
4
|
const image_parser_1 = require("./image-parser");
|
|
5
5
|
function parseCompany(raw) {
|
|
6
|
+
const r = raw;
|
|
6
7
|
const company = {
|
|
7
|
-
companyId: String(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
companyId: String(r?.id ?? '')
|
|
9
|
+
.replace(/^urn:li:(?:fsd_)?company:/i, '') ||
|
|
10
|
+
String(r?.entityUrn ?? '')
|
|
11
|
+
.replace(/^urn:li:(?:fsd_)?company:/i, ''),
|
|
12
|
+
universalName: r?.universalName,
|
|
13
|
+
name: r?.name,
|
|
14
|
+
websiteUrl: r?.websiteUrl,
|
|
15
|
+
sizeLabel: r?.employeeCountRange?.localizedName,
|
|
16
|
+
headquarters: r?.headquarterLocation?.defaultLocalizedName ||
|
|
17
|
+
r?.headquarter?.defaultLocalizedName,
|
|
13
18
|
logoUrl: undefined,
|
|
14
19
|
coverUrl: undefined,
|
|
15
20
|
};
|
|
16
|
-
const logoVector =
|
|
17
|
-
const coverVector =
|
|
21
|
+
const logoVector = r?.logo?.vectorImage || r?.logoV2?.vectorImage;
|
|
22
|
+
const coverVector = r?.coverPhoto?.vectorImage || r?.backgroundImage?.vectorImage;
|
|
18
23
|
const logoUrl = (0, image_parser_1.selectBestImageUrl)(logoVector);
|
|
19
24
|
const coverUrl = (0, image_parser_1.selectBestImageUrl)(coverVector);
|
|
20
25
|
if (logoUrl)
|
|
@@ -1 +1,10 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type VectorArtifact = {
|
|
2
|
+
width?: number;
|
|
3
|
+
fileIdentifyingUrlPathSegment?: string;
|
|
4
|
+
url?: string;
|
|
5
|
+
};
|
|
6
|
+
export type VectorImage = {
|
|
7
|
+
rootUrl?: string;
|
|
8
|
+
artifacts?: VectorArtifact[];
|
|
9
|
+
};
|
|
10
|
+
export declare function selectBestImageUrl(vector: unknown): string | undefined;
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.selectBestImageUrl = selectBestImageUrl;
|
|
4
4
|
function selectBestImageUrl(vector) {
|
|
5
|
-
|
|
5
|
+
const v = vector;
|
|
6
|
+
if (!v || !Array.isArray(v.artifacts) || v.artifacts.length === 0)
|
|
6
7
|
return undefined;
|
|
7
|
-
const best =
|
|
8
|
+
const best = v.artifacts.reduce((prev, curr) => ((curr?.width || 0) > (prev?.width || 0) ? curr : prev), {});
|
|
8
9
|
const seg = best?.fileIdentifyingUrlPathSegment || best?.url;
|
|
9
10
|
if (!seg)
|
|
10
11
|
return undefined;
|
|
11
12
|
if (/^https?:\/\//i.test(seg))
|
|
12
13
|
return seg;
|
|
13
|
-
const root = String(
|
|
14
|
+
const root = String(v.rootUrl || '');
|
|
14
15
|
return root + seg;
|
|
15
16
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { LinkedInProfile } from '../types';
|
|
2
|
-
export declare function parseFullProfile(rawResponse:
|
|
2
|
+
export declare function parseFullProfile(rawResponse: unknown, vanity: string): LinkedInProfile;
|
|
@@ -3,7 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.parseFullProfile = parseFullProfile;
|
|
4
4
|
const image_parser_1 = require("./image-parser");
|
|
5
5
|
function parseFullProfile(rawResponse, vanity) {
|
|
6
|
-
const
|
|
6
|
+
const rr = rawResponse;
|
|
7
|
+
const included = Array.isArray(rr?.included) ? rr.included : [];
|
|
7
8
|
const identity = included.find((it) => String(it?.$type || '').includes('identity.profile.Profile')) || {};
|
|
8
9
|
const profile = {
|
|
9
10
|
vanity,
|
|
@@ -33,8 +34,9 @@ function parseFullProfile(rawResponse, vanity) {
|
|
|
33
34
|
return obj;
|
|
34
35
|
if (typeof obj !== 'object')
|
|
35
36
|
return undefined;
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
const rec = obj;
|
|
38
|
+
for (const k of Object.keys(rec)) {
|
|
39
|
+
const v = rec[k];
|
|
38
40
|
if (typeof v === 'string' && /urn:li:(?:fsd_)?company:/i.test(v))
|
|
39
41
|
return v;
|
|
40
42
|
if (v && typeof v === 'object') {
|
|
@@ -46,25 +48,26 @@ function parseFullProfile(rawResponse, vanity) {
|
|
|
46
48
|
return undefined;
|
|
47
49
|
}
|
|
48
50
|
for (const item of included) {
|
|
49
|
-
const
|
|
51
|
+
const rec = item;
|
|
52
|
+
const urn = rec?.entityUrn || '';
|
|
50
53
|
if (!urn.includes('fsd_profilePosition'))
|
|
51
54
|
continue;
|
|
52
55
|
const pos = {
|
|
53
|
-
title:
|
|
54
|
-
companyName:
|
|
55
|
-
description:
|
|
56
|
-
isCurrent: !
|
|
57
|
-
startYear:
|
|
58
|
-
startMonth:
|
|
59
|
-
endYear:
|
|
60
|
-
endMonth:
|
|
56
|
+
title: rec?.title,
|
|
57
|
+
companyName: rec?.companyName,
|
|
58
|
+
description: rec?.description,
|
|
59
|
+
isCurrent: !rec?.timePeriod?.endDate,
|
|
60
|
+
startYear: rec?.timePeriod?.startDate?.year,
|
|
61
|
+
startMonth: rec?.timePeriod?.startDate?.month,
|
|
62
|
+
endYear: rec?.timePeriod?.endDate?.year,
|
|
63
|
+
endMonth: rec?.timePeriod?.endDate?.month,
|
|
61
64
|
};
|
|
62
65
|
// Try to extract company URN and numeric id robustly
|
|
63
66
|
const candUrns = [
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
rec?.companyUrn,
|
|
68
|
+
rec?.company?.entityUrn,
|
|
69
|
+
rec?.company?.companyUrn,
|
|
70
|
+
rec?.companyUrnV2,
|
|
68
71
|
].filter(Boolean);
|
|
69
72
|
const foundUrn = candUrns.find(u => /urn:li:(?:fsd_)?company:/i.test(u)) || deepFindCompanyUrn(item);
|
|
70
73
|
if (foundUrn) {
|
|
@@ -77,17 +80,18 @@ function parseFullProfile(rawResponse, vanity) {
|
|
|
77
80
|
}
|
|
78
81
|
// Educations
|
|
79
82
|
for (const item of included) {
|
|
80
|
-
const
|
|
83
|
+
const rec = item;
|
|
84
|
+
const urn = rec?.entityUrn || '';
|
|
81
85
|
if (!urn.includes('fsd_profileEducation'))
|
|
82
86
|
continue;
|
|
83
87
|
const edu = {
|
|
84
|
-
schoolName:
|
|
85
|
-
degree:
|
|
86
|
-
fieldOfStudy:
|
|
87
|
-
startYear:
|
|
88
|
-
startMonth:
|
|
89
|
-
endYear:
|
|
90
|
-
endMonth:
|
|
88
|
+
schoolName: rec?.schoolName,
|
|
89
|
+
degree: rec?.degreeName,
|
|
90
|
+
fieldOfStudy: rec?.fieldOfStudy,
|
|
91
|
+
startYear: rec?.timePeriod?.startDate?.year,
|
|
92
|
+
startMonth: rec?.timePeriod?.startDate?.month,
|
|
93
|
+
endYear: rec?.timePeriod?.endDate?.year,
|
|
94
|
+
endMonth: rec?.timePeriod?.endDate?.month,
|
|
91
95
|
};
|
|
92
96
|
profile.educations.push(edu);
|
|
93
97
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { SalesLeadSearchResult } from '../types';
|
|
2
|
-
export declare function parseSalesSearchResults(rawResponse:
|
|
2
|
+
export declare function parseSalesSearchResults(rawResponse: unknown): SalesLeadSearchResult[];
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.parseSalesSearchResults = parseSalesSearchResults;
|
|
4
4
|
function parseSalesSearchResults(rawResponse) {
|
|
5
|
-
const
|
|
5
|
+
const rr = rawResponse;
|
|
6
|
+
const elements = Array.isArray(rr?.elements) ? rr?.elements : [];
|
|
6
7
|
const results = [];
|
|
7
8
|
for (const el of elements) {
|
|
8
9
|
const name = [el?.firstName, el?.lastName].filter(Boolean).join(' ').trim() || undefined;
|
package/dist/utils/logger.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
2
|
-
export declare function log(level: LogLevel, message: string, data?:
|
|
2
|
+
export declare function log(level: LogLevel, message: string, data?: unknown): void;
|
package/dist/utils/metrics.d.ts
CHANGED
|
@@ -19,4 +19,7 @@ export interface Metrics {
|
|
|
19
19
|
typeaheadRequests: number;
|
|
20
20
|
}
|
|
21
21
|
export declare function incrementMetric(key: keyof Metrics, by?: number): void;
|
|
22
|
-
export
|
|
22
|
+
export interface MetricsSnapshot extends Metrics {
|
|
23
|
+
requestHistorySize: number;
|
|
24
|
+
}
|
|
25
|
+
export declare function getSnapshot(): MetricsSnapshot;
|
package/dist/utils/metrics.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { SalesSearchFilters } from '../types';
|
|
2
|
-
export declare function stableStringify(obj:
|
|
2
|
+
export declare function stableStringify(obj: unknown): string;
|
|
3
3
|
export declare function buildFilterSignature(filters?: SalesSearchFilters, rawQuery?: string): string | undefined;
|
|
4
4
|
export declare function buildLeadSearchQuery(keywords: string, filters?: SalesSearchFilters): string;
|
|
@@ -9,8 +9,9 @@ function stableStringify(obj) {
|
|
|
9
9
|
return JSON.stringify(obj);
|
|
10
10
|
if (Array.isArray(obj))
|
|
11
11
|
return '[' + obj.map((v) => stableStringify(v)).join(',') + ']';
|
|
12
|
-
const
|
|
13
|
-
|
|
12
|
+
const rec = obj;
|
|
13
|
+
const keys = Object.keys(rec).sort();
|
|
14
|
+
return '{' + keys.map((k) => JSON.stringify(k) + ':' + stableStringify(rec[k])).join(',') + '}';
|
|
14
15
|
}
|
|
15
16
|
function buildFilterSignature(filters, rawQuery) {
|
|
16
17
|
if (rawQuery)
|
package/package.json
CHANGED
|
@@ -1,54 +1,59 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "linkedin-secret-sauce",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Private LinkedIn Sales Navigator client with automatic cookie management",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
"dist"
|
|
9
|
-
],
|
|
10
|
-
"publishConfig": {
|
|
11
|
-
"registry": "https://registry.npmjs.org/"
|
|
12
|
-
},
|
|
13
|
-
"scripts": {
|
|
14
|
-
"dev:playground": "pnpm -C apps/playground dev",
|
|
15
|
-
"search": "node scripts/rg-fast.mjs",
|
|
16
|
-
"rg:fast": "node scripts/rg-fast.mjs",
|
|
17
|
-
"build": "tsc -p tsconfig.json",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"release:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"
|
|
49
|
-
"@
|
|
50
|
-
"@
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "linkedin-secret-sauce",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Private LinkedIn Sales Navigator client with automatic cookie management",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"registry": "https://registry.npmjs.org/"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"dev:playground": "pnpm -C apps/playground dev",
|
|
15
|
+
"search": "node scripts/rg-fast.mjs",
|
|
16
|
+
"rg:fast": "node scripts/rg-fast.mjs",
|
|
17
|
+
"build": "tsc -p tsconfig.json",
|
|
18
|
+
"lint": "eslint \"src/**/*.ts\" --max-warnings=0",
|
|
19
|
+
"lint:fix": "eslint \"src/**/*.ts\" --fix",
|
|
20
|
+
"dev": "tsc -w -p tsconfig.json",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"prepare": "husky",
|
|
23
|
+
"prepublishOnly": "npm run build",
|
|
24
|
+
"release:patch": "npm version patch && git push --follow-tags",
|
|
25
|
+
"release:minor": "npm version minor && git push --follow-tags",
|
|
26
|
+
"release:major": "npm version major && git push --follow-tags"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"linkedin",
|
|
30
|
+
"sales-navigator",
|
|
31
|
+
"client",
|
|
32
|
+
"typescript"
|
|
33
|
+
],
|
|
34
|
+
"author": "Your Company",
|
|
35
|
+
"license": "UNLICENSED",
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18.0.0"
|
|
38
|
+
},
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/enerage/LinkedInSecretSauce.git"
|
|
42
|
+
},
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/enerage/LinkedInSecretSauce/issues"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/enerage/LinkedInSecretSauce#readme",
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^20.11.0",
|
|
49
|
+
"@typescript-eslint/eslint-plugin": "^8.9.0",
|
|
50
|
+
"@typescript-eslint/parser": "^8.9.0",
|
|
51
|
+
"eslint": "^9.12.0",
|
|
52
|
+
"typescript": "^5.3.3",
|
|
53
|
+
"vitest": "^1.6.0",
|
|
54
|
+
"@commitlint/cli": "^19.4.0",
|
|
55
|
+
"@commitlint/config-conventional": "^19.4.0",
|
|
56
|
+
"husky": "^9.0.11"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
54
59
|
|