tines 0.0.123 → 0.0.124
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 +57 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3838,7 +3838,11 @@ function createApiClient(options) {
|
|
|
3838
3838
|
listLabels: () => get("/api/v1/labels"),
|
|
3839
3839
|
createLabel: (body) => request("POST", "/api/v1/labels", body),
|
|
3840
3840
|
updateLabel: (labelRef, body) => request("PATCH", `/api/v1/labels/${encodeURIComponent(labelRef)}`, body),
|
|
3841
|
-
deleteLabel: (labelRef) => request(
|
|
3841
|
+
deleteLabel: (labelRef, body = {}) => request(
|
|
3842
|
+
"DELETE",
|
|
3843
|
+
`/api/v1/labels/${encodeURIComponent(labelRef)}`,
|
|
3844
|
+
body
|
|
3845
|
+
),
|
|
3842
3846
|
addIssueLabels: (issueId, labels) => request("POST", `/api/v1/issues/${issueId}/labels`, { labels }),
|
|
3843
3847
|
removeIssueLabel: (issueId, labelRef) => request("DELETE", `/api/v1/issues/${issueId}/labels/${encodeURIComponent(labelRef)}`),
|
|
3844
3848
|
listProjectIssues: (projectId, filters = {}) => get(`/api/v1/projects/${projectId}/issues${query(filters)}`),
|
|
@@ -4467,6 +4471,13 @@ async function resolveIssue(api, ref) {
|
|
|
4467
4471
|
const proj = await resolveProject(api, project);
|
|
4468
4472
|
return api.getIssueByNumber(proj.id, number);
|
|
4469
4473
|
}
|
|
4474
|
+
async function resolveLabelFlag(api, ref) {
|
|
4475
|
+
const match = (await api.listLabels()).items.find(
|
|
4476
|
+
(l) => l.id === ref || l.name.toLowerCase() === ref.toLowerCase()
|
|
4477
|
+
);
|
|
4478
|
+
if (!match) die(`no such label: ${ref}`);
|
|
4479
|
+
return match.id;
|
|
4480
|
+
}
|
|
4470
4481
|
async function resolveStateFlag(api, ref) {
|
|
4471
4482
|
const sep2 = ref.indexOf("/");
|
|
4472
4483
|
if (sep2 < 1 || sep2 === ref.length - 1) {
|
|
@@ -4499,6 +4510,7 @@ async function resolveScopeFlags(api, opts) {
|
|
|
4499
4510
|
if (opts.state !== void 0)
|
|
4500
4511
|
scope.workflow_state_id = (await resolveStateFlag(api, opts.state)).state.id;
|
|
4501
4512
|
if (opts.issue !== void 0) scope.issue_id = (await resolveIssue(api, opts.issue)).id;
|
|
4513
|
+
if (opts.label !== void 0) scope.label_id = await resolveLabelFlag(api, opts.label);
|
|
4502
4514
|
return scope;
|
|
4503
4515
|
}
|
|
4504
4516
|
function printContextItem(item) {
|
|
@@ -4537,9 +4549,10 @@ Scope flags (combinable \u2014 an item applies where ALL of its set dimensions m
|
|
|
4537
4549
|
--project <name> only for issues in this project
|
|
4538
4550
|
--state <workflow>/<state> only for issues currently in this state
|
|
4539
4551
|
--issue <project>/<number> only for this issue
|
|
4552
|
+
--label <name> only for issues carrying this label
|
|
4540
4553
|
`;
|
|
4541
4554
|
function withScopeFlags(cmd) {
|
|
4542
|
-
return cmd.option("-p, --project <name>", "scope: project name or id").option("-s, --state <workflow/state>", "scope: workflow-qualified state").option("-i, --issue <ref>", "scope: issue (<project>/<number>)").addHelpText("after", SCOPE_FLAGS_HELP);
|
|
4555
|
+
return cmd.option("-p, --project <name>", "scope: project name or id").option("-s, --state <workflow/state>", "scope: workflow-qualified state").option("-i, --issue <ref>", "scope: issue (<project>/<number>)").option("-l, --label <name>", "scope: issue label name or id").addHelpText("after", SCOPE_FLAGS_HELP);
|
|
4543
4556
|
}
|
|
4544
4557
|
function register(program3) {
|
|
4545
4558
|
const context = program3.command("context").description(
|
|
@@ -4562,6 +4575,7 @@ function register(program3) {
|
|
|
4562
4575
|
project: scope.project_id ?? void 0,
|
|
4563
4576
|
state: scope.workflow_state_id ?? void 0,
|
|
4564
4577
|
issue: scope.issue_id ?? void 0,
|
|
4578
|
+
label: scope.label_id ?? void 0,
|
|
4565
4579
|
q: opts.search,
|
|
4566
4580
|
exact: opts.exact ? true : void 0,
|
|
4567
4581
|
...page
|
|
@@ -4630,7 +4644,7 @@ function register(program3) {
|
|
|
4630
4644
|
withScopeFlags(
|
|
4631
4645
|
context.command("edit <id>").description("Edit a context item: payload, name, description, or scope").option("-n, --name <name>", "rename the item").option("-d, --description <text>", "set the description").option("--body <md>", "prompt body: inline Markdown or @file (escape a literal @ as @@)").option("--file <path>=@<local>", "add or replace a skill file (repeatable)", collect, []).option("--remove-file <path>", "remove a skill file (repeatable)", collect, []).option("--repo-url <url>", "repo: clone URL").option("--branch <branch>", "repo: branch (empty string clears it)").option("--dir <dir>", "repo: checkout directory (empty string restores the URL default)").option(
|
|
4632
4646
|
"--unset <dimension>",
|
|
4633
|
-
"drop a scope dimension: project, state, or
|
|
4647
|
+
"drop a scope dimension: project, state, issue, or label (repeatable)",
|
|
4634
4648
|
collect,
|
|
4635
4649
|
[]
|
|
4636
4650
|
).option(
|
|
@@ -4652,7 +4666,8 @@ function register(program3) {
|
|
|
4652
4666
|
if (dim === "project") body.project_id = null;
|
|
4653
4667
|
else if (dim === "state") body.workflow_state_id = null;
|
|
4654
4668
|
else if (dim === "issue") body.issue_id = null;
|
|
4655
|
-
else
|
|
4669
|
+
else if (dim === "label") body.label_id = null;
|
|
4670
|
+
else die(`--unset takes project, state, issue, or label, got "${dim}"`);
|
|
4656
4671
|
}
|
|
4657
4672
|
if (opts.body !== void 0) body.body = readBodyValue(opts.body);
|
|
4658
4673
|
if (opts.file.length > 0 || opts.removeFile.length > 0) {
|
|
@@ -5574,6 +5589,9 @@ function stateScope(issue, state, workflow) {
|
|
|
5574
5589
|
workflow_name: workflow.name,
|
|
5575
5590
|
issue_id: null,
|
|
5576
5591
|
issue_ref: null,
|
|
5592
|
+
label_id: null,
|
|
5593
|
+
label_name: null,
|
|
5594
|
+
label_color: null,
|
|
5577
5595
|
label: `project ${issue.project_name} \xB7 state ${state.name}`
|
|
5578
5596
|
};
|
|
5579
5597
|
}
|
|
@@ -5692,8 +5710,15 @@ function register4(program3) {
|
|
|
5692
5710
|
if (opts.json) return printJson(res);
|
|
5693
5711
|
if (res.items.length === 0) return console.log("no labels");
|
|
5694
5712
|
table([
|
|
5695
|
-
["NAME", "COLOR", "ISSUES", "DESCRIPTION"],
|
|
5696
|
-
...res.items.map((l) => [
|
|
5713
|
+
["NAME", "COLOR", "ISSUES", "ITEMS", "RULES", "DESCRIPTION"],
|
|
5714
|
+
...res.items.map((l) => [
|
|
5715
|
+
l.name,
|
|
5716
|
+
l.color,
|
|
5717
|
+
String(l.issue_count),
|
|
5718
|
+
String(l.context_item_count),
|
|
5719
|
+
String(l.routing_rule_count),
|
|
5720
|
+
l.description
|
|
5721
|
+
])
|
|
5697
5722
|
]);
|
|
5698
5723
|
});
|
|
5699
5724
|
withCommon(
|
|
@@ -5724,7 +5749,7 @@ function register4(program3) {
|
|
|
5724
5749
|
}
|
|
5725
5750
|
);
|
|
5726
5751
|
withCommon(
|
|
5727
|
-
labels.command("delete <name>").description("Delete a label and detach it from every issue").option("-y, --yes", "skip the confirmation")
|
|
5752
|
+
labels.command("delete <name>").description("Delete a label and detach it from every issue").option("-y, --yes", "skip the confirmation").option("-f, --force", "also delete the context items and routing rules scoped to this label")
|
|
5728
5753
|
).action(async (name2, opts) => {
|
|
5729
5754
|
const api = client(opts);
|
|
5730
5755
|
if (!opts.yes) {
|
|
@@ -5732,18 +5757,33 @@ function register4(program3) {
|
|
|
5732
5757
|
(l) => l.name.toLowerCase() === name2.toLowerCase() || l.id === name2
|
|
5733
5758
|
);
|
|
5734
5759
|
if (!existing) die(`no such label: ${name2}`);
|
|
5760
|
+
const scoped = [
|
|
5761
|
+
`${existing.issue_count} issue${existing.issue_count === 1 ? "" : "s"}`,
|
|
5762
|
+
...existing.context_item_count > 0 ? [
|
|
5763
|
+
`${existing.context_item_count} context item${existing.context_item_count === 1 ? "" : "s"}`
|
|
5764
|
+
] : [],
|
|
5765
|
+
...existing.routing_rule_count > 0 ? [
|
|
5766
|
+
`${existing.routing_rule_count} routing rule${existing.routing_rule_count === 1 ? "" : "s"}`
|
|
5767
|
+
] : []
|
|
5768
|
+
].join(", ");
|
|
5735
5769
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
5736
5770
|
const answer = await rl.question(
|
|
5737
|
-
`Delete label "${existing.name}"
|
|
5771
|
+
`Delete label "${existing.name}"${opts.force ? " and everything scoped to it" : ""}? It is on ${scoped}. [y/N] `
|
|
5738
5772
|
);
|
|
5739
5773
|
rl.close();
|
|
5740
5774
|
if (!/^y(es)?$/i.test(answer.trim())) die("aborted");
|
|
5741
5775
|
}
|
|
5742
|
-
const res = await api.deleteLabel(name2);
|
|
5776
|
+
const res = await api.deleteLabel(name2, opts.force ? { force: true } : {});
|
|
5743
5777
|
if (opts.json) return printJson(res);
|
|
5744
5778
|
console.log(
|
|
5745
5779
|
`deleted label "${name2}" (was on ${res.issue_count} issue${res.issue_count === 1 ? "" : "s"})`
|
|
5746
5780
|
);
|
|
5781
|
+
for (const item of res.context_items_deleted) {
|
|
5782
|
+
console.log(` deleted ${item.kind} "${item.name}" (${item.scope_label})`);
|
|
5783
|
+
}
|
|
5784
|
+
for (const rule of res.routing_rules_deleted) {
|
|
5785
|
+
console.log(` deleted routing rule (${rule.scope_label})`);
|
|
5786
|
+
}
|
|
5747
5787
|
});
|
|
5748
5788
|
}
|
|
5749
5789
|
|
|
@@ -5938,10 +5978,12 @@ default workflow: ${defaultWorkflow}`);
|
|
|
5938
5978
|
async function resolveRoutingScope(api, opts) {
|
|
5939
5979
|
const projectId = opts.project !== void 0 ? (await resolveProject(api, opts.project)).id : null;
|
|
5940
5980
|
const stateId = opts.state !== void 0 ? (await resolveStateFlag(api, opts.state)).state.id : null;
|
|
5981
|
+
const labelId = opts.label !== void 0 ? await resolveLabelFlag(api, opts.label) : null;
|
|
5941
5982
|
const parts = [];
|
|
5942
5983
|
if (opts.project) parts.push(`project ${opts.project}`);
|
|
5943
5984
|
if (opts.state) parts.push(`state ${opts.state}`);
|
|
5944
|
-
|
|
5985
|
+
if (opts.label) parts.push(`label ${opts.label}`);
|
|
5986
|
+
return { projectId, stateId, labelId, label: parts.length > 0 ? parts.join(" \xB7 ") : "global" };
|
|
5945
5987
|
}
|
|
5946
5988
|
function register7(program3) {
|
|
5947
5989
|
const routing = program3.command("routing").description(
|
|
@@ -5961,7 +6003,7 @@ function register7(program3) {
|
|
|
5961
6003
|
withCommon(
|
|
5962
6004
|
routing.command("set <target...>").description(
|
|
5963
6005
|
"Create or replace the rule at a scope: an ordered list of <runner>[:tier] targets"
|
|
5964
|
-
).option("-p, --project <name>", "scope: project name or id").option("-s, --state <workflow/state>", "scope: workflow-qualified state")
|
|
6006
|
+
).option("-p, --project <name>", "scope: project name or id").option("-s, --state <workflow/state>", "scope: workflow-qualified state").option("-l, --label <name>", "scope: issue label name or id")
|
|
5965
6007
|
).action(async (targetSpecs, opts) => {
|
|
5966
6008
|
const api = client(opts);
|
|
5967
6009
|
const scope = await resolveRoutingScope(api, opts);
|
|
@@ -5973,11 +6015,12 @@ function register7(program3) {
|
|
|
5973
6015
|
}
|
|
5974
6016
|
const { items } = await api.listRoutingRules();
|
|
5975
6017
|
const existing = items.find(
|
|
5976
|
-
(r) => r.scope.project_id === scope.projectId && r.scope.workflow_state_id === scope.stateId
|
|
6018
|
+
(r) => r.scope.project_id === scope.projectId && r.scope.workflow_state_id === scope.stateId && r.scope.label_id === scope.labelId
|
|
5977
6019
|
);
|
|
5978
6020
|
const rule = existing ? await api.updateRoutingRule(existing.id, { targets }) : await api.createRoutingRule({
|
|
5979
6021
|
project_id: scope.projectId,
|
|
5980
6022
|
workflow_state_id: scope.stateId,
|
|
6023
|
+
label_id: scope.labelId,
|
|
5981
6024
|
targets
|
|
5982
6025
|
});
|
|
5983
6026
|
if (opts.json) return printJson(rule);
|
|
@@ -5987,13 +6030,13 @@ function register7(program3) {
|
|
|
5987
6030
|
for (const warning of rule.warnings) console.log(`warning: ${warning.message}`);
|
|
5988
6031
|
});
|
|
5989
6032
|
withCommon(
|
|
5990
|
-
routing.command("clear").description("Delete the rule at a scope (issues it matched stop dispatching)").option("-p, --project <name>", "scope: project name or id").option("-s, --state <workflow/state>", "scope: workflow-qualified state")
|
|
6033
|
+
routing.command("clear").description("Delete the rule at a scope (issues it matched stop dispatching)").option("-p, --project <name>", "scope: project name or id").option("-s, --state <workflow/state>", "scope: workflow-qualified state").option("-l, --label <name>", "scope: issue label name or id")
|
|
5991
6034
|
).action(async (opts) => {
|
|
5992
6035
|
const api = client(opts);
|
|
5993
6036
|
const scope = await resolveRoutingScope(api, opts);
|
|
5994
6037
|
const { items } = await api.listRoutingRules();
|
|
5995
6038
|
const existing = items.find(
|
|
5996
|
-
(r) => r.scope.project_id === scope.projectId && r.scope.workflow_state_id === scope.stateId
|
|
6039
|
+
(r) => r.scope.project_id === scope.projectId && r.scope.workflow_state_id === scope.stateId && r.scope.label_id === scope.labelId
|
|
5997
6040
|
);
|
|
5998
6041
|
if (!existing) die(`no routing rule at scope ${scope.label}`);
|
|
5999
6042
|
await api.deleteRoutingRule(existing.id);
|