git-push-time 1.1.0 → 1.1.1
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/.github/workflows/npm-publish.yml +33 -0
- package/README.md +215 -215
- package/bin/index.js +337 -291
- package/lib/commands/edit-time.js +141 -127
- package/lib/commands/fix.js +113 -105
- package/lib/commands/github.js +439 -436
- package/lib/commands/pull.js +89 -88
- package/lib/commands/push.js +673 -653
- package/lib/config.js +220 -210
- package/lib/fix.js +286 -260
- package/lib/git.js +492 -452
- package/lib/github.js +322 -304
- package/lib/prompt-helpers.js +62 -62
- package/lib/secrets.js +92 -87
- package/lib/ui.js +804 -844
- package/lib/utils.js +120 -106
- package/package.json +35 -32
package/lib/utils.js
CHANGED
|
@@ -1,106 +1,120 @@
|
|
|
1
|
-
import dayjs from 'dayjs';
|
|
2
|
-
import customParseFormat from 'dayjs/plugin/customParseFormat.js';
|
|
3
|
-
|
|
4
|
-
dayjs.extend(customParseFormat);
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Kiểm tra xem URL git có hợp lệ hay không (HTTP/HTTPS, SSH, hoặc `.git`)
|
|
8
|
-
* @param {string} url
|
|
9
|
-
* @returns {boolean}
|
|
10
|
-
*/
|
|
11
|
-
export function isValidGitUrl(url) {
|
|
12
|
-
if (!url || typeof url !== 'string') return false;
|
|
13
|
-
const trimmed = url.trim();
|
|
14
|
-
// Standard git remote URL patterns: https://, http://, git@, ssh://, or file path
|
|
15
|
-
const gitRegex = /^(https?:\/\/|git@|ssh:\/\/|ftps?:\/\/).+$/i;
|
|
16
|
-
return gitRegex.test(trimmed) || trimmed.endsWith('.git');
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Parse chuỗi thời gian thành định dạng ISO/Git hợp lệ.
|
|
21
|
-
* Hỗ trợ các định dạng:
|
|
22
|
-
* - "now" hoặc để trống -> Thời gian hiện tại
|
|
23
|
-
* - Relative
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
else if (
|
|
55
|
-
else if (
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
import customParseFormat from 'dayjs/plugin/customParseFormat.js';
|
|
3
|
+
|
|
4
|
+
dayjs.extend(customParseFormat);
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Kiểm tra xem URL git có hợp lệ hay không (HTTP/HTTPS, SSH, hoặc `.git`)
|
|
8
|
+
* @param {string} url
|
|
9
|
+
* @returns {boolean}
|
|
10
|
+
*/
|
|
11
|
+
export function isValidGitUrl(url) {
|
|
12
|
+
if (!url || typeof url !== 'string') return false;
|
|
13
|
+
const trimmed = url.trim();
|
|
14
|
+
// Standard git remote URL patterns: https://, http://, git@, ssh://, or file path
|
|
15
|
+
const gitRegex = /^(https?:\/\/|git@|ssh:\/\/|ftps?:\/\/).+$/i;
|
|
16
|
+
return gitRegex.test(trimmed) || trimmed.endsWith('.git');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Parse chuỗi thời gian thành định dạng ISO/Git hợp lệ.
|
|
21
|
+
* Hỗ trợ các định dạng:
|
|
22
|
+
* - "now" hoặc để trống -> Thời gian hiện tại
|
|
23
|
+
* - Relative (phân biệt hoa/thường cho đơn vị 1 ký tự):
|
|
24
|
+
* s=second, m=minute, h=hour, d=day, w=week, M=month, y=year
|
|
25
|
+
* VD: "-2d", "-5h", "-30m" (phút), "-1w", "-3M"/"-3mo"/"-3month" (tháng), "-1y"
|
|
26
|
+
* - Absolute: "YYYY-MM-DD HH:mm:ss", "YYYY-MM-DD HH:mm", "YYYY-MM-DD"
|
|
27
|
+
*
|
|
28
|
+
* @param {string} dateStr
|
|
29
|
+
* @returns {{ valid: boolean, formatted: string, display: string, error?: string }}
|
|
30
|
+
*/
|
|
31
|
+
export function parseCustomDate(dateStr) {
|
|
32
|
+
if (!dateStr || dateStr.trim().toLowerCase() === 'now') {
|
|
33
|
+
const now = dayjs();
|
|
34
|
+
return {
|
|
35
|
+
valid: true,
|
|
36
|
+
formatted: now.toISOString(),
|
|
37
|
+
display: now.format('YYYY-MM-DD HH:mm:ss Z')
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const str = dateStr.trim();
|
|
42
|
+
|
|
43
|
+
// Kiểm tra relative time: ví dụ -2d, -5h, -30m, -1w, -3M/-3mo, -1y hoặc 2d, 5h
|
|
44
|
+
// Lưu ý: đơn vị 1 ký tự phân biệt hoa/thường (m = minute, M = month).
|
|
45
|
+
const relativeMatch = str.match(/^([+-]?\d+)\s*(\S+)$/);
|
|
46
|
+
if (relativeMatch) {
|
|
47
|
+
let amount = parseInt(relativeMatch[1], 10);
|
|
48
|
+
const unitRaw = relativeMatch[2];
|
|
49
|
+
const unitLower = unitRaw.toLowerCase();
|
|
50
|
+
|
|
51
|
+
// Map unit: ưu tiên so khớp từ dài trước, đơn vị 1 ký tự giữ case-sensitive
|
|
52
|
+
let unit = null;
|
|
53
|
+
if (['sec', 'secs', 'second', 'seconds'].includes(unitLower)) unit = 'second';
|
|
54
|
+
else if (['min', 'mins', 'minute', 'minutes'].includes(unitLower)) unit = 'minute';
|
|
55
|
+
else if (['hour', 'hours'].includes(unitLower)) unit = 'hour';
|
|
56
|
+
else if (['day', 'days'].includes(unitLower)) unit = 'day';
|
|
57
|
+
else if (['week', 'weeks'].includes(unitLower)) unit = 'week';
|
|
58
|
+
else if (['mo', 'mos', 'month', 'months'].includes(unitLower)) unit = 'month';
|
|
59
|
+
else if (['year', 'years'].includes(unitLower)) unit = 'year';
|
|
60
|
+
else if (unitRaw === 's') unit = 'second';
|
|
61
|
+
else if (unitRaw === 'm') unit = 'minute';
|
|
62
|
+
else if (unitRaw === 'h') unit = 'hour';
|
|
63
|
+
else if (unitRaw === 'd') unit = 'day';
|
|
64
|
+
else if (unitRaw === 'w') unit = 'week';
|
|
65
|
+
else if (unitRaw === 'M') unit = 'month';
|
|
66
|
+
else if (unitRaw === 'y' || unitRaw === 'Y') unit = 'year';
|
|
67
|
+
|
|
68
|
+
if (unit) {
|
|
69
|
+
// Nếu người dùng nhập "2d" mà không có dấu "-", mặc định hiểu là "lùi 2d" (-2d)
|
|
70
|
+
if (amount > 0 && !str.startsWith('+')) {
|
|
71
|
+
amount = -amount;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const calculated = dayjs().add(amount, unit);
|
|
75
|
+
if (!calculated.isValid()) {
|
|
76
|
+
return { valid: false, formatted: '', display: '', error: `Không thể tính toán thời gian từ '${dateStr}'` };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
valid: true,
|
|
81
|
+
formatted: calculated.toISOString(),
|
|
82
|
+
display: calculated.format('YYYY-MM-DD HH:mm:ss Z')
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// Rơi xuống parse absolute nếu unit không khớp (vd user gõ nhầm sẽ báo lỗi ở dưới)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Thủ định dạng ngày giờ tuyệt đối
|
|
89
|
+
const formats = [
|
|
90
|
+
'YYYY-MM-DD HH:mm:ss',
|
|
91
|
+
'YYYY-MM-DD HH:mm',
|
|
92
|
+
'YYYY-MM-DD',
|
|
93
|
+
'YYYY/MM/DD HH:mm:ss',
|
|
94
|
+
'YYYY/MM/DD HH:mm',
|
|
95
|
+
'YYYY/MM/DD',
|
|
96
|
+
'DD/MM/YYYY HH:mm:ss',
|
|
97
|
+
'DD/MM/YYYY HH:mm',
|
|
98
|
+
'DD/MM/YYYY'
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
let parsed = dayjs(str, formats, true);
|
|
102
|
+
if (!parsed.isValid()) {
|
|
103
|
+
parsed = dayjs(str); // Thử parse chuẩn ISO
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (parsed.isValid()) {
|
|
107
|
+
return {
|
|
108
|
+
valid: true,
|
|
109
|
+
formatted: parsed.toISOString(),
|
|
110
|
+
display: parsed.format('YYYY-MM-DD HH:mm:ss Z')
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
valid: false,
|
|
116
|
+
formatted: '',
|
|
117
|
+
display: '',
|
|
118
|
+
error: `Định dạng ngày giờ không hợp lệ: '${dateStr}'. Ví dụ đúng: "2024-01-15 14:30:00", "-2d", "-5h", "now"`
|
|
119
|
+
};
|
|
120
|
+
}
|
package/package.json
CHANGED
|
@@ -1,32 +1,35 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "git-push-time",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"description": "CLI tool to push project to Git with custom repo URL and custom commit timestamp",
|
|
5
|
-
"main": "bin/index.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"bin": {
|
|
8
|
-
"githubcli": "bin/index.js",
|
|
9
|
-
"git-push-time": "bin/index.js",
|
|
10
|
-
"git-custom-push": "bin/index.js"
|
|
11
|
-
},
|
|
12
|
-
"scripts": {
|
|
13
|
-
"start": "node bin/index.js"
|
|
14
|
-
},
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "git-push-time",
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "CLI tool to push project to Git with custom repo URL and custom commit timestamp",
|
|
5
|
+
"main": "bin/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"githubcli": "bin/index.js",
|
|
9
|
+
"git-push-time": "bin/index.js",
|
|
10
|
+
"git-custom-push": "bin/index.js"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"start": "node bin/index.js"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"git",
|
|
20
|
+
"push",
|
|
21
|
+
"commit-date",
|
|
22
|
+
"backdate",
|
|
23
|
+
"cli"
|
|
24
|
+
],
|
|
25
|
+
"author": "",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@inquirer/prompts": "^7.3.2",
|
|
29
|
+
"chalk": "^5.4.1",
|
|
30
|
+
"commander": "^13.1.0",
|
|
31
|
+
"dayjs": "^1.11.13",
|
|
32
|
+
"ora": "^8.2.0",
|
|
33
|
+
"string-width": "^7.2.0"
|
|
34
|
+
}
|
|
35
|
+
}
|