@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
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__publicField
|
|
3
|
+
} from "./chunk-QZ7TP4HQ.mjs";
|
|
4
|
+
|
|
5
|
+
// src/github/client.ts
|
|
6
|
+
import { execSync } from "child_process";
|
|
7
|
+
var GitHubClient = class {
|
|
8
|
+
constructor(options) {
|
|
9
|
+
__publicField(this, "owner");
|
|
10
|
+
__publicField(this, "repo");
|
|
11
|
+
__publicField(this, "repoPath");
|
|
12
|
+
this.owner = options.owner;
|
|
13
|
+
this.repo = options.repo;
|
|
14
|
+
this.repoPath = `${this.owner}/${this.repo}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Execute gh CLI command
|
|
18
|
+
*/
|
|
19
|
+
exec(command) {
|
|
20
|
+
try {
|
|
21
|
+
return execSync(command, {
|
|
22
|
+
encoding: "utf-8",
|
|
23
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
24
|
+
}).trim();
|
|
25
|
+
} catch (error) {
|
|
26
|
+
throw new Error(`gh CLI command failed: ${error.message}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Fetch all labels from repository
|
|
31
|
+
*/
|
|
32
|
+
async fetchLabels() {
|
|
33
|
+
try {
|
|
34
|
+
const output = this.exec(
|
|
35
|
+
`gh label list --repo ${this.repoPath} --json name,color,description --limit 1000`
|
|
36
|
+
);
|
|
37
|
+
if (!output) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
const labels = JSON.parse(output);
|
|
41
|
+
return labels.map((label) => ({
|
|
42
|
+
name: label.name,
|
|
43
|
+
color: label.color,
|
|
44
|
+
description: label.description || ""
|
|
45
|
+
}));
|
|
46
|
+
} catch (error) {
|
|
47
|
+
throw new Error(`Failed to fetch labels from ${this.repoPath}: ${error}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Create a new label
|
|
52
|
+
*/
|
|
53
|
+
async createLabel(label) {
|
|
54
|
+
try {
|
|
55
|
+
const name = label.name.replace(/"/g, '\\"');
|
|
56
|
+
const description = label.description.replace(/"/g, '\\"');
|
|
57
|
+
const color = label.color.replace("#", "");
|
|
58
|
+
this.exec(
|
|
59
|
+
`gh label create "${name}" --color "${color}" --description "${description}" --repo ${this.repoPath}`
|
|
60
|
+
);
|
|
61
|
+
return {
|
|
62
|
+
name: label.name,
|
|
63
|
+
color: label.color,
|
|
64
|
+
description: label.description
|
|
65
|
+
};
|
|
66
|
+
} catch (error) {
|
|
67
|
+
throw new Error(`Failed to create label "${label.name}": ${error}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Update an existing label
|
|
72
|
+
*/
|
|
73
|
+
async updateLabel(currentName, label) {
|
|
74
|
+
try {
|
|
75
|
+
const escapedCurrentName = currentName.replace(/"/g, '\\"');
|
|
76
|
+
const args = [];
|
|
77
|
+
if (label.name && label.name !== currentName) {
|
|
78
|
+
args.push(`--name "${label.name.replace(/"/g, '\\"')}"`);
|
|
79
|
+
}
|
|
80
|
+
if (label.color) {
|
|
81
|
+
args.push(`--color "${label.color.replace("#", "")}"`);
|
|
82
|
+
}
|
|
83
|
+
if (label.description !== void 0) {
|
|
84
|
+
args.push(`--description "${label.description.replace(/"/g, '\\"')}"`);
|
|
85
|
+
}
|
|
86
|
+
if (args.length === 0) {
|
|
87
|
+
return {
|
|
88
|
+
name: currentName,
|
|
89
|
+
color: label.color || "",
|
|
90
|
+
description: label.description || ""
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
this.exec(
|
|
94
|
+
`gh label edit "${escapedCurrentName}" ${args.join(" ")} --repo ${this.repoPath}`
|
|
95
|
+
);
|
|
96
|
+
return {
|
|
97
|
+
name: label.name || currentName,
|
|
98
|
+
color: label.color || "",
|
|
99
|
+
description: label.description || ""
|
|
100
|
+
};
|
|
101
|
+
} catch (error) {
|
|
102
|
+
throw new Error(`Failed to update label "${currentName}": ${error}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Delete a label
|
|
107
|
+
*/
|
|
108
|
+
async deleteLabel(name) {
|
|
109
|
+
try {
|
|
110
|
+
const escapedName = name.replace(/"/g, '\\"');
|
|
111
|
+
this.exec(`gh label delete "${escapedName}" --repo ${this.repoPath} --yes`);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
throw new Error(`Failed to delete label "${name}": ${error}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Check if label exists
|
|
118
|
+
*/
|
|
119
|
+
async hasLabel(name) {
|
|
120
|
+
try {
|
|
121
|
+
const labels = await this.fetchLabels();
|
|
122
|
+
return labels.some((label) => label.name.toLowerCase() === name.toLowerCase());
|
|
123
|
+
} catch (error) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// src/github/sync.ts
|
|
130
|
+
var GitHubLabelSync = class {
|
|
131
|
+
constructor(options) {
|
|
132
|
+
__publicField(this, "client");
|
|
133
|
+
__publicField(this, "options");
|
|
134
|
+
this.client = new GitHubClient(options);
|
|
135
|
+
this.options = options;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Log message if verbose mode is enabled
|
|
139
|
+
*/
|
|
140
|
+
log(message) {
|
|
141
|
+
if (this.options.verbose) {
|
|
142
|
+
console.log(`[labels-config] ${message}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Sync labels to GitHub repository
|
|
147
|
+
*/
|
|
148
|
+
async syncLabels(localLabels) {
|
|
149
|
+
this.log("Fetching remote labels...");
|
|
150
|
+
const remoteLabels = await this.client.fetchLabels();
|
|
151
|
+
const result = {
|
|
152
|
+
created: [],
|
|
153
|
+
updated: [],
|
|
154
|
+
deleted: [],
|
|
155
|
+
unchanged: [],
|
|
156
|
+
errors: []
|
|
157
|
+
};
|
|
158
|
+
const remoteLabelMap = new Map(remoteLabels.map((label) => [label.name.toLowerCase(), label]));
|
|
159
|
+
const localLabelMap = new Map(localLabels.map((label) => [label.name.toLowerCase(), label]));
|
|
160
|
+
for (const label of localLabels) {
|
|
161
|
+
const remoteLabel = remoteLabelMap.get(label.name.toLowerCase());
|
|
162
|
+
try {
|
|
163
|
+
if (!remoteLabel) {
|
|
164
|
+
if (!this.options.dryRun) {
|
|
165
|
+
await this.client.createLabel(label);
|
|
166
|
+
}
|
|
167
|
+
result.created.push(label);
|
|
168
|
+
this.log(`Created label: ${label.name}`);
|
|
169
|
+
} else if (this.hasChanges(label, remoteLabel)) {
|
|
170
|
+
if (!this.options.dryRun) {
|
|
171
|
+
await this.client.updateLabel(remoteLabel.name, label);
|
|
172
|
+
}
|
|
173
|
+
result.updated.push(label);
|
|
174
|
+
this.log(`Updated label: ${label.name}`);
|
|
175
|
+
} else {
|
|
176
|
+
result.unchanged.push(label);
|
|
177
|
+
this.log(`Unchanged label: ${label.name}`);
|
|
178
|
+
}
|
|
179
|
+
} catch (error) {
|
|
180
|
+
result.errors.push({
|
|
181
|
+
name: label.name,
|
|
182
|
+
error: error instanceof Error ? error.message : String(error)
|
|
183
|
+
});
|
|
184
|
+
this.log(`Error processing label "${label.name}": ${error}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (this.options.deleteExtra) {
|
|
188
|
+
for (const remoteLabel of remoteLabels) {
|
|
189
|
+
if (!localLabelMap.has(remoteLabel.name.toLowerCase())) {
|
|
190
|
+
try {
|
|
191
|
+
if (!this.options.dryRun) {
|
|
192
|
+
await this.client.deleteLabel(remoteLabel.name);
|
|
193
|
+
}
|
|
194
|
+
result.deleted.push(remoteLabel.name);
|
|
195
|
+
this.log(`Deleted label: ${remoteLabel.name}`);
|
|
196
|
+
} catch (error) {
|
|
197
|
+
result.errors.push({
|
|
198
|
+
name: remoteLabel.name,
|
|
199
|
+
error: error instanceof Error ? error.message : String(error)
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Check if label has changes
|
|
209
|
+
*/
|
|
210
|
+
hasChanges(local, remote) {
|
|
211
|
+
return local.color.toLowerCase() !== remote.color.toLowerCase() || local.description !== (remote.description || "");
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Fetch labels from GitHub
|
|
215
|
+
*/
|
|
216
|
+
async fetchLabels() {
|
|
217
|
+
const labels = await this.client.fetchLabels();
|
|
218
|
+
return labels.map((label) => ({
|
|
219
|
+
name: label.name,
|
|
220
|
+
color: label.color,
|
|
221
|
+
description: label.description || ""
|
|
222
|
+
}));
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Delete a single label
|
|
226
|
+
*/
|
|
227
|
+
async deleteLabel(name) {
|
|
228
|
+
if (!this.options.dryRun) {
|
|
229
|
+
await this.client.deleteLabel(name);
|
|
230
|
+
}
|
|
231
|
+
this.log(`Deleted label: ${name}`);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Update a single label
|
|
235
|
+
*/
|
|
236
|
+
async updateLabel(name, updates) {
|
|
237
|
+
if (!this.options.dryRun) {
|
|
238
|
+
await this.client.updateLabel(name, updates);
|
|
239
|
+
}
|
|
240
|
+
this.log(`Updated label: ${name}`);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
export {
|
|
245
|
+
GitHubClient,
|
|
246
|
+
GitHubLabelSync
|
|
247
|
+
};
|
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|