linkedin-secret-sauce 0.10.1 → 0.11.1

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/index.d.ts CHANGED
@@ -1,18 +1,208 @@
1
+ /**
2
+ * LinkedIn Secret Sauce
3
+ *
4
+ * A complete LinkedIn Sales Navigator client + Email Enrichment library.
5
+ *
6
+ * ## Two Main Modules
7
+ *
8
+ * ### 1. LinkedIn API
9
+ * Server-side LinkedIn Sales Navigator client with automatic cookie management,
10
+ * retries, caching, and parsing.
11
+ *
12
+ * ```typescript
13
+ * import { initializeLinkedInClient, searchSalesLeads, getProfileByVanity } from 'linkedin-secret-sauce';
14
+ *
15
+ * initializeLinkedInClient({
16
+ * cosiallApiUrl: process.env.COSIALL_API_URL,
17
+ * cosiallApiKey: process.env.COSIALL_API_KEY,
18
+ * });
19
+ *
20
+ * const profile = await getProfileByVanity('john-doe');
21
+ * const leads = await searchSalesLeads('cto fintech', { count: 25 });
22
+ * ```
23
+ *
24
+ * ### 2. Email Enrichment
25
+ * Find business emails using multiple providers with waterfall/parallel strategies.
26
+ *
27
+ * ```typescript
28
+ * import { createEnrichmentClient } from 'linkedin-secret-sauce';
29
+ *
30
+ * const enrichment = createEnrichmentClient({
31
+ * providers: {
32
+ * hunter: { apiKey: process.env.HUNTER_API_KEY },
33
+ * bouncer: { apiKey: process.env.BOUNCER_API_KEY },
34
+ * },
35
+ * });
36
+ *
37
+ * const result = await enrichment.enrich({
38
+ * firstName: 'John',
39
+ * lastName: 'Doe',
40
+ * domain: 'acme.com',
41
+ * });
42
+ * console.log(result.business_email); // john.doe@acme.com
43
+ * ```
44
+ *
45
+ * @packageDocumentation
46
+ */
1
47
  export { initializeLinkedInClient, getConfig } from "./config";
2
48
  export type { LinkedInClientConfig } from "./config";
49
+ export * from "./linkedin-api";
50
+ export * from "./types";
51
+ export type { LinkedInTenure, LinkedInPosition, LinkedInSpotlightBadge, SalesLeadSearchResult, } from "./types";
3
52
  export { LinkedInClientError } from "./utils/errors";
4
53
  export * from "./cosiall-client";
5
54
  export * from "./cookie-pool";
6
55
  export { parseFullProfile } from "./parsers/profile-parser";
7
56
  export { parseSalesSearchResults } from "./parsers/search-parser";
8
- export * from "./linkedin-api";
9
- export * from "./types";
10
- export type { LinkedInTenure, LinkedInPosition, LinkedInSpotlightBadge, SalesLeadSearchResult, } from "./types";
11
57
  export * from "./utils/metrics";
12
58
  export { getRequestHistory, clearRequestHistory, } from "./utils/request-history";
13
59
  export type { RequestHistoryEntry } from "./utils/request-history";
14
60
  export * from "./constants";
61
+ /**
62
+ * Create an enrichment client for finding business emails
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const enrichment = createEnrichmentClient({
67
+ * providers: {
68
+ * construct: {}, // FREE pattern matching
69
+ * hunter: { apiKey: 'xxx' },
70
+ * bouncer: { apiKey: 'xxx' },
71
+ * },
72
+ * onCost: (provider, cost) => console.log(`${provider}: $${cost}`),
73
+ * });
74
+ *
75
+ * const result = await enrichment.enrich({
76
+ * firstName: 'John',
77
+ * lastName: 'Doe',
78
+ * domain: 'acme.com',
79
+ * });
80
+ * ```
81
+ */
15
82
  export { createEnrichmentClient } from "./enrichment";
