freelancer-kit 1.0.1 → 1.0.2

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
@@ -11,6 +11,7 @@ This repository provides a comprehensive JavaScript toolkit for interacting with
11
11
  * **Token Management:** Easily handle access and refresh tokens for persistent API access.
12
12
  * **Profile Retrieval:** Fetch and manage your Freelancer profile information.
13
13
  * **Project Searching:** Efficiently search for projects based on various criteria.
14
+ * **Create Bid:** you can create a bid.
14
15
 
15
16
  ## Installation 📥
16
17
 
@@ -33,103 +34,99 @@ npm install
33
34
  ### Authentication Example
34
35
 
35
36
  ```javascript
36
- const FreelancerAuth = require('freelancer-kit').FreelancerAuth;
37
-
38
- const auth = new FreelancerAuth({
39
- clientId: 'YOUR_CLIENT_ID',
40
- clientSecret: 'YOUR_CLIENT_SECRET',
41
- redirectUri: 'YOUR_REDIRECT_URI'
42
- });
43
-
44
- // Get authorization URL
45
- const authorizationUrl = auth.getAuthorizationUrl(['email', 'profile']);
46
- console.log('Please visit this URL to authorize:', authorizationUrl);
47
-
48
- // After user authorizes, you'll receive a code. Exchange it for tokens.
49
- // Assuming you have the authorization code:
50
- async function exchangeCodeForToken(code) {
51
- try {
52
- const tokens = await auth.exchangeCodeForToken(code);
53
- console.log('Access Token:', tokens.access_token);
54
- console.log('Refresh Token:', tokens.refresh_token);
55
- // Store tokens securely
56
- } catch (error) {
57
- console.error('Error exchanging code for token:', error);
58
- }
59
- }
60
-
61
- // Example of refreshing a token
62
- async function refreshTokenExample(refreshToken) {
63
- try {
64
- const newTokens = await auth.refreshToken(refreshToken);
65
- console.log('New Access Token:', newTokens.access_token);
66
- // Update stored tokens
67
- } catch (error) {
68
- console.error('Error refreshing token:', error);
69
- }
70
- }
37
+ const { FreelancerAuth } = require("../src/index");
38
+
39
+ (async () => {
40
+ const clientId = "app_id";
41
+ const clientSecret = "client_secret";
42
+ const redirectUri = "https://example.com/callback";
43
+ const sandbox = true;
44
+
45
+ const flags = {
46
+ messaging: true,
47
+ project_create: true,
48
+ project_manage: false,
49
+ contest_create: false,
50
+ contest_manage: false,
51
+ user_information: true,
52
+ location_tracking_create: false,
53
+ location_tracking_view: false,
54
+ };
55
+
56
+ const auth = new FreelancerAuth({ clientId, clientSecret, redirectUri, sandbox, flags });
57
+
58
+ const authUrl = auth.generateAuthLink();
59
+ console.log("Open this link in your browser to authorize the app:");
60
+ console.log(authUrl);
61
+ const code = await FreelancerAuth.askCode("Enter the code you received: ");
62
+
63
+ const tokens = await auth.exchangeCode(code.trim());
64
+
65
+ console.log("Access Token:", tokens.access_token);
66
+ console.log("Refresh Token:", tokens.refresh_token);
67
+ })();
71
68
  ```
72
69
 
73
70
  ### Self Profile Example
74
71
 
75
72
  ```javascript
76
- const SelfProfile = require('freelancer-kit').SelfProfile;
77
- const FreelancerAuth = require('freelancer-kit').FreelancerAuth; // Needed for token management
78
-
79
- // Assuming you have obtained and stored your access token
80
- const accessToken = 'YOUR_STORED_ACCESS_TOKEN';
81
-
82
- async function getProfile() {
83
- try {
84
- const profile = new SelfProfile(accessToken);
85
- const userProfile = await profile.getProfile();
86
- console.log('User Profile:', userProfile);
87
- } catch (error) {
88
- console.error('Error fetching profile:', error);
89
- }
90
- }
91
-
92
- getProfile();
73
+ const { SelfProfile } = require("../src/index");
74
+ (async () => {
75
+ try {
76
+ const profile = new SelfProfile({
77
+ accessToken: "access_token",
78
+ sandbox: true
79
+ });
80
+
81
+ const res = await profile.getMyProfile({
82
+ avatar: true,
83
+ display_info: true,
84
+ profile_description: true,
85
+ });
86
+
87
+ console.log(res);
88
+ } catch (err) {
89
+ console.error("Error:", err.message);
90
+ }
91
+ })();
93
92
  ```
94
93
 
95
94
  ### Search Projects Example
96
95
 
97
96
  ```javascript
98
- const SearchProjects = require('freelancer-kit').SearchProjects;
99
- const FreelancerAuth = require('freelancer-kit').FreelancerAuth; // Needed for token management
100
-
101
- // Assuming you have obtained and stored your access token
102
- const accessToken = 'YOUR_STORED_ACCESS_TOKEN';
103
-
104
- async function searchProjects() {
105
- try {
106
- const searcher = new SearchProjects(accessToken);
107
- const projects = await searcher.search({
108
- limit: 10,
109
- full_description: 1,
110
- query: 'web development'
111
- });
112
- console.log('Found Projects:', projects);
113
- } catch (error) {
114
- console.error('Error searching projects:', error);
115
- }
116
- }
117
-
118
- searchProjects();
119
- ```
120
-
121
- ## Contributing 🤝
97
+ const { SearchProjects } = require("../src/index");
122
98
 
123
- We welcome contributions to `freelancer-kit`! Please follow these guidelines:
99
+ const projects = new SearchProjects({
100
+ accessToken: "access_token",
101
+ sandbox: true,
102
+ });
124
103
 
125
- 1. **Fork the repository.**
126
- 2. **Create a new branch** for your feature or bug fix.
127
- 3. **Make your changes** and ensure they are well-documented.
128
- 4. **Add tests** for your new functionality.
129
- 5. **Submit a Pull Request** with a clear description of your changes.
104
+ (async () => {
105
+ try {
106
+ const result = await projects.search({
107
+ query: "software",
108
+ project_types: ["fixed"],
109
+ min_price: 50,
110
+ max_price: 1000,
111
+ jobs: [1, 2, 3], // job id
112
+ languages: ["en"],
113
+ project_statuses: ["active"],
114
+ sort_field: "time_updated",
115
+ limit: 10,
116
+ full_description: true,
117
+ user_details: true,
118
+ });
119
+
120
+ console.log(result.result.projects);
121
+ } catch (err) {
122
+ console.error("Error:", err.details || err.message);
123
+ }
124
+ })();
125
+ ```
130
126
 
131
- Please ensure your code adheres to the existing style and formatting.
127
+ ## Contributing 🤝
132
128
 
129
+ We welcome contributions to `freelancer-kit`
133
130
  ## License 📜
134
131
 
135
132
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
@@ -142,78 +139,4 @@ The `freelancer-kit` library exposes several classes to interact with the Freela
142
139
 
143
140
  Handles authentication and token management.
144
141
 
145
- **Constructor:**
146
-
147
- ```javascript
148
- new FreelancerAuth(options: {
149
- clientId: string;
150
- clientSecret: string;
151
- redirectUri: string;
152
- })
153
- ```
154
-
155
- **Methods:**
156
-
157
- * `getAuthorizationUrl(scopes: string[]): string`
158
- * Generates the OAuth 2.0 authorization URL.
159
- * `exchangeCodeForToken(code: string): Promise<TokenResponse>`
160
- * Exchanges an authorization code for an access token and refresh token.
161
- * `refreshToken(refreshToken: string): Promise<TokenResponse>`
162
- * Refreshes an expired access token using a refresh token.
163
-
164
- ### `SearchProjects` 🔍
165
-
166
- Facilitates searching for projects.
167
-
168
- **Constructor:**
169
-
170
- ```javascript
171
- new SearchProjects(accessToken: string)
172
- ```
173
-
174
- **Methods:**
175
-
176
- * `search(params: SearchParams): Promise<Project[]>`
177
- * Searches for projects.
178
- * `SearchParams` can include:
179
- * `limit`: Maximum number of results.
180
- * `full_description`: Whether to include full project descriptions (1 for yes, 0 for no).
181
- * `query`: Search term.
182
- * `page`: Page number for results.
183
- * `sort_field`: Field to sort by (e.g., 'time_left', 'budget').
184
- * `sort_order`: Sort order ('asc' or 'desc').
185
- * `min_budget`: Minimum budget for projects.
186
- * `max_budget`: Maximum budget for projects.
187
- * `category_id`: Filter by category ID.
188
-
189
- ### `SelfProfile` 👤
190
-
191
- Provides access to the authenticated user's profile.
192
-
193
- **Constructor:**
194
-
195
- ```javascript
196
- new SelfProfile(accessToken: string)
197
- ```
198
-
199
- **Methods:**
200
-
201
- * `getProfile(): Promise<UserProfile>`
202
- * Fetches the authenticated user's profile information.
203
-
204
- ## Configuration Options & Environment Variables ⚙️
205
-
206
- While the library can be configured directly via constructor options, it's recommended to use environment variables for sensitive information like API keys and secrets.
207
-
208
- * `FREELANCER_CLIENT_ID`: Your Freelancer API Client ID.
209
- * `FREELANCER_CLIENT_SECRET`: Your Freelancer API Client Secret.
210
- * `FREELANCER_REDIRECT_URI`: Your registered Redirect URI.
211
-
212
- When using these environment variables, you can instantiate classes without passing explicit options:
213
-
214
- ```javascript
215
- // Example using environment variables for FreelancerAuth
216
- const auth = new FreelancerAuth(); // Reads from process.env.FREELANCER_CLIENT_ID, etc.
217
- ```
218
-
219
142
  ---
@@ -0,0 +1,21 @@
1
+ const { Bid } = require("../src/index");
2
+
3
+ (async () => {
4
+ try {
5
+ const bid = new Bid({
6
+ accessToken: "access_token",
7
+ sandbox: true,
8
+ });
9
+
10
+ const res = await bid.placeBid("project_id", {
11
+ amount: "how much money",
12
+ period: "how many days",
13
+ description: "description",
14
+ milestone_percentage: "milestone percentage",
15
+ });
16
+
17
+ console.log(`SUCCESS: Bid placed successfully (ID: ${res.result.id})`);
18
+ } catch (err) {
19
+ console.error(`FAILED: ${err.message}`);
20
+ }
21
+ })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "freelancer-kit",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Unofficial Node.js toolkit for integrating with the Freelancer.com API",
5
5
  "author": "MURTESA",
6
6
  "license": "MIT",
@@ -9,6 +9,8 @@
9
9
  "freelancer",
10
10
  "freelancer-kit",
11
11
  "freelancer-api",
12
+ "freelancer-client",
13
+ "freelance",
12
14
  "nodejs",
13
15
  "sdk",
14
16
  "client",
@@ -18,7 +20,6 @@
18
20
  "node": ">=14"
19
21
  },
20
22
  "dependencies": {
21
- "freelancer-kit": "^1.0.0",
22
23
  "node-fetch": "^2.7.0"
23
24
  }
24
25
  }
@@ -0,0 +1,82 @@
1
+ const fetch = require("node-fetch");
2
+
3
+ class Bid {
4
+ constructor({ accessToken, sandbox = false }) {
5
+ if (!accessToken) {
6
+ throw new Error("accessToken is required");
7
+ }
8
+
9
+ this.accessToken = accessToken;
10
+ this.sandbox = sandbox;
11
+
12
+ this.projectBaseUrl = sandbox
13
+ ? "https://www.freelancer-sandbox.com/api/projects/0.1"
14
+ : "https://www.freelancer.com/api/projects/0.1";
15
+
16
+ this.userBaseUrl = sandbox
17
+ ? "https://www.freelancer-sandbox.com/api/users/0.1"
18
+ : "https://www.freelancer.com/api/users/0.1";
19
+ }
20
+
21
+ async request(method, url, body = null) {
22
+ const options = {
23
+ method,
24
+ headers: {
25
+ "Content-Type": "application/json",
26
+ "freelancer-oauth-v1": this.accessToken,
27
+ },
28
+ };
29
+
30
+ if (body) {
31
+ options.body = JSON.stringify(body);
32
+ }
33
+
34
+ const res = await fetch(url, options);
35
+ const data = await res.json();
36
+
37
+ if (!res.ok) {
38
+ const error = new Error(data?.message || "Freelancer API Error");
39
+ error.status = res.status;
40
+ error.details = data;
41
+ throw error;
42
+ }
43
+
44
+ return data;
45
+ }
46
+
47
+ async getMyUserId() {
48
+ const data = await this.request(
49
+ "GET",
50
+ `${this.userBaseUrl}/self/`
51
+ );
52
+
53
+ if (!data?.result?.id) {
54
+ throw new Error("Failed to retrieve self user ID");
55
+ }
56
+
57
+ return Number(data.result.id);
58
+ }
59
+
60
+ async placeBid(projectId, bidData = {}) {
61
+ const bidderId = await this.getMyUserId();
62
+
63
+ const payload = {
64
+ project_id: Number(projectId),
65
+ bidder_id: bidderId,
66
+ amount: Number(bidData.amount),
67
+ period: Number(bidData.period),
68
+ description: String(bidData.description || ""),
69
+ milestone_percentage: bidData.milestone_percentage ?? 0,
70
+ sponsored: Boolean(bidData.sponsored),
71
+ highlighted: Boolean(bidData.highlighted),
72
+ };
73
+
74
+ return this.request(
75
+ "POST",
76
+ `${this.projectBaseUrl}/bids/`,
77
+ payload
78
+ );
79
+ }
80
+ }
81
+
82
+ module.exports = Bid;
package/src/index.js CHANGED
@@ -2,11 +2,12 @@ const SelfProfile = require("./classes/SelfProfile");
2
2
  const Token = require("./classes/Token");
3
3
  const SearchProjects = require("./classes/SearchProjects");
4
4
  const FreelancerAuth = require("./classes/FreelancerAuth");
5
-
5
+ const Bid = require("./classes/Bid")
6
6
 
7
7
  module.exports = {
8
8
  SelfProfile,
9
9
  Token,
10
10
  SearchProjects,
11
11
  FreelancerAuth,
12
+ Bid,
12
13
  };