@fettle/cli 0.1.3
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/LICENSE +21 -0
- package/README.md +21 -0
- package/dist/cli.d.ts +57 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +211 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fettle contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# @fettle/cli
|
|
2
|
+
|
|
3
|
+
Command-line interface for [Fettle](https://github.com/rumankazi/fettle) — grade the
|
|
4
|
+
maintenance health of GitHub repositories.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
export GITHUB_TOKEN=...
|
|
8
|
+
npx @fettle/cli --repos vitest-dev/vitest --format markdown
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
fettle --repos acme/api,acme/web --format json > report.json
|
|
13
|
+
fettle --repos acme/api --fail-below C # exit 1 if it grades below C
|
|
14
|
+
fettle --repos acme/api --api-url https://ghe.acme.com/api/v3
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Exit codes: `0` success, `1` graded below `--fail-below`, `2` invalid usage, `3` a
|
|
18
|
+
repository or its configuration could not be read.
|
|
19
|
+
|
|
20
|
+
Run `fettle --help` for all flags. Full documentation:
|
|
21
|
+
[github.com/rumankazi/fettle](https://github.com/rumankazi/fettle).
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI argument parsing, rendering and exit codes.
|
|
3
|
+
*
|
|
4
|
+
* Kept separate from `index.ts` (the bin shim) so the whole command is testable as
|
|
5
|
+
* a function: nothing here reads `process` directly or calls `process.exit`.
|
|
6
|
+
*/
|
|
7
|
+
import { type AssessOptions, type BadgePayload, type FloorGrade, type HealthReport } from '@fettle/core';
|
|
8
|
+
export declare const EXIT_OK = 0;
|
|
9
|
+
export declare const EXIT_BELOW_FLOOR = 1;
|
|
10
|
+
export declare const EXIT_USAGE = 2;
|
|
11
|
+
/** A repository or its configuration could not be read; nothing was graded. */
|
|
12
|
+
export declare const EXIT_SCAN_FAILED = 3;
|
|
13
|
+
declare const FORMATS: readonly ["json", "markdown", "badge"];
|
|
14
|
+
export type Format = (typeof FORMATS)[number];
|
|
15
|
+
export interface CliOptions {
|
|
16
|
+
repos: string[];
|
|
17
|
+
format: Format;
|
|
18
|
+
failBelow?: FloorGrade;
|
|
19
|
+
apiUrl?: string;
|
|
20
|
+
/** A local config file; absent means each repository supplies its own. */
|
|
21
|
+
configPath?: string;
|
|
22
|
+
help: boolean;
|
|
23
|
+
version: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** A problem with how the command was invoked. Reported to stderr, exit code 2. */
|
|
26
|
+
export declare class UsageError extends Error {
|
|
27
|
+
constructor(message: string);
|
|
28
|
+
}
|
|
29
|
+
export declare const USAGE: string;
|
|
30
|
+
/**
|
|
31
|
+
* Parses argv strictly: an unknown or misspelled flag is an error, never a silently
|
|
32
|
+
* ignored one, because a swallowed `--fail-below` turns a gate into a no-op.
|
|
33
|
+
*/
|
|
34
|
+
export declare function parseCliOptions(argv: readonly string[], env?: Readonly<Record<string, string | undefined>>): CliOptions;
|
|
35
|
+
/** Badge payloads keyed by repository, so multi-repo output stays valid JSON. */
|
|
36
|
+
export declare function renderBadges(report: HealthReport): Record<string, BadgePayload>;
|
|
37
|
+
export declare function render(report: HealthReport, format: Format): string;
|
|
38
|
+
/**
|
|
39
|
+
* Performs the scan.
|
|
40
|
+
*
|
|
41
|
+
* Injected so the command can be tested without a network. The real
|
|
42
|
+
* implementation is core's `assess`, which owns request pacing and concurrency —
|
|
43
|
+
* the CLI's job is arguments, configuration, rendering and exit codes.
|
|
44
|
+
*/
|
|
45
|
+
export type Scanner = (repos: readonly string[], options: AssessOptions) => Promise<HealthReport>;
|
|
46
|
+
export interface RunOptions {
|
|
47
|
+
argv: readonly string[];
|
|
48
|
+
env?: Readonly<Record<string, string | undefined>>;
|
|
49
|
+
stdout: (chunk: string) => void;
|
|
50
|
+
stderr: (chunk: string) => void;
|
|
51
|
+
scan?: Scanner;
|
|
52
|
+
now?: Date;
|
|
53
|
+
}
|
|
54
|
+
/** Runs the command and returns its exit code. Never throws for expected failures. */
|
|
55
|
+
export declare function run(options: RunOptions): Promise<number>;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAWL,KAAK,aAAa,EAClB,KAAK,YAAY,EAEjB,KAAK,UAAU,EAEf,KAAK,YAAY,EAClB,MAAM,cAAc,CAAC;AAEtB,eAAO,MAAM,OAAO,IAAI,CAAC;AACzB,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,UAAU,IAAI,CAAC;AAC5B,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,QAAA,MAAM,OAAO,wCAAyC,CAAC;AACvD,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,mFAAmF;AACnF,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAI5B;AAED,eAAO,MAAM,KAAK,QAyByD,CAAC;AAsB5E;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,GAAG,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAM,GACrD,UAAU,CAqDZ;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAI/E;AAED,wBAAgB,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CASnE;AAMD;;;;;;GAMG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;AAElG,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IACnD,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAyBD,sFAAsF;AACtF,wBAAsB,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAkE9D"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI argument parsing, rendering and exit codes.
|
|
3
|
+
*
|
|
4
|
+
* Kept separate from `index.ts` (the bin shim) so the whole command is testable as
|
|
5
|
+
* a function: nothing here reads `process` directly or calls `process.exit`.
|
|
6
|
+
*/
|
|
7
|
+
import { readFile } from 'node:fs/promises';
|
|
8
|
+
import { parseArgs } from 'node:util';
|
|
9
|
+
import { assess, badgeFilename, buildBadgePayload, CONFIG_FILENAME, FLOOR_GRADES, meetsGradeFloor, parseConfig, renderMarkdown, TOOL_NAME, TOOL_VERSION, } from '@fettle/core';
|
|
10
|
+
export const EXIT_OK = 0;
|
|
11
|
+
export const EXIT_BELOW_FLOOR = 1;
|
|
12
|
+
export const EXIT_USAGE = 2;
|
|
13
|
+
/** A repository or its configuration could not be read; nothing was graded. */
|
|
14
|
+
export const EXIT_SCAN_FAILED = 3;
|
|
15
|
+
const FORMATS = ['json', 'markdown', 'badge'];
|
|
16
|
+
/** A problem with how the command was invoked. Reported to stderr, exit code 2. */
|
|
17
|
+
export class UsageError extends Error {
|
|
18
|
+
constructor(message) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = 'UsageError';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export const USAGE = `${TOOL_NAME} — grade the maintenance health of GitHub repositories
|
|
24
|
+
|
|
25
|
+
Usage:
|
|
26
|
+
${TOOL_NAME} --repos <org/name[,org/other]> [options]
|
|
27
|
+
|
|
28
|
+
Options:
|
|
29
|
+
--repos <list> Comma- or newline-separated repositories. Defaults to
|
|
30
|
+
$GITHUB_REPOSITORY when set.
|
|
31
|
+
--format <format> Output format: ${FORMATS.join(' | ')} (default: json).
|
|
32
|
+
--fail-below <grade> Exit ${EXIT_BELOW_FLOOR} if any repository grades below this
|
|
33
|
+
floor: ${FLOOR_GRADES.join(' | ')}.
|
|
34
|
+
--api-url <url> GitHub API base URL for GitHub Enterprise Server.
|
|
35
|
+
Defaults to $GITHUB_API_URL, then https://api.github.com.
|
|
36
|
+
--config <path> Local config file to apply to every repository, instead of
|
|
37
|
+
reading ${CONFIG_FILENAME} from each one.
|
|
38
|
+
--version Print the version and exit.
|
|
39
|
+
--help Print this message and exit.
|
|
40
|
+
|
|
41
|
+
Authentication:
|
|
42
|
+
Reads the token from $GITHUB_TOKEN.
|
|
43
|
+
|
|
44
|
+
Exit codes:
|
|
45
|
+
${EXIT_OK} success
|
|
46
|
+
${EXIT_BELOW_FLOOR} a repository graded below --fail-below
|
|
47
|
+
${EXIT_USAGE} invalid usage
|
|
48
|
+
${EXIT_SCAN_FAILED} a repository or its configuration could not be read`;
|
|
49
|
+
function splitRepoList(value) {
|
|
50
|
+
return value
|
|
51
|
+
.split(/[\n,]+/)
|
|
52
|
+
.map((repo) => repo.trim())
|
|
53
|
+
.filter((repo) => repo.length > 0);
|
|
54
|
+
}
|
|
55
|
+
function assertRepoName(repo) {
|
|
56
|
+
if (!/^[^/\s]+\/[^/\s]+$/.test(repo)) {
|
|
57
|
+
throw new UsageError(`'${repo}' is not a valid repository; expected the form org/name`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function oneOf(value, allowed, flag) {
|
|
61
|
+
if (!allowed.includes(value)) {
|
|
62
|
+
throw new UsageError(`--${flag} must be one of ${allowed.join(', ')}; received '${value}'`);
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Parses argv strictly: an unknown or misspelled flag is an error, never a silently
|
|
68
|
+
* ignored one, because a swallowed `--fail-below` turns a gate into a no-op.
|
|
69
|
+
*/
|
|
70
|
+
export function parseCliOptions(argv, env = {}) {
|
|
71
|
+
let parsed;
|
|
72
|
+
// `npm run cli -- --repos …` and `pnpm cli -- --repos …` forward the separator
|
|
73
|
+
// itself, and we take no positionals, so drop one leading `--`.
|
|
74
|
+
const args = argv[0] === '--' ? argv.slice(1) : [...argv];
|
|
75
|
+
try {
|
|
76
|
+
parsed = parseArgs({
|
|
77
|
+
args,
|
|
78
|
+
strict: true,
|
|
79
|
+
allowPositionals: false,
|
|
80
|
+
options: {
|
|
81
|
+
repos: { type: 'string' },
|
|
82
|
+
format: { type: 'string' },
|
|
83
|
+
'fail-below': { type: 'string' },
|
|
84
|
+
'api-url': { type: 'string' },
|
|
85
|
+
config: { type: 'string' },
|
|
86
|
+
version: { type: 'boolean', default: false },
|
|
87
|
+
help: { type: 'boolean', short: 'h', default: false },
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
throw new UsageError(error instanceof Error ? error.message : String(error));
|
|
93
|
+
}
|
|
94
|
+
const { values } = parsed;
|
|
95
|
+
const help = values.help === true;
|
|
96
|
+
const version = values.version === true;
|
|
97
|
+
const reposInput = values.repos ?? env.GITHUB_REPOSITORY;
|
|
98
|
+
const repos = reposInput === undefined ? [] : splitRepoList(reposInput);
|
|
99
|
+
if (!help && !version) {
|
|
100
|
+
if (repos.length === 0) {
|
|
101
|
+
throw new UsageError('no repositories given; pass --repos org/name or set $GITHUB_REPOSITORY');
|
|
102
|
+
}
|
|
103
|
+
repos.forEach(assertRepoName);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
repos,
|
|
107
|
+
format: values.format === undefined ? 'json' : oneOf(values.format, FORMATS, 'format'),
|
|
108
|
+
failBelow: values['fail-below'] === undefined
|
|
109
|
+
? undefined
|
|
110
|
+
: oneOf(values['fail-below'], FLOOR_GRADES, 'fail-below'),
|
|
111
|
+
apiUrl: values['api-url'] ?? env.GITHUB_API_URL,
|
|
112
|
+
configPath: values.config,
|
|
113
|
+
help,
|
|
114
|
+
version,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/** Badge payloads keyed by repository, so multi-repo output stays valid JSON. */
|
|
118
|
+
export function renderBadges(report) {
|
|
119
|
+
return Object.fromEntries(report.repos.map((repo) => [badgeFilename(repo.repo), buildBadgePayload(repo)]));
|
|
120
|
+
}
|
|
121
|
+
export function render(report, format) {
|
|
122
|
+
switch (format) {
|
|
123
|
+
case 'json':
|
|
124
|
+
return JSON.stringify(report, null, 2);
|
|
125
|
+
case 'markdown':
|
|
126
|
+
return renderMarkdown(report);
|
|
127
|
+
case 'badge':
|
|
128
|
+
return JSON.stringify(renderBadges(report), null, 2);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function belowFloor(report, floor) {
|
|
132
|
+
return report.repos.filter((repo) => !meetsGradeFloor(repo.grade, floor)).map((r) => r.grade);
|
|
133
|
+
}
|
|
134
|
+
function describe(error) {
|
|
135
|
+
return error instanceof Error ? error.message : String(error);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Loads the `--config` file, if one was given.
|
|
139
|
+
*
|
|
140
|
+
* A local file replaces each repository's own `.fettle.yml`, which is how one
|
|
141
|
+
* policy gets applied across a fleet.
|
|
142
|
+
*/
|
|
143
|
+
async function readLocalConfig(path, warn) {
|
|
144
|
+
if (path === undefined)
|
|
145
|
+
return undefined;
|
|
146
|
+
const contents = await readFile(path, 'utf8');
|
|
147
|
+
const { config, warnings } = parseConfig(contents, path);
|
|
148
|
+
for (const warning of warnings)
|
|
149
|
+
warn(`${path}: ${warning}`);
|
|
150
|
+
return config;
|
|
151
|
+
}
|
|
152
|
+
/** Runs the command and returns its exit code. Never throws for expected failures. */
|
|
153
|
+
export async function run(options) {
|
|
154
|
+
const { stdout, stderr } = options;
|
|
155
|
+
let cli;
|
|
156
|
+
try {
|
|
157
|
+
cli = parseCliOptions(options.argv, options.env ?? {});
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
if (!(error instanceof UsageError))
|
|
161
|
+
throw error;
|
|
162
|
+
stderr(`${TOOL_NAME}: ${error.message}\n\n${USAGE}\n`);
|
|
163
|
+
return EXIT_USAGE;
|
|
164
|
+
}
|
|
165
|
+
if (cli.help) {
|
|
166
|
+
stdout(`${USAGE}\n`);
|
|
167
|
+
return EXIT_OK;
|
|
168
|
+
}
|
|
169
|
+
if (cli.version) {
|
|
170
|
+
stdout(`${TOOL_NAME} ${TOOL_VERSION}\n`);
|
|
171
|
+
return EXIT_OK;
|
|
172
|
+
}
|
|
173
|
+
const env = options.env ?? {};
|
|
174
|
+
const warn = (text) => stderr(`${TOOL_NAME}: ${text}\n`);
|
|
175
|
+
let config;
|
|
176
|
+
try {
|
|
177
|
+
config = await readLocalConfig(cli.configPath, warn);
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
warn(describe(error));
|
|
181
|
+
return EXIT_USAGE;
|
|
182
|
+
}
|
|
183
|
+
if (env.GITHUB_TOKEN === undefined) {
|
|
184
|
+
warn('no $GITHUB_TOKEN set; scanning anonymously. Private repositories will look missing and ' +
|
|
185
|
+
'the rate limit is low.');
|
|
186
|
+
}
|
|
187
|
+
let report;
|
|
188
|
+
try {
|
|
189
|
+
report = await (options.scan ?? assess)(cli.repos, {
|
|
190
|
+
token: env.GITHUB_TOKEN,
|
|
191
|
+
apiUrl: cli.apiUrl,
|
|
192
|
+
config,
|
|
193
|
+
now: options.now,
|
|
194
|
+
onWarning: (repo, warning) => warn(`${repo}: ${warning}`),
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
warn(describe(error));
|
|
199
|
+
return EXIT_SCAN_FAILED;
|
|
200
|
+
}
|
|
201
|
+
stdout(`${render(report, cli.format)}\n`);
|
|
202
|
+
if (cli.failBelow === undefined)
|
|
203
|
+
return EXIT_OK;
|
|
204
|
+
const failures = belowFloor(report, cli.failBelow);
|
|
205
|
+
if (failures.length === 0)
|
|
206
|
+
return EXIT_OK;
|
|
207
|
+
stderr(`${TOOL_NAME}: ${failures.length} repository/repositories graded below ${cli.failBelow} ` +
|
|
208
|
+
`(${failures.join(', ')})\n`);
|
|
209
|
+
return EXIT_BELOW_FLOOR;
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { run } from './cli.js';
|
|
3
|
+
process.exitCode = await run({
|
|
4
|
+
argv: process.argv.slice(2),
|
|
5
|
+
env: process.env,
|
|
6
|
+
stdout: (chunk) => process.stdout.write(chunk),
|
|
7
|
+
stderr: (chunk) => process.stderr.write(chunk),
|
|
8
|
+
});
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,OAAO,CAAC,QAAQ,GAAG,MAAM,GAAG,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3B,GAAG,EAAE,OAAO,CAAC,GAAG;IAChB,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;IAC9C,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;CAC/C,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fettle/cli",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Command-line interface for grading repository maintenance health.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://github.com/rumankazi/fettle#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/rumankazi/fettle.git",
|
|
10
|
+
"directory": "packages/cli"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/rumankazi/fettle/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"github",
|
|
17
|
+
"repository",
|
|
18
|
+
"maintenance",
|
|
19
|
+
"health",
|
|
20
|
+
"cli",
|
|
21
|
+
"ghes"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"bin": {
|
|
25
|
+
"fettle": "./dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=20"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@fettle/core": "0.1.3"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc -p tsconfig.build.json",
|
|
38
|
+
"typecheck": "tsc -p tsconfig.json"
|
|
39
|
+
}
|
|
40
|
+
}
|