16
- export type { CanonicalEmail, EnrichmentCandidate, ProviderResult, ProviderFunc, ProviderName, EnrichmentClientConfig, EnrichmentClient, ProvidersConfig, EnrichmentOptions, BatchEnrichmentOptions, HunterConfig, ApolloConfig, SmartProspectConfig, LddConfig, DropcontactConfig, ConstructConfig, CacheAdapter, CostCallback, EnrichmentLogger, VerificationResult, SmartProspectContact, SmartProspectSearchFilters, LddProfileData, LddApiResponse, } from "./enrichment";
17
- export { isPersonalEmail, isBusinessEmail, isPersonalDomain, isDisposableEmail, isDisposableDomain, isValidEmailSyntax, isRoleAccount, verifyEmailMx, PERSONAL_DOMAINS, DISPOSABLE_DOMAINS, DEFAULT_PROVIDER_ORDER, PROVIDER_COSTS, getSmartLeadToken, getSmartLeadUser, clearSmartLeadToken, clearAllSmartLeadTokens, getSmartLeadTokenCacheStats, } from "./enrichment";
18
- export type { SmartLeadCredentials, SmartLeadAuthConfig, SmartLeadUser, SmartLeadLoginResponse, } from "./enrichment";
83
+ export type {
84
+ /** Result returned by enrichment operations */
85
+ CanonicalEmail,
86
+ /** Input candidate for email lookup */
87
+ EnrichmentCandidate,
88
+ /** Raw provider result */
89
+ ProviderResult,
90
+ /** Provider function signature */
91
+ ProviderFunc,
92
+ /** Supported provider names */
93
+ ProviderName,
94
+ /** Full client configuration */
95
+ EnrichmentClientConfig,
96
+ /** Enrichment client interface */
97
+ EnrichmentClient,
98
+ /** Provider configuration map */
99
+ ProvidersConfig,
100
+ /** Enrichment options */
101
+ EnrichmentOptions,
102
+ /** Batch processing options */
103
+ BatchEnrichmentOptions,
104
+ /** Hunter.io configuration */
105
+ HunterConfig,
106
+ /** SmartProspect/SmartLead configuration */
107
+ SmartProspectConfig,
108
+ /** LinkedIn Data Dump configuration */
109
+ LddConfig,
110
+ /** Dropcontact configuration */
111
+ DropcontactConfig,
112
+ /** Construct provider configuration */
113
+ ConstructConfig,
114
+ /** Cache adapter interface */
115
+ CacheAdapter,
116
+ /** Cost tracking callback */
117
+ CostCallback,
118
+ /** Logger interface */
119
+ EnrichmentLogger,
120
+ /** Email verification result */
121
+ VerificationResult,
122
+ /** SmartProspect contact */
123
+ SmartProspectContact,
124
+ /** SmartProspect search filters */
125
+ SmartProspectSearchFilters,
126
+ /** LDD profile data */
127
+ LddProfileData,
128
+ /** LDD API response */
129
+ LddApiResponse, } from "./enrichment";
130
+ export {
131
+ /**
132
+ * Check if email is from a personal domain (Gmail, Yahoo, etc.)
133
+ * @example isPersonalEmail('john@gmail.com') // true
134
+ */
135
+ isPersonalEmail,
136
+ /**
137
+ * Check if email is from a business domain
138
+ * @example isBusinessEmail('john@acme.com') // true
139
+ */
140
+ isBusinessEmail,
141
+ /**
142
+ * Check if domain is a personal email provider
143
+ * @example isPersonalDomain('gmail.com') // true
144
+ */
145
+ isPersonalDomain,
146
+ /**
147
+ * Check if email is from a disposable/temporary email service
148
+ * @example isDisposableEmail('test@mailinator.com') // true
149
+ */
150
+ isDisposableEmail,
151
+ /**
152
+ * Check if domain is a disposable email provider
153
+ * @example isDisposableDomain('guerrillamail.com') // true
154
+ */
155
+ isDisposableDomain,
156
+ /**
157
+ * Validate email syntax
158
+ * @example isValidEmailSyntax('john@example.com') // true
159
+ */
160
+ isValidEmailSyntax,
161
+ /**
162
+ * Check if email is a role account (info@, support@, etc.)
163
+ * @example isRoleAccount('info@company.com') // true
164
+ */
165
+ isRoleAccount,
166
+ /**
167
+ * Verify email via MX record lookup
168
+ */
169
+ verifyEmailMx,
170
+ /** Set of known personal email domains */
171
+ PERSONAL_DOMAINS,
172
+ /** Set of known disposable email domains */
173
+ DISPOSABLE_DOMAINS,
174
+ /** Default provider execution order */
175
+ DEFAULT_PROVIDER_ORDER,
176
+ /** Cost per lookup by provider (USD) */
177
+ PROVIDER_COSTS, } from "./enrichment";
178
+ export {
179
+ /**
180
+ * Get JWT token for SmartLead API (cached, auto-refreshes)
181
+ * @example const token = await getSmartLeadToken({ credentials: { email, password } });
182
+ */
183
+ getSmartLeadToken,
184
+ /**
185
+ * Get SmartLead user info from cached login
186
+ */
187
+ getSmartLeadUser,
188
+ /**
189
+ * Clear cached token for an email (e.g., on 401 error)
190
+ */
191
+ clearSmartLeadToken,
192
+ /**
193
+ * Clear all cached SmartLead tokens
194
+ */
195
+ clearAllSmartLeadTokens,
196
+ /**
197
+ * Get token cache statistics for debugging
198
+ */
199
+ getSmartLeadTokenCacheStats, } from "./enrichment";
200
+ export type {
201
+ /** SmartLead login credentials */
202
+ SmartLeadCredentials,
203
+ /** SmartLead authentication configuration */
204
+ SmartLeadAuthConfig,
205
+ /** SmartLead user info */
206
+ SmartLeadUser,
207
+ /** SmartLead login response */
208
+ SmartLeadLoginResponse, } from "./enrichment";
package/dist/index.js CHANGED
@@ -1,4 +1,50 @@
1
1
  "use strict";
