@shortcut-cli/shortcut-cli 3.2.4 → 3.4.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.
@@ -1,369 +1,742 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5
- return new (P || (P = Promise))(function (resolve, reject) {
6
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
8
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
9
- step((generator = generator.apply(thisArg, _arguments || [])).next());
10
- });
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
11
15
  };
12
- var __generator = (this && this.__generator) || function (thisArg, body) {
13
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
14
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
15
- function verb(n) { return function (v) { return step([n, v]); }; }
16
- function step(op) {
17
- if (f) throw new TypeError("Generator is already executing.");
18
- while (_) try {
19
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
20
- if (y = 0, t) op = [op[0] & 2, t.value];
21
- switch (op[0]) {
22
- case 0: case 1: t = op; break;
23
- case 4: _.label++; return { value: op[1], done: false };
24
- case 5: _.label++; y = op[1]; op = [0]; continue;
25
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
26
- default:
27
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
28
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
29
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
30
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
31
- if (t[2]) _.ops.pop();
32
- _.trys.pop(); continue;
33
- }
34
- op = body.call(thisArg, _);
35
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
36
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+
25
+ // src/bin/short-story.ts
26
+ var import_child_process2 = require("child_process");
27
+ var import_os2 = __toESM(require("os"));
28
+ var import_path2 = __toESM(require("path"));
29
+ var import_fs2 = __toESM(require("fs"));
30
+ var import_https = __toESM(require("https"));
31
+ var import_commander = __toESM(require("commander"));
32
+ var import_chalk2 = __toESM(require("chalk"));
33
+ var import_debug2 = __toESM(require("debug"));
34
+
35
+ // src/lib/client.ts
36
+ var import_client = require("@shortcut/client");
37
+
38
+ // src/lib/configure.ts
39
+ var import_path = __toESM(require("path"));
40
+ var import_fs = __toESM(require("fs"));
41
+ var import_os = __toESM(require("os"));
42
+ function getConfigDir(suffix) {
43
+ const configBaseDir = process.env.XDG_CONFIG_HOME || import_path.default.resolve(process.env.XDG_DATA_HOME || import_os.default.homedir(), ".config");
44
+ return import_path.default.resolve(configBaseDir, suffix);
45
+ }
46
+ var configDir = getConfigDir("shortcut-cli");
47
+ var configFile = import_path.default.resolve(configDir, "config.json");
48
+ var legacyConfigDirs = [
49
+ getConfigDir("clubhouse-cli"),
50
+ import_path.default.resolve(import_os.default.homedir(), ".clubhouse-cli")
51
+ ];
52
+ var CONFIG_CACHE = null;
53
+ var loadConfig = () => {
54
+ const config4 = loadCachedConfig();
55
+ if (!config4 || config4 === {} || !config4.token) {
56
+ console.error("Please run 'short install' to configure Shortcut API access.");
57
+ process.exit(11);
58
+ }
59
+ if (!config4.urlSlug) {
60
+ console.error(
61
+ "Your config must be updated with data from Shortcut. Please run 'short install --refresh'."
62
+ );
63
+ process.exit(12);
64
+ }
65
+ return config4;
66
+ };
67
+ var loadCachedConfig = () => {
68
+ if (CONFIG_CACHE) {
69
+ return { ...CONFIG_CACHE };
70
+ }
71
+ let config4 = {};
72
+ const token = process.env.SHORTCUT_API_TOKEN || process.env.CLUBHOUSE_API_TOKEN;
73
+ legacyConfigDirs.forEach((dir) => {
74
+ if (import_fs.default.existsSync(dir)) {
75
+ createConfigDir();
76
+ import_fs.default.renameSync(dir, configDir);
77
+ }
78
+ });
79
+ if (import_fs.default.existsSync(configFile)) {
80
+ try {
81
+ config4 = JSON.parse(import_fs.default.readFileSync(configFile, "utf8"));
82
+ } catch (e) {
83
+ console.error(e);
84
+ process.exit(10);
37
85
  }
86
+ }
87
+ if (token) {
88
+ config4 = { token, ...config4 };
89
+ }
90
+ CONFIG_CACHE = { ...config4 };
91
+ return config4;
38
92
  };
39
- Object.defineProperty(exports, "__esModule", { value: true });
40
- var child_process_1 = require("child_process");
41
- var commander = require("commander");
42
- var os = require("os");
43
- var path = require("path");
44
- var fs = require("fs");
45
- var https = require("https");
46
- var chalk_1 = require("chalk");
47
- var configure_1 = require("../lib/configure");
48
- var debug_1 = require("debug");
49
- var client_1 = require("../lib/client");
50
- var stories_1 = require("../lib/stories");
51
- var spinner_1 = require("../lib/spinner");
52
- var config = (0, configure_1.loadConfig)();
53
- var spin = (0, spinner_1.default)();
93
+ var createConfigDir = () => {
94
+ const dir = import_path.default.dirname(configDir);
95
+ if (!import_fs.default.existsSync(dir)) {
96
+ import_fs.default.mkdirSync(dir);
97
+ }
98
+ if (!import_fs.default.existsSync(configDir)) {
99
+ import_fs.default.mkdirSync(configDir);
100
+ }
101
+ };
102
+
103
+ // src/lib/client.ts
104
+ var config = loadConfig();
105
+ var client = new import_client.ShortcutClient(config.token);
106
+ var client_default = client;
107
+
108
+ // src/lib/stories.ts
109
+ var import_child_process = require("child_process");
110
+ var import_chalk = __toESM(require("chalk"));
111
+ var import_debug = __toESM(require("debug"));
112
+ var debug = (0, import_debug.default)("club");
113
+ var config2 = loadConfig();
54
114
  var log = console.log;
55
- var logError = console.error;
56
- var debug = (0, debug_1.default)('short');
57
- var program = commander
58
- .usage('[options] <id>')
59
- .description('Update and/or display story details')
60
- .option('-a, --archived', 'Update story as archived')
61
- .option('-c, --comment [text]', 'Add comment to story', '')
62
- .option('-d, --description [text]', 'Update description of story', '')
63
- .option('-D, --download', 'Download all attached files', '')
64
- .option('--download-dir [path]', 'Directory to download files to', '.')
65
- .option('-e, --estimate [number]', 'Update estimate of story', '')
66
- .option('--epic [id|name]', 'Set epic of story')
67
- .option('-i, --iteration [id|name]', 'Set iteration of story')
68
- .option('-f, --format [template]', 'Format the story output by template', '')
69
- .option('--from-git', 'Fetch story parsed by ID from current git branch')
70
- .option('--git-branch', 'Checkout git branch from story slug <mention-name>/ch<id>/<type>-<title>\n' +
71
- '\t\t\t\tas required by the Git integration: https://bit.ly/2RKO1FF')
72
- .option('--git-branch-short', 'Checkout git branch from story slug <mention-name>/ch<id>/<title>')
73
- .option('-I, --idonly', 'Print only ID of story results', '')
74
- .option('-l, --label [id|name]', 'Stories with label id/name, by regex', '')
75
- .option('--move-after [id]', 'Move story to position below story ID')
76
- .option('--move-before [id]', 'Move story to position above story ID')
77
- .option('--move-down [n]', 'Move story position downward by n stories')
78
- .option('--move-up [n]', 'Move story position upward by n stories')
79
- .option('-o, --owners [id|name]', 'Update owners of story, comma-separated', '')
80
- .option('-O, --open', 'Open story in browser')
81
- .option('--oe, --open-epic', "Open story's epic in browser")
82
- .option('--oi, --open-iteration', "Open story's iteration in browser")
83
- .option('--op, --open-project', "Open story's project in browser")
84
- .option('-q, --quiet', 'Print only story output, no loading dialog', '')
85
- .option('-s, --state [id|name]', 'Update workflow state of story', '')
86
- .option('-t, --title [text]', 'Update title/name of story', '')
87
- .option('--task [text]', 'Create new task on story')
88
- .option('--task-complete [text]', 'Toggle completion of task on story matching text')
89
- .option('-y, --type [name]', 'Update type of story', '')
90
- .parse(process.argv);
91
- var main = function () { return __awaiter(void 0, void 0, void 0, function () {
92
- var entities, update, typeMatch_1, hasPositionUpdate, hasUpdate, gitID, branch, id, argIDs;
93
- return __generator(this, function (_a) {
94
- switch (_a.label) {
95
- case 0: return [4, stories_1.default.fetchEntities()];
96
- case 1:
97
- entities = _a.sent();
98
- if (!(program.idonly || program.quiet))
99
- spin.start();
100
- debug('constructing story update');
101
- update = {};
102
- if (program.archived) {
103
- update.archived = true;
104
- }
105
- if (program.state) {
106
- update.workflow_state_id = (stories_1.default.findState(entities, program.state) || {}).id;
107
- }
108
- if (program.estimate) {
109
- update.estimate = parseInt(program.estimate, 10);
110
- }
111
- if (program.title) {
112
- update.name = program.title;
113
- }
114
- if (program.description) {
115
- update.description = "" + program.description;
116
- }
117
- if (program.type) {
118
- typeMatch_1 = new RegExp(program.type, 'i');
119
- update.story_type = ['feature', 'bug', 'chore'].filter(function (t) { return !!t.match(typeMatch_1); })[0];
120
- }
121
- if (program.owners) {
122
- update.owner_ids = stories_1.default.findOwnerIds(entities, program.owners);
123
- }
124
- if (program.epic) {
125
- update.epic_id = (stories_1.default.findEpic(entities, program.epic) || {}).id;
126
- }
127
- if (program.iteration) {
128
- update.iteration_id = (stories_1.default.findIteration(entities, program.iteration) || {}).id;
129
- }
130
- if (program.label) {
131
- update.labels = stories_1.default.findLabelNames(entities, program.label);
132
- }
133
- hasPositionUpdate = program.moveAfter !== undefined ||
134
- program.moveBefore !== undefined ||
135
- program.moveDown !== undefined ||
136
- program.moveUp !== undefined;
137
- hasUpdate = Object.keys(update).length > 0 || hasPositionUpdate;
138
- debug('constructed story update', update);
139
- gitID = [];
140
- if (program.fromGit || !program.args.length) {
141
- debug('fetching story ID from git');
142
- branch = '';
143
- try {
144
- branch = (0, child_process_1.execSync)('git branch').toString('utf-8');
145
- }
146
- catch (e) {
147
- debug(e);
148
- }
149
- if (branch.match(/\*.*[0-9]+/)) {
150
- debug('parsing story ID from git branch:', branch);
151
- id = parseInt(branch.match(/\*.*/)[0].match(/\/(ch|sc-)([0-9]+)/)[2], 10);
152
- debug('parsed story ID from git branch:', id);
153
- if (id) {
154
- gitID.push(id.toString());
155
- }
156
- }
157
- else {
158
- stopSpinner();
159
- logError('No story ID argument present or found in git branch');
160
- process.exit(2);
161
- }
162
- }
163
- argIDs = program.args.map(function (a) { return (a.match(/\d+/) || [])[0]; });
164
- argIDs.concat(gitID).map(function (_id) { return __awaiter(void 0, void 0, void 0, function () {
165
- var id, story, e_1, e_2, e_3, descMatch_1, tasks, updatedTaskIds_1, e_4, siblings, siblingIds, storyIndex, changed, e_5;
166
- return __generator(this, function (_a) {
167
- switch (_a.label) {
168
- case 0:
169
- id = parseInt(_id, 10);
170
- _a.label = 1;
171
- case 1:
172
- _a.trys.push([1, 4, , 5]);
173
- if (!program.comment) return [3, 3];
174
- debug('request comment create');
175
- return [4, client_1.default.createStoryComment(id, program.comment)];
176
- case 2:
177
- _a.sent();
178
- debug('response comment create');
179
- _a.label = 3;
180
- case 3: return [3, 5];
181
- case 4:
182
- e_1 = _a.sent();
183
- stopSpinner();
184
- log('Error creating comment', id);
185
- process.exit(3);
186
- return [3, 5];
187
- case 5:
188
- _a.trys.push([5, 8, , 9]);
189
- if (!program.task) return [3, 7];
190
- debug('request task create');
191
- return [4, client_1.default.createTask(id, { description: program.task })];
192
- case 6:
193
- _a.sent();
194
- debug('response task create');
195
- _a.label = 7;
196
- case 7: return [3, 9];
197
- case 8:
198
- e_2 = _a.sent();
199
- stopSpinner();
200
- log('Error creating task', id);
201
- process.exit(3);
202
- return [3, 9];
203
- case 9:
204
- _a.trys.push([9, 11, , 12]);
205
- debug('request story');
206
- return [4, client_1.default.getStory(id).then(function (r) { return r.data; })];
207
- case 10:
208
- story = _a.sent();
209
- debug('response story');
210
- return [3, 12];
211
- case 11:
212
- e_3 = _a.sent();
213
- stopSpinner();
214
- logError('Error fetching story', id);
215
- process.exit(4);
216
- return [3, 12];
217
- case 12:
218
- _a.trys.push([12, 15, , 16]);
219
- if (!program.taskComplete) return [3, 14];
220
- debug('calculating task(s) to complete');
221
- descMatch_1 = new RegExp(program.taskComplete, 'i');
222
- tasks = story.tasks.filter(function (t) { return t.description.match(descMatch_1); });
223
- updatedTaskIds_1 = tasks.map(function (t) { return t.id; });
224
- debug('request tasks complete', updatedTaskIds_1);
225
- return [4, Promise.all(tasks.map(function (t) { return client_1.default.updateTask(id, t.id, { complete: !t.complete }); }))];
226
- case 13:
227
- _a.sent();
228
- debug('response tasks complete');
229
- story.tasks = story.tasks.map(function (t) {
230
- if (updatedTaskIds_1.indexOf(t.id) > -1)
231
- t.complete = !t.complete;
232
- return t;
233
- });
234
- _a.label = 14;
235
- case 14: return [3, 16];
236
- case 15:
237
- e_4 = _a.sent();
238
- stopSpinner();
239
- log('Error updating tasks', e_4);
240
- process.exit(3);
241
- return [3, 16];
242
- case 16:
243
- _a.trys.push([16, 21, , 22]);
244
- if (!hasUpdate) return [3, 20];
245
- if (!hasPositionUpdate) return [3, 18];
246
- debug('calculating move up/down');
247
- return [4, stories_1.default.listStories({
248
- state: story.workflow_state_id.toString(),
249
- sort: 'state.position:asc,position:asc',
250
- })];
251
- case 17:
252
- siblings = _a.sent();
253
- siblingIds = siblings.map(function (s) { return s.id; });
254
- storyIndex = siblingIds.indexOf(~~id);
255
- if (program.moveAfter) {
256
- update.after_id = ~~program.moveAfter;
257
- }
258
- else if (program.moveBefore) {
259
- update.before_id = ~~program.moveBefore;
260
- }
261
- else if (program.moveUp) {
262
- update.before_id =
263
- siblingIds[Math.max(0, storyIndex - (~~program.moveUp || 1))];
264
- }
265
- else if (program.moveDown) {
266
- update.after_id =
267
- siblingIds[Math.min(siblings.length - 1, storyIndex + (~~program.moveDown || 1))];
268
- }
269
- debug('constructed story position update', update);
270
- _a.label = 18;
271
- case 18:
272
- debug('request story update');
273
- return [4, client_1.default.updateStory(id, update)];
274
- case 19:
275
- changed = _a.sent();
276
- debug('response story update');
277
- story = Object.assign({}, story, changed);
278
- _a.label = 20;
279
- case 20: return [3, 22];
280
- case 21:
281
- e_5 = _a.sent();
282
- stopSpinner();
283
- logError('Error updating story', id);
284
- process.exit(5);
285
- return [3, 22];
286
- case 22:
287
- if (story) {
288
- story = stories_1.default.hydrateStory(entities, story);
289
- }
290
- if (!program.idonly)
291
- spin.stop(true);
292
- if (story) {
293
- printStory(story, entities);
294
- if (program.open) {
295
- openURL(stories_1.default.storyURL(story));
296
- }
297
- if (program.openEpic) {
298
- if (!story.epic_id) {
299
- logError('This story is not part of an epic.');
300
- process.exit(21);
301
- }
302
- openURL(stories_1.default.buildURL('epic', story.epic_id));
303
- }
304
- if (program.openIteration) {
305
- if (!story.iteration_id) {
306
- logError('This story is not part of an iteration.');
307
- process.exit(22);
308
- }
309
- openURL(stories_1.default.buildURL('iteration', story.iteration_id));
310
- }
311
- if (program.openProject) {
312
- openURL(stories_1.default.buildURL('project', story.project_id));
313
- }
314
- }
315
- if (program.download) {
316
- downloadFiles(story);
317
- }
318
- if (story && program.gitBranch) {
319
- if (!config.mentionName) {
320
- stopSpinner();
321
- stories_1.default.checkoutStoryBranch(story, story.story_type + "-" + story.id + "-");
322
- logError('Error creating story branch in Shortcut format');
323
- logError('Please run: "short install --force" to add your mention name to the config.');
324
- process.exit(10);
325
- }
326
- stories_1.default.checkoutStoryBranch(story);
327
- }
328
- else if (story && program.gitBranchShort) {
329
- stories_1.default.checkoutStoryBranch(story, config.mentionName + "/sc-" + story.id + "/");
330
- }
331
- return [2];
332
- }
333
- });
334
- }); });
335
- stopSpinner();
336
- return [2];
337
- }
338
- });
339
- }); };
340
- var openURL = function (url) {
341
- var open = os.platform() === 'darwin' ? 'open' : 'xdg-open';
342
- (0, child_process_1.execSync)(open + " '" + url + "'");
115
+ async function fetchEntities() {
116
+ const [projectsById, statesById, membersById, groupsById, epicsById, iterationsById, labels] = await Promise.all([
117
+ client_default.listProjects().then((r) => r.data).then(mapByItemId),
118
+ client_default.listWorkflows().then((r) => r.data).then((wfs) => wfs.reduce((states, wf) => states.concat(wf.states), [])).then(mapByItemId),
119
+ client_default.listMembers(null).then((r) => r.data).then(mapByItemStringId),
120
+ client_default.listGroups().then((r) => r.data).then(mapByItemStringId),
121
+ client_default.listEpics(null).then((r) => r.data).then(mapByItemId),
122
+ client_default.listIterations(null).then((r) => r.data).then(mapByItemId),
123
+ client_default.listLabels(null).then((r) => r.data)
124
+ ]).catch((err) => {
125
+ log(`Error fetching workflows: ${err}`);
126
+ process.exit(2);
127
+ });
128
+ debug("response workflows, members, groups, projects, epics, iterations");
129
+ return { projectsById, statesById, membersById, groupsById, epicsById, iterationsById, labels };
130
+ }
131
+ var listStories = async (program2) => {
132
+ debug("request workflows, members, projects, epics");
133
+ const entities = await fetchEntities();
134
+ const stories = await fetchStories(program2, entities);
135
+ debug("filtering stories");
136
+ return filterStories(program2, stories, entities).sort(sortStories(program2));
343
137
  };
344
- var stopSpinner = function () {
345
- if (!(program.idonly || program.quiet))
346
- spin.stop(true);
138
+ function mapByItemId(items) {
139
+ return items.reduce((map, obj) => map.set(obj.id, obj), /* @__PURE__ */ new Map());
140
+ }
141
+ function mapByItemStringId(items) {
142
+ return items.reduce((map, obj) => map.set(obj.id, obj), /* @__PURE__ */ new Map());
143
+ }
144
+ async function fetchStories(program2, entities) {
145
+ if ((program2.args || []).length) {
146
+ debug("using the search endpoint");
147
+ return searchStories(program2);
148
+ }
149
+ debug("filtering projects");
150
+ const regexProject = new RegExp(program2.project, "i");
151
+ const projectIds = [...entities.projectsById.values()].filter(
152
+ (p) => !!(p.id + p.name).match(regexProject)
153
+ );
154
+ debug("request all stories for project(s)", projectIds.map((p) => p.name).join(", "));
155
+ return Promise.all(projectIds.map((p) => client_default.listStories(p.id, null))).then(
156
+ (projectStories) => projectStories.reduce((acc, stories) => acc.concat(stories.data), [])
157
+ );
158
+ }
159
+ async function searchStories(program2) {
160
+ const query = program2.args.join(" ").replace("%self%", config2.mentionName);
161
+ let result = await client_default.searchStories({ query });
162
+ let stories = result.data.data.map(storySearchResultToStory);
163
+ while (result.data.next) {
164
+ const nextCursor = new URLSearchParams(result.data.next).get("next");
165
+ result = await client_default.searchStories({ query, next: nextCursor });
166
+ stories = stories.concat(result.data.data.map(storySearchResultToStory));
167
+ }
168
+ return stories;
169
+ }
170
+ var storySearchResultToStory = (storySearchResult) => {
171
+ return {
172
+ ...storySearchResult,
173
+ description: storySearchResult.description || "",
174
+ linked_files: storySearchResult.linked_files || [],
175
+ comments: storySearchResult.comments || [],
176
+ branches: storySearchResult.branches || [],
177
+ tasks: storySearchResult.tasks || [],
178
+ pull_requests: storySearchResult.pull_requests || [],
179
+ commits: storySearchResult.commits || [],
180
+ files: storySearchResult.files || []
181
+ };
347
182
  };
348
- var downloadFiles = function (story) {
349
- return story.files.map(function (file) {
350
- https.get(stories_1.default.fileURL(file), function (res) {
351
- var filePath = path.join(program.downloadDir, file.name);
352
- log(chalk_1.default.bold('Downloading file to: ') + filePath);
353
- var stream = fs.createWriteStream(filePath);
354
- res.pipe(stream);
355
- stream.on('finish', function () { return stream.close(); });
356
- });
357
- });
183
+ var hydrateStory = (entities, story) => {
184
+ debug("hydrating story");
185
+ const augmented = story;
186
+ augmented.project = entities.projectsById.get(story.project_id);
187
+ augmented.state = entities.statesById.get(story.workflow_state_id);
188
+ augmented.epic = entities.epicsById.get(story.epic_id);
189
+ augmented.iteration = entities.iterationsById.get(story.iteration_id);
190
+ augmented.owners = story.owner_ids.map((id) => entities.membersById.get(id));
191
+ augmented.requester = entities.membersById.get(story.requested_by_id);
192
+ augmented.group = entities.groupsById.get(story.group_id);
193
+ debug("hydrated story");
194
+ return augmented;
195
+ };
196
+ var isNumber = (val) => !!(val || val === 0) && !isNaN(Number(val.toString()));
197
+ var findEntity = (entities, id) => {
198
+ if (entities.get(id)) {
199
+ return entities.get(id);
200
+ }
201
+ if (isNumber(id) && Number(id.toString())) {
202
+ return entities.get(Number(id.toString()));
203
+ }
204
+ const match = new RegExp(`${id}`, "i");
205
+ return Object.values(entities).filter((s) => !!s.name.match(match))[0];
358
206
  };
359
- var printStory = function (story, entities) {
360
- if (program.idonly) {
361
- return log(story.id);
207
+ var findProject = (entities, project) => findEntity(entities.projectsById, project);
208
+ var findGroup = (entities, group) => findEntity(entities.groupsById, group);
209
+ var findState = (entities, state) => findEntity(entities.statesById, state);
210
+ var findEpic = (entities, epicName) => findEntity(entities.epicsById, epicName);
211
+ var findIteration = (entities, iterationName) => findEntity(entities.statesById, iterationName);
212
+ var findOwnerIds = (entities, owners) => {
213
+ const ownerMatch = new RegExp(owners.split(",").join("|"), "i");
214
+ return Object.values(entities.membersById).filter((m) => !!`${m.id} ${m.profile.name} ${m.profile.mention_name}`.match(ownerMatch)).map((m) => m.id);
215
+ };
216
+ var findLabelNames = (entities, label) => {
217
+ const labelMatch = new RegExp(label.split(",").join("|"), "i");
218
+ return entities.labels.filter((m) => !!`${m.id} ${m.name}`.match(labelMatch)).map((m) => ({ name: m.name }));
219
+ };
220
+ var filterStories = (program2, stories, entities) => {
221
+ let created_at;
222
+ if (program2.created) {
223
+ created_at = parseDateComparator(program2.created);
224
+ }
225
+ let updated_at;
226
+ if (program2.updated) {
227
+ updated_at = parseDateComparator(program2.updated);
228
+ }
229
+ let estimate;
230
+ if (program2.estimate) {
231
+ estimate = parseNumberComparator(program2.estimate);
232
+ }
233
+ const regexLabel = new RegExp(program2.label, "i");
234
+ const regexState = new RegExp(program2.state, "i");
235
+ const regexOwner = new RegExp(program2.owner, "i");
236
+ const regexText = new RegExp(program2.text, "i");
237
+ const regexType = new RegExp(program2.type, "i");
238
+ const regexEpic = new RegExp(program2.epic, "i");
239
+ const regexIteration = new RegExp(program2.iteration, "i");
240
+ return stories.map((story) => hydrateStory(entities, story)).filter((s) => {
241
+ if (!program2.archived && s.archived) {
242
+ return false;
243
+ }
244
+ if (!(s.labels.map((l) => `${l.id},${l.name}`).join(",") + "").match(regexLabel)) {
245
+ return false;
246
+ }
247
+ if (!(s.workflow_state_id + " " + (s.state || {}).name).match(
248
+ regexState
249
+ )) {
250
+ return false;
251
+ }
252
+ if (!(s.epic_id + " " + (s.epic || {}).name).match(regexEpic)) {
253
+ return false;
254
+ }
255
+ if (!(s.iteration_id + " " + (s.iteration || {}).name).match(
256
+ regexIteration
257
+ )) {
258
+ return false;
362
259
  }
363
- if (program.format) {
364
- return stories_1.default.printFormattedStory(program)(story);
260
+ if (program2.owner) {
261
+ const owned = s.owners.filter((o) => {
262
+ return !!`${o.profile.name} ${o.profile.mention_name}`.match(regexOwner);
263
+ }).length > 0;
264
+ if (!owned) return false;
265
+ }
266
+ if (!s.name.match(regexText)) {
267
+ return false;
268
+ }
269
+ if (!s.story_type.match(regexType)) {
270
+ return false;
271
+ }
272
+ if (created_at && !created_at(s.created_at)) {
273
+ return false;
274
+ }
275
+ if (updated_at && !updated_at(s.updated_at)) {
276
+ return false;
277
+ }
278
+ return !(estimate && !estimate(s.estimate));
279
+ });
280
+ };
281
+ var sortStories = (program2) => {
282
+ const fields = (program2.sort || "").split(",").map((s) => {
283
+ return s.split(":").map((ss) => ss.split("."));
284
+ });
285
+ const pluck = (acc, val) => {
286
+ if (acc[val] === void 0) return {};
287
+ return acc[val];
288
+ };
289
+ debug("sorting stories");
290
+ return (a, b) => {
291
+ return fields.reduce((acc, field) => {
292
+ if (acc !== 0) return acc;
293
+ const ap = field[0].reduce(pluck, a);
294
+ const bp = field[0].reduce(pluck, b);
295
+ if (ap === bp) return 0;
296
+ const direction = (field[1] || [""])[0].match(/des/i) ? 1 : -1;
297
+ if (ap > bp) {
298
+ if (direction > 0) return -1;
299
+ } else {
300
+ if (direction < 0) return -1;
301
+ }
302
+ return 1;
303
+ }, 0);
304
+ };
305
+ };
306
+ var printFormattedStory = (program2) => {
307
+ return (story) => {
308
+ const defaultFormat = `#%id %t
309
+ Type: %y/%e
310
+ Team: %T
311
+ Project: %p
312
+ Epic: %epic
313
+ Iteration: %i
314
+ Requester: %r
315
+ Owners: %o
316
+ State: %s
317
+ Labels: %l
318
+ URL: %u
319
+ Created: %c
320
+ Updated: %updated
321
+ Archived: %a
322
+ `;
323
+ const format = program2.format || defaultFormat;
324
+ const labels = story.labels.map((l) => `${l.name} (#${l.id})`);
325
+ const owners = story.owners.map(
326
+ (o) => `${o.profile.name} (${o.profile.mention_name})`
327
+ );
328
+ const url = `https://app.shortcut.com/story/${story.id}`;
329
+ const project = story.project ? `${story.project.name} (#${story.project.id})` : "None";
330
+ log(
331
+ format.replace(/%j/, JSON.stringify({ ...story, url }, null, 2)).replace(/%id/, import_chalk.default.blue.bold(`${story.id}`)).replace(/%t/, import_chalk.default.blue(`${story.name}`)).replace(/%d/, story.description || "").replace(/%y/, story.story_type).replace(/%l/, labels.join(", ") || "_").replace(
332
+ /%epic/,
333
+ story.epic_id ? `${(story.epic || {}).name} (#${story.epic_id})` : "_"
334
+ ).replace(/%e/, `${story.estimate || "_"}`).replace(
335
+ /%i/,
336
+ story.iteration_id ? `${(story.iteration || {}).name} (#${story.iteration_id})` : "_"
337
+ ).replace(/%p/, project).replace(/%T/, story.group?.name || "_").replace(/%o/, owners.join(", ") || "_").replace(
338
+ /%r/,
339
+ // eslint-disable-next-line no-constant-binary-expression
340
+ `${story.requester.profile.name} (${story.requester.profile.mention_name})` || "_"
341
+ ).replace(
342
+ /%s/,
343
+ `${(story.state || {}).name} (#${story.workflow_state_id})`
344
+ ).replace(/%c/, `${story.created_at}`).replace(
345
+ /%updated/,
346
+ `${story.updated_at !== story.created_at ? story.updated_at : "_"}`
347
+ ).replace(/%u/, url).replace(/%a/, `${story.archived}`).replace(
348
+ /%gbs/,
349
+ `${buildStoryBranch(story, `${config2.mentionName}/sc-${story.id}/`)}`
350
+ ).replace(/%gb/, `${buildStoryBranch(story)}`)
351
+ );
352
+ return story;
353
+ };
354
+ };
355
+ var buildURL = (...segments) => {
356
+ return [
357
+ "https://app.shortcut.com",
358
+ config2.urlSlug,
359
+ ...segments.map((item) => item.toString())
360
+ ].join("/");
361
+ };
362
+ var storyURL = (story) => buildURL("story", story.id);
363
+ var printDetailedStory = (story, entities = {}) => {
364
+ const labels = story.labels.map((l) => {
365
+ return import_chalk.default.bold(`#${l.id}`) + ` ${l.name}`;
366
+ });
367
+ const owners = story.owners.map((o) => {
368
+ const mentionName = import_chalk.default.bold(`${o.profile.mention_name}`);
369
+ return `${o.profile.name} (${mentionName})`;
370
+ });
371
+ log(import_chalk.default.blue.bold(`#${story.id}`) + import_chalk.default.blue(` ${story.name}`));
372
+ log(import_chalk.default.bold("Desc:") + ` ${formatLong(story.description || "_")}`);
373
+ log(import_chalk.default.bold("Team:") + ` ${story.group?.name || "_"}`);
374
+ log(import_chalk.default.bold("Owners:") + ` ${owners.join(", ") || "_"}`);
375
+ log(
376
+ import_chalk.default.bold("Requester:") + ` ${story.requester.profile.name} (${story.requester.profile.mention_name})`
377
+ );
378
+ log(import_chalk.default.bold("Type:") + ` ${story.story_type}/${story.estimate || "_"}`);
379
+ log(import_chalk.default.bold("Label:") + ` ${labels.join(", ") || "_"}`);
380
+ if (story.project) {
381
+ log(import_chalk.default.bold("Project:") + import_chalk.default.bold(` #${story.project_id} `) + story.project.name);
382
+ }
383
+ if (story.group) {
384
+ log(import_chalk.default.bold("Team:") + import_chalk.default.bold(` #${story.group_id} `) + story.group.name);
385
+ }
386
+ if (story.epic) {
387
+ log(import_chalk.default.bold("Epic:") + import_chalk.default.bold(` #${story.epic_id} `) + story.epic.name);
388
+ } else {
389
+ log(import_chalk.default.bold("Epic:") + " _");
390
+ }
391
+ if (story.iteration) {
392
+ log(
393
+ import_chalk.default.bold("Iteration:") + import_chalk.default.bold(` #${story.iteration_id} `) + story.iteration.name
394
+ );
395
+ } else {
396
+ log(import_chalk.default.bold("Iteration:") + " _");
397
+ }
398
+ log(import_chalk.default.bold("State:") + import_chalk.default.bold(` #${story.workflow_state_id} `) + story.state.name);
399
+ log(import_chalk.default.bold("Created:") + ` ${story.created_at}`);
400
+ if (story.created_at !== story.updated_at) {
401
+ log(import_chalk.default.bold("Updated:") + ` ${story.updated_at}`);
402
+ }
403
+ log(import_chalk.default.bold("URL:") + ` ${storyURL(story)}`);
404
+ if (story.archived) {
405
+ log(import_chalk.default.bold("Archived: ") + import_chalk.default.bold(`${story.archived}`));
406
+ }
407
+ if (story.completed) {
408
+ log(import_chalk.default.bold("Completed: ") + import_chalk.default.bold(`${story.completed_at}`));
409
+ }
410
+ story.tasks.map((c) => {
411
+ log(
412
+ import_chalk.default.bold("Task: ") + (c.complete ? "[X]" : "[ ]") + " " + formatLong(c.description)
413
+ );
414
+ return c;
415
+ });
416
+ story.comments.filter((comment) => !comment.deleted).map((c) => {
417
+ const author = entities.membersById.get(c.author_id);
418
+ log(import_chalk.default.bold("Comment:") + ` ${formatLong(c.text)}`);
419
+ log(` ${author.profile.name} ` + import_chalk.default.bold("at:") + ` ${c.updated_at}`);
420
+ return c;
421
+ });
422
+ story.files.map((file) => {
423
+ log(import_chalk.default.bold("File:") + ` ${file.name}`);
424
+ log(` ${file.url}`);
425
+ return file;
426
+ });
427
+ log();
428
+ };
429
+ var formatLong = (str) => str.split("\n").join("\n ");
430
+ var parseDateComparator = (arg) => {
431
+ const match = arg.match(/[0-9].*/) || { index: 0, "0": { length: 30 } };
432
+ const parsedDate = new Date(arg.slice(match.index));
433
+ const comparator = arg.slice(0, match.index);
434
+ return (date) => {
435
+ switch (comparator) {
436
+ case "<":
437
+ return new Date(date) < parsedDate;
438
+ case ">":
439
+ return new Date(date) > parsedDate;
440
+ case "=":
441
+ default:
442
+ return new Date(date.slice(0, match[0].length)).getTime() === parsedDate.getTime();
443
+ }
444
+ };
445
+ };
446
+ var parseNumberComparator = (arg) => {
447
+ const match = arg.match(/[0-9].*/) || { index: 0, "0": { length: 30 } };
448
+ const parsedNumber = Number(arg.slice(match.index));
449
+ const comparator = arg.slice(0, match.index).trimRight();
450
+ return (n) => {
451
+ switch (comparator) {
452
+ case "<":
453
+ return Number(n) < parsedNumber;
454
+ case ">":
455
+ return Number(n) > parsedNumber;
456
+ case "=":
457
+ default:
458
+ return Number(n) === parsedNumber;
365
459
  }
366
- stories_1.default.printDetailedStory(story, entities);
460
+ };
461
+ };
462
+ var buildStoryBranch = (story, prefix = "") => {
463
+ prefix = prefix || `${config2.mentionName}/sc-${story.id}/${story.story_type}-`;
464
+ const slug = story.name.toLowerCase().replace(/\W/g, "-").replace(/[^a-z0-9-]/g, "").slice(0, 30).replace(/-$/, "");
465
+ return `${prefix}${slug}`;
466
+ };
467
+ var checkoutStoryBranch = (story, prefix = "") => {
468
+ const branch = buildStoryBranch(story, prefix);
469
+ debug("checking out git branch: " + branch);
470
+ (0, import_child_process.execSync)(`git checkout ${branch} 2> /dev/null || git checkout -b ${branch}`);
471
+ };
472
+ var fileURL = (file) => `${file.url}?token=${config2.token}`;
473
+ var stories_default = {
474
+ listStories,
475
+ printFormattedStory,
476
+ printDetailedStory,
477
+ checkoutStoryBranch,
478
+ fetchEntities,
479
+ hydrateStory,
480
+ findProject,
481
+ findGroup,
482
+ findState,
483
+ findEpic,
484
+ findIteration,
485
+ findOwnerIds,
486
+ findLabelNames,
487
+ fileURL,
488
+ storyURL,
489
+ buildURL
490
+ };
491
+
492
+ // src/lib/spinner.ts
493
+ var import_cli_spinner = require("cli-spinner");
494
+ var spinner = (text = "") => {
495
+ const spin2 = new import_cli_spinner.Spinner({
496
+ text: text ? text : "Loading... %s ",
497
+ stream: process.stderr
498
+ });
499
+ spin2.setSpinnerString(27);
500
+ return spin2;
501
+ };
502
+ var spinner_default = spinner;
503
+
504
+ // src/bin/short-story.ts
505
+ var config3 = loadConfig();
506
+ var spin = spinner_default();
507
+ var log2 = console.log;
508
+ var logError = console.error;
509
+ var debug2 = (0, import_debug2.default)("short");
510
+ var program = import_commander.default.usage("[options] <id>").description("Update and/or display story details").option("-a, --archived", "Update story as archived").option("-c, --comment [text]", "Add comment to story", "").option("-d, --description [text]", "Update description of story", "").option("-D, --download", "Download all attached files", "").option("--download-dir [path]", "Directory to download files to", ".").option("-e, --estimate [number]", "Update estimate of story", "").option("--epic [id|name]", "Set epic of story").option("-i, --iteration [id|name]", "Set iteration of story").option("-f, --format [template]", "Format the story output by template", "").option("--from-git", "Fetch story parsed by ID from current git branch").option(
511
+ "--git-branch",
512
+ "Checkout git branch from story slug <mention-name>/ch<id>/<type>-<title>\n as required by the Git integration: https://bit.ly/2RKO1FF"
513
+ ).option(
514
+ "--git-branch-short",
515
+ "Checkout git branch from story slug <mention-name>/ch<id>/<title>"
516
+ ).option("-I, --idonly", "Print only ID of story results", "").option("-l, --label [id|name]", "Stories with label id/name, by regex", "").option("--move-after [id]", "Move story to position below story ID").option("--move-before [id]", "Move story to position above story ID").option("--move-down [n]", "Move story position downward by n stories").option("--move-up [n]", "Move story position upward by n stories").option("-o, --owners [id|name]", "Update owners of story, comma-separated", "").option("-O, --open", "Open story in browser").option("--oe, --open-epic", "Open story's epic in browser").option("--oi, --open-iteration", "Open story's iteration in browser").option("--op, --open-project", "Open story's project in browser").option("-q, --quiet", "Print only story output, no loading dialog", "").option("-s, --state [id|name]", "Update workflow state of story", "").option("-t, --title [text]", "Update title/name of story", "").option("--task [text]", "Create new task on story").option("--task-complete [text]", "Toggle completion of task on story matching text").option("-y, --type [name]", "Update type of story", "").parse(process.argv);
517
+ var main = async () => {
518
+ const entities = await stories_default.fetchEntities();
519
+ if (!(program.idonly || program.quiet)) spin.start();
520
+ debug2("constructing story update");
521
+ const update = {};
522
+ if (program.archived) {
523
+ update.archived = true;
524
+ }
525
+ if (program.state) {
526
+ update.workflow_state_id = (stories_default.findState(entities, program.state) || {}).id;
527
+ }
528
+ if (program.estimate) {
529
+ update.estimate = parseInt(program.estimate, 10);
530
+ }
531
+ if (program.title) {
532
+ update.name = program.title;
533
+ }
534
+ if (program.description) {
535
+ update.description = `${program.description}`;
536
+ }
537
+ if (program.type) {
538
+ const typeMatch = new RegExp(program.type, "i");
539
+ update.story_type = ["feature", "bug", "chore"].filter(
540
+ (t) => !!t.match(typeMatch)
541
+ )[0];
542
+ }
543
+ if (program.owners) {
544
+ update.owner_ids = stories_default.findOwnerIds(entities, program.owners);
545
+ }
546
+ if (program.epic) {
547
+ update.epic_id = (stories_default.findEpic(entities, program.epic) || {}).id;
548
+ }
549
+ if (program.iteration) {
550
+ update.iteration_id = (stories_default.findIteration(entities, program.iteration) || {}).id;
551
+ }
552
+ if (program.label) {
553
+ update.labels = stories_default.findLabelNames(entities, program.label);
554
+ }
555
+ const hasPositionUpdate = program.moveAfter !== void 0 || program.moveBefore !== void 0 || program.moveDown !== void 0 || program.moveUp !== void 0;
556
+ const hasUpdate = Object.keys(update).length > 0 || hasPositionUpdate;
557
+ debug2("constructed story update", update);
558
+ const gitID = [];
559
+ if (program.fromGit || !program.args.length) {
560
+ debug2("fetching story ID from git");
561
+ let branch = "";
562
+ try {
563
+ branch = (0, import_child_process2.execSync)("git branch").toString("utf-8");
564
+ } catch (e) {
565
+ debug2(e);
566
+ }
567
+ if (branch.match(/\*.*[0-9]+/)) {
568
+ debug2("parsing story ID from git branch:", branch);
569
+ const id = parseInt(branch.match(/\*.*/)[0].match(/\/(ch|sc-)([0-9]+)/)[2], 10);
570
+ debug2("parsed story ID from git branch:", id);
571
+ if (id) {
572
+ gitID.push(id.toString());
573
+ }
574
+ } else {
575
+ stopSpinner();
576
+ logError("No story ID argument present or found in git branch");
577
+ process.exit(2);
578
+ }
579
+ }
580
+ const argIDs = program.args.map((a) => (a.match(/\d+/) || [])[0]);
581
+ argIDs.concat(gitID).map(async (_id) => {
582
+ const id = parseInt(_id, 10);
583
+ let story;
584
+ try {
585
+ if (program.comment) {
586
+ debug2("request comment create");
587
+ await client_default.createStoryComment(id, program.comment);
588
+ debug2("response comment create");
589
+ }
590
+ } catch (e) {
591
+ stopSpinner();
592
+ log2("Error creating comment", id);
593
+ process.exit(3);
594
+ }
595
+ try {
596
+ if (program.task) {
597
+ debug2("request task create");
598
+ await client_default.createTask(id, { description: program.task });
599
+ debug2("response task create");
600
+ }
601
+ } catch (e) {
602
+ stopSpinner();
603
+ log2("Error creating task", id);
604
+ process.exit(3);
605
+ }
606
+ try {
607
+ debug2("request story");
608
+ story = await client_default.getStory(id).then((r) => r.data);
609
+ debug2("response story");
610
+ } catch (e) {
611
+ stopSpinner();
612
+ logError("Error fetching story", id);
613
+ process.exit(4);
614
+ }
615
+ try {
616
+ if (program.taskComplete) {
617
+ debug2("calculating task(s) to complete");
618
+ const descMatch = new RegExp(program.taskComplete, "i");
619
+ const tasks = story.tasks.filter((t) => t.description.match(descMatch));
620
+ const updatedTaskIds = tasks.map((t) => t.id);
621
+ debug2("request tasks complete", updatedTaskIds);
622
+ await Promise.all(
623
+ tasks.map((t) => client_default.updateTask(id, t.id, { complete: !t.complete }))
624
+ );
625
+ debug2("response tasks complete");
626
+ story.tasks = story.tasks.map((t) => {
627
+ if (updatedTaskIds.indexOf(t.id) > -1) t.complete = !t.complete;
628
+ return t;
629
+ });
630
+ }
631
+ } catch (e) {
632
+ stopSpinner();
633
+ log2("Error updating tasks", e);
634
+ process.exit(3);
635
+ }
636
+ try {
637
+ if (hasUpdate) {
638
+ if (hasPositionUpdate) {
639
+ debug2("calculating move up/down");
640
+ const siblings = await stories_default.listStories({
641
+ state: story.workflow_state_id.toString(),
642
+ sort: "state.position:asc,position:asc"
643
+ });
644
+ const siblingIds = siblings.map((s) => s.id);
645
+ const storyIndex = siblingIds.indexOf(~~id);
646
+ if (program.moveAfter) {
647
+ update.after_id = ~~program.moveAfter;
648
+ } else if (program.moveBefore) {
649
+ update.before_id = ~~program.moveBefore;
650
+ } else if (program.moveUp) {
651
+ update.before_id = siblingIds[Math.max(0, storyIndex - (~~program.moveUp || 1))];
652
+ } else if (program.moveDown) {
653
+ update.after_id = siblingIds[Math.min(
654
+ siblings.length - 1,
655
+ storyIndex + (~~program.moveDown || 1)
656
+ )];
657
+ }
658
+ debug2("constructed story position update", update);
659
+ }
660
+ debug2("request story update");
661
+ const changed = await client_default.updateStory(id, update);
662
+ debug2("response story update");
663
+ story = Object.assign({}, story, changed);
664
+ }
665
+ } catch (e) {
666
+ stopSpinner();
667
+ logError("Error updating story", id);
668
+ process.exit(5);
669
+ }
670
+ if (story) {
671
+ story = stories_default.hydrateStory(entities, story);
672
+ }
673
+ if (!program.idonly) spin.stop(true);
674
+ if (story) {
675
+ printStory(story, entities);
676
+ if (program.open) {
677
+ openURL(stories_default.storyURL(story));
678
+ }
679
+ if (program.openEpic) {
680
+ if (!story.epic_id) {
681
+ logError("This story is not part of an epic.");
682
+ process.exit(21);
683
+ }
684
+ openURL(stories_default.buildURL("epic", story.epic_id));
685
+ }
686
+ if (program.openIteration) {
687
+ if (!story.iteration_id) {
688
+ logError("This story is not part of an iteration.");
689
+ process.exit(22);
690
+ }
691
+ openURL(stories_default.buildURL("iteration", story.iteration_id));
692
+ }
693
+ if (program.openProject) {
694
+ openURL(stories_default.buildURL("project", story.project_id));
695
+ }
696
+ }
697
+ if (program.download) {
698
+ downloadFiles(story);
699
+ }
700
+ if (story && program.gitBranch) {
701
+ if (!config3.mentionName) {
702
+ stopSpinner();
703
+ stories_default.checkoutStoryBranch(story, `${story.story_type}-${story.id}-`);
704
+ logError("Error creating story branch in Shortcut format");
705
+ logError(
706
+ 'Please run: "short install --force" to add your mention name to the config.'
707
+ );
708
+ process.exit(10);
709
+ }
710
+ stories_default.checkoutStoryBranch(story);
711
+ } else if (story && program.gitBranchShort) {
712
+ stories_default.checkoutStoryBranch(story, `${config3.mentionName}/sc-${story.id}/`);
713
+ }
714
+ });
715
+ stopSpinner();
716
+ };
717
+ var openURL = (url) => {
718
+ const open = import_os2.default.platform() === "darwin" ? "open" : "xdg-open";
719
+ (0, import_child_process2.execSync)(`${open} '${url}'`);
720
+ };
721
+ var stopSpinner = () => {
722
+ if (!(program.idonly || program.quiet)) spin.stop(true);
723
+ };
724
+ var downloadFiles = (story) => story.files.map((file) => {
725
+ import_https.default.get(stories_default.fileURL(file), (res) => {
726
+ const filePath = import_path2.default.join(program.downloadDir, file.name);
727
+ log2(import_chalk2.default.bold("Downloading file to: ") + filePath);
728
+ const stream = import_fs2.default.createWriteStream(filePath);
729
+ res.pipe(stream);
730
+ stream.on("finish", () => stream.close());
731
+ });
732
+ });
733
+ var printStory = (story, entities) => {
734
+ if (program.idonly) {
735
+ return log2(story.id);
736
+ }
737
+ if (program.format) {
738
+ return stories_default.printFormattedStory(program)(story);
739
+ }
740
+ stories_default.printDetailedStory(story, entities);
367
741
  };
368
742
  main();
369
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hvcnQtc3RvcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYmluL3Nob3J0LXN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUNBLCtDQUF5QztBQUN6QyxxQ0FBdUM7QUFFdkMsdUJBQXlCO0FBQ3pCLDJCQUE2QjtBQUM3Qix1QkFBeUI7QUFDekIsNkJBQStCO0FBQy9CLCtCQUEwQjtBQUMxQiw4Q0FBOEM7QUFFOUMsK0JBQThCO0FBQzlCLHdDQUFtQztBQUNuQywwQ0FBbUU7QUFVbkUsMENBQXFDO0FBRXJDLElBQU0sTUFBTSxHQUFHLElBQUEsc0JBQVUsR0FBRSxDQUFDO0FBQzVCLElBQU0sSUFBSSxHQUFHLElBQUEsaUJBQU8sR0FBRSxDQUFDO0FBQ3ZCLElBQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUM7QUFDeEIsSUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQztBQUMvQixJQUFNLEtBQUssR0FBRyxJQUFBLGVBQVMsRUFBQyxPQUFPLENBQUMsQ0FBQztBQUVqQyxJQUFNLE9BQU8sR0FBRyxTQUFTO0tBQ3BCLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQztLQUN2QixXQUFXLENBQUMscUNBQXFDLENBQUM7S0FDbEQsTUFBTSxDQUFDLGdCQUFnQixFQUFFLDBCQUEwQixDQUFDO0tBQ3BELE1BQU0sQ0FBQyxzQkFBc0IsRUFBRSxzQkFBc0IsRUFBRSxFQUFFLENBQUM7S0FDMUQsTUFBTSxDQUFDLDBCQUEwQixFQUFFLDZCQUE2QixFQUFFLEVBQUUsQ0FBQztLQUNyRSxNQUFNLENBQUMsZ0JBQWdCLEVBQUUsNkJBQTZCLEVBQUUsRUFBRSxDQUFDO0tBQzNELE1BQU0sQ0FBQyx1QkFBdUIsRUFBRSxnQ0FBZ0MsRUFBRSxHQUFHLENBQUM7S0FDdEUsTUFBTSxDQUFDLHlCQUF5QixFQUFFLDBCQUEwQixFQUFFLEVBQUUsQ0FB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