git-push-time 1.1.2 → 1.1.4
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 +59 -32
- package/README.md +110 -112
- package/bin/index.js +321 -339
- package/lib/commands/edit-time.js +141 -141
- package/lib/commands/fix.js +113 -113
- package/lib/commands/github.js +429 -445
- package/lib/commands/pull.js +90 -90
- package/lib/commands/push.js +720 -720
- package/lib/config.js +220 -220
- package/lib/fix.js +286 -286
- package/lib/git.js +525 -516
- package/lib/github.js +322 -322
- package/lib/prompt-helpers.js +19 -20
- package/lib/secrets.js +92 -92
- package/lib/ui.js +1057 -1063
- package/lib/utils.js +120 -120
- package/package.json +36 -36
package/lib/utils.js
CHANGED
|
@@ -1,120 +1,120 @@
|
|
|
1
|
-
import dayjs from 'dayjs';
|
|
2
|
-
import customParseFormat from 'dayjs/plugin/customParseFormat.js';
|
|
3
|
-
|
|
4
|
-
dayjs.extend(customParseFormat);
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
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
|
|
21
|
-
*
|
|
22
|
-
* - "now"
|
|
23
|
-
* - Relative (
|
|
24
|
-
* s=second, m=minute, h=hour, d=day, w=week, M=month, y=year
|
|
25
|
-
*
|
|
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
|
-
//
|
|
44
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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: `
|
|
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
|
-
//
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
//
|
|
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); //
|
|
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:
|
|
119
|
-
};
|
|
120
|
-
}
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
import customParseFormat from 'dayjs/plugin/customParseFormat.js';
|
|
3
|
+
|
|
4
|
+
dayjs.extend(customParseFormat);
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Check whether a Git URL is valid (HTTP/HTTPS, SSH, or `.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 a date string into a valid ISO/Git timestamp.
|
|
21
|
+
* Supported formats:
|
|
22
|
+
* - "now" or blank -> current time
|
|
23
|
+
* - Relative times (single-character units are case-sensitive):
|
|
24
|
+
* s=second, m=minute, h=hour, d=day, w=week, M=month, y=year
|
|
25
|
+
* e.g. "-2d", "-5h", "-30m" (minutes), "-1w", "-3M"/"-3mo"/"-3month" (months), "-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
|
+
// Check relative time: e.g. -2d, -5h, -30m, -1w, -3M/-3mo, -1y, or 2d, 5h.
|
|
44
|
+
// Single-character units are case-sensitive (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
|
+
// Match longer units first; preserve case for single-character units.
|
|
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
|
+
// Without a leading + or -, interpret "2d" as "2 days ago" (-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: `Could not calculate a date from '${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
|
+
// Fall through to absolute date parsing if the unit is unknown.
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Try absolute date and time formats.
|
|
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); // Try standard ISO parsing.
|
|
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: `Invalid date or time: '${dateStr}'. Examples: "2024-01-15 14:30:00", "-2d", "-5h", "now"`
|
|
119
|
+
};
|
|
120
|
+
}
|
package/package.json
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
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
|
-
"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
|
-
"boxen": "^9.0.0",
|
|
30
|
-
"chalk": "^5.4.1",
|
|
31
|
-
"commander": "^13.1.0",
|
|
32
|
-
"dayjs": "^1.11.13",
|
|
33
|
-
"ora": "^8.2.0",
|
|
34
|
-
"string-width": "^7.2.0"
|
|
35
|
-
}
|
|
36
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "git-push-time",
|
|
3
|
+
"version": "1.1.4",
|
|
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
|
+
"boxen": "^9.0.0",
|
|
30
|
+
"chalk": "^5.4.1",
|
|
31
|
+
"commander": "^13.1.0",
|
|
32
|
+
"dayjs": "^1.11.13",
|
|
33
|
+
"ora": "^8.2.0",
|
|
34
|
+
"string-width": "^7.2.0"
|
|
35
|
+
}
|
|
36
|
+
}
|