2
+ /**
3
+ * LinkedIn Secret Sauce
4
+ *
5
+ * A complete LinkedIn Sales Navigator client + Email Enrichment library.
6
+ *
7
+ * ## Two Main Modules
8
+ *
9
+ * ### 1. LinkedIn API
10
+ * Server-side LinkedIn Sales Navigator client with automatic cookie management,
11
+ * retries, caching, and parsing.
12
+ *
13
+ * ```typescript
14
+ * import { initializeLinkedInClient, searchSalesLeads, getProfileByVanity } from 'linkedin-secret-sauce';
15
+ *
16
+ * initializeLinkedInClient({
17
+ * cosiallApiUrl: process.env.COSIALL_API_URL,
18
+ * cosiallApiKey: process.env.COSIALL_API_KEY,
19
+ * });
20
+ *
21
+ * const profile = await getProfileByVanity('john-doe');
22
+ * const leads = await searchSalesLeads('cto fintech', { count: 25 });
23
+ * ```
24
+ *
25
+ * ### 2. Email Enrichment
26
+ * Find business emails using multiple providers with waterfall/parallel strategies.
27
+ *
28
+ * ```typescript
29
+ * import { createEnrichmentClient } from 'linkedin-secret-sauce';
30
+ *
31
+ * const enrichment = createEnrichmentClient({
32
+ * providers: {
33
+ * hunter: { apiKey: process.env.HUNTER_API_KEY },
34
+ * bouncer: { apiKey: process.env.BOUNCER_API_KEY },
35
+ * },
36
+ * });
37
+ *
38
+ * const result = await enrichment.enrich({
39
+ * firstName: 'John',
40
+ * lastName: 'Doe',
41
+ * domain: 'acme.com',
42
+ * });
43
+ * console.log(result.business_email); // john.doe@acme.com
44
+ * ```
45
+ *
46
+ * @packageDocumentation
47
+ */
2
48
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
49
  if (k2 === undefined) k2 = k;
4
50
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -15,46 +61,147 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
61
  };
16
62
  Object.defineProperty(exports, "__esModule", { value: true });
17
63
  exports.getSmartLeadTokenCacheStats = exports.clearAllSmartLeadTokens = exports.clearSmartLeadToken = exports.getSmartLeadUser = exports.getSmartLeadToken = exports.PROVIDER_COSTS = exports.DEFAULT_PROVIDER_ORDER = exports.DISPOSABLE_DOMAINS = exports.PERSONAL_DOMAINS = exports.verifyEmailMx = exports.isRoleAccount = exports.isValidEmailSyntax = exports.isDisposableDomain = exports.isDisposableEmail = exports.isPersonalDomain = exports.isBusinessEmail = exports.isPersonalEmail = exports.createEnrichmentClient = exports.clearRequestHistory = exports.getRequestHistory = exports.parseSalesSearchResults = exports.parseFullProfile = exports.LinkedInClientError = exports.getConfig = exports.initializeLinkedInClient = void 0;
64
+ // =============================================================================
65
+ // LinkedIn API - Configuration
66
+ // =============================================================================
18
67
  var config_1 = require("./config");
19
68
  Object.defineProperty(exports, "initializeLinkedInClient", { enumerable: true, get: function () { return config_1.initializeLinkedInClient; } });
20
69
  Object.defineProperty(exports, "getConfig", { enumerable: true, get: function () { return config_1.getConfig; } });
70
+ // =============================================================================
71
+ // LinkedIn API - Core Functions
72
+ // =============================================================================
73
+ __exportStar(require("./linkedin-api"), exports);
74
+ // =============================================================================
75
+ // LinkedIn API - Types
76
+ // =============================================================================
77
+ __exportStar(require("./types"), exports);
78
+ // =============================================================================
79
+ // LinkedIn API - Errors
80
+ // =============================================================================
21
81
  var errors_1 = require("./utils/errors");
22
82
  Object.defineProperty(exports, "LinkedInClientError", { enumerable: true, get: function () { return errors_1.LinkedInClientError; } });
83
+ // =============================================================================
84
+ // LinkedIn API - Cookie Management
85
+ // =============================================================================
23
86
  __exportStar(require("./cosiall-client"), exports);
24
87
  __exportStar(require("./cookie-pool"), exports);
88
+ // =============================================================================
89
+ // LinkedIn API - Parsers
90
+ // =============================================================================
25
91
  var profile_parser_1 = require("./parsers/profile-parser");
26
92
  Object.defineProperty(exports, "parseFullProfile", { enumerable: true, get: function () { return profile_parser_1.parseFullProfile; } });
27
93
  var search_parser_1 = require("./parsers/search-parser");
28
94
  Object.defineProperty(exports, "parseSalesSearchResults", { enumerable: true, get: function () { return search_parser_1.parseSalesSearchResults; } });
29
- __exportStar(require("./linkedin-api"), exports);
30
- __exportStar(require("./types"), exports);
95
+ // =============================================================================
96
+ // LinkedIn API - Metrics & Monitoring
97
+ // =============================================================================
31
98
  __exportStar(require("./utils/metrics"), exports);
32
99
  var request_history_1 = require("./utils/request-history");
33
100
  Object.defineProperty(exports, "getRequestHistory", { enumerable: true, get: function () { return request_history_1.getRequestHistory; } });
34
101
  Object.defineProperty(exports, "clearRequestHistory", { enumerable: true, get: function () { return request_history_1.clearRequestHistory; } });
102
+ // =============================================================================
103
+ // LinkedIn API - Constants
104
+ // =============================================================================
35
105
  __exportStar(require("./constants"), exports);
36
- // Email Enrichment Module
106
+ // =============================================================================
107
+ // Email Enrichment - Client
108
+ // =============================================================================
109
+ /**
110
+ * Create an enrichment client for finding business emails
111
+ *
112
+ * @example
113
+ * ```typescript
114
+ * const enrichment = createEnrichmentClient({
115
+ * providers: {
116
+ * construct: {}, // FREE pattern matching
117
+ * hunter: { apiKey: 'xxx' },
118
+ * bouncer: { apiKey: 'xxx' },
119
+ * },
120
+ * onCost: (provider, cost) => console.log(`${provider}: $${cost}`),
121
+ * });
122
+ *
123
+ * const result = await enrichment.enrich({
124
+ * firstName: 'John',
125
+ * lastName: 'Doe',
126
+ * domain: 'acme.com',
127
+ * });
128
+ * ```
129
+ */
37
130
  var enrichment_1 = require("./enrichment");
38
131
  Object.defineProperty(exports, "createEnrichmentClient", { enumerable: true, get: function () { return enrichment_1.createEnrichmentClient; } });
132
+ // =============================================================================
133
+ // Email Enrichment - Utilities
134
+ // =============================================================================
39
135
  var enrichment_2 = require("./enrichment");
40
- // Utilities
136
+ /**
137
+ * Check if email is from a personal domain (Gmail, Yahoo, etc.)
138
+ * @example isPersonalEmail('john@gmail.com') // true
139
+ */
41
140
  Object.defineProperty(exports, "isPersonalEmail", { enumerable: true, get: function () { return enrichment_2.isPersonalEmail; } });
141
+ /**
142
+ * Check if email is from a business domain
143
+ * @example isBusinessEmail('john@acme.com') // true
144
+ */
42
145
  Object.defineProperty(exports, "isBusinessEmail", { enumerable: true, get: function () { return enrichment_2.isBusinessEmail; } });
146
+ /**
147
+ * Check if domain is a personal email provider
148
+ * @example isPersonalDomain('gmail.com') // true
149
+ */
43
150
  Object.defineProperty(exports, "isPersonalDomain", { enumerable: true, get: function () { return enrichment_2.isPersonalDomain; } });
151
+ /**
152
+ * Check if email is from a disposable/temporary email service
153
+ * @example isDisposableEmail('test@mailinator.com') // true
154
+ */
44
155
  Object.defineProperty(exports, "isDisposableEmail", { enumerable: true, get: function () { return enrichment_2.isDisposableEmail; } });
156
+ /**
157
+ * Check if domain is a disposable email provider
158
+ * @example isDisposableDomain('guerrillamail.com') // true
159
+ */
45
160
  Object.defineProperty(exports, "isDisposableDomain", { enumerable: true, get: function () { return enrichment_2.isDisposableDomain; } });
161
+ /**
162
+ * Validate email syntax
163
+ * @example isValidEmailSyntax('john@example.com') // true
164
+ */
46
165
  Object.defineProperty(exports, "isValidEmailSyntax", { enumerable: true, get: function () { return enrichment_2.isValidEmailSyntax; } });
166
+ /**
167
+ * Check if email is a role account (info@, support@, etc.)
168
+ * @example isRoleAccount('info@company.com') // true
169
+ */
47
170
  Object.defineProperty(exports, "isRoleAccount", { enumerable: true, get: function () { return enrichment_2.isRoleAccount; } });
48
- // Verification
171
+ /**
172
+ * Verify email via MX record lookup
173
+ */
49
174
  Object.defineProperty(exports, "verifyEmailMx", { enumerable: true, get: function () { return enrichment_2.verifyEmailMx; } });
50
- // Constants
175
+ /** Set of known personal email domains */
51
176
  Object.defineProperty(exports, "PERSONAL_DOMAINS", { enumerable: true, get: function () { return enrichment_2.PERSONAL_DOMAINS; } });
177
+ /** Set of known disposable email domains */
52
178
  Object.defineProperty(exports, "DISPOSABLE_DOMAINS", { enumerable: true, get: function () { return enrichment_2.DISPOSABLE_DOMAINS; } });
179
+ /** Default provider execution order */
53
180
  Object.defineProperty(exports, "DEFAULT_PROVIDER_ORDER", { enumerable: true, get: function () { return enrichment_2.DEFAULT_PROVIDER_ORDER; } });
181
+ /** Cost per lookup by provider (USD) */
54
182
  Object.defineProperty(exports, "PROVIDER_COSTS", { enumerable: true, get: function () { return enrichment_2.PROVIDER_COSTS; } });
55
- // SmartLead Auth
56
- Object.defineProperty(exports, "getSmartLeadToken", { enumerable: true, get: function () { return enrichment_2.getSmartLeadToken; } });
57
- Object.defineProperty(exports, "getSmartLeadUser", { enumerable: true, get: function () { return enrichment_2.getSmartLeadUser; } });
58
- Object.defineProperty(exports, "clearSmartLeadToken", { enumerable: true, get: function () { return enrichment_2.clearSmartLeadToken; } });
59
- Object.defineProperty(exports, "clearAllSmartLeadTokens", { enumerable: true, get: function () { return enrichment_2.clearAllSmartLeadTokens; } });
60
- Object.defineProperty(exports, "getSmartLeadTokenCacheStats", { enumerable: true, get: function () { return enrichment_2.getSmartLeadTokenCacheStats; } });
183
+ // =============================================================================
184
+ // Email Enrichment - SmartLead Authentication
185
+ // =============================================================================
186
+ var enrichment_3 = require("./enrichment");
187
+ /**
188
+ * Get JWT token for SmartLead API (cached, auto-refreshes)
189
+ * @example const token = await getSmartLeadToken({ credentials: { email, password } });
190
+ */
191
+ Object.defineProperty(exports, "getSmartLeadToken", { enumerable: true, get: function () { return enrichment_3.getSmartLeadToken; } });
192
+ /**
193
+ * Get SmartLead user info from cached login
194
+ */
195
+ Object.defineProperty(exports, "getSmartLeadUser", { enumerable: true, get: function () { return enrichment_3.getSmartLeadUser; } });
196
+ /**
197
+ * Clear cached token for an email (e.g., on 401 error)
198
+ */
199
+ Object.defineProperty(exports, "clearSmartLeadToken", { enumerable: true, get: function () { return enrichment_3.clearSmartLeadToken; } });
200
+ /**
201
+ * Clear all cached SmartLead tokens
202
+ */
203
+ Object.defineProperty(exports, "clearAllSmartLeadTokens", { enumerable: true, get: function () { return enrichment_3.clearAllSmartLeadTokens; } });
204
+ /**
205
+ * Get token cache statistics for debugging
206
+ */
207
+ Object.defineProperty(exports, "getSmartLeadTokenCacheStats", { enumerable: true, get: function () { return enrichment_3.getSmartLeadTokenCacheStats; } });
@@ -9,10 +9,14 @@ function parseSalesSearchResults(rawResponse) {
9
9
  : [];
10
10
  const results = [];
11
11
  for (const el of elements) {
12
- const name = [el?.firstName, el?.lastName].filter(Boolean).join(" ").trim() ||
13
- undefined;
12
+ const firstName = (0, json_sanitizer_1.sanitizeForJson)(el?.firstName) || undefined;
13
+ const lastName = (0, json_sanitizer_1.sanitizeForJson)(el?.lastName) || undefined;
14
+ const fullName = [firstName, lastName].filter(Boolean).join(" ").trim() || undefined;
14
15
  const res = {
15
- name: (0, json_sanitizer_1.sanitizeForJson)(name),
16
+ firstName,
17
+ lastName,
18
+ fullName,
19
+ name: fullName, // Backward compatible
16
20
  headline: (0, json_sanitizer_1.sanitizeForJson)((el?.summary || "").split("\n")[0]?.slice(0, 180)),
17
21
  salesProfileUrn: el?.entityUrn,
18
22
  objectUrn: el?.objectUrn,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linkedin-secret-sauce",
3
- "version": "0.10.1",
3
+ "version": "0.11.1",
4
4
  "description": "Private LinkedIn Sales Navigator client with automatic cookie management",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,8 +23,12 @@
23
23
  "lint:all": "eslint \"src/**/*.ts\" \"apps/playground/src/**/*.{ts,tsx}\" \"apps/playground/server/**/*.ts\" --max-warnings=0",
24
24
  "lint:fix": "eslint \"src/**/*.ts\" \"apps/playground/src/**/*.{ts,tsx}\" \"apps/playground/server/**/*.ts\" --fix",
25
25
  "check": "pnpm typecheck:all && pnpm lint:all",
26
- "dev": "tsc -w -p tsconfig.json",
26
+ "dev": "pnpm dev:playground",
27
+ "dev:watch": "tsc -w -p tsconfig.json",
27
28
  "test": "vitest run",
29
+ "docs": "typedoc",
30
+ "docs:netlify": "rm -rf docs/api && typedoc && echo 'Build complete'",
31
+ "docs:watch": "typedoc --watch",
28
32
  "prepublishOnly": "npm run build",
29
33
  "release:patch": "npm version patch && git push --follow-tags",
30
34
  "release:minor": "npm version minor && git push --follow-tags",
@@ -48,15 +52,18 @@
48
52
  "bugs": {
49
53
  "url": "https://github.com/enerage/LinkedInSecretSauce/issues"
50
54
  },
51
- "homepage": "https://github.com/enerage/LinkedInSecretSauce#readme",
55
+ "homepage": "https://enerage.github.io/LinkedInSecretSauce/",
52
56
  "devDependencies": {
53
57
  "@commitlint/cli": "^19.4.0",
54
58
  "@commitlint/config-conventional": "^19.4.0",
55
59
  "@types/node": "^20.11.0",
56
60
  "@typescript-eslint/eslint-plugin": "^8.9.0",
57
61
  "@typescript-eslint/parser": "^8.9.0",
62
+ "concurrently": "^9.2.1",
58
63
  "eslint": "^9.12.0",
59
64
  "husky": "^9.0.11",
65
+ "typedoc": "^0.28.15",
66
+ "typedoc-plugin-markdown": "^4.9.0",
60
67
  "typescript": "^5.9.3",
61
68
  "vitest": "^1.6.0"
62
69
  }