huntr-cli 1.0.9
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/.env.example +7 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +43 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +29 -0
- package/.github/labels.json +92 -0
- package/.github/pull_request_template.md +64 -0
- package/.github/workflows/ci.yml +87 -0
- package/.github/workflows/labels.yml +27 -0
- package/.github/workflows/manual-publish.yml +105 -0
- package/.github/workflows/publish.yml +57 -0
- package/.github/workflows/release.yml +124 -0
- package/.github/workflows/security-audit.yml +44 -0
- package/.husky/pre-commit +12 -0
- package/.husky/pre-push +27 -0
- package/.lintstagedrc.json +3 -0
- package/AGENTS.md +449 -0
- package/CHANGELOG.md +38 -0
- package/CHANGES.md +259 -0
- package/LICENSE +15 -0
- package/PUBLISHING.md +191 -0
- package/README.md +385 -0
- package/ROADMAP.md +158 -0
- package/SETUP-COMPLETE.md +446 -0
- package/WORKFLOW-SUMMARY.md +368 -0
- package/completions/_huntr +168 -0
- package/completions/huntr.1 +266 -0
- package/completions/huntr.bash +91 -0
- package/dist/api/client.d.ts +14 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +74 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/personal/activities.d.ts +20 -0
- package/dist/api/personal/activities.d.ts.map +1 -0
- package/dist/api/personal/activities.js +50 -0
- package/dist/api/personal/activities.js.map +1 -0
- package/dist/api/personal/boards.d.ts +9 -0
- package/dist/api/personal/boards.d.ts.map +1 -0
- package/dist/api/personal/boards.js +16 -0
- package/dist/api/personal/boards.js.map +1 -0
- package/dist/api/personal/index.d.ts +17 -0
- package/dist/api/personal/index.d.ts.map +1 -0
- package/dist/api/personal/index.js +37 -0
- package/dist/api/personal/index.js.map +1 -0
- package/dist/api/personal/jobs.d.ts +13 -0
- package/dist/api/personal/jobs.d.ts.map +1 -0
- package/dist/api/personal/jobs.js +31 -0
- package/dist/api/personal/jobs.js.map +1 -0
- package/dist/api/personal/user.d.ts +8 -0
- package/dist/api/personal/user.d.ts.map +1 -0
- package/dist/api/personal/user.js +13 -0
- package/dist/api/personal/user.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +501 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/capture-session.d.ts +10 -0
- package/dist/commands/capture-session.d.ts.map +1 -0
- package/dist/commands/capture-session.js +478 -0
- package/dist/commands/capture-session.js.map +1 -0
- package/dist/config/clerk-session-manager.d.ts +44 -0
- package/dist/config/clerk-session-manager.d.ts.map +1 -0
- package/dist/config/clerk-session-manager.js +232 -0
- package/dist/config/clerk-session-manager.js.map +1 -0
- package/dist/config/config-manager.d.ts +15 -0
- package/dist/config/config-manager.d.ts.map +1 -0
- package/dist/config/config-manager.js +51 -0
- package/dist/config/config-manager.js.map +1 -0
- package/dist/config/keychain-manager.d.ts +6 -0
- package/dist/config/keychain-manager.d.ts.map +1 -0
- package/dist/config/keychain-manager.js +37 -0
- package/dist/config/keychain-manager.js.map +1 -0
- package/dist/config/token-capture.d.ts +11 -0
- package/dist/config/token-capture.d.ts.map +1 -0
- package/dist/config/token-capture.js +252 -0
- package/dist/config/token-capture.js.map +1 -0
- package/dist/config/token-manager.d.ts +38 -0
- package/dist/config/token-manager.d.ts.map +1 -0
- package/dist/config/token-manager.js +153 -0
- package/dist/config/token-manager.js.map +1 -0
- package/dist/lib/list-options.d.ts +69 -0
- package/dist/lib/list-options.d.ts.map +1 -0
- package/dist/lib/list-options.js +299 -0
- package/dist/lib/list-options.js.map +1 -0
- package/dist/types/personal.d.ts +113 -0
- package/dist/types/personal.d.ts.map +1 -0
- package/dist/types/personal.js +4 -0
- package/dist/types/personal.js.map +1 -0
- package/docs/AUTOMATIC-PUBLISHING.md +520 -0
- package/docs/CHANGELOG-AUTOMATION.md +418 -0
- package/docs/CI-CD-SETUP.md +582 -0
- package/docs/DEV-SETUP.md +512 -0
- package/docs/ENHANCEMENT-PLAN.md +204 -0
- package/docs/ENTITY-TYPES.md +462 -0
- package/docs/GITHUB-ACTIONS-GUIDE.md +367 -0
- package/docs/NPM-PUBLISHING.md +324 -0
- package/docs/OUTPUT-EXAMPLES.md +414 -0
- package/docs/OUTPUT-FORMATS.md +299 -0
- package/docs/TESTING.md +216 -0
- package/eslint.config.js +68 -0
- package/package.json +64 -0
- package/src/api/client.ts +88 -0
- package/src/api/personal/activities.ts +66 -0
- package/src/api/personal/boards.ts +14 -0
- package/src/api/personal/index.ts +25 -0
- package/src/api/personal/jobs.ts +33 -0
- package/src/api/personal/user.ts +10 -0
- package/src/cli.ts +487 -0
- package/src/commands/capture-session.ts +582 -0
- package/src/config/clerk-session-manager.ts +263 -0
- package/src/config/config-manager.ts +56 -0
- package/src/config/keychain-manager.ts +30 -0
- package/src/config/token-capture.ts +233 -0
- package/src/config/token-manager.ts +139 -0
- package/src/lib/list-options.ts +370 -0
- package/src/types/personal.ts +114 -0
- package/tests/example.test.ts +130 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ClerkSessionManager } from './clerk-session-manager';
|
|
2
|
+
import type { TokenProvider } from '../api/client';
|
|
3
|
+
export interface TokenOptions {
|
|
4
|
+
token?: string;
|
|
5
|
+
usePrompt?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare class TokenManager {
|
|
8
|
+
private configManager;
|
|
9
|
+
private keychainManager;
|
|
10
|
+
readonly clerkSession: ClerkSessionManager;
|
|
11
|
+
constructor();
|
|
12
|
+
/**
|
|
13
|
+
* Returns a TokenProvider for use with HuntrPersonalApi.
|
|
14
|
+
*
|
|
15
|
+
* Resolution order:
|
|
16
|
+
* 1. CLI --token argument (static, passed via options)
|
|
17
|
+
* 2. HUNTR_API_TOKEN env var (static)
|
|
18
|
+
* 3. Stored Clerk session cookie → auto-refresh on every call
|
|
19
|
+
* 4. Static token from config file or keychain
|
|
20
|
+
* 5. Interactive prompt
|
|
21
|
+
*/
|
|
22
|
+
getTokenProvider(options?: TokenOptions): Promise<TokenProvider>;
|
|
23
|
+
/**
|
|
24
|
+
* Legacy helper — returns a resolved static token string.
|
|
25
|
+
* Use getTokenProvider() for new code so session refresh works.
|
|
26
|
+
*/
|
|
27
|
+
getToken(options?: TokenOptions): Promise<string>;
|
|
28
|
+
private promptSaveLocation;
|
|
29
|
+
saveToken(token: string, location: 'config' | 'keychain'): Promise<void>;
|
|
30
|
+
clearToken(location?: 'config' | 'keychain' | 'all'): Promise<void>;
|
|
31
|
+
showTokenSources(): Promise<{
|
|
32
|
+
env: boolean;
|
|
33
|
+
config: boolean;
|
|
34
|
+
keychain: boolean;
|
|
35
|
+
clerkSession: boolean;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=token-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-manager.d.ts","sourceRoot":"","sources":["../../src/config/token-manager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,eAAe,CAAkB;IACzC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;;IAQ3C;;;;;;;;;OASG;IACG,gBAAgB,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,aAAa,CAAC;IAiD1E;;;OAGG;IACG,QAAQ,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;YAW7C,kBAAkB;IAY1B,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAQxE,UAAU,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IASnE,gBAAgB,IAAI,OAAO,CAAC;QAChC,GAAG,EAAE,OAAO,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;QAChB,QAAQ,EAAE,OAAO,CAAC;QAClB,YAAY,EAAE,OAAO,CAAC;KACvB,CAAC;CAQH"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.TokenManager = void 0;
|
|
37
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
38
|
+
const config_manager_1 = require("./config-manager");
|
|
39
|
+
const keychain_manager_1 = require("./keychain-manager");
|
|
40
|
+
const clerk_session_manager_1 = require("./clerk-session-manager");
|
|
41
|
+
class TokenManager {
|
|
42
|
+
constructor() {
|
|
43
|
+
this.configManager = new config_manager_1.ConfigManager();
|
|
44
|
+
this.keychainManager = new keychain_manager_1.KeychainManager();
|
|
45
|
+
this.clerkSession = new clerk_session_manager_1.ClerkSessionManager();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Returns a TokenProvider for use with HuntrPersonalApi.
|
|
49
|
+
*
|
|
50
|
+
* Resolution order:
|
|
51
|
+
* 1. CLI --token argument (static, passed via options)
|
|
52
|
+
* 2. HUNTR_API_TOKEN env var (static)
|
|
53
|
+
* 3. Stored Clerk session cookie → auto-refresh on every call
|
|
54
|
+
* 4. Static token from config file or keychain
|
|
55
|
+
* 5. Interactive prompt
|
|
56
|
+
*/
|
|
57
|
+
async getTokenProvider(options = {}) {
|
|
58
|
+
// 1. CLI argument — static token
|
|
59
|
+
if (options.token) {
|
|
60
|
+
return options.token;
|
|
61
|
+
}
|
|
62
|
+
// 2. Environment variable — static token
|
|
63
|
+
const envToken = process.env.HUNTR_API_TOKEN;
|
|
64
|
+
if (envToken) {
|
|
65
|
+
return envToken;
|
|
66
|
+
}
|
|
67
|
+
// 3. Clerk session — dynamic refresh
|
|
68
|
+
if (await this.clerkSession.hasSession()) {
|
|
69
|
+
return () => this.clerkSession.getFreshToken();
|
|
70
|
+
}
|
|
71
|
+
// 4. Static token from config or keychain
|
|
72
|
+
const configToken = this.configManager.getToken();
|
|
73
|
+
if (configToken)
|
|
74
|
+
return configToken;
|
|
75
|
+
const keychainToken = await this.keychainManager.getToken();
|
|
76
|
+
if (keychainToken)
|
|
77
|
+
return keychainToken;
|
|
78
|
+
// 5. Interactive prompt — static token (short-lived, but usable)
|
|
79
|
+
if (options.usePrompt !== false) {
|
|
80
|
+
const promptedToken = await (0, prompts_1.password)({
|
|
81
|
+
message: 'Enter your Huntr API token:',
|
|
82
|
+
mask: '*',
|
|
83
|
+
});
|
|
84
|
+
if (promptedToken) {
|
|
85
|
+
const saveChoice = await this.promptSaveLocation();
|
|
86
|
+
if (saveChoice !== 'none') {
|
|
87
|
+
await this.saveToken(promptedToken, saveChoice);
|
|
88
|
+
}
|
|
89
|
+
return promptedToken;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
throw new Error('No Huntr credentials found. Options:\n' +
|
|
93
|
+
' • Clerk session (recommended): huntr config set-session <__session-cookie>\n' +
|
|
94
|
+
' • Static token: huntr config set-token <token> [--keychain]\n' +
|
|
95
|
+
' • CLI flag: huntr --token <token> <command>\n' +
|
|
96
|
+
' • Environment: HUNTR_API_TOKEN=<token> huntr <command>');
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Legacy helper — returns a resolved static token string.
|
|
100
|
+
* Use getTokenProvider() for new code so session refresh works.
|
|
101
|
+
*/
|
|
102
|
+
async getToken(options = {}) {
|
|
103
|
+
if (options.token)
|
|
104
|
+
return options.token;
|
|
105
|
+
const envToken = process.env.HUNTR_API_TOKEN;
|
|
106
|
+
if (envToken)
|
|
107
|
+
return envToken;
|
|
108
|
+
const configToken = this.configManager.getToken();
|
|
109
|
+
if (configToken)
|
|
110
|
+
return configToken;
|
|
111
|
+
const keychainToken = await this.keychainManager.getToken();
|
|
112
|
+
if (keychainToken)
|
|
113
|
+
return keychainToken;
|
|
114
|
+
throw new Error('No static token found. Try huntr config set-token or set-session.');
|
|
115
|
+
}
|
|
116
|
+
async promptSaveLocation() {
|
|
117
|
+
const { select } = await Promise.resolve().then(() => __importStar(require('@inquirer/prompts')));
|
|
118
|
+
return await select({
|
|
119
|
+
message: 'Where would you like to save this token?',
|
|
120
|
+
choices: [
|
|
121
|
+
{ name: 'Save to config file (~/.huntr/config.json)', value: 'config' },
|
|
122
|
+
{ name: 'Save to macOS Keychain (secure)', value: 'keychain' },
|
|
123
|
+
{ name: 'Do not save (enter each time)', value: 'none' },
|
|
124
|
+
],
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
async saveToken(token, location) {
|
|
128
|
+
if (location === 'config') {
|
|
129
|
+
this.configManager.setToken(token);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
await this.keychainManager.setToken(token);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async clearToken(location) {
|
|
136
|
+
if (!location || location === 'all' || location === 'config') {
|
|
137
|
+
this.configManager.clearToken();
|
|
138
|
+
}
|
|
139
|
+
if (!location || location === 'all' || location === 'keychain') {
|
|
140
|
+
await this.keychainManager.deleteToken();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async showTokenSources() {
|
|
144
|
+
return {
|
|
145
|
+
env: !!process.env.HUNTR_API_TOKEN,
|
|
146
|
+
config: !!this.configManager.getToken(),
|
|
147
|
+
keychain: !!(await this.keychainManager.getToken()),
|
|
148
|
+
clerkSession: await this.clerkSession.hasSession(),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.TokenManager = TokenManager;
|
|
153
|
+
//# sourceMappingURL=token-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-manager.js","sourceRoot":"","sources":["../../src/config/token-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CLI options for list commands (boards, jobs, activities).
|
|
3
|
+
* Provides consistent flag parsing and validation across all list subcommands.
|
|
4
|
+
*/
|
|
5
|
+
export type OutputFormat = 'table' | 'json' | 'csv' | 'pdf' | 'excel';
|
|
6
|
+
export interface ListOptions {
|
|
7
|
+
/** Output format: table (default), json, csv, pdf, or excel */
|
|
8
|
+
format: OutputFormat;
|
|
9
|
+
/** Number of days to filter to (activities only, default: all) */
|
|
10
|
+
days?: number;
|
|
11
|
+
/** Action types to filter (activities only, comma-separated) */
|
|
12
|
+
types?: string[];
|
|
13
|
+
/** Selected fields to include in output (comma-separated) */
|
|
14
|
+
fields?: string[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Parses common list options from CLI arguments.
|
|
18
|
+
* Supports aliases: -f/--format, -d/--days, --json (legacy compatibility), --fields.
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseListOptions(opts: Record<string, unknown>): ListOptions;
|
|
21
|
+
/**
|
|
22
|
+
* Formats table output with consistent column widths.
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatTable<T extends Record<string, unknown>>(rows: T[]): string;
|
|
25
|
+
/**
|
|
26
|
+
* Converts array of objects to CSV with proper escaping.
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatCsv<T extends Record<string, unknown>>(rows: T[], headers?: string[]): string;
|
|
29
|
+
/**
|
|
30
|
+
* Validates and filters fields based on available fields.
|
|
31
|
+
* If no fields are requested, returns all available fields.
|
|
32
|
+
* Throws an error if requested fields don't exist.
|
|
33
|
+
*/
|
|
34
|
+
export declare function validateFields(availableFields: string[], requestedFields?: string[]): string[];
|
|
35
|
+
/**
|
|
36
|
+
* Formats table output with specific fields and consistent column widths.
|
|
37
|
+
* @param rows Data rows
|
|
38
|
+
* @param headers Field names to include (in order)
|
|
39
|
+
*/
|
|
40
|
+
export declare function formatTableWithFields<T extends Record<string, unknown>>(rows: T[], headers: string[]): string;
|
|
41
|
+
/**
|
|
42
|
+
* Formats CSV output with specific fields.
|
|
43
|
+
* @param rows Data rows
|
|
44
|
+
* @param headers Field names to include (in order)
|
|
45
|
+
*/
|
|
46
|
+
export declare function formatCsvWithFields<T extends Record<string, unknown>>(rows: T[], headers: string[]): string;
|
|
47
|
+
/**
|
|
48
|
+
* Formats JSON output with specific fields.
|
|
49
|
+
* @param rows Data rows
|
|
50
|
+
* @param headers Field names to include (in order)
|
|
51
|
+
*/
|
|
52
|
+
export declare function formatJsonWithFields<T extends Record<string, unknown>>(rows: T[], headers: string[]): string;
|
|
53
|
+
/**
|
|
54
|
+
* Formats PDF output with specific fields.
|
|
55
|
+
* Requires pdfkit to be installed.
|
|
56
|
+
* @param rows Data rows
|
|
57
|
+
* @param headers Field names to include (in order)
|
|
58
|
+
* @param title Optional title for the PDF
|
|
59
|
+
*/
|
|
60
|
+
export declare function formatPdf<T extends Record<string, unknown>>(rows: T[], headers: string[], title?: string): Buffer;
|
|
61
|
+
/**
|
|
62
|
+
* Formats Excel output with specific fields.
|
|
63
|
+
* Requires exceljs to be installed.
|
|
64
|
+
* @param rows Data rows
|
|
65
|
+
* @param headers Field names to include (in order)
|
|
66
|
+
* @param title Optional sheet title
|
|
67
|
+
*/
|
|
68
|
+
export declare function formatExcel<T extends Record<string, unknown>>(rows: T[], headers: string[], title?: string): Promise<Buffer>;
|
|
69
|
+
//# sourceMappingURL=list-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-options.d.ts","sourceRoot":"","sources":["../../src/lib/list-options.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC;AAEtE,MAAM,WAAW,WAAW;IAC1B,+DAA+D;IAC/D,MAAM,EAAE,YAAY,CAAC;IACrB,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CA+C3E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,MAAM,CA2BhF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAelG;AASD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,eAAe,EAAE,MAAM,EAAE,EAAE,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAe9F;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrE,IAAI,EAAE,CAAC,EAAE,EACT,OAAO,EAAE,MAAM,EAAE,GAChB,MAAM,CA0BR;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,IAAI,EAAE,CAAC,EAAE,EACT,OAAO,EAAE,MAAM,EAAE,GAChB,MAAM,CAcR;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpE,IAAI,EAAE,CAAC,EAAE,EACT,OAAO,EAAE,MAAM,EAAE,GAChB,MAAM,CASR;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzD,IAAI,EAAE,CAAC,EAAE,EACT,OAAO,EAAE,MAAM,EAAE,EACjB,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,CAyER;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,IAAI,EAAE,CAAC,EAAE,EACT,OAAO,EAAE,MAAM,EAAE,EACjB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAyCjB"}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared CLI options for list commands (boards, jobs, activities).
|
|
4
|
+
* Provides consistent flag parsing and validation across all list subcommands.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.parseListOptions = parseListOptions;
|
|
8
|
+
exports.formatTable = formatTable;
|
|
9
|
+
exports.formatCsv = formatCsv;
|
|
10
|
+
exports.validateFields = validateFields;
|
|
11
|
+
exports.formatTableWithFields = formatTableWithFields;
|
|
12
|
+
exports.formatCsvWithFields = formatCsvWithFields;
|
|
13
|
+
exports.formatJsonWithFields = formatJsonWithFields;
|
|
14
|
+
exports.formatPdf = formatPdf;
|
|
15
|
+
exports.formatExcel = formatExcel;
|
|
16
|
+
/**
|
|
17
|
+
* Parses common list options from CLI arguments.
|
|
18
|
+
* Supports aliases: -f/--format, -d/--days, --json (legacy compatibility), --fields.
|
|
19
|
+
*/
|
|
20
|
+
function parseListOptions(opts) {
|
|
21
|
+
let format = 'table';
|
|
22
|
+
// Handle legacy --json flag
|
|
23
|
+
if (opts.json) {
|
|
24
|
+
format = 'json';
|
|
25
|
+
}
|
|
26
|
+
// Handle new --format flag (takes precedence over --json)
|
|
27
|
+
if (opts.format) {
|
|
28
|
+
const fmt = String(opts.format).toLowerCase();
|
|
29
|
+
if (!['table', 'json', 'csv', 'pdf', 'excel'].includes(fmt)) {
|
|
30
|
+
throw new Error(`Invalid format: ${fmt}. Must be table, json, csv, pdf, or excel.`);
|
|
31
|
+
}
|
|
32
|
+
format = fmt;
|
|
33
|
+
}
|
|
34
|
+
let days;
|
|
35
|
+
if (opts.days) {
|
|
36
|
+
const d = parseInt(String(opts.days), 10);
|
|
37
|
+
if (isNaN(d) || d < 1 || d > 365) {
|
|
38
|
+
throw new Error('Days must be a number between 1 and 365');
|
|
39
|
+
}
|
|
40
|
+
days = d;
|
|
41
|
+
}
|
|
42
|
+
// Legacy --week flag for activities (maps to 7 days)
|
|
43
|
+
if (opts.week && !days) {
|
|
44
|
+
days = 7;
|
|
45
|
+
}
|
|
46
|
+
let types;
|
|
47
|
+
if (opts.types) {
|
|
48
|
+
types = String(opts.types)
|
|
49
|
+
.split(',')
|
|
50
|
+
.map(t => t.trim())
|
|
51
|
+
.filter(t => t.length > 0);
|
|
52
|
+
}
|
|
53
|
+
let fields;
|
|
54
|
+
if (opts.fields) {
|
|
55
|
+
fields = String(opts.fields)
|
|
56
|
+
.split(',')
|
|
57
|
+
.map(f => f.trim())
|
|
58
|
+
.filter(f => f.length > 0);
|
|
59
|
+
}
|
|
60
|
+
return { format, days, types, fields };
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Formats table output with consistent column widths.
|
|
64
|
+
*/
|
|
65
|
+
function formatTable(rows) {
|
|
66
|
+
if (rows.length === 0)
|
|
67
|
+
return '';
|
|
68
|
+
const keys = Object.keys(rows[0]);
|
|
69
|
+
const colWidths = {};
|
|
70
|
+
// Calculate column widths
|
|
71
|
+
for (const key of keys) {
|
|
72
|
+
colWidths[key] = key.length;
|
|
73
|
+
for (const row of rows) {
|
|
74
|
+
const val = String(row[key] ?? '');
|
|
75
|
+
colWidths[key] = Math.max(colWidths[key], val.length);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Format header
|
|
79
|
+
const header = keys.map(k => k.padEnd(colWidths[k])).join(' ');
|
|
80
|
+
const divider = keys.map(k => '─'.repeat(colWidths[k])).join(' ');
|
|
81
|
+
// Format rows
|
|
82
|
+
const lines = [header, divider];
|
|
83
|
+
for (const row of rows) {
|
|
84
|
+
const line = keys.map(k => String(row[k] ?? '').padEnd(colWidths[k])).join(' ');
|
|
85
|
+
lines.push(line);
|
|
86
|
+
}
|
|
87
|
+
return lines.join('\n');
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Converts array of objects to CSV with proper escaping.
|
|
91
|
+
*/
|
|
92
|
+
function formatCsv(rows, headers) {
|
|
93
|
+
if (rows.length === 0)
|
|
94
|
+
return headers ? headers.join(',') : '';
|
|
95
|
+
const keys = headers || Object.keys(rows[0]);
|
|
96
|
+
const lines = [keys.map(escapeCsvField).join(',')];
|
|
97
|
+
for (const row of rows) {
|
|
98
|
+
const values = keys.map(k => {
|
|
99
|
+
const val = row[k];
|
|
100
|
+
return escapeCsvField(String(val ?? ''));
|
|
101
|
+
});
|
|
102
|
+
lines.push(values.join(','));
|
|
103
|
+
}
|
|
104
|
+
return lines.join('\n');
|
|
105
|
+
}
|
|
106
|
+
function escapeCsvField(field) {
|
|
107
|
+
if (field.includes(',') || field.includes('"') || field.includes('\n')) {
|
|
108
|
+
return `"${field.replace(/"/g, '""')}"`;
|
|
109
|
+
}
|
|
110
|
+
return field;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Validates and filters fields based on available fields.
|
|
114
|
+
* If no fields are requested, returns all available fields.
|
|
115
|
+
* Throws an error if requested fields don't exist.
|
|
116
|
+
*/
|
|
117
|
+
function validateFields(availableFields, requestedFields) {
|
|
118
|
+
if (!requestedFields || requestedFields.length === 0) {
|
|
119
|
+
return availableFields;
|
|
120
|
+
}
|
|
121
|
+
const invalid = requestedFields.filter(f => !availableFields.includes(f));
|
|
122
|
+
if (invalid.length > 0) {
|
|
123
|
+
const invalidStr = invalid.join(', ');
|
|
124
|
+
const availableStr = availableFields.join(', ');
|
|
125
|
+
throw new Error(`Unknown field(s): ${invalidStr}\nAvailable fields: ${availableStr}`);
|
|
126
|
+
}
|
|
127
|
+
return requestedFields;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Formats table output with specific fields and consistent column widths.
|
|
131
|
+
* @param rows Data rows
|
|
132
|
+
* @param headers Field names to include (in order)
|
|
133
|
+
*/
|
|
134
|
+
function formatTableWithFields(rows, headers) {
|
|
135
|
+
if (rows.length === 0)
|
|
136
|
+
return '';
|
|
137
|
+
const colWidths = {};
|
|
138
|
+
// Calculate column widths
|
|
139
|
+
for (const key of headers) {
|
|
140
|
+
colWidths[key] = key.length;
|
|
141
|
+
for (const row of rows) {
|
|
142
|
+
const val = String(row[key] ?? '');
|
|
143
|
+
colWidths[key] = Math.max(colWidths[key], val.length);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Format header
|
|
147
|
+
const header = headers.map(k => k.padEnd(colWidths[k])).join(' ');
|
|
148
|
+
const divider = headers.map(k => '─'.repeat(colWidths[k])).join(' ');
|
|
149
|
+
// Format rows
|
|
150
|
+
const lines = [header, divider];
|
|
151
|
+
for (const row of rows) {
|
|
152
|
+
const line = headers.map(k => String(row[k] ?? '').padEnd(colWidths[k])).join(' ');
|
|
153
|
+
lines.push(line);
|
|
154
|
+
}
|
|
155
|
+
return lines.join('\n');
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Formats CSV output with specific fields.
|
|
159
|
+
* @param rows Data rows
|
|
160
|
+
* @param headers Field names to include (in order)
|
|
161
|
+
*/
|
|
162
|
+
function formatCsvWithFields(rows, headers) {
|
|
163
|
+
if (rows.length === 0)
|
|
164
|
+
return headers.join(',');
|
|
165
|
+
const lines = [headers.map(escapeCsvField).join(',')];
|
|
166
|
+
for (const row of rows) {
|
|
167
|
+
const values = headers.map(h => {
|
|
168
|
+
const val = row[h];
|
|
169
|
+
return escapeCsvField(String(val ?? ''));
|
|
170
|
+
});
|
|
171
|
+
lines.push(values.join(','));
|
|
172
|
+
}
|
|
173
|
+
return lines.join('\n');
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Formats JSON output with specific fields.
|
|
177
|
+
* @param rows Data rows
|
|
178
|
+
* @param headers Field names to include (in order)
|
|
179
|
+
*/
|
|
180
|
+
function formatJsonWithFields(rows, headers) {
|
|
181
|
+
const filtered = rows.map(row => {
|
|
182
|
+
const obj = {};
|
|
183
|
+
for (const header of headers) {
|
|
184
|
+
obj[header] = row[header];
|
|
185
|
+
}
|
|
186
|
+
return obj;
|
|
187
|
+
});
|
|
188
|
+
return JSON.stringify(filtered, null, 2);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Formats PDF output with specific fields.
|
|
192
|
+
* Requires pdfkit to be installed.
|
|
193
|
+
* @param rows Data rows
|
|
194
|
+
* @param headers Field names to include (in order)
|
|
195
|
+
* @param title Optional title for the PDF
|
|
196
|
+
*/
|
|
197
|
+
function formatPdf(rows, headers, title) {
|
|
198
|
+
// Dynamically import pdfkit to avoid hard dependency at load time
|
|
199
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires, global-require
|
|
200
|
+
const PDFDocument = require('pdfkit');
|
|
201
|
+
const doc = new PDFDocument({ margin: 40, size: 'letter' });
|
|
202
|
+
const chunks = [];
|
|
203
|
+
// Collect output
|
|
204
|
+
doc.on('data', (chunk) => chunks.push(chunk));
|
|
205
|
+
// Title
|
|
206
|
+
if (title) {
|
|
207
|
+
doc.fontSize(16).font('Helvetica-Bold').text(title, { underline: true });
|
|
208
|
+
doc.moveDown();
|
|
209
|
+
}
|
|
210
|
+
// Metadata
|
|
211
|
+
const now = new Date();
|
|
212
|
+
doc
|
|
213
|
+
.fontSize(10)
|
|
214
|
+
.font('Helvetica')
|
|
215
|
+
.text(`Generated: ${now.toISOString()}`, { lineGap: 5 });
|
|
216
|
+
doc.moveDown();
|
|
217
|
+
// Table header
|
|
218
|
+
const colWidth = (doc.page.width - 80) / headers.length;
|
|
219
|
+
const yStart = doc.y;
|
|
220
|
+
// Header background
|
|
221
|
+
doc.rect(40, yStart, doc.page.width - 80, 25).fill('#e8e8e8');
|
|
222
|
+
// Header text
|
|
223
|
+
doc.fontSize(10).font('Helvetica-Bold').fillColor('black');
|
|
224
|
+
headers.forEach((header, i) => {
|
|
225
|
+
doc.text(header, 40 + i * colWidth + 5, yStart + 5, {
|
|
226
|
+
width: colWidth - 10,
|
|
227
|
+
ellipsis: true,
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
doc.moveDown(1.5);
|
|
231
|
+
// Data rows
|
|
232
|
+
doc.font('Helvetica').fontSize(9);
|
|
233
|
+
const rowHeight = 20;
|
|
234
|
+
for (const row of rows) {
|
|
235
|
+
const yRow = doc.y;
|
|
236
|
+
// Alternate row background
|
|
237
|
+
if (rows.indexOf(row) % 2 === 0) {
|
|
238
|
+
doc.rect(40, yRow, doc.page.width - 80, rowHeight).fill('#f5f5f5');
|
|
239
|
+
doc.fillColor('black');
|
|
240
|
+
}
|
|
241
|
+
headers.forEach((header, i) => {
|
|
242
|
+
const val = String(row[header] ?? '');
|
|
243
|
+
doc.text(val, 40 + i * colWidth + 5, yRow + 3, {
|
|
244
|
+
width: colWidth - 10,
|
|
245
|
+
ellipsis: true,
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
doc.moveDown(1.2);
|
|
249
|
+
}
|
|
250
|
+
// Footer
|
|
251
|
+
doc.fontSize(9).font('Helvetica').text('huntr-cli', { align: 'center' });
|
|
252
|
+
doc.end();
|
|
253
|
+
return Buffer.concat(chunks);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Formats Excel output with specific fields.
|
|
257
|
+
* Requires exceljs to be installed.
|
|
258
|
+
* @param rows Data rows
|
|
259
|
+
* @param headers Field names to include (in order)
|
|
260
|
+
* @param title Optional sheet title
|
|
261
|
+
*/
|
|
262
|
+
async function formatExcel(rows, headers, title) {
|
|
263
|
+
// Dynamically import exceljs to avoid hard dependency at load time
|
|
264
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires, global-require
|
|
265
|
+
const ExcelJS = require('exceljs');
|
|
266
|
+
const workbook = new ExcelJS.Workbook();
|
|
267
|
+
const worksheet = workbook.addWorksheet(title || 'Data', {
|
|
268
|
+
pageSetup: { paperSize: 9, orientation: 'landscape' },
|
|
269
|
+
});
|
|
270
|
+
// Add header row
|
|
271
|
+
worksheet.addRow(headers);
|
|
272
|
+
const headerRow = worksheet.getRow(1);
|
|
273
|
+
headerRow.font = { bold: true, color: { argb: 'FFFFFFFF' } };
|
|
274
|
+
headerRow.fill = {
|
|
275
|
+
type: 'pattern',
|
|
276
|
+
pattern: 'solid',
|
|
277
|
+
fgColor: { argb: 'FF4472C4' },
|
|
278
|
+
};
|
|
279
|
+
headerRow.alignment = { horizontal: 'center', vertical: 'center' };
|
|
280
|
+
// Add data rows
|
|
281
|
+
for (const row of rows) {
|
|
282
|
+
const values = headers.map(h => row[h] ?? '');
|
|
283
|
+
worksheet.addRow(values);
|
|
284
|
+
}
|
|
285
|
+
// Auto-adjust column widths
|
|
286
|
+
headers.forEach((header, i) => {
|
|
287
|
+
let maxLen = header.length;
|
|
288
|
+
for (const row of rows) {
|
|
289
|
+
const val = String(row[header] ?? '');
|
|
290
|
+
maxLen = Math.max(maxLen, val.length);
|
|
291
|
+
}
|
|
292
|
+
const col = worksheet.getColumn(i + 1);
|
|
293
|
+
col.width = Math.min(maxLen + 2, 50); // Cap at 50 chars
|
|
294
|
+
});
|
|
295
|
+
// Generate buffer
|
|
296
|
+
const buffer = await workbook.xlsx.writeBuffer();
|
|
297
|
+
return buffer;
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=list-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-options.js","sourceRoot":"","sources":["../../src/lib/list-options.ts"],"names":[],"mappings":"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"}
|