@asagiri-design/labels-config 0.2.2
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.ja.md +387 -0
- package/README.md +387 -0
- package/dist/chunk-4ZUJQMV7.mjs +285 -0
- package/dist/chunk-DGUMSQAI.mjs +496 -0
- package/dist/chunk-DSI7SDAM.mjs +161 -0
- package/dist/chunk-QJLMZSVA.mjs +496 -0
- package/dist/chunk-QZ7TP4HQ.mjs +7 -0
- package/dist/chunk-VU2JB66N.mjs +103 -0
- package/dist/chunk-ZYHIDOG2.mjs +247 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1417 -0
- package/dist/cli.mjs +436 -0
- package/dist/config/index.d.mts +49 -0
- package/dist/config/index.d.ts +49 -0
- package/dist/config/index.js +554 -0
- package/dist/config/index.mjs +10 -0
- package/dist/github/index.d.mts +113 -0
- package/dist/github/index.d.ts +113 -0
- package/dist/github/index.js +310 -0
- package/dist/github/index.mjs +9 -0
- package/dist/index.d.mts +309 -0
- package/dist/index.d.ts +309 -0
- package/dist/index.js +306 -0
- package/dist/index.mjs +44 -0
- package/dist/types-CkwsO1Iu.d.mts +50 -0
- package/dist/types-CkwsO1Iu.d.ts +50 -0
- package/docs/API.md +309 -0
- package/docs/GETTING_STARTED.md +305 -0
- package/package.json +87 -0
- package/templates/prod-labels.json +106 -0
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
LabelManager
|
|
4
|
+
} from "./chunk-DSI7SDAM.mjs";
|
|
5
|
+
import {
|
|
6
|
+
CONFIG_TEMPLATES,
|
|
7
|
+
ConfigLoader,
|
|
8
|
+
listTemplates
|
|
9
|
+
} from "./chunk-QJLMZSVA.mjs";
|
|
10
|
+
import {
|
|
11
|
+
validateWithDetails
|
|
12
|
+
} from "./chunk-VU2JB66N.mjs";
|
|
13
|
+
import {
|
|
14
|
+
GitHubLabelSync
|
|
15
|
+
} from "./chunk-4ZUJQMV7.mjs";
|
|
16
|
+
import {
|
|
17
|
+
__publicField
|
|
18
|
+
} from "./chunk-QZ7TP4HQ.mjs";
|
|
19
|
+
|
|
20
|
+
// src/cli.ts
|
|
21
|
+
import { promises as fs } from "fs";
|
|
22
|
+
|
|
23
|
+
// src/utils/args.ts
|
|
24
|
+
function parseArgs(argv) {
|
|
25
|
+
const result = {
|
|
26
|
+
command: void 0,
|
|
27
|
+
flags: /* @__PURE__ */ new Set(),
|
|
28
|
+
options: /* @__PURE__ */ new Map(),
|
|
29
|
+
positional: []
|
|
30
|
+
};
|
|
31
|
+
let i = 0;
|
|
32
|
+
if (i < argv.length && !argv[i].startsWith("-")) {
|
|
33
|
+
result.command = argv[i];
|
|
34
|
+
i++;
|
|
35
|
+
}
|
|
36
|
+
while (i < argv.length) {
|
|
37
|
+
const arg = argv[i];
|
|
38
|
+
if (arg.startsWith("--")) {
|
|
39
|
+
const parts = arg.split("=", 2);
|
|
40
|
+
if (parts.length === 2) {
|
|
41
|
+
result.options.set(parts[0], parts[1]);
|
|
42
|
+
i++;
|
|
43
|
+
} else {
|
|
44
|
+
const nextArg = argv[i + 1];
|
|
45
|
+
if (!nextArg || nextArg.startsWith("-")) {
|
|
46
|
+
result.flags.add(arg);
|
|
47
|
+
i++;
|
|
48
|
+
} else {
|
|
49
|
+
result.options.set(arg, nextArg);
|
|
50
|
+
i += 2;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} else if (arg.startsWith("-")) {
|
|
54
|
+
result.flags.add(arg);
|
|
55
|
+
i++;
|
|
56
|
+
} else {
|
|
57
|
+
result.positional.push(arg);
|
|
58
|
+
i++;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
function getRequiredOption(args, name, errorMessage) {
|
|
64
|
+
const value = args.options.get(name);
|
|
65
|
+
if (!value) {
|
|
66
|
+
throw new Error(errorMessage || `Missing required option: ${name}`);
|
|
67
|
+
}
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
function getOption(args, name, defaultValue) {
|
|
71
|
+
return args.options.get(name) || defaultValue;
|
|
72
|
+
}
|
|
73
|
+
function hasFlag(args, ...names) {
|
|
74
|
+
return names.some((name) => args.flags.has(name));
|
|
75
|
+
}
|
|
76
|
+
function getPositional(args, index) {
|
|
77
|
+
return args.positional[index];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/utils/ui.ts
|
|
81
|
+
var colors = {
|
|
82
|
+
reset: "\x1B[0m",
|
|
83
|
+
bright: "\x1B[1m",
|
|
84
|
+
dim: "\x1B[2m",
|
|
85
|
+
// Foreground colors
|
|
86
|
+
red: "\x1B[31m",
|
|
87
|
+
green: "\x1B[32m",
|
|
88
|
+
yellow: "\x1B[33m",
|
|
89
|
+
blue: "\x1B[34m",
|
|
90
|
+
magenta: "\x1B[35m",
|
|
91
|
+
cyan: "\x1B[36m",
|
|
92
|
+
white: "\x1B[37m",
|
|
93
|
+
gray: "\x1B[90m",
|
|
94
|
+
// Background colors
|
|
95
|
+
bgRed: "\x1B[41m",
|
|
96
|
+
bgGreen: "\x1B[42m",
|
|
97
|
+
bgYellow: "\x1B[43m",
|
|
98
|
+
bgBlue: "\x1B[44m"
|
|
99
|
+
};
|
|
100
|
+
function supportsColor() {
|
|
101
|
+
if (process.env.NO_COLOR) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
if (process.env.FORCE_COLOR) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
if (!process.stdout.isTTY) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
if (process.platform === "win32") {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
function colorize(text, color) {
|
|
116
|
+
if (!supportsColor()) {
|
|
117
|
+
return text;
|
|
118
|
+
}
|
|
119
|
+
return `${colors[color]}${text}${colors.reset}`;
|
|
120
|
+
}
|
|
121
|
+
function success(message) {
|
|
122
|
+
return colorize("\u2713", "green") + " " + message;
|
|
123
|
+
}
|
|
124
|
+
function error(message) {
|
|
125
|
+
return colorize("\u2717", "red") + " " + message;
|
|
126
|
+
}
|
|
127
|
+
function warning(message) {
|
|
128
|
+
return colorize("\u26A0", "yellow") + " " + message;
|
|
129
|
+
}
|
|
130
|
+
function info(message) {
|
|
131
|
+
return colorize("\u2139", "blue") + " " + message;
|
|
132
|
+
}
|
|
133
|
+
function header(text) {
|
|
134
|
+
return "\n" + colorize(text, "bright") + "\n" + "\u2500".repeat(Math.min(text.length, 50));
|
|
135
|
+
}
|
|
136
|
+
var Spinner = class {
|
|
137
|
+
constructor() {
|
|
138
|
+
__publicField(this, "frames", ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"]);
|
|
139
|
+
__publicField(this, "interval", null);
|
|
140
|
+
__publicField(this, "frameIndex", 0);
|
|
141
|
+
__publicField(this, "message", "");
|
|
142
|
+
}
|
|
143
|
+
start(message) {
|
|
144
|
+
this.message = message;
|
|
145
|
+
if (!process.stdout.isTTY || !supportsColor()) {
|
|
146
|
+
console.log(message + "...");
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this.interval = setInterval(() => {
|
|
150
|
+
const frame = this.frames[this.frameIndex];
|
|
151
|
+
process.stdout.write(`\r${colorize(frame, "cyan")} ${this.message}`);
|
|
152
|
+
this.frameIndex = (this.frameIndex + 1) % this.frames.length;
|
|
153
|
+
}, 80);
|
|
154
|
+
}
|
|
155
|
+
succeed(message) {
|
|
156
|
+
this.stop();
|
|
157
|
+
console.log(success(message || this.message));
|
|
158
|
+
}
|
|
159
|
+
fail(message) {
|
|
160
|
+
this.stop();
|
|
161
|
+
console.log(error(message || this.message));
|
|
162
|
+
}
|
|
163
|
+
warn(message) {
|
|
164
|
+
this.stop();
|
|
165
|
+
console.log(warning(message || this.message));
|
|
166
|
+
}
|
|
167
|
+
stop() {
|
|
168
|
+
if (this.interval) {
|
|
169
|
+
clearInterval(this.interval);
|
|
170
|
+
this.interval = null;
|
|
171
|
+
if (process.stdout.isTTY) {
|
|
172
|
+
process.stdout.write("\r\x1B[K");
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// src/cli.ts
|
|
179
|
+
var rawArgs = process.argv.slice(2);
|
|
180
|
+
var parsedArgs = parseArgs(rawArgs);
|
|
181
|
+
function printUsage() {
|
|
182
|
+
console.log(colorize("\nlabels-config", "bright") + " - Terminal-first GitHub label management\n");
|
|
183
|
+
console.log(header("Commands"));
|
|
184
|
+
console.log(" " + colorize("validate", "cyan") + " <file> Validate label configuration file");
|
|
185
|
+
console.log(" " + colorize("sync", "cyan") + " Sync labels to GitHub repository");
|
|
186
|
+
console.log(" " + colorize("export", "cyan") + " Export labels from GitHub repository");
|
|
187
|
+
console.log(" " + colorize("init", "cyan") + " <template> Initialize new configuration");
|
|
188
|
+
console.log(" " + colorize("help", "cyan") + " Show this help message");
|
|
189
|
+
console.log(header("Prerequisites"));
|
|
190
|
+
console.log(" " + info("gh CLI must be installed and authenticated"));
|
|
191
|
+
console.log(" Run: " + colorize("gh auth login", "yellow"));
|
|
192
|
+
console.log(" No GitHub token required - uses gh CLI authentication");
|
|
193
|
+
console.log(header("Options"));
|
|
194
|
+
console.log(" " + colorize("--owner", "green") + " <owner> Repository owner (required for sync/export)");
|
|
195
|
+
console.log(" " + colorize("--repo", "green") + " <repo> Repository name (required for sync/export)");
|
|
196
|
+
console.log(" " + colorize("--file", "green") + " <file> Configuration file path");
|
|
197
|
+
console.log(" " + colorize("--dry-run", "green") + " Dry run mode (don't make changes)");
|
|
198
|
+
console.log(" " + colorize("--delete-extra", "green") + " Replace mode: delete labels not in config");
|
|
199
|
+
console.log(" " + colorize("--verbose", "green") + " Verbose output");
|
|
200
|
+
console.log(header("Available Templates"));
|
|
201
|
+
console.log(" " + colorize("minimal", "magenta") + " Basic 3-label set (bug, feature, documentation)");
|
|
202
|
+
console.log(" " + colorize("github", "magenta") + " GitHub standard labels");
|
|
203
|
+
console.log(" " + colorize("react", "magenta") + " React ecosystem (components, hooks, state)");
|
|
204
|
+
console.log(" " + colorize("vue", "magenta") + " Vue.js ecosystem (composables, Pinia, router)");
|
|
205
|
+
console.log(" " + colorize("frontend", "magenta") + " General frontend development");
|
|
206
|
+
console.log(" " + colorize("prod-en", "magenta") + " Production project (14 labels, English)");
|
|
207
|
+
console.log(" " + colorize("prod-ja", "magenta") + " Production project (14 labels, Japanese)");
|
|
208
|
+
console.log(" " + colorize("prod", "magenta") + " Production project (alias for prod-ja)");
|
|
209
|
+
console.log(" " + colorize("agile", "magenta") + " Agile/Scrum workflow");
|
|
210
|
+
console.log(header("Examples"));
|
|
211
|
+
console.log(" # Validate configuration");
|
|
212
|
+
console.log(" " + colorize("labels-config validate ./labels.json", "gray"));
|
|
213
|
+
console.log("");
|
|
214
|
+
console.log(" # Initialize from template");
|
|
215
|
+
console.log(" " + colorize("labels-config init react --file ./labels.json", "gray"));
|
|
216
|
+
console.log("");
|
|
217
|
+
console.log(" # Sync labels (append mode)");
|
|
218
|
+
console.log(" " + colorize("labels-config sync --owner user --repo repo --file labels.json", "gray"));
|
|
219
|
+
console.log("");
|
|
220
|
+
console.log(" # Sync with dry run");
|
|
221
|
+
console.log(" " + colorize("labels-config sync --owner user --repo repo --file labels.json --dry-run", "gray"));
|
|
222
|
+
console.log("");
|
|
223
|
+
}
|
|
224
|
+
async function validateCommand() {
|
|
225
|
+
const file = getPositional(parsedArgs, 0);
|
|
226
|
+
if (!file) {
|
|
227
|
+
console.error(error("File path required"));
|
|
228
|
+
console.error("Usage: labels-config validate <file>");
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
const spinner = new Spinner();
|
|
232
|
+
try {
|
|
233
|
+
try {
|
|
234
|
+
await fs.access(file);
|
|
235
|
+
} catch {
|
|
236
|
+
console.error(error(`File not found: ${file}`));
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
|
239
|
+
spinner.start(`Reading ${file}`);
|
|
240
|
+
const content = await fs.readFile(file, "utf-8");
|
|
241
|
+
let data;
|
|
242
|
+
try {
|
|
243
|
+
data = JSON.parse(content);
|
|
244
|
+
} catch (err) {
|
|
245
|
+
spinner.fail(`Invalid JSON in file: ${file}`);
|
|
246
|
+
console.error(error(err instanceof Error ? err.message : String(err)));
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
spinner.stop();
|
|
250
|
+
spinner.start("Validating configuration");
|
|
251
|
+
const result = validateWithDetails(data);
|
|
252
|
+
spinner.stop();
|
|
253
|
+
console.log(info(`Validating: ${file}`));
|
|
254
|
+
console.log(info(`Total labels: ${result.labels.length}`));
|
|
255
|
+
if (result.valid) {
|
|
256
|
+
console.log(success("Configuration is valid!"));
|
|
257
|
+
return;
|
|
258
|
+
} else {
|
|
259
|
+
console.log(error("Validation errors found:"));
|
|
260
|
+
const errors = result.errors;
|
|
261
|
+
if (errors.duplicateNames && errors.duplicateNames.length > 0) {
|
|
262
|
+
console.log(colorize(` \u2022 Duplicate names: ${errors.duplicateNames.join(", ")}`, "red"));
|
|
263
|
+
}
|
|
264
|
+
if (errors.duplicateColors && errors.duplicateColors.length > 0) {
|
|
265
|
+
console.log(colorize(` \u2022 Duplicate colors: ${errors.duplicateColors.join(", ")}`, "red"));
|
|
266
|
+
}
|
|
267
|
+
if (errors.validationErrors && errors.validationErrors.length > 0) {
|
|
268
|
+
console.log(colorize(" \u2022 Validation errors:", "red"));
|
|
269
|
+
errors.validationErrors.forEach((err) => {
|
|
270
|
+
console.log(` ${err.path.join(".")}: ${err.message}`);
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
process.exit(1);
|
|
274
|
+
}
|
|
275
|
+
} catch (err) {
|
|
276
|
+
spinner.fail("Validation failed");
|
|
277
|
+
console.error(error(err instanceof Error ? err.message : String(err)));
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
async function syncCommand() {
|
|
282
|
+
const spinner = new Spinner();
|
|
283
|
+
try {
|
|
284
|
+
const owner = getRequiredOption(parsedArgs, "--owner", "Error: --owner is required for sync command");
|
|
285
|
+
const repo = getRequiredOption(parsedArgs, "--repo", "Error: --repo is required for sync command");
|
|
286
|
+
const file = getRequiredOption(parsedArgs, "--file", "Error: --file is required for sync command");
|
|
287
|
+
const dryRun = hasFlag(parsedArgs, "--dry-run");
|
|
288
|
+
const deleteExtra = hasFlag(parsedArgs, "--delete-extra");
|
|
289
|
+
const verbose = hasFlag(parsedArgs, "--verbose");
|
|
290
|
+
try {
|
|
291
|
+
await fs.access(file);
|
|
292
|
+
} catch {
|
|
293
|
+
console.error(error(`File not found: ${file}`));
|
|
294
|
+
process.exit(1);
|
|
295
|
+
}
|
|
296
|
+
spinner.start(`Loading labels from ${file}`);
|
|
297
|
+
const content = await fs.readFile(file, "utf-8");
|
|
298
|
+
let labels;
|
|
299
|
+
try {
|
|
300
|
+
const loader = new ConfigLoader();
|
|
301
|
+
labels = loader.loadFromString(content);
|
|
302
|
+
spinner.succeed(`Loaded ${labels.length} labels`);
|
|
303
|
+
} catch (err) {
|
|
304
|
+
spinner.fail(`Failed to load labels from file: ${file}`);
|
|
305
|
+
console.error(error(err instanceof Error ? err.message : String(err)));
|
|
306
|
+
process.exit(1);
|
|
307
|
+
}
|
|
308
|
+
const sync = new GitHubLabelSync({
|
|
309
|
+
owner,
|
|
310
|
+
repo,
|
|
311
|
+
dryRun,
|
|
312
|
+
deleteExtra,
|
|
313
|
+
verbose
|
|
314
|
+
});
|
|
315
|
+
const modeText = dryRun ? colorize("[DRY RUN]", "yellow") : "";
|
|
316
|
+
console.log(`
|
|
317
|
+
${modeText} ${info(`Syncing to ${owner}/${repo}`)}`);
|
|
318
|
+
if (deleteExtra) {
|
|
319
|
+
console.log(warning("Replace mode: Will delete labels not in config"));
|
|
320
|
+
}
|
|
321
|
+
spinner.start("Syncing labels");
|
|
322
|
+
const result = await sync.syncLabels(labels);
|
|
323
|
+
spinner.succeed("Sync complete");
|
|
324
|
+
console.log(header("Results"));
|
|
325
|
+
if (result.created.length > 0) {
|
|
326
|
+
console.log(success(`Created: ${result.created.length}`));
|
|
327
|
+
if (verbose) {
|
|
328
|
+
result.created.forEach((label) => console.log(` \u2022 ${label.name}`));
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (result.updated.length > 0) {
|
|
332
|
+
console.log(info(`Updated: ${result.updated.length}`));
|
|
333
|
+
if (verbose) {
|
|
334
|
+
result.updated.forEach((label) => console.log(` \u2022 ${label.name}`));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (result.deleted.length > 0) {
|
|
338
|
+
console.log(warning(`Deleted: ${result.deleted.length}`));
|
|
339
|
+
if (verbose) {
|
|
340
|
+
result.deleted.forEach((name) => console.log(` \u2022 ${name}`));
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
if (result.unchanged.length > 0) {
|
|
344
|
+
console.log(colorize(`Unchanged: ${result.unchanged.length}`, "gray"));
|
|
345
|
+
}
|
|
346
|
+
if (result.errors.length > 0) {
|
|
347
|
+
console.log(header("Errors"));
|
|
348
|
+
result.errors.forEach((err) => {
|
|
349
|
+
console.log(error(`${err.name}: ${err.error}`));
|
|
350
|
+
});
|
|
351
|
+
process.exit(1);
|
|
352
|
+
}
|
|
353
|
+
} catch (err) {
|
|
354
|
+
spinner.fail("Sync failed");
|
|
355
|
+
console.error(error(err instanceof Error ? err.message : String(err)));
|
|
356
|
+
process.exit(1);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
async function exportCommand() {
|
|
360
|
+
const spinner = new Spinner();
|
|
361
|
+
try {
|
|
362
|
+
const owner = getRequiredOption(parsedArgs, "--owner", "Error: --owner is required for export command");
|
|
363
|
+
const repo = getRequiredOption(parsedArgs, "--repo", "Error: --repo is required for export command");
|
|
364
|
+
const file = getOption(parsedArgs, "--file") || "labels.json";
|
|
365
|
+
spinner.start(`Fetching labels from ${owner}/${repo}`);
|
|
366
|
+
const sync = new GitHubLabelSync({ owner, repo });
|
|
367
|
+
const labels = await sync.fetchLabels();
|
|
368
|
+
spinner.succeed(`Fetched ${labels.length} labels`);
|
|
369
|
+
spinner.start("Creating registry");
|
|
370
|
+
const manager = new LabelManager({ labels });
|
|
371
|
+
const registry = manager.exportRegistry("1.0.0", { source: `${owner}/${repo}` });
|
|
372
|
+
await fs.writeFile(file, JSON.stringify(registry, null, 2));
|
|
373
|
+
spinner.succeed(`Exported to ${file}`);
|
|
374
|
+
console.log(success(`Successfully exported ${labels.length} labels`));
|
|
375
|
+
} catch (err) {
|
|
376
|
+
spinner.fail("Export failed");
|
|
377
|
+
console.error(error(err instanceof Error ? err.message : String(err)));
|
|
378
|
+
process.exit(1);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
async function initCommand() {
|
|
382
|
+
const template = getPositional(parsedArgs, 0);
|
|
383
|
+
const file = getOption(parsedArgs, "--file") || "labels.json";
|
|
384
|
+
if (!template || !listTemplates().includes(template)) {
|
|
385
|
+
console.log(error(`Invalid template "${template || ""}"`));
|
|
386
|
+
console.log(info("Available templates: ") + listTemplates().map((t) => colorize(t, "magenta")).join(", "));
|
|
387
|
+
process.exit(1);
|
|
388
|
+
}
|
|
389
|
+
const spinner = new Spinner();
|
|
390
|
+
try {
|
|
391
|
+
spinner.start(`Creating configuration from "${template}" template`);
|
|
392
|
+
const labels = CONFIG_TEMPLATES[template];
|
|
393
|
+
const manager = new LabelManager({ labels });
|
|
394
|
+
const registry = manager.exportRegistry("1.0.0");
|
|
395
|
+
await fs.writeFile(file, JSON.stringify(registry, null, 2));
|
|
396
|
+
spinner.succeed(`Created ${file}`);
|
|
397
|
+
console.log(success(`Initialized with ${labels.length} labels from "${template}" template`));
|
|
398
|
+
console.log(info("Next steps:"));
|
|
399
|
+
console.log(` 1. Review and edit: ${colorize(file, "cyan")}`);
|
|
400
|
+
console.log(` 2. Validate: ${colorize(`labels-config validate ${file}`, "gray")}`);
|
|
401
|
+
console.log(` 3. Sync to repo: ${colorize(`labels-config sync --owner <owner> --repo <repo> --file ${file}`, "gray")}`);
|
|
402
|
+
} catch (err) {
|
|
403
|
+
spinner.fail("Initialization failed");
|
|
404
|
+
console.error(error(err instanceof Error ? err.message : String(err)));
|
|
405
|
+
process.exit(1);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
async function main() {
|
|
409
|
+
const command = parsedArgs.command;
|
|
410
|
+
if (!command || command === "help" || hasFlag(parsedArgs, "--help", "-h")) {
|
|
411
|
+
printUsage();
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
switch (command) {
|
|
415
|
+
case "validate":
|
|
416
|
+
await validateCommand();
|
|
417
|
+
break;
|
|
418
|
+
case "sync":
|
|
419
|
+
await syncCommand();
|
|
420
|
+
break;
|
|
421
|
+
case "export":
|
|
422
|
+
await exportCommand();
|
|
423
|
+
break;
|
|
424
|
+
case "init":
|
|
425
|
+
await initCommand();
|
|
426
|
+
break;
|
|
427
|
+
default:
|
|
428
|
+
console.error(`Unknown command: ${command}`);
|
|
429
|
+
printUsage();
|
|
430
|
+
process.exit(1);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
main().catch((error2) => {
|
|
434
|
+
console.error("Fatal error:", error2);
|
|
435
|
+
process.exit(1);
|
|
436
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { L as LabelConfig, a as LabelRegistry } from '../types-CkwsO1Iu.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration Loader
|
|
5
|
+
* Load label configurations from files and various sources
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface LoaderOptions {
|
|
9
|
+
/** Strict validation mode */
|
|
10
|
+
strict?: boolean;
|
|
11
|
+
}
|
|
12
|
+
declare class ConfigLoader {
|
|
13
|
+
private strict;
|
|
14
|
+
constructor(options?: LoaderOptions);
|
|
15
|
+
/**
|
|
16
|
+
* Load labels from JSON object
|
|
17
|
+
*/
|
|
18
|
+
loadFromJSON(data: unknown): LabelConfig[];
|
|
19
|
+
/**
|
|
20
|
+
* Load from JSON string
|
|
21
|
+
*/
|
|
22
|
+
loadFromString(jsonString: string): LabelConfig[];
|
|
23
|
+
/**
|
|
24
|
+
* Load from registry object
|
|
25
|
+
*/
|
|
26
|
+
loadRegistry(registry: LabelRegistry): LabelConfig[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Configuration Templates
|
|
31
|
+
* Pre-built label configurations for common use cases
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* All available templates
|
|
36
|
+
*/
|
|
37
|
+
declare const CONFIG_TEMPLATES: {
|
|
38
|
+
minimal: LabelConfig[];
|
|
39
|
+
github: LabelConfig[];
|
|
40
|
+
react: LabelConfig[];
|
|
41
|
+
vue: LabelConfig[];
|
|
42
|
+
frontend: LabelConfig[];
|
|
43
|
+
'prod-en': LabelConfig[];
|
|
44
|
+
'prod-ja': LabelConfig[];
|
|
45
|
+
prod: LabelConfig[];
|
|
46
|
+
agile: LabelConfig[];
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export { CONFIG_TEMPLATES, ConfigLoader, type LoaderOptions };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { L as LabelConfig, a as LabelRegistry } from '../types-CkwsO1Iu.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration Loader
|
|
5
|
+
* Load label configurations from files and various sources
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface LoaderOptions {
|
|
9
|
+
/** Strict validation mode */
|
|
10
|
+
strict?: boolean;
|
|
11
|
+
}
|
|
12
|
+
declare class ConfigLoader {
|
|
13
|
+
private strict;
|
|
14
|
+
constructor(options?: LoaderOptions);
|
|
15
|
+
/**
|
|
16
|
+
* Load labels from JSON object
|
|
17
|
+
*/
|
|
18
|
+
loadFromJSON(data: unknown): LabelConfig[];
|
|
19
|
+
/**
|
|
20
|
+
* Load from JSON string
|
|
21
|
+
*/
|
|
22
|
+
loadFromString(jsonString: string): LabelConfig[];
|
|
23
|
+
/**
|
|
24
|
+
* Load from registry object
|
|
25
|
+
*/
|
|
26
|
+
loadRegistry(registry: LabelRegistry): LabelConfig[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Configuration Templates
|
|
31
|
+
* Pre-built label configurations for common use cases
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* All available templates
|
|
36
|
+
*/
|
|
37
|
+
declare const CONFIG_TEMPLATES: {
|
|
38
|
+
minimal: LabelConfig[];
|
|
39
|
+
github: LabelConfig[];
|
|
40
|
+
react: LabelConfig[];
|
|
41
|
+
vue: LabelConfig[];
|
|
42
|
+
frontend: LabelConfig[];
|
|
43
|
+
'prod-en': LabelConfig[];
|
|
44
|
+
'prod-ja': LabelConfig[];
|
|
45
|
+
prod: LabelConfig[];
|
|
46
|
+
agile: LabelConfig[];
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export { CONFIG_TEMPLATES, ConfigLoader, type LoaderOptions };
|