@entergreat/unipile-wrapper 1.0.11 → 2.1.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 (101) hide show
  1. package/README.md +290 -161
  2. package/dist/client/httpClient.d.ts +14 -0
  3. package/dist/client/httpClient.d.ts.map +1 -0
  4. package/dist/client/httpClient.js +50 -0
  5. package/dist/client/httpClient.js.map +1 -0
  6. package/dist/client/index.d.ts +2 -0
  7. package/dist/client/index.d.ts.map +1 -0
  8. package/dist/client/index.js +2 -0
  9. package/dist/client/index.js.map +1 -0
  10. package/dist/index.d.ts +12 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +21 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/services/accountService.d.ts +11 -0
  15. package/dist/services/accountService.d.ts.map +1 -0
  16. package/dist/services/accountService.js +17 -0
  17. package/dist/services/accountService.js.map +1 -0
  18. package/dist/services/baseService.d.ts +10 -0
  19. package/dist/services/baseService.d.ts.map +1 -0
  20. package/dist/services/baseService.js +23 -0
  21. package/dist/services/baseService.js.map +1 -0
  22. package/dist/services/companyService.d.ts +11 -0
  23. package/dist/services/companyService.d.ts.map +1 -0
  24. package/dist/services/companyService.js +26 -0
  25. package/dist/services/companyService.js.map +1 -0
  26. package/dist/services/index.d.ts +6 -0
  27. package/dist/services/index.d.ts.map +1 -0
  28. package/dist/services/index.js +6 -0
  29. package/dist/services/index.js.map +1 -0
  30. package/dist/services/profileService.d.ts +20 -0
  31. package/dist/services/profileService.d.ts.map +1 -0
  32. package/dist/services/profileService.js +85 -0
  33. package/dist/services/profileService.js.map +1 -0
  34. package/dist/services/searchService.d.ts +19 -0
  35. package/dist/services/searchService.d.ts.map +1 -0
  36. package/dist/services/searchService.js +54 -0
  37. package/dist/services/searchService.js.map +1 -0
  38. package/dist/types/account.d.ts +8 -0
  39. package/dist/types/account.d.ts.map +1 -0
  40. package/dist/types/account.js +2 -0
  41. package/dist/types/account.js.map +1 -0
  42. package/dist/types/common.d.ts +19 -0
  43. package/dist/types/common.d.ts.map +1 -0
  44. package/dist/types/common.js +2 -0
  45. package/dist/types/common.js.map +1 -0
  46. package/dist/types/company.d.ts +11 -0
  47. package/dist/types/company.d.ts.map +1 -0
  48. package/dist/types/company.js +2 -0
  49. package/dist/types/company.js.map +1 -0
  50. package/dist/types/index.d.ts +6 -0
  51. package/dist/types/index.d.ts.map +1 -0
  52. package/dist/types/index.js +6 -0
  53. package/dist/types/index.js.map +1 -0
  54. package/dist/types/profile.d.ts +46 -0
  55. package/dist/types/profile.d.ts.map +1 -0
  56. package/dist/types/profile.js +2 -0
  57. package/dist/types/profile.js.map +1 -0
  58. package/dist/types/search.d.ts +22 -0
  59. package/dist/types/search.d.ts.map +1 -0
  60. package/dist/types/search.js +2 -0
  61. package/dist/types/search.js.map +1 -0
  62. package/dist/utils/helpers.d.ts +14 -0
  63. package/dist/utils/helpers.d.ts.map +1 -0
  64. package/dist/utils/helpers.js +34 -0
  65. package/dist/utils/helpers.js.map +1 -0
  66. package/dist/utils/index.d.ts +4 -0
  67. package/dist/utils/index.d.ts.map +1 -0
  68. package/dist/utils/index.js +4 -0
  69. package/dist/utils/index.js.map +1 -0
  70. package/dist/utils/urlBuilder.d.ts +11 -0
  71. package/dist/utils/urlBuilder.d.ts.map +1 -0
  72. package/dist/utils/urlBuilder.js +23 -0
  73. package/dist/utils/urlBuilder.js.map +1 -0
  74. package/dist/utils/validators.d.ts +13 -0
  75. package/dist/utils/validators.d.ts.map +1 -0
  76. package/dist/utils/validators.js +39 -0
  77. package/dist/utils/validators.js.map +1 -0
  78. package/package.json +19 -8
  79. package/src/client/httpClient.ts +61 -0
  80. package/src/client/index.ts +1 -0
  81. package/src/index.ts +31 -0
  82. package/src/services/accountService.ts +21 -0
  83. package/src/services/baseService.ts +31 -0
  84. package/src/services/companyService.ts +37 -0
  85. package/src/services/index.ts +5 -0
  86. package/src/services/profileService.ts +142 -0
  87. package/src/services/searchService.ts +88 -0
  88. package/src/types/account.ts +9 -0
  89. package/src/types/common.ts +21 -0
  90. package/src/types/company.ts +13 -0
  91. package/src/types/index.ts +5 -0
  92. package/src/types/profile.ts +50 -0
  93. package/src/types/search.ts +27 -0
  94. package/src/utils/helpers.ts +41 -0
  95. package/src/utils/index.ts +3 -0
  96. package/src/utils/urlBuilder.ts +29 -0
  97. package/src/utils/validators.ts +47 -0
  98. package/tsconfig.json +21 -0
  99. package/src/index.js +0 -3
  100. package/src/services/linkedinService.js +0 -262
  101. package/src/utils/api.js +0 -28
@@ -0,0 +1,11 @@
1
+ type QueryParams = Record<string, string | number | boolean | undefined>;
2
+ /**
3
+ * Builds a URL with query parameters, filtering out undefined values
4
+ */
5
+ export declare function buildUrl(baseUrl: string, path: string, params?: QueryParams): string;
6
+ /**
7
+ * Appends array values as repeated query parameters
8
+ */
9
+ export declare function appendArrayParams(url: string, key: string, values: string[]): string;
10
+ export {};
11
+ //# sourceMappingURL=urlBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urlBuilder.d.ts","sourceRoot":"","sources":["../../src/utils/urlBuilder.ts"],"names":[],"mappings":"AAAA,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;AAEzE;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,WAAgB,GAAG,MAAM,CAUxF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAQpF"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Builds a URL with query parameters, filtering out undefined values
3
+ */
4
+ export function buildUrl(baseUrl, path, params = {}) {
5
+ const url = new URL(path, baseUrl);
6
+ for (const [key, value] of Object.entries(params)) {
7
+ if (value !== undefined && value !== "") {
8
+ url.searchParams.append(key, String(value));
9
+ }
10
+ }
11
+ return url.toString();
12
+ }
13
+ /**
14
+ * Appends array values as repeated query parameters
15
+ */
16
+ export function appendArrayParams(url, key, values) {
17
+ const urlObj = new URL(url);
18
+ for (const value of values) {
19
+ urlObj.searchParams.append(key, value);
20
+ }
21
+ return urlObj.toString();
22
+ }
23
+ //# sourceMappingURL=urlBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urlBuilder.js","sourceRoot":"","sources":["../../src/utils/urlBuilder.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,IAAY,EAAE,SAAsB,EAAE;IAC9E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAEnC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;YACxC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW,EAAE,GAAW,EAAE,MAAgB;IAC1E,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAE5B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,13 @@
1
+ export declare class ValidationError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export declare function validateRequired(params: Record<string, unknown>, requiredFields: string[]): void;
5
+ export declare function validateAccountId(accountId: string | undefined): void;
6
+ export declare function validateProfileId(profileId: string | undefined): void;
7
+ export declare function validateExperience(experience: {
8
+ role?: string;
9
+ company?: string;
10
+ } | undefined): void;
11
+ export declare function validateProfileData(profileData: Record<string, unknown> | undefined): void;
12
+ export declare function validateCompanyIdOrUrl(companyId?: string, companyUrl?: string): void;
13
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAAA,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,cAAc,EAAE,MAAM,EAAE,GACvB,IAAI,CAMN;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAIrE;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAIrE;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,GAAG,IAAI,CAIpG;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CAI1F;AAED,wBAAgB,sBAAsB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAIpF"}
@@ -0,0 +1,39 @@
1
+ export class ValidationError extends Error {
2
+ constructor(message) {
3
+ super(message);
4
+ this.name = "ValidationError";
5
+ }
6
+ }
7
+ export function validateRequired(params, requiredFields) {
8
+ for (const field of requiredFields) {
9
+ if (!params[field]) {
10
+ throw new ValidationError(`${field} must be provided`);
11
+ }
12
+ }
13
+ }
14
+ export function validateAccountId(accountId) {
15
+ if (!accountId) {
16
+ throw new ValidationError("accountId must be provided");
17
+ }
18
+ }
19
+ export function validateProfileId(profileId) {
20
+ if (!profileId) {
21
+ throw new ValidationError("profileId must be provided");
22
+ }
23
+ }
24
+ export function validateExperience(experience) {
25
+ if (!experience || !experience.role || !experience.company) {
26
+ throw new ValidationError("experience with role and company is required");
27
+ }
28
+ }
29
+ export function validateProfileData(profileData) {
30
+ if (!profileData || Object.keys(profileData).length === 0) {
31
+ throw new ValidationError("profileData must be provided with at least one field to update");
32
+ }
33
+ }
34
+ export function validateCompanyIdOrUrl(companyId, companyUrl) {
35
+ if (!companyId && !companyUrl) {
36
+ throw new ValidationError("companyId or companyUrl must be provided");
37
+ }
38
+ }
39
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,UAAU,gBAAgB,CAC9B,MAA+B,EAC/B,cAAwB;IAExB,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,eAAe,CAAC,GAAG,KAAK,mBAAmB,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAA6B;IAC7D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,eAAe,CAAC,4BAA4B,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAA6B;IAC7D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,eAAe,CAAC,4BAA4B,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,UAA2D;IAC5F,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QAC3D,MAAM,IAAI,eAAe,CAAC,8CAA8C,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,WAAgD;IAClF,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,eAAe,CAAC,gEAAgE,CAAC,CAAC;IAC9F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,SAAkB,EAAE,UAAmB;IAC5E,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU,EAAE,CAAC;QAC9B,MAAM,IAAI,eAAe,CAAC,0CAA0C,CAAC,CAAC;IACxE,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,27 +1,38 @@
1
1
  {
2
2
  "name": "@entergreat/unipile-wrapper",
3
- "version": "1.0.11",
4
- "description": "",
5
- "main": "src/index.js",
3
+ "version": "2.1.0",
4
+ "description": "A lightweight TypeScript wrapper for Unipile's LinkedIn API",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
6
7
  "type": "module",
7
8
  "scripts": {
8
- "test": "echo \"Error: no test specified\" && exit 1",
9
- "start": "src/index.js"
9
+ "build": "tsc",
10
+ "build:watch": "tsc --watch",
11
+ "prepublishOnly": "npm run build",
12
+ "test": "echo \"Error: no test specified\" && exit 1"
10
13
  },
11
14
  "repository": {
12
15
  "type": "git",
13
16
  "url": "git+https://github.com/nivkman/unipile-wrapper.git"
14
17
  },
15
- "keywords": [],
18
+ "keywords": [
19
+ "unipile",
20
+ "linkedin",
21
+ "automation",
22
+ "api-wrapper"
23
+ ],
16
24
  "author": "",
17
- "license": "ISC",
25
+ "license": "MIT",
18
26
  "bugs": {
19
27
  "url": "https://github.com/nivkman/unipile-wrapper/issues"
20
28
  },
21
29
  "homepage": "https://github.com/nivkman/unipile-wrapper#readme",
22
30
  "dependencies": {
23
31
  "axios": "^1.7.9",
24
- "cors": "^2.8.5",
25
32
  "form-data": "^4.0.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^20.11.0",
36
+ "typescript": "^5.3.3"
26
37
  }
27
38
  }
@@ -0,0 +1,61 @@
1
+ import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
2
+ import FormData from "form-data";
3
+ import { ServiceConfig } from "../types/index.js";
4
+
5
+ export class HttpClient {
6
+ private client: AxiosInstance;
7
+ private apiKey: string;
8
+
9
+ constructor(config: ServiceConfig) {
10
+ const baseURL = `https://${config.subdomain}.unipile.com:${config.port}/api/v1`;
11
+ this.apiKey = config.unipileToken;
12
+
13
+ this.client = axios.create({
14
+ baseURL,
15
+ headers: {
16
+ accept: "application/json",
17
+ "content-type": "application/json",
18
+ },
19
+ });
20
+
21
+ this.setupInterceptors();
22
+ }
23
+
24
+ private setupInterceptors(): void {
25
+ this.client.interceptors.request.use((config) => {
26
+ config.headers["X-API-KEY"] = this.apiKey;
27
+ return config;
28
+ });
29
+ }
30
+
31
+ get baseURL(): string {
32
+ return this.client.defaults.baseURL || "";
33
+ }
34
+
35
+ async get<T>(url: string): Promise<T> {
36
+ const response = await this.client.get<T>(url);
37
+ return response.data;
38
+ }
39
+
40
+ async post<T>(url: string, body: Record<string, unknown> = {}): Promise<T> {
41
+ const response = await this.client.post<T>(url, body);
42
+ return response.data;
43
+ }
44
+
45
+ async patch<T>(url: string, body: Record<string, unknown> = {}): Promise<T> {
46
+ const response = await this.client.patch<T>(url, body);
47
+ return response.data;
48
+ }
49
+
50
+ async patchFormData<T>(url: string, formData: FormData): Promise<T> {
51
+ const config: AxiosRequestConfig = {
52
+ headers: {
53
+ ...formData.getHeaders(),
54
+ "X-API-KEY": this.apiKey,
55
+ accept: "application/json",
56
+ },
57
+ };
58
+ const response = await this.client.patch<T>(url, formData, config);
59
+ return response.data;
60
+ }
61
+ }
@@ -0,0 +1 @@
1
+ export * from "./httpClient.js";
package/src/index.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { HttpClient } from "./client/index.js";
2
+ import {
3
+ AccountService,
4
+ SearchService,
5
+ ProfileService,
6
+ CompanyService,
7
+ } from "./services/index.js";
8
+ import { ServiceConfig } from "./types/index.js";
9
+
10
+ export class LinkedinService {
11
+ public account: AccountService;
12
+ public search: SearchService;
13
+ public profile: ProfileService;
14
+ public company: CompanyService;
15
+
16
+ constructor(config: ServiceConfig) {
17
+ const client = new HttpClient(config);
18
+ const { accountId } = config;
19
+
20
+ this.account = new AccountService(client, accountId);
21
+ this.search = new SearchService(client, accountId);
22
+ this.profile = new ProfileService(client, accountId);
23
+ this.company = new CompanyService(client, accountId);
24
+ }
25
+ }
26
+
27
+ // Re-export types for consumers
28
+ export * from "./types/index.js";
29
+
30
+ // Re-export utilities that might be useful
31
+ export { ValidationError } from "./utils/validators.js";
@@ -0,0 +1,21 @@
1
+ import { HttpClient } from "../client/index.js";
2
+ import { BaseService } from "./baseService.js";
3
+ import { ConnectParams, ConnectResponse } from "../types/index.js";
4
+
5
+ export class AccountService extends BaseService {
6
+ constructor(client: HttpClient, defaultAccountId?: string) {
7
+ super(client, defaultAccountId);
8
+ }
9
+
10
+ /**
11
+ * Connect a LinkedIn account to Unipile using a li_at cookie
12
+ */
13
+ async connect({ loginCookie }: ConnectParams): Promise<ConnectResponse> {
14
+ const body = {
15
+ provider: "LINKEDIN",
16
+ access_token: loginCookie,
17
+ };
18
+
19
+ return this.client.post<ConnectResponse>("/accounts", body);
20
+ }
21
+ }
@@ -0,0 +1,31 @@
1
+ import { HttpClient } from "../client/index.js";
2
+ import { buildUrl, appendArrayParams, ValidationError } from "../utils/index.js";
3
+
4
+ export abstract class BaseService {
5
+ protected client: HttpClient;
6
+ protected defaultAccountId?: string;
7
+
8
+ constructor(client: HttpClient, defaultAccountId?: string) {
9
+ this.client = client;
10
+ this.defaultAccountId = defaultAccountId;
11
+ }
12
+
13
+ protected resolveAccountId(accountId?: string): string {
14
+ const resolved = accountId ?? this.defaultAccountId;
15
+ if (!resolved) {
16
+ throw new ValidationError("accountId must be provided either in config or method call");
17
+ }
18
+ return resolved;
19
+ }
20
+
21
+ protected buildUrl(
22
+ path: string,
23
+ params: Record<string, string | number | boolean | undefined> = {}
24
+ ): string {
25
+ return buildUrl(this.client.baseURL, path, params);
26
+ }
27
+
28
+ protected appendArrayParams(url: string, key: string, values: string[]): string {
29
+ return appendArrayParams(url, key, values);
30
+ }
31
+ }
@@ -0,0 +1,37 @@
1
+ import { HttpClient } from "../client/index.js";
2
+ import { BaseService } from "./baseService.js";
3
+ import { RetrieveCompanyRequest, CompanyResponse } from "../types/index.js";
4
+ import { validateCompanyIdOrUrl, extractCompanyIdFromUrl } from "../utils/index.js";
5
+
6
+ export class CompanyService extends BaseService {
7
+ constructor(client: HttpClient, defaultAccountId?: string) {
8
+ super(client, defaultAccountId);
9
+ }
10
+
11
+ /**
12
+ * Retrieve LinkedIn company information by ID or URL
13
+ */
14
+ async retrieve({
15
+ accountId,
16
+ companyId,
17
+ companyUrl,
18
+ }: RetrieveCompanyRequest): Promise<CompanyResponse> {
19
+ const resolvedAccountId = this.resolveAccountId(accountId);
20
+ validateCompanyIdOrUrl(companyId, companyUrl);
21
+
22
+ let id = companyId;
23
+ if (!id && companyUrl) {
24
+ id = extractCompanyIdFromUrl(companyUrl) || undefined;
25
+ }
26
+
27
+ if (!id) {
28
+ throw new Error("Could not extract company ID from URL");
29
+ }
30
+
31
+ const url = this.buildUrl(`/linkedin/company/${id}`, {
32
+ account_id: resolvedAccountId,
33
+ });
34
+
35
+ return this.client.get<CompanyResponse>(url);
36
+ }
37
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./baseService.js";
2
+ export * from "./accountService.js";
3
+ export * from "./searchService.js";
4
+ export * from "./profileService.js";
5
+ export * from "./companyService.js";
@@ -0,0 +1,142 @@
1
+ import FormData from "form-data";
2
+ import { HttpClient } from "../client/index.js";
3
+ import { BaseService } from "./baseService.js";
4
+ import {
5
+ RetrieveProfileRequest,
6
+ EditProfileRequest,
7
+ AddExperienceRequest,
8
+ ProfileResponse,
9
+ } from "../types/index.js";
10
+ import {
11
+ validateProfileId,
12
+ validateProfileData,
13
+ validateExperience,
14
+ convertToBracketNotation,
15
+ } from "../utils/index.js";
16
+
17
+ export class ProfileService extends BaseService {
18
+ constructor(client: HttpClient, defaultAccountId?: string) {
19
+ super(client, defaultAccountId);
20
+ }
21
+
22
+ /**
23
+ * Retrieve a LinkedIn user profile
24
+ */
25
+ async retrieve({
26
+ accountId,
27
+ profileId,
28
+ linkedinSections = [],
29
+ notify = false,
30
+ }: RetrieveProfileRequest): Promise<ProfileResponse> {
31
+ const resolvedAccountId = this.resolveAccountId(accountId);
32
+ validateProfileId(profileId);
33
+
34
+ let url = this.buildUrl(`/users/${profileId}`, {
35
+ account_id: resolvedAccountId,
36
+ notify,
37
+ });
38
+
39
+ if (linkedinSections.length > 0) {
40
+ url = this.appendArrayParams(url, "linkedin_sections", linkedinSections);
41
+ }
42
+
43
+ return this.client.get<ProfileResponse>(url);
44
+ }
45
+
46
+ /**
47
+ * Edit the LinkedIn profile of the account owner
48
+ */
49
+ async edit({ accountId, profileData }: EditProfileRequest): Promise<ProfileResponse> {
50
+ const resolvedAccountId = this.resolveAccountId(accountId);
51
+ validateProfileData(profileData);
52
+
53
+ const url = this.buildUrl("/users/me/edit", {
54
+ account_id: resolvedAccountId,
55
+ });
56
+
57
+ const body = convertToBracketNotation(profileData);
58
+
59
+ return this.client.patch<ProfileResponse>(url, body);
60
+ }
61
+
62
+ /**
63
+ * Add a work experience position to the profile
64
+ */
65
+ async addExperience({
66
+ accountId,
67
+ experience,
68
+ }: AddExperienceRequest): Promise<ProfileResponse> {
69
+ const resolvedAccountId = this.resolveAccountId(accountId);
70
+ validateExperience(experience);
71
+
72
+ const url = this.buildUrl("/users/me/edit", {
73
+ account_id: resolvedAccountId,
74
+ });
75
+
76
+ const formData = this.buildExperienceFormData(resolvedAccountId, experience);
77
+
78
+ return this.client.patchFormData<ProfileResponse>(url, formData);
79
+ }
80
+
81
+ private buildExperienceFormData(
82
+ accountId: string,
83
+ experience: AddExperienceRequest["experience"]
84
+ ): FormData {
85
+ const formData = new FormData();
86
+
87
+ formData.append("type", "LINKEDIN");
88
+ formData.append("account_id", accountId);
89
+ formData.append("experience[role]", experience.role);
90
+ formData.append("experience[company]", experience.company);
91
+
92
+ if (experience.company_id) {
93
+ formData.append("company_id", experience.company_id);
94
+ }
95
+
96
+ if (experience.description) {
97
+ formData.append("description", experience.description);
98
+ }
99
+
100
+ if (experience.location) {
101
+ formData.append("location", experience.location);
102
+ }
103
+
104
+ if (experience.notify_network !== undefined) {
105
+ formData.append("notify_network", experience.notify_network.toString());
106
+ }
107
+
108
+ if (experience.start_month) {
109
+ formData.append(
110
+ "experience[seniority][start_date][month]",
111
+ experience.start_month.toString()
112
+ );
113
+ }
114
+ if (experience.start_year) {
115
+ formData.append(
116
+ "experience[seniority][start_date][year]",
117
+ experience.start_year.toString()
118
+ );
119
+ }
120
+
121
+ if (experience.end_month) {
122
+ formData.append(
123
+ "experience[seniority][end_date][month]",
124
+ experience.end_month.toString()
125
+ );
126
+ }
127
+ if (experience.end_year) {
128
+ formData.append(
129
+ "experience[seniority][end_date][year]",
130
+ experience.end_year.toString()
131
+ );
132
+ }
133
+
134
+ if (experience.skills && Array.isArray(experience.skills)) {
135
+ for (const skill of experience.skills) {
136
+ formData.append("skills", skill);
137
+ }
138
+ }
139
+
140
+ return formData;
141
+ }
142
+ }
@@ -0,0 +1,88 @@
1
+ import { HttpClient } from "../client/index.js";
2
+ import { BaseService } from "./baseService.js";
3
+ import {
4
+ SearchByParamsRequest,
5
+ SearchByUrlRequest,
6
+ RetrieveSearchParametersRequest,
7
+ SearchResult,
8
+ SearchParametersResult,
9
+ } from "../types/index.js";
10
+
11
+ export class SearchService extends BaseService {
12
+ constructor(client: HttpClient, defaultAccountId?: string) {
13
+ super(client, defaultAccountId);
14
+ }
15
+
16
+ /**
17
+ * Perform a LinkedIn search using parameters
18
+ */
19
+ async byParams({
20
+ accountId,
21
+ params = {},
22
+ cursor,
23
+ limit = 10,
24
+ }: SearchByParamsRequest): Promise<SearchResult> {
25
+ const resolvedAccountId = this.resolveAccountId(accountId);
26
+
27
+ const url = this.buildUrl("/linkedin/search", {
28
+ account_id: resolvedAccountId,
29
+ limit,
30
+ cursor,
31
+ });
32
+
33
+ const body = {
34
+ ...params,
35
+ api: "classic",
36
+ category: "people",
37
+ };
38
+
39
+ return this.client.post<SearchResult>(url, body);
40
+ }
41
+
42
+ /**
43
+ * Perform a LinkedIn search using a LinkedIn URL
44
+ */
45
+ async byUrl({
46
+ accountId,
47
+ searchUrl,
48
+ cursor,
49
+ limit = 10,
50
+ }: SearchByUrlRequest): Promise<SearchResult> {
51
+ const resolvedAccountId = this.resolveAccountId(accountId);
52
+
53
+ const url = this.buildUrl("/linkedin/search", {
54
+ account_id: resolvedAccountId,
55
+ limit,
56
+ cursor,
57
+ });
58
+
59
+ const body = {
60
+ api: "classic",
61
+ category: "people",
62
+ url: searchUrl,
63
+ };
64
+
65
+ return this.client.post<SearchResult>(url, body);
66
+ }
67
+
68
+ /**
69
+ * Retrieve LinkedIn search parameter suggestions
70
+ */
71
+ async retrieveParameters({
72
+ accountId,
73
+ type,
74
+ keywords = "",
75
+ limit = 3,
76
+ }: RetrieveSearchParametersRequest): Promise<SearchParametersResult> {
77
+ const resolvedAccountId = this.resolveAccountId(accountId);
78
+
79
+ const url = this.buildUrl("/linkedin/search/parameters", {
80
+ account_id: resolvedAccountId,
81
+ keywords,
82
+ type: type.toUpperCase(),
83
+ limit,
84
+ });
85
+
86
+ return this.client.get<SearchParametersResult>(url);
87
+ }
88
+ }
@@ -0,0 +1,9 @@
1
+ export interface ConnectParams {
2
+ loginCookie: string;
3
+ }
4
+
5
+ export interface ConnectResponse {
6
+ object: string;
7
+ account_id: string;
8
+ // Add more fields as needed based on API response
9
+ }
@@ -0,0 +1,21 @@
1
+ export interface ServiceConfig {
2
+ unipileToken: string;
3
+ subdomain: string;
4
+ port: number | string;
5
+ accountId?: string;
6
+ }
7
+
8
+ export interface RequestHeaders {
9
+ accept: string;
10
+ "content-type": string;
11
+ "X-API-KEY": string;
12
+ }
13
+
14
+ export interface PaginationParams {
15
+ cursor?: string;
16
+ limit?: number;
17
+ }
18
+
19
+ export interface AccountIdParam {
20
+ accountId?: string;
21
+ }
@@ -0,0 +1,13 @@
1
+ import { AccountIdParam } from "./common.js";
2
+
3
+ export interface RetrieveCompanyRequest extends AccountIdParam {
4
+ companyId?: string;
5
+ companyUrl?: string;
6
+ }
7
+
8
+ export interface CompanyResponse {
9
+ object: string;
10
+ id: string;
11
+ name?: string;
12
+ // Add more fields as needed
13
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./common.js";
2
+ export * from "./account.js";
3
+ export * from "./search.js";
4
+ export * from "./profile.js";
5
+ export * from "./company.js";