bamboohr-cli 1.0.15 → 1.0.16
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.js +151 -38
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -106,32 +106,13 @@ function getClient() {
|
|
|
106
106
|
return new BambooHRClient({ apiToken, companyDomain });
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
// src/utils/strip-response.ts
|
|
110
|
-
function stripResponse(obj) {
|
|
111
|
-
if (Array.isArray(obj)) {
|
|
112
|
-
return obj.map(stripResponse);
|
|
113
|
-
}
|
|
114
|
-
if (obj === null || typeof obj !== "object") {
|
|
115
|
-
return obj;
|
|
116
|
-
}
|
|
117
|
-
const record = obj;
|
|
118
|
-
const result = {};
|
|
119
|
-
for (const [key, value] of Object.entries(record)) {
|
|
120
|
-
if (value === null || value === void 0) {
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
result[key] = stripResponse(value);
|
|
124
|
-
}
|
|
125
|
-
return result;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
109
|
// src/utils/output.ts
|
|
129
110
|
var prettyPrint = false;
|
|
130
111
|
function setPretty(value) {
|
|
131
112
|
prettyPrint = value;
|
|
132
113
|
}
|
|
133
114
|
function output(data) {
|
|
134
|
-
process.stdout.write(`${JSON.stringify(
|
|
115
|
+
process.stdout.write(`${JSON.stringify(data, null, prettyPrint ? 2 : void 0)}
|
|
135
116
|
`);
|
|
136
117
|
}
|
|
137
118
|
function handleError(err) {
|
|
@@ -197,35 +178,166 @@ function handleError(err) {
|
|
|
197
178
|
process.exit(1);
|
|
198
179
|
}
|
|
199
180
|
|
|
181
|
+
// src/utils/transformers/base.ts
|
|
182
|
+
function bamboohrBaseUrl() {
|
|
183
|
+
return `https://${process.env.BAMBOO_COMPANY_DOMAIN ?? ""}.bamboohr.com`;
|
|
184
|
+
}
|
|
185
|
+
function stripNullish(value) {
|
|
186
|
+
if (Array.isArray(value)) {
|
|
187
|
+
return value.map(stripNullish);
|
|
188
|
+
}
|
|
189
|
+
if (value === null || typeof value !== "object") {
|
|
190
|
+
return value;
|
|
191
|
+
}
|
|
192
|
+
const record = value;
|
|
193
|
+
const result = {};
|
|
194
|
+
for (const [key, v] of Object.entries(record)) {
|
|
195
|
+
if (v === null || v === void 0) {
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
result[key] = stripNullish(v);
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// src/utils/transformers/employee.ts
|
|
204
|
+
function employeeUrl(id) {
|
|
205
|
+
return `${bamboohrBaseUrl()}/employees/employee.php?id=${id}`;
|
|
206
|
+
}
|
|
207
|
+
function transformEmployee(employee, opts = {}) {
|
|
208
|
+
const { photoUrl, canUploadPhoto: _canUploadPhoto, photoUploaded, ...rest } = employee;
|
|
209
|
+
const id = typeof rest.id === "string" ? rest.id : void 0;
|
|
210
|
+
const withUrl = id ? { ...rest, url: employeeUrl(id) } : { ...rest };
|
|
211
|
+
if (opts.withPhotos) {
|
|
212
|
+
if (photoUrl !== null && photoUrl !== void 0) {
|
|
213
|
+
withUrl.photoUrl = photoUrl;
|
|
214
|
+
}
|
|
215
|
+
if (photoUploaded !== null && photoUploaded !== void 0) {
|
|
216
|
+
withUrl.photoUploaded = photoUploaded;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return stripNullish(withUrl);
|
|
220
|
+
}
|
|
221
|
+
function transformEmployeeDirectory(directory2, opts = {}) {
|
|
222
|
+
return { employees: directory2.employees.map((e) => transformEmployee(e, opts)) };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// src/utils/transformers/goal.ts
|
|
226
|
+
function transformGoalMilestone(milestone) {
|
|
227
|
+
return stripNullish(milestone);
|
|
228
|
+
}
|
|
229
|
+
function transformGoal(goal) {
|
|
230
|
+
const { milestones, ...rest } = goal;
|
|
231
|
+
const shaped = {
|
|
232
|
+
...rest,
|
|
233
|
+
...milestones && { milestones: milestones.map(transformGoalMilestone) }
|
|
234
|
+
};
|
|
235
|
+
return stripNullish(shaped);
|
|
236
|
+
}
|
|
237
|
+
function transformGoals(response) {
|
|
238
|
+
return { goals: response.goals.map(transformGoal) };
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// src/utils/transformers/timeoff.ts
|
|
242
|
+
function transformTimeOffRequest(request) {
|
|
243
|
+
const { actions: _actions, ...rest } = request;
|
|
244
|
+
return stripNullish(rest);
|
|
245
|
+
}
|
|
246
|
+
function transformTimeOffRequests(requests2) {
|
|
247
|
+
return requests2.map(transformTimeOffRequest);
|
|
248
|
+
}
|
|
249
|
+
function transformTimeOffBalance(balance2) {
|
|
250
|
+
return stripNullish(balance2);
|
|
251
|
+
}
|
|
252
|
+
function transformTimeOffBalances(balances) {
|
|
253
|
+
return balances.map(transformTimeOffBalance);
|
|
254
|
+
}
|
|
255
|
+
function transformTimeOffType(type) {
|
|
256
|
+
return stripNullish(type);
|
|
257
|
+
}
|
|
258
|
+
function transformTimeOffTypesResponse(response) {
|
|
259
|
+
return {
|
|
260
|
+
timeOffTypes: response.timeOffTypes.map(transformTimeOffType),
|
|
261
|
+
defaultHours: response.defaultHours
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
function transformWhosOutEvent(event) {
|
|
265
|
+
return stripNullish(event);
|
|
266
|
+
}
|
|
267
|
+
function transformWhosOut(events) {
|
|
268
|
+
return events.map(transformWhosOutEvent);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// src/utils/transformers/file.ts
|
|
272
|
+
function transformCompanyFile(file) {
|
|
273
|
+
const {
|
|
274
|
+
shareWithEmployees: _shareWithEmployees,
|
|
275
|
+
canRenameFile: _canRenameFile,
|
|
276
|
+
canDeleteFile: _canDeleteFile,
|
|
277
|
+
...rest
|
|
278
|
+
} = file;
|
|
279
|
+
return stripNullish(rest);
|
|
280
|
+
}
|
|
281
|
+
function transformCompanyFileCategory(category) {
|
|
282
|
+
const { files, canUploadFiles: _canUploadFiles, ...rest } = category;
|
|
283
|
+
return stripNullish({ ...rest, files: files.map(transformCompanyFile) });
|
|
284
|
+
}
|
|
285
|
+
function transformCompanyFiles(response) {
|
|
286
|
+
return { categories: response.categories.map(transformCompanyFileCategory) };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// src/utils/transformers/meta.ts
|
|
290
|
+
function transformField(field) {
|
|
291
|
+
return stripNullish(field);
|
|
292
|
+
}
|
|
293
|
+
function transformFields(fields2) {
|
|
294
|
+
return fields2.map(transformField);
|
|
295
|
+
}
|
|
296
|
+
|
|
200
297
|
// src/commands/employee/directory.ts
|
|
201
298
|
function directory(parent) {
|
|
202
|
-
parent.command("directory").description("Get the company employee directory").
|
|
299
|
+
parent.command("directory").description("Get the company employee directory").option("--with-photos", "Include each employee's signed photo URL and photoUploaded flag (large)").addHelpText(
|
|
300
|
+
"after",
|
|
301
|
+
`
|
|
302
|
+
Examples:
|
|
303
|
+
$ bamboohr employee directory
|
|
304
|
+
$ bamboohr employee directory --with-photos`
|
|
305
|
+
).action(async (opts) => {
|
|
203
306
|
const client = getClient();
|
|
204
307
|
const result = await getDirectory(client);
|
|
205
|
-
output(result);
|
|
308
|
+
output(transformEmployeeDirectory(result, { withPhotos: opts.withPhotos }));
|
|
206
309
|
});
|
|
207
310
|
}
|
|
208
311
|
|
|
209
312
|
// src/commands/employee/get.ts
|
|
210
313
|
function get(parent) {
|
|
211
|
-
parent.command("get [id]").description("Get employee data by ID (default: current user)").option("--fields <fields>", "Comma-separated field names", "firstName,lastName,email,jobTitle").option("--include-future", "Include future-dated values from history fields").addHelpText(
|
|
314
|
+
parent.command("get [id]").description("Get employee data by ID (default: current user)").option("--fields <fields>", "Comma-separated field names", "firstName,lastName,email,jobTitle").option("--include-future", "Include future-dated values from history fields").option("--with-photos", "Include the employee's signed photo URL and photoUploaded flag").addHelpText(
|
|
212
315
|
"after",
|
|
213
316
|
`
|
|
214
317
|
Examples:
|
|
215
318
|
$ bamboohr employee get
|
|
216
319
|
$ bamboohr employee get 123
|
|
217
320
|
$ bamboohr employee get 123 --fields "firstName,lastName,department,hireDate"
|
|
218
|
-
$ bamboohr employee get 123 --include-future
|
|
321
|
+
$ bamboohr employee get 123 --include-future
|
|
322
|
+
$ bamboohr employee get 123 --with-photos`
|
|
219
323
|
).action(async (id, opts) => {
|
|
220
324
|
const client = getClient();
|
|
325
|
+
const fields2 = opts.withPhotos ? mergeFields(opts.fields, ["photoUrl", "photoUploaded"]) : opts.fields;
|
|
221
326
|
const result = await client.employees.get({
|
|
222
327
|
id: id ?? "0",
|
|
223
|
-
fields:
|
|
328
|
+
fields: fields2,
|
|
224
329
|
onlyCurrent: !opts.includeFuture
|
|
225
330
|
});
|
|
226
|
-
output(result);
|
|
331
|
+
output(transformEmployee(result, { withPhotos: opts.withPhotos }));
|
|
227
332
|
});
|
|
228
333
|
}
|
|
334
|
+
function mergeFields(existing, extra) {
|
|
335
|
+
const set = new Set(
|
|
336
|
+
existing.split(",").map((s) => s.trim()).filter(Boolean)
|
|
337
|
+
);
|
|
338
|
+
for (const f of extra) set.add(f);
|
|
339
|
+
return [...set].join(",");
|
|
340
|
+
}
|
|
229
341
|
|
|
230
342
|
// src/commands/employee/goals.ts
|
|
231
343
|
import { Option } from "commander";
|
|
@@ -243,7 +355,7 @@ Examples:
|
|
|
243
355
|
employeeId: id,
|
|
244
356
|
filter: opts.filter === "all" ? void 0 : opts.filter
|
|
245
357
|
});
|
|
246
|
-
output(result);
|
|
358
|
+
output(transformGoals(result));
|
|
247
359
|
});
|
|
248
360
|
}
|
|
249
361
|
|
|
@@ -278,14 +390,15 @@ async function resolveEmployeeId(client, employeeId) {
|
|
|
278
390
|
|
|
279
391
|
// src/commands/employee/search.ts
|
|
280
392
|
function search(parent) {
|
|
281
|
-
parent.command("search [query]").description("Search and filter employees").option("--supervisor <name>", 'Filter by supervisor name (use "me" for current user)').option("--department <name>", "Filter by department").option("--location <name>", "Filter by location").option("--division <name>", "Filter by division").addHelpText(
|
|
393
|
+
parent.command("search [query]").description("Search and filter employees").option("--supervisor <name>", 'Filter by supervisor name (use "me" for current user)').option("--department <name>", "Filter by department").option("--location <name>", "Filter by location").option("--division <name>", "Filter by division").option("--with-photos", "Include each result's signed photo URL and photoUploaded flag").addHelpText(
|
|
282
394
|
"after",
|
|
283
395
|
`
|
|
284
396
|
Examples:
|
|
285
397
|
bamboohr employee search john
|
|
286
398
|
bamboohr employee search --supervisor me
|
|
287
399
|
bamboohr employee search --department "R&D" --location Sofia
|
|
288
|
-
bamboohr employee search --supervisor "Borislav Mihaylov"
|
|
400
|
+
bamboohr employee search --supervisor "Borislav Mihaylov"
|
|
401
|
+
bamboohr employee search john --with-photos`
|
|
289
402
|
).action(
|
|
290
403
|
async (query, opts) => {
|
|
291
404
|
const client = getClient();
|
|
@@ -320,7 +433,7 @@ Examples:
|
|
|
320
433
|
const dv = opts.division.toLowerCase();
|
|
321
434
|
matches = matches.filter((e) => (e.division ?? "").toLowerCase().includes(dv));
|
|
322
435
|
}
|
|
323
|
-
output(matches);
|
|
436
|
+
output(matches.map((e) => transformEmployee(e, { withPhotos: opts.withPhotos })));
|
|
324
437
|
}
|
|
325
438
|
);
|
|
326
439
|
}
|
|
@@ -366,7 +479,7 @@ function list(parent) {
|
|
|
366
479
|
parent.command("list").description("List all company files and categories").addHelpText("after", "\nExamples:\n $ bamboohr file list").action(async () => {
|
|
367
480
|
const client = getClient();
|
|
368
481
|
const result = await client.files.list();
|
|
369
|
-
output(result);
|
|
482
|
+
output(transformCompanyFiles(result));
|
|
370
483
|
});
|
|
371
484
|
}
|
|
372
485
|
|
|
@@ -409,7 +522,7 @@ function fields(parent) {
|
|
|
409
522
|
parent.command("fields").description("List all available BambooHR fields").addHelpText("after", "\nExamples:\n $ bamboohr meta fields").action(async () => {
|
|
410
523
|
const client = getClient();
|
|
411
524
|
const result = await getMetaFields(client);
|
|
412
|
-
output(result);
|
|
525
|
+
output(transformFields(result));
|
|
413
526
|
});
|
|
414
527
|
}
|
|
415
528
|
|
|
@@ -454,7 +567,7 @@ Examples:
|
|
|
454
567
|
const client = getClient();
|
|
455
568
|
const id = await resolveEmployeeId(client, employeeId);
|
|
456
569
|
const result = await client.timeOff.getBalance({ employeeId: id, date: opts.date });
|
|
457
|
-
output(result);
|
|
570
|
+
output(transformTimeOffBalances(result));
|
|
458
571
|
});
|
|
459
572
|
}
|
|
460
573
|
|
|
@@ -495,7 +608,7 @@ Examples:
|
|
|
495
608
|
notes: opts.note ? [{ from: "employee", note: opts.note }] : void 0,
|
|
496
609
|
dates: opts.dates ? JSON.parse(opts.dates) : void 0
|
|
497
610
|
});
|
|
498
|
-
output(result
|
|
611
|
+
output(result ? stripNullish(result) : { created: true, employeeId: id, start: opts.start, end: opts.end });
|
|
499
612
|
}
|
|
500
613
|
);
|
|
501
614
|
}
|
|
@@ -538,7 +651,7 @@ Examples:
|
|
|
538
651
|
status: opts.status,
|
|
539
652
|
type: opts.type
|
|
540
653
|
});
|
|
541
|
-
output(result);
|
|
654
|
+
output(transformTimeOffRequests(result));
|
|
542
655
|
}
|
|
543
656
|
);
|
|
544
657
|
}
|
|
@@ -554,7 +667,7 @@ Examples:
|
|
|
554
667
|
).action(async (opts) => {
|
|
555
668
|
const client = getClient();
|
|
556
669
|
const result = opts.requestable ? await client.timeOff.getTypes({ mode: "request" }) : await getTimeOffTypes(client);
|
|
557
|
-
output(result);
|
|
670
|
+
output(transformTimeOffTypesResponse(result));
|
|
558
671
|
});
|
|
559
672
|
}
|
|
560
673
|
|
|
@@ -577,7 +690,7 @@ Examples:
|
|
|
577
690
|
status: opts.status,
|
|
578
691
|
note: opts.note
|
|
579
692
|
});
|
|
580
|
-
output(result
|
|
693
|
+
output(result ? stripNullish(result) : { updated: true, requestId, status: opts.status });
|
|
581
694
|
});
|
|
582
695
|
}
|
|
583
696
|
|
|
@@ -595,7 +708,7 @@ Examples:
|
|
|
595
708
|
const start = opts.start ?? today;
|
|
596
709
|
const end = opts.end ?? (opts.start ? void 0 : today);
|
|
597
710
|
const result = await client.timeOff.getWhosOut({ start, end });
|
|
598
|
-
output(result);
|
|
711
|
+
output(transformWhosOut(result));
|
|
599
712
|
});
|
|
600
713
|
}
|
|
601
714
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bamboohr-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.16",
|
|
4
4
|
"publish": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
],
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"commander": "^13.1.0",
|
|
15
|
-
"bamboohr-client": "1.0.
|
|
15
|
+
"bamboohr-client": "1.0.23"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/node": "24.10.4",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"tsx": "^4.19.2",
|
|
23
23
|
"typescript": "^5.7.2",
|
|
24
24
|
"vitest": "^4.0.16",
|
|
25
|
-
"cli-utils": "1.0.0",
|
|
26
25
|
"config-eslint": "0.0.0",
|
|
26
|
+
"cli-utils": "1.0.0",
|
|
27
27
|
"config-typescript": "0.0.0"
|
|
28
28
|
},
|
|
29
29
|
"engines": {
|