@entergreat/unipile-wrapper 1.0.5 → 1.0.7

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 CHANGED
@@ -7,6 +7,7 @@ A lightweight JavaScript wrapper for Unipile's social network automation platfor
7
7
  - Simplified interface for Unipile's LinkedIn API
8
8
  - Easy account connection using li_at cookies
9
9
  - Streamlined search capabilities (URL-based and parameter-based)
10
+ - Profile management (retrieve and edit)
10
11
  - Built-in pagination support
11
12
  - Clean error handling
12
13
  - Promise-based async/await interface
@@ -87,6 +88,43 @@ try {
87
88
  }
88
89
  ```
89
90
 
91
+ ### Edit LinkedIn Profile
92
+ Update the authenticated account's LinkedIn profile:
93
+
94
+ ```javascript
95
+ try {
96
+ const result = await linkedinService.editProfile({
97
+ accountId: 'your-unipile-account-id',
98
+ profileData: {
99
+ headline: 'Senior Software Engineer | Node.js Expert'
100
+ }
101
+ });
102
+ console.log('Profile updated successfully:', result);
103
+ } catch (error) {
104
+ console.error('Profile update failed:', error);
105
+ }
106
+ ```
107
+
108
+ #### Update multiple fields at once:
109
+ ```javascript
110
+ try {
111
+ const result = await linkedinService.editProfile({
112
+ accountId: 'your-unipile-account-id',
113
+ profileData: {
114
+ headline: 'Full Stack Developer',
115
+ summary: 'Passionate developer with 10+ years of experience...',
116
+ location: { id: '105015875' },
117
+ experience: {
118
+ skills: ['JavaScript', 'Python', 'React', 'Node.js']
119
+ }
120
+ }
121
+ });
122
+ console.log('Profile updated successfully:', result);
123
+ } catch (error) {
124
+ console.error('Profile update failed:', error);
125
+ }
126
+ ```
127
+
90
128
  ## API Reference 📚
91
129
 
92
130
  ### LinkedinService
@@ -127,6 +165,41 @@ Performs a LinkedIn search through Unipile using a LinkedIn search URL.
127
165
  - `limit`: Results per page (optional, default: 10)
128
166
  - **Returns:** Promise with search results
129
167
 
168
+ ##### retrieveSearchParameters({ accountId: string, type: string, keywords?: string, limit?: number })
169
+ Retrieves LinkedIn search parameter suggestions from Unipile.
170
+ - **Parameters:**
171
+ - `accountId`: Unipile account ID (required)
172
+ - `type`: Parameter type to retrieve (required)
173
+ - `keywords`: Search keywords for suggestions (optional, default: "")
174
+ - `limit`: Number of suggestions (optional, default: 3)
175
+ - **Returns:** Promise with search parameter suggestions
176
+
177
+ ##### retrieveProfile({ accountId: string, profileId: string, linkedinSections?: array, notify?: boolean })
178
+ Retrieves a LinkedIn user profile through Unipile.
179
+ - **Parameters:**
180
+ - `accountId`: Unipile account ID (required)
181
+ - `profileId`: LinkedIn profile ID or URL (required)
182
+ - `linkedinSections`: Array of specific LinkedIn sections to retrieve (optional, default: [])
183
+ - `notify`: Whether to notify the profile owner (optional, default: false)
184
+ - **Returns:** Promise with user profile data
185
+
186
+ ##### editProfile({ accountId: string, profileData: object })
187
+ Edits the LinkedIn profile of the account owner through Unipile.
188
+ - **Parameters:**
189
+ - `accountId`: Unipile account ID (required)
190
+ - `profileData`: Object containing profile fields to update (required)
191
+ - Supported fields include: `headline`, `summary`, `location`, `picture`, `experience`, `education`, and more
192
+ - Nested objects are automatically converted to Unipile's bracket notation format
193
+ - Example fields:
194
+ - `headline`: string - Professional headline
195
+ - `summary`: string - Profile bio/summary
196
+ - `location`: object - Location with `id` field
197
+ - `picture`: object - Profile/cover picture settings
198
+ - `experience`: object - Experience data with `skills` array, positions, etc.
199
+ - `education`: object - Education entries
200
+ - **Returns:** Promise with updated profile data
201
+ - **Note:** Only the account owner's profile can be edited (the profile associated with the accountId)
202
+
130
203
  ## Error Handling ⚠️
131
204
  The wrapper provides error handling for common Unipile API interactions:
132
205
  - Validates required parameters (e.g., accountId)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@entergreat/unipile-wrapper",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -1,4 +1,33 @@
1
- import { get, post } from "../utils/api.js";
1
+ import { get, post, patch } from "../utils/api.js";
2
+
3
+ function extractCompanyIdFromUrl(url) {
4
+ // Handle URLs like:
5
+ // https://www.linkedin.com/company/company-name/
6
+ // https://www.linkedin.com/company/12345678/
7
+ // https://linkedin.com/company/company-name
8
+ const match = url.match(/linkedin\.com\/company\/([^\/\?]+)/i);
9
+ return match ? match[1] : null;
10
+ }
11
+
12
+ function convertToBracketNotation(obj, prefix = '') {
13
+ const result = {};
14
+
15
+ for (const key in obj) {
16
+ if (obj[key] === undefined) continue;
17
+
18
+ const fullKey = prefix ? `${prefix}[${key}]` : key;
19
+
20
+ if (Array.isArray(obj[key])) {
21
+ result[fullKey] = obj[key];
22
+ } else if (typeof obj[key] === 'object' && obj[key] !== null) {
23
+ Object.assign(result, convertToBracketNotation(obj[key], fullKey));
24
+ } else {
25
+ result[fullKey] = obj[key];
26
+ }
27
+ }
28
+
29
+ return result;
30
+ }
2
31
 
3
32
  export default class LinkedinService {
4
33
  constructor({ uniphileToken, subdomain, port }) {
@@ -120,4 +149,49 @@ export default class LinkedinService {
120
149
  throw error;
121
150
  }
122
151
  }
152
+
153
+ // retrieve LinkedIn company by URL or ID
154
+ async retrieveCompany({ accountId, companyId, companyUrl }) {
155
+ try {
156
+ if (!accountId) {
157
+ throw "account_id must be provided";
158
+ }
159
+
160
+ let id = companyId;
161
+ if (!id && companyUrl) {
162
+ id = extractCompanyIdFromUrl(companyUrl);
163
+ }
164
+
165
+ if (!id) {
166
+ throw "company_id or company_url must be provided";
167
+ }
168
+
169
+ const url = `${this.unipileUrl}/linkedin/company/${id}?account_id=${accountId}`;
170
+
171
+ return await get(url, this.headers);
172
+ } catch (error) {
173
+ throw error;
174
+ }
175
+ }
176
+
177
+ // edit LinkedIn profile
178
+ async editProfile({ accountId, profileData }) {
179
+ try {
180
+ if (!accountId) {
181
+ throw "account_id must be provided";
182
+ }
183
+
184
+ if (!profileData || Object.keys(profileData).length === 0) {
185
+ throw "profileData must be provided with at least one field to update";
186
+ }
187
+
188
+ const url = `${this.unipileUrl}/users/me/edit?account_id=${accountId}`;
189
+
190
+ const body = convertToBracketNotation(profileData);
191
+
192
+ return await patch(url, body, this.headers);
193
+ } catch (error) {
194
+ throw error;
195
+ }
196
+ }
123
197
  }
package/src/utils/api.js CHANGED
@@ -17,3 +17,12 @@ export const post = async (route, body = {}, headers = {}) => {
17
17
  throw error;
18
18
  }
19
19
  };
20
+
21
+ export const patch = async (route, body = {}, headers = {}) => {
22
+ try {
23
+ const response = await axios.patch(route, body, { headers });
24
+ return response.data;
25
+ } catch (error) {
26
+ throw error;
27
+ }
28
+ };