@shortcut-cli/shortcut-cli 3.8.1 → 5.0.0
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 +549 -10
- package/build/bin/short-api.js +21 -22
- package/build/bin/short-create.js +58 -38
- package/build/bin/short-custom-field.js +50 -0
- package/build/bin/short-custom-fields.js +29 -0
- package/build/bin/short-doc.js +38 -41
- package/build/bin/short-docs.js +34 -27
- package/build/bin/short-epic.js +147 -36
- package/build/bin/short-epics.js +23 -24
- package/build/bin/short-find.js +4 -5
- package/build/bin/short-install.js +73 -29
- package/build/bin/short-iteration.js +180 -0
- package/build/bin/short-iterations.js +62 -0
- package/build/bin/short-label.js +130 -0
- package/build/bin/short-labels.js +27 -0
- package/build/bin/short-members.js +17 -21
- package/build/bin/short-objective.js +151 -0
- package/build/bin/short-objectives.js +63 -0
- package/build/bin/short-projects.js +17 -21
- package/build/bin/short-search.js +23 -32
- package/build/bin/short-story.js +350 -104
- package/build/bin/short-team.js +78 -0
- package/build/bin/short-teams.js +28 -0
- package/build/bin/short-workflows.js +12 -16
- package/build/bin/short-workspace.js +27 -28
- package/build/bin/short.js +5 -8
- package/build/lib/client.js +7 -9
- package/build/lib/configure.js +20 -29
- package/build/lib/spinner.js +3 -8
- package/build/lib/stories.js +171 -129
- package/build/package.js +3 -16
- package/package.json +67 -67
- package/build/_virtual/rolldown_runtime.js +0 -29
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import client from "../lib/client.js";
|
|
3
|
+
import spinner from "../lib/spinner.js";
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
//#region src/bin/short-teams.ts
|
|
7
|
+
const spin = spinner();
|
|
8
|
+
const log = console.log;
|
|
9
|
+
const opts = new Command().description("Display teams available for stories and epics").option("-a, --archived", "List teams including archived", "").option("-s, --search [query]", "List teams with name containing query", "").parse(process.argv).opts();
|
|
10
|
+
async function main() {
|
|
11
|
+
spin.start();
|
|
12
|
+
const teams = await client.listGroups().then((r) => r.data);
|
|
13
|
+
spin.stop(true);
|
|
14
|
+
const searchMatch = new RegExp(opts.search ?? "", "i");
|
|
15
|
+
teams.filter((team) => !!`${team.id} ${team.name} ${team.mention_name}`.match(searchMatch)).forEach(printTeamSummary);
|
|
16
|
+
}
|
|
17
|
+
function printTeamSummary(team) {
|
|
18
|
+
if (team.archived && !opts.archived) return;
|
|
19
|
+
log(chalk.bold(`#${team.id}`) + chalk.blue(` ${team.name}`));
|
|
20
|
+
log(chalk.bold("Mention: ") + ` ${team.mention_name}`);
|
|
21
|
+
log(chalk.bold("Stories: ") + ` ${team.num_stories}`);
|
|
22
|
+
log(chalk.bold("Started: ") + ` ${team.num_stories_started}`);
|
|
23
|
+
if (team.archived) log(chalk.bold("Archived: ") + ` ${team.archived}`);
|
|
24
|
+
log();
|
|
25
|
+
}
|
|
26
|
+
main();
|
|
27
|
+
//#endregion
|
|
28
|
+
export {};
|
|
@@ -1,33 +1,29 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
commander = require_rolldown_runtime.__toESM(commander);
|
|
7
|
-
let chalk = require("chalk");
|
|
8
|
-
chalk = require_rolldown_runtime.__toESM(chalk);
|
|
9
|
-
|
|
2
|
+
import client from "../lib/client.js";
|
|
3
|
+
import spinner from "../lib/spinner.js";
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import chalk from "chalk";
|
|
10
6
|
//#region src/bin/short-workflows.ts
|
|
11
|
-
const spin =
|
|
7
|
+
const spin = spinner();
|
|
12
8
|
const log = console.log;
|
|
13
|
-
const
|
|
9
|
+
const opts = new Command().description("Display workflows/states available for stories").option("-s, --search [query]", "List states containing query", "").parse(process.argv).opts();
|
|
14
10
|
const main = async () => {
|
|
15
11
|
spin.start();
|
|
16
|
-
const wfs = await
|
|
12
|
+
const wfs = await client.listWorkflows().then((r) => r.data);
|
|
17
13
|
spin.stop(true);
|
|
18
14
|
wfs.map(printWf);
|
|
19
15
|
};
|
|
20
16
|
const printWf = (wf) => {
|
|
21
|
-
log(chalk.
|
|
17
|
+
log(chalk.bold(`#${wf.id}`) + ` ${wf.name}`);
|
|
22
18
|
log(" == States:");
|
|
23
19
|
wf.states.map(printWfState);
|
|
24
20
|
};
|
|
25
21
|
const printWfState = (state) => {
|
|
26
|
-
if (!state.name.match(new RegExp(
|
|
27
|
-
log(chalk.
|
|
22
|
+
if (!state.name.match(new RegExp(opts.search ?? "", "i"))) return;
|
|
23
|
+
log(chalk.bold(` #${state.id}`) + ` ${state.name}`);
|
|
28
24
|
log(` Type: \t${state.type}`);
|
|
29
25
|
log(` Stories:\t${state.num_stories}`);
|
|
30
26
|
};
|
|
31
27
|
main();
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
//#endregion
|
|
29
|
+
export {};
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
let commander = require("commander");
|
|
7
|
-
commander = require_rolldown_runtime.__toESM(commander);
|
|
8
|
-
|
|
2
|
+
import configure_default from "../lib/configure.js";
|
|
3
|
+
import stories_default from "../lib/stories.js";
|
|
4
|
+
import { program as program$1 } from "./short-search.js";
|
|
5
|
+
import { Command } from "commander";
|
|
9
6
|
//#region src/bin/short-workspace.ts
|
|
10
|
-
const config =
|
|
7
|
+
const config = configure_default.loadConfig();
|
|
11
8
|
const log = console.log;
|
|
12
|
-
const program
|
|
9
|
+
const program = new Command().description("List stories matching saved workspace query").argument("[name]").option("-l, --list", "List saved workspaces").option("-q, --quiet", "Print only workspace story output, no loading dialog", "").option("-n, --name [name]", "Load named workspace", "").option("-u, --unset [name]", "Force unset saved workspace").parse(process.argv);
|
|
10
|
+
const opts = program.opts();
|
|
11
|
+
const toArgs = (obj) => Object.entries(obj).map(([k, v]) => `--${k} '${v}'`).join(" ");
|
|
13
12
|
const main = async () => {
|
|
14
13
|
if (!config || !config.token) {
|
|
15
14
|
log("Not installed yet.");
|
|
@@ -21,19 +20,20 @@ const main = async () => {
|
|
|
21
20
|
log(" short search [options] --save");
|
|
22
21
|
log("to create your first one.");
|
|
23
22
|
return;
|
|
24
|
-
} else if (
|
|
23
|
+
} else if (opts.list) {
|
|
25
24
|
log("Workspaces:");
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
const workspaces = config.workspaces ?? {};
|
|
26
|
+
Object.keys(workspaces).forEach((w) => {
|
|
27
|
+
log(" ", w + ":", toArgs(workspaces[w] ?? {}));
|
|
28
28
|
});
|
|
29
29
|
return;
|
|
30
|
-
} else if (
|
|
31
|
-
if (
|
|
32
|
-
else log("Failed to remove %s workspace",
|
|
30
|
+
} else if (opts.unset) {
|
|
31
|
+
if (configure_default.removeWorkspace(opts.unset)) log("Successfully removed %s workspace", opts.unset);
|
|
32
|
+
else log("Failed to remove %s workspace", opts.unset);
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
35
|
-
const name = `${
|
|
36
|
-
const workspace = config.workspaces[name];
|
|
35
|
+
const name = `${opts.name || program.args[0] || "default"}`;
|
|
36
|
+
const workspace = config.workspaces?.[name];
|
|
37
37
|
if (!workspace) {
|
|
38
38
|
log("No workspace saved with name", name);
|
|
39
39
|
log("Please run:");
|
|
@@ -41,24 +41,23 @@ const main = async () => {
|
|
|
41
41
|
log("to create it.");
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
|
-
const
|
|
45
|
-
const additionalArgs =
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
if (!
|
|
44
|
+
const foundOpts = program$1.parse(process.argv).opts();
|
|
45
|
+
const additionalArgs = {
|
|
46
|
+
...workspace,
|
|
47
|
+
...Object.fromEntries(Object.entries(foundOpts).filter(([, v]) => v !== void 0 && v !== "" && v !== false))
|
|
48
|
+
};
|
|
49
|
+
if (!opts.quiet) {
|
|
50
50
|
log("Loading %s workspace ...", name);
|
|
51
51
|
log();
|
|
52
52
|
}
|
|
53
53
|
let stories = [];
|
|
54
54
|
try {
|
|
55
|
-
stories = await
|
|
55
|
+
stories = await stories_default.listStories(additionalArgs);
|
|
56
56
|
} catch (e) {
|
|
57
57
|
log("Error fetching stories:", e);
|
|
58
58
|
}
|
|
59
|
-
stories.map(
|
|
59
|
+
stories.map(stories_default.printFormattedStory(additionalArgs));
|
|
60
60
|
};
|
|
61
61
|
main();
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
//#endregion
|
|
62
|
+
//#endregion
|
|
63
|
+
export {};
|
package/build/bin/short.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
let commander = require("commander");
|
|
5
|
-
commander = require_rolldown_runtime.__toESM(commander);
|
|
6
|
-
|
|
2
|
+
import { description, version } from "../package.js";
|
|
3
|
+
import { Command } from "commander";
|
|
7
4
|
//#region src/bin/short.ts
|
|
8
5
|
process.on("unhandledRejection", console.log);
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
new Command().version(version).description(description).command("install [options]", "install and configure API access").command("search [options] [SEARCH OPERATORS]", "search stories with optional query").alias("s").command("find [options] [SEARCH OPERATORS]", "[DEPRECATED] search stories with optional query").command("story [ID|command] [options]", "view or manipulate stories").alias("st").command("create [options]", "create a story").alias("c").command("members [options]", "list members").alias("m").command("teams [options]", "list teams").command("team [command] [options]", "view a team or list its stories").command("labels [options]", "list labels").command("label [command] [options]", "view stories for a label").command("custom-fields [options]", "list custom fields").command("custom-field <id> [options]", "view a custom field").command("workflows [options]", "list workflows and their states").alias("wf").command("epics [options]", "list epics and their states").alias("e").command("epic [command] [options]", "create, view, or update an epic").command("objectives [options]", "list objectives and their states").alias("o").command("objective [command] [options]", "view, create, or update objectives").command("iterations [options]", "list iterations").alias("i").command("iteration [command] [options]", "view, create, update, or delete an iteration").command("docs [options]", "list and search docs").alias("d").command("doc [command] [options]", "view, create, or update a doc").command("projects [options]", "list projects and their states").alias("p").command("workspace [NAME] [options]", "list stories matching saved workspace query", { isDefault: true }).alias("w").command("api <path> [options]", "make a request to the Shortcut API").parse(process.argv);
|
|
7
|
+
//#endregion
|
|
8
|
+
export {};
|
package/build/lib/client.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const require_lib_configure = require('./configure.js');
|
|
4
|
-
let __shortcut_client = require("@shortcut/client");
|
|
5
|
-
|
|
1
|
+
import { loadConfig } from "./configure.js";
|
|
2
|
+
import { ShortcutClient } from "@shortcut/client";
|
|
6
3
|
//#region src/lib/client.ts
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
const config = loadConfig();
|
|
5
|
+
const clientConfig = {};
|
|
6
|
+
if (process.env.SHORTCUT_API_BASE_URL) clientConfig.baseURL = process.env.SHORTCUT_API_BASE_URL;
|
|
7
|
+
const client = new ShortcutClient(config.token ?? "", clientConfig);
|
|
10
8
|
//#endregion
|
|
11
|
-
|
|
9
|
+
export { client as default };
|
package/build/lib/configure.js
CHANGED
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
path = require_rolldown_runtime.__toESM(path);
|
|
5
|
-
let fs = require("fs");
|
|
6
|
-
fs = require_rolldown_runtime.__toESM(fs);
|
|
7
|
-
let os = require("os");
|
|
8
|
-
os = require_rolldown_runtime.__toESM(os);
|
|
9
|
-
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import os from "os";
|
|
3
|
+
import path from "path";
|
|
10
4
|
//#region src/lib/configure.ts
|
|
11
5
|
function getConfigDir(suffix) {
|
|
12
|
-
const configBaseDir = process.env.XDG_CONFIG_HOME || path.
|
|
13
|
-
return path.
|
|
6
|
+
const configBaseDir = process.env.XDG_CONFIG_HOME || path.resolve(process.env.XDG_DATA_HOME || os.homedir(), ".config");
|
|
7
|
+
return path.resolve(configBaseDir, suffix);
|
|
14
8
|
}
|
|
15
9
|
const configDir = getConfigDir("shortcut-cli");
|
|
16
|
-
const configFile = path.
|
|
17
|
-
const legacyConfigDirs = [getConfigDir("clubhouse-cli"), path.
|
|
10
|
+
const configFile = path.resolve(configDir, "config.json");
|
|
11
|
+
const legacyConfigDirs = [getConfigDir("clubhouse-cli"), path.resolve(os.homedir(), ".clubhouse-cli")];
|
|
18
12
|
let CONFIG_CACHE = null;
|
|
19
13
|
/**
|
|
20
14
|
* Config load function to be used in most-cases.
|
|
21
15
|
*/
|
|
22
16
|
const loadConfig = () => {
|
|
23
17
|
const config = loadCachedConfig();
|
|
24
|
-
if (!config ||
|
|
18
|
+
if (!config || !config.token) {
|
|
25
19
|
console.error("Please run 'short install' to configure Shortcut API access or set SHORTCUT_API_TOKEN.");
|
|
26
20
|
process.exit(11);
|
|
27
21
|
}
|
|
@@ -49,13 +43,14 @@ const loadCachedConfig = () => {
|
|
|
49
43
|
let config = {};
|
|
50
44
|
const token = process.env.SHORTCUT_API_TOKEN || process.env.CLUBHOUSE_API_TOKEN;
|
|
51
45
|
legacyConfigDirs.forEach((dir) => {
|
|
52
|
-
if (fs.
|
|
46
|
+
if (fs.existsSync(dir)) {
|
|
53
47
|
createConfigDir();
|
|
54
|
-
fs.
|
|
48
|
+
fs.renameSync(dir, configDir);
|
|
55
49
|
}
|
|
56
50
|
});
|
|
57
|
-
if (fs.
|
|
58
|
-
|
|
51
|
+
if (fs.existsSync(configFile)) try {
|
|
52
|
+
const rawConfig = fs.readFileSync(configFile, "utf8").trim();
|
|
53
|
+
config = rawConfig ? JSON.parse(rawConfig) : {};
|
|
59
54
|
} catch (e) {
|
|
60
55
|
console.error(e);
|
|
61
56
|
process.exit(10);
|
|
@@ -69,14 +64,14 @@ const loadCachedConfig = () => {
|
|
|
69
64
|
return config;
|
|
70
65
|
};
|
|
71
66
|
const createConfigDir = () => {
|
|
72
|
-
const dir = path.
|
|
73
|
-
if (!fs.
|
|
74
|
-
if (!fs.
|
|
67
|
+
const dir = path.dirname(configDir);
|
|
68
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir);
|
|
69
|
+
if (!fs.existsSync(configDir)) fs.mkdirSync(configDir);
|
|
75
70
|
};
|
|
76
71
|
const saveConfig = (config) => {
|
|
77
72
|
try {
|
|
78
73
|
createConfigDir();
|
|
79
|
-
fs.
|
|
74
|
+
fs.writeFileSync(configFile, JSON.stringify(config), { flag: "w" });
|
|
80
75
|
CONFIG_CACHE = { ...config };
|
|
81
76
|
return true;
|
|
82
77
|
} catch (e) {
|
|
@@ -93,7 +88,7 @@ const updateConfig = (newConfig) => {
|
|
|
93
88
|
};
|
|
94
89
|
const saveWorkspace = (name, workspace) => {
|
|
95
90
|
const extantConfig = loadCachedConfig();
|
|
96
|
-
const workspaces = extantConfig.workspaces
|
|
91
|
+
const workspaces = extantConfig.workspaces ?? {};
|
|
97
92
|
workspaces[name] = workspace;
|
|
98
93
|
return saveConfig({
|
|
99
94
|
workspaces,
|
|
@@ -102,7 +97,7 @@ const saveWorkspace = (name, workspace) => {
|
|
|
102
97
|
};
|
|
103
98
|
const removeWorkspace = (name) => {
|
|
104
99
|
const extant = loadCachedConfig();
|
|
105
|
-
delete extant.workspaces[name];
|
|
100
|
+
delete extant.workspaces?.[name];
|
|
106
101
|
return saveConfig(Object.assign({}, extant));
|
|
107
102
|
};
|
|
108
103
|
var configure_default = {
|
|
@@ -111,9 +106,5 @@ var configure_default = {
|
|
|
111
106
|
saveWorkspace,
|
|
112
107
|
removeWorkspace
|
|
113
108
|
};
|
|
114
|
-
|
|
115
109
|
//#endregion
|
|
116
|
-
|
|
117
|
-
exports.loadCachedConfig = loadCachedConfig;
|
|
118
|
-
exports.loadConfig = loadConfig;
|
|
119
|
-
exports.updateConfig = updateConfig;
|
|
110
|
+
export { configure_default as default, loadCachedConfig, loadConfig, updateConfig };
|
package/build/lib/spinner.js
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
const require_rolldown_runtime = require('../_virtual/rolldown_runtime.js');
|
|
3
|
-
let cli_spinner = require("cli-spinner");
|
|
4
|
-
|
|
1
|
+
import { Spinner } from "cli-spinner";
|
|
5
2
|
//#region src/lib/spinner.ts
|
|
6
3
|
const spinner = (text = "") => {
|
|
7
|
-
const spin = new
|
|
4
|
+
const spin = new Spinner({
|
|
8
5
|
text: text ? text : "Loading... %s ",
|
|
9
6
|
stream: process.stderr
|
|
10
7
|
});
|
|
11
8
|
spin.setSpinnerString(27);
|
|
12
9
|
return spin;
|
|
13
10
|
};
|
|
14
|
-
var spinner_default = spinner;
|
|
15
|
-
|
|
16
11
|
//#endregion
|
|
17
|
-
|
|
12
|
+
export { spinner as default };
|