bamboohr-cli 1.0.19-g3f22a81.1 → 1.0.20
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 +79 -25
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -68,9 +68,57 @@ function positiveInt(raw) {
|
|
|
68
68
|
return n;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
// ../../cli-utils/dist/
|
|
71
|
+
// ../../cli-utils/dist/text-or-file.js
|
|
72
72
|
import { readFileSync as readFileSync3 } from "fs";
|
|
73
|
-
import { InvalidArgumentError as InvalidArgumentError2 } from "commander";
|
|
73
|
+
import { InvalidArgumentError as InvalidArgumentError2, Option } from "commander";
|
|
74
|
+
var STDIN_REF = "-";
|
|
75
|
+
function rejectStdinSentinel(value) {
|
|
76
|
+
if (value === "@-" || value === STDIN_REF) {
|
|
77
|
+
throw new InvalidArgumentError2(`"${value}" looks like a stdin redirect, which is not supported here. Pass the text directly, or read it from a file/stdin with the matching --\u2026-file <path|-> option.`);
|
|
78
|
+
}
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
function readFileOrStdin(ref) {
|
|
82
|
+
if (ref === STDIN_REF) {
|
|
83
|
+
if (process.stdin.isTTY) {
|
|
84
|
+
throw new InvalidArgumentError2('"--\u2026-file -" reads stdin, but stdin is a terminal (nothing piped).');
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
return readFileSync3(0, "utf8");
|
|
88
|
+
} catch (err) {
|
|
89
|
+
throw new InvalidArgumentError2(`failed to read stdin for "--\u2026-file -": ${err.message}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
return readFileSync3(ref, "utf8");
|
|
94
|
+
} catch (err) {
|
|
95
|
+
const e = err;
|
|
96
|
+
if (e.code === "ENOENT") {
|
|
97
|
+
throw new InvalidArgumentError2(`file not found: "${ref}".`);
|
|
98
|
+
}
|
|
99
|
+
throw new InvalidArgumentError2(`failed to read file "${ref}": ${e.message}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function textOrFileOption(cmd, name, opts = {}) {
|
|
103
|
+
const label = `${name.charAt(0).toUpperCase()}${name.slice(1)} content`;
|
|
104
|
+
cmd.option(`--${name} <text>`, opts.description ?? label, rejectStdinSentinel);
|
|
105
|
+
cmd.addOption(new Option(`--${name}-file <path>`, `Read --${name} from a file, or "-" for stdin (mutually exclusive with --${name})`).conflicts(name));
|
|
106
|
+
return cmd;
|
|
107
|
+
}
|
|
108
|
+
function resolveTextOrFile(opts, name, { required = true } = {}) {
|
|
109
|
+
const literal = opts[name];
|
|
110
|
+
const ref = opts[`${name}File`];
|
|
111
|
+
if (literal !== void 0 && ref !== void 0) {
|
|
112
|
+
throw new InvalidArgumentError2(`--${name} and --${name}-file are mutually exclusive; provide only one.`);
|
|
113
|
+
}
|
|
114
|
+
if (ref !== void 0) {
|
|
115
|
+
return readFileOrStdin(ref);
|
|
116
|
+
}
|
|
117
|
+
if (literal === void 0 && required) {
|
|
118
|
+
throw new InvalidArgumentError2(`a ${name} is required: provide --${name} <text> or --${name}-file <path>.`);
|
|
119
|
+
}
|
|
120
|
+
return literal;
|
|
121
|
+
}
|
|
74
122
|
|
|
75
123
|
// ../../cli-utils/dist/builders.js
|
|
76
124
|
var EXAMPLES = /* @__PURE__ */ new WeakSet();
|
|
@@ -500,10 +548,10 @@ function mergeFields(existing, extra) {
|
|
|
500
548
|
}
|
|
501
549
|
|
|
502
550
|
// src/commands/employee/goals.ts
|
|
503
|
-
import { Option } from "commander";
|
|
551
|
+
import { Option as Option2 } from "commander";
|
|
504
552
|
var GOAL_FILTERS = ["open", "closed", "all"];
|
|
505
553
|
function goals(parent) {
|
|
506
|
-
const cmd = parent.command("goals <employeeId>").description("Get employee performance goals").addOption(new
|
|
554
|
+
const cmd = parent.command("goals <employeeId>").description("Get employee performance goals").addOption(new Option2("--filter <filter>", "Filter goals by status").choices(GOAL_FILTERS).default("all"));
|
|
507
555
|
examples(cmd, ["123", ["123 --filter open", "only open goals"], ["123 --filter closed", "only closed goals"]]);
|
|
508
556
|
cmd.action(async (employeeId, opts) => {
|
|
509
557
|
const client = getClient();
|
|
@@ -517,10 +565,10 @@ function goals(parent) {
|
|
|
517
565
|
|
|
518
566
|
// src/commands/employee/photo.ts
|
|
519
567
|
import { writeFileSync as writeFileSync2 } from "fs";
|
|
520
|
-
import { Option as
|
|
568
|
+
import { Option as Option3 } from "commander";
|
|
521
569
|
var PHOTO_SIZES = ["original", "large", "medium", "small", "xs", "tiny"];
|
|
522
570
|
function photo(parent) {
|
|
523
|
-
const cmd = parent.command("photo <employeeId>").description("Download employee photo").requiredOption("--output <path>", "File path to save photo").addOption(new
|
|
571
|
+
const cmd = parent.command("photo <employeeId>").description("Download employee photo").requiredOption("--output <path>", "File path to save photo").addOption(new Option3("--size <size>", "Photo size").choices(PHOTO_SIZES).default("medium"));
|
|
524
572
|
examples(cmd, [["123 --output ./photo.jpg", "medium size (default)"], "123 --output ./photo.jpg --size large"]);
|
|
525
573
|
cmd.action(async (employeeId, opts) => {
|
|
526
574
|
const client = getClient();
|
|
@@ -708,11 +756,12 @@ function balance(parent) {
|
|
|
708
756
|
}
|
|
709
757
|
|
|
710
758
|
// src/commands/timeoff/create.ts
|
|
711
|
-
import { Option as
|
|
759
|
+
import { Option as Option4 } from "commander";
|
|
712
760
|
function create(parent) {
|
|
713
761
|
const cmd = parent.command("create [employeeId]").description("Create a time off request (defaults to current user)").requiredOption("--start-date <date>", "Start date (YYYY-MM-DD)").requiredOption("--end-date <date>", "End date (YYYY-MM-DD)").requiredOption("--type-id <id>", 'Time off type ID (use "timeoff types" to find IDs)', positiveInt).requiredOption("--amount <amount>", "Total amount of time off (in days or hours depending on type)", parseFloat).addOption(
|
|
714
|
-
new
|
|
715
|
-
).option("--
|
|
762
|
+
new Option4("--status <status>", "Request status").choices(["requested", "approved"]).default("requested")
|
|
763
|
+
).option("--dates <json>", `Per-day amounts as JSON array, e.g. '[{"ymd":"2026-03-21","amount":4}]' for half-day`);
|
|
764
|
+
textOrFileOption(cmd, "note", { description: "Note to include with the request" });
|
|
716
765
|
examples(cmd, [
|
|
717
766
|
"--start-date 2026-04-01 --end-date 2026-04-01 --type-id 83 --amount 1",
|
|
718
767
|
[
|
|
@@ -724,6 +773,7 @@ function create(parent) {
|
|
|
724
773
|
async (employeeId, opts) => {
|
|
725
774
|
const client = getClient();
|
|
726
775
|
const id = await resolveEmployeeId(client, employeeId);
|
|
776
|
+
const note = resolveTextOrFile(opts, "note", { required: false });
|
|
727
777
|
const result = await client.timeOff.createRequest({
|
|
728
778
|
employeeId: id,
|
|
729
779
|
status: opts.status,
|
|
@@ -731,7 +781,7 @@ function create(parent) {
|
|
|
731
781
|
end: opts.endDate,
|
|
732
782
|
timeOffTypeId: opts.typeId,
|
|
733
783
|
amount: opts.amount,
|
|
734
|
-
notes:
|
|
784
|
+
notes: note ? [{ from: "employee", note }] : void 0,
|
|
735
785
|
dates: opts.dates ? JSON.parse(opts.dates) : void 0
|
|
736
786
|
});
|
|
737
787
|
output(
|
|
@@ -742,10 +792,10 @@ function create(parent) {
|
|
|
742
792
|
}
|
|
743
793
|
|
|
744
794
|
// src/commands/timeoff/requests.ts
|
|
745
|
-
import { Option as
|
|
795
|
+
import { Option as Option5 } from "commander";
|
|
746
796
|
function requests(parent) {
|
|
747
|
-
const cmd = parent.command("requests").description("Get time off requests (defaults to current user)").option("--request-id <id>", "Specific request ID", positiveInt).addOption(new
|
|
748
|
-
new
|
|
797
|
+
const cmd = parent.command("requests").description("Get time off requests (defaults to current user)").option("--request-id <id>", "Specific request ID", positiveInt).addOption(new Option5("--action <action>", "Access level filter").choices(["view", "approve"])).option("--employee-id <id>", "Filter by employee ID").option("--all", "Show all visible requests instead of just current user").option("--start-date <date>", "Start date (YYYY-MM-DD)").option("--end-date <date>", "End date (YYYY-MM-DD)").addOption(
|
|
798
|
+
new Option5("--status <status>", "Filter by request status").choices([
|
|
749
799
|
"approved",
|
|
750
800
|
"denied",
|
|
751
801
|
"superceded",
|
|
@@ -795,25 +845,29 @@ function types(parent) {
|
|
|
795
845
|
}
|
|
796
846
|
|
|
797
847
|
// src/commands/timeoff/update-status.ts
|
|
798
|
-
import { Option as
|
|
848
|
+
import { Option as Option6 } from "commander";
|
|
799
849
|
function updateStatus(parent) {
|
|
800
850
|
const cmd = parent.command("update-status <requestId>").description("Update time off request status (approve, deny, cancel)").addOption(
|
|
801
|
-
new
|
|
802
|
-
)
|
|
851
|
+
new Option6("--status <status>", "New status").choices(["approved", "denied", "canceled"]).makeOptionMandatory()
|
|
852
|
+
);
|
|
853
|
+
textOrFileOption(cmd, "note", { description: "Note to attach to the status change" });
|
|
803
854
|
examples(cmd, [
|
|
804
855
|
"7890 --status approved",
|
|
805
856
|
['7890 --status denied --note "Team at capacity that week"', "deny with note"],
|
|
806
857
|
"7890 --status canceled"
|
|
807
858
|
]);
|
|
808
|
-
cmd.action(
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
859
|
+
cmd.action(
|
|
860
|
+
async (requestId, opts) => {
|
|
861
|
+
const client = getClient();
|
|
862
|
+
const note = resolveTextOrFile(opts, "note", { required: false });
|
|
863
|
+
const result = await client.timeOff.updateRequestStatus({
|
|
864
|
+
requestId,
|
|
865
|
+
status: opts.status,
|
|
866
|
+
note
|
|
867
|
+
});
|
|
868
|
+
output(result ? stripNullish(result) : { updated: true, requestId, status: opts.status });
|
|
869
|
+
}
|
|
870
|
+
);
|
|
817
871
|
}
|
|
818
872
|
|
|
819
873
|
// src/commands/timeoff/whos-out.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bamboohr-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20",
|
|
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.24
|
|
15
|
+
"bamboohr-client": "1.0.24"
|
|
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": {
|