hyouji 0.0.12 → 0.0.14
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/dist/index.js +83 -65
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -8,8 +8,7 @@ import * as path from "path";
|
|
|
8
8
|
import { join, dirname } from "path";
|
|
9
9
|
import { createHash, randomBytes, createCipheriv, createDecipheriv } from "crypto";
|
|
10
10
|
import prompts from "prompts";
|
|
11
|
-
import
|
|
12
|
-
import yaml__default from "js-yaml";
|
|
11
|
+
import YAML from "yaml";
|
|
13
12
|
import { Octokit } from "@octokit/core";
|
|
14
13
|
import { exec } from "child_process";
|
|
15
14
|
import { promisify } from "util";
|
|
@@ -1027,16 +1026,10 @@ const log$2 = console.log;
|
|
|
1027
1026
|
const generateSampleYaml = async () => {
|
|
1028
1027
|
try {
|
|
1029
1028
|
const outputPath = "./hyouji.yaml";
|
|
1030
|
-
const yamlContent =
|
|
1029
|
+
const yamlContent = YAML.stringify(sampleData, {
|
|
1031
1030
|
indent: 2,
|
|
1032
|
-
|
|
1033
|
-
// Disable line wrapping
|
|
1034
|
-
noRefs: true,
|
|
1035
|
-
// Disable references
|
|
1036
|
-
quotingType: '"',
|
|
1031
|
+
singleQuote: false
|
|
1037
1032
|
// Use double quotes for strings
|
|
1038
|
-
forceQuotes: false
|
|
1039
|
-
// Only quote when necessary
|
|
1040
1033
|
});
|
|
1041
1034
|
log$2(chalk.blue("Generating sample YAML file..."));
|
|
1042
1035
|
fs.writeFileSync(outputPath, yamlContent, "utf8");
|
|
@@ -1095,10 +1088,10 @@ const parseJsonContent = (content) => {
|
|
|
1095
1088
|
};
|
|
1096
1089
|
const parseYamlContent = (content) => {
|
|
1097
1090
|
try {
|
|
1098
|
-
return
|
|
1091
|
+
return YAML.parse(content);
|
|
1099
1092
|
} catch (error) {
|
|
1100
|
-
if (error instanceof
|
|
1101
|
-
throw new Error(`
|
|
1093
|
+
if (error instanceof Error) {
|
|
1094
|
+
throw new Error(`YAML Error: ${error.message}`);
|
|
1102
1095
|
}
|
|
1103
1096
|
throw error;
|
|
1104
1097
|
}
|
|
@@ -1280,6 +1273,13 @@ const getTargetLabel = async () => {
|
|
|
1280
1273
|
};
|
|
1281
1274
|
const GIT_COMMAND_TIMEOUT_MS = 5e3;
|
|
1282
1275
|
const _GitRepositoryDetector = class _GitRepositoryDetector {
|
|
1276
|
+
/**
|
|
1277
|
+
* Overrides the internal execAsync function for testing purposes.
|
|
1278
|
+
* @param mock - The mock function to use for execAsync.
|
|
1279
|
+
*/
|
|
1280
|
+
static overrideExecAsync(mock) {
|
|
1281
|
+
this.execAsyncInternal = mock;
|
|
1282
|
+
}
|
|
1283
1283
|
/**
|
|
1284
1284
|
* Detects Git repository information from the current working directory
|
|
1285
1285
|
* @param cwd - Current working directory (defaults to process.cwd())
|
|
@@ -1287,58 +1287,64 @@ const _GitRepositoryDetector = class _GitRepositoryDetector {
|
|
|
1287
1287
|
*/
|
|
1288
1288
|
static async detectRepository(cwd) {
|
|
1289
1289
|
const workingDir = cwd || process.cwd();
|
|
1290
|
+
let gitRoot;
|
|
1290
1291
|
try {
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
isGitRepository: false,
|
|
1295
|
-
error: "Not a Git repository"
|
|
1296
|
-
};
|
|
1297
|
-
}
|
|
1298
|
-
const remotes = await this.getAllRemotes(gitRoot);
|
|
1299
|
-
if (remotes.length === 0) {
|
|
1300
|
-
return {
|
|
1301
|
-
isGitRepository: true,
|
|
1302
|
-
error: "No remotes configured"
|
|
1303
|
-
};
|
|
1304
|
-
}
|
|
1305
|
-
let remoteUrl = null;
|
|
1306
|
-
let detectionMethod = "origin";
|
|
1307
|
-
if (remotes.includes("origin")) {
|
|
1308
|
-
remoteUrl = await this.getRemoteUrl(gitRoot, "origin");
|
|
1309
|
-
}
|
|
1310
|
-
if (!remoteUrl && remotes.length > 0) {
|
|
1311
|
-
remoteUrl = await this.getRemoteUrl(gitRoot, remotes[0]);
|
|
1312
|
-
detectionMethod = "first-remote";
|
|
1313
|
-
}
|
|
1314
|
-
if (!remoteUrl) {
|
|
1315
|
-
return {
|
|
1316
|
-
isGitRepository: true,
|
|
1317
|
-
error: "Could not retrieve remote URL"
|
|
1318
|
-
};
|
|
1319
|
-
}
|
|
1320
|
-
const parsedUrl = this.parseGitUrl(remoteUrl);
|
|
1321
|
-
if (!parsedUrl) {
|
|
1322
|
-
return {
|
|
1323
|
-
isGitRepository: true,
|
|
1324
|
-
error: "Could not parse remote URL"
|
|
1325
|
-
};
|
|
1326
|
-
}
|
|
1292
|
+
gitRoot = await this.findGitRoot(workingDir);
|
|
1293
|
+
} catch (err) {
|
|
1294
|
+
const error = err;
|
|
1327
1295
|
return {
|
|
1328
|
-
isGitRepository:
|
|
1329
|
-
|
|
1330
|
-
owner: parsedUrl.owner,
|
|
1331
|
-
repo: parsedUrl.repo,
|
|
1332
|
-
remoteUrl,
|
|
1333
|
-
detectionMethod
|
|
1334
|
-
}
|
|
1296
|
+
isGitRepository: false,
|
|
1297
|
+
error: error instanceof Error ? error.message : "Unknown error occurred"
|
|
1335
1298
|
};
|
|
1336
|
-
}
|
|
1299
|
+
}
|
|
1300
|
+
if (!gitRoot) {
|
|
1337
1301
|
return {
|
|
1338
1302
|
isGitRepository: false,
|
|
1339
|
-
error:
|
|
1303
|
+
error: "Not a Git repository"
|
|
1340
1304
|
};
|
|
1341
1305
|
}
|
|
1306
|
+
const remotesResult = await this.getAllRemotes(gitRoot);
|
|
1307
|
+
if ("error" in remotesResult) {
|
|
1308
|
+
return { isGitRepository: false, error: remotesResult.error };
|
|
1309
|
+
}
|
|
1310
|
+
const remotes = remotesResult.remotes;
|
|
1311
|
+
if (remotes.length === 0) {
|
|
1312
|
+
return {
|
|
1313
|
+
isGitRepository: true,
|
|
1314
|
+
error: "No remotes configured"
|
|
1315
|
+
};
|
|
1316
|
+
}
|
|
1317
|
+
let remoteUrl = null;
|
|
1318
|
+
let detectionMethod = "origin";
|
|
1319
|
+
if (remotes.includes("origin")) {
|
|
1320
|
+
remoteUrl = await this.getRemoteUrl(gitRoot, "origin");
|
|
1321
|
+
}
|
|
1322
|
+
if (!remoteUrl && remotes.length > 0) {
|
|
1323
|
+
remoteUrl = await this.getRemoteUrl(gitRoot, remotes[0]);
|
|
1324
|
+
detectionMethod = "first-remote";
|
|
1325
|
+
}
|
|
1326
|
+
if (!remoteUrl) {
|
|
1327
|
+
return {
|
|
1328
|
+
isGitRepository: true,
|
|
1329
|
+
error: "Could not retrieve remote URL"
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1332
|
+
const parsedUrl = this.parseGitUrl(remoteUrl);
|
|
1333
|
+
if (!parsedUrl) {
|
|
1334
|
+
return {
|
|
1335
|
+
isGitRepository: true,
|
|
1336
|
+
error: "Could not parse remote URL"
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
return {
|
|
1340
|
+
isGitRepository: true,
|
|
1341
|
+
repositoryInfo: {
|
|
1342
|
+
owner: parsedUrl.owner,
|
|
1343
|
+
repo: parsedUrl.repo,
|
|
1344
|
+
remoteUrl,
|
|
1345
|
+
detectionMethod
|
|
1346
|
+
}
|
|
1347
|
+
};
|
|
1342
1348
|
}
|
|
1343
1349
|
/**
|
|
1344
1350
|
* Finds the Git root directory by traversing up the directory tree
|
|
@@ -1354,6 +1360,9 @@ const _GitRepositoryDetector = class _GitRepositoryDetector {
|
|
|
1354
1360
|
}
|
|
1355
1361
|
currentPath = dirname(currentPath);
|
|
1356
1362
|
}
|
|
1363
|
+
if (existsSync(join(currentPath, ".git"))) {
|
|
1364
|
+
return currentPath;
|
|
1365
|
+
}
|
|
1357
1366
|
return null;
|
|
1358
1367
|
}
|
|
1359
1368
|
/**
|
|
@@ -1364,7 +1373,7 @@ const _GitRepositoryDetector = class _GitRepositoryDetector {
|
|
|
1364
1373
|
*/
|
|
1365
1374
|
static async getRemoteUrl(gitRoot, remoteName) {
|
|
1366
1375
|
try {
|
|
1367
|
-
const { stdout } = await
|
|
1376
|
+
const { stdout } = await this.execAsyncInternal(
|
|
1368
1377
|
`git remote get-url ${remoteName}`,
|
|
1369
1378
|
{
|
|
1370
1379
|
cwd: gitRoot,
|
|
@@ -1437,21 +1446,30 @@ const _GitRepositoryDetector = class _GitRepositoryDetector {
|
|
|
1437
1446
|
/**
|
|
1438
1447
|
* Gets all configured Git remotes
|
|
1439
1448
|
* @param gitRoot - Git repository root directory
|
|
1440
|
-
* @returns Promise
|
|
1449
|
+
* @returns Promise with remotes array or error object
|
|
1441
1450
|
*/
|
|
1442
1451
|
static async getAllRemotes(gitRoot) {
|
|
1443
1452
|
try {
|
|
1444
|
-
const { stdout } = await
|
|
1453
|
+
const { stdout } = await this.execAsyncInternal("git remote", {
|
|
1445
1454
|
cwd: gitRoot,
|
|
1446
1455
|
timeout: GIT_COMMAND_TIMEOUT_MS
|
|
1447
1456
|
});
|
|
1448
|
-
return
|
|
1449
|
-
|
|
1450
|
-
|
|
1457
|
+
return {
|
|
1458
|
+
remotes: stdout.trim().split("\n").filter((remote) => remote.length > 0)
|
|
1459
|
+
};
|
|
1460
|
+
} catch (err) {
|
|
1461
|
+
const error = err;
|
|
1462
|
+
if (error.code === "ENOENT") {
|
|
1463
|
+
return { error: "Git command not available" };
|
|
1464
|
+
}
|
|
1465
|
+
if (error instanceof Error && (error.message.includes("not a git repository") || error.message.includes("Not a git repository"))) {
|
|
1466
|
+
return { error: "Not a Git repository" };
|
|
1467
|
+
}
|
|
1468
|
+
return { remotes: [] };
|
|
1451
1469
|
}
|
|
1452
1470
|
}
|
|
1453
1471
|
};
|
|
1454
|
-
_GitRepositoryDetector.
|
|
1472
|
+
_GitRepositoryDetector.execAsyncInternal = promisify(exec);
|
|
1455
1473
|
let GitRepositoryDetector = _GitRepositoryDetector;
|
|
1456
1474
|
const getGitHubConfigs = async () => {
|
|
1457
1475
|
var _a, _b;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hyouji",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "Hyouji (表示) — A command-line tool for organizing and displaying GitHub labels with clarity and harmony.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "koji <baxin1919@gmail.com>",
|
|
@@ -58,16 +58,16 @@
|
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@octokit/core": "^7.0.6",
|
|
60
60
|
"chalk": "^5.6.2",
|
|
61
|
-
"js-yaml": "^4.1.0",
|
|
62
61
|
"oh-my-logo": "^0.3.2",
|
|
63
|
-
"prompts": "^2.4.2"
|
|
62
|
+
"prompts": "^2.4.2",
|
|
63
|
+
"yaml": "^2.8.1"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@biomejs/biome": "2.3.4",
|
|
67
|
-
"@types/js-yaml": "^4.0.9",
|
|
68
67
|
"@types/node": "^24.10.0",
|
|
69
68
|
"@vitest/coverage-v8": "^4.0.8",
|
|
70
69
|
"@vitest/ui": "^4.0.8",
|
|
70
|
+
"knip": "^5.68.0",
|
|
71
71
|
"standard-version": "^9.5.0",
|
|
72
72
|
"typescript": "^5.9.3",
|
|
73
73
|
"vite": "^7.2.2",
|