@puya/ts 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +21 -0
- package/README.md +8 -0
- package/Timestamper.js +188 -0
- package/TimestamperCLI.js +47 -0
- package/bin/ts +5 -0
- package/index.js +4 -0
- package/package.json +38 -0
- package/test.js +3 -0
package/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 puyacodes
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/Timestamper.js
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
const path = require("path");
|
2
|
+
const fs = require("fs");
|
3
|
+
const moment = require("jalali-moment");
|
4
|
+
|
5
|
+
const version = '1.0.0';
|
6
|
+
|
7
|
+
let default_options = {
|
8
|
+
locale: "en",
|
9
|
+
outputFileName: "info.json",
|
10
|
+
outPutFilePath: path.join(process.cwd(), "info.json"),
|
11
|
+
template: "{ \"ts\": \"{ts}\" }",
|
12
|
+
templatePath: "",
|
13
|
+
format: "YYYYMMDDHHmm",
|
14
|
+
inlineTemplate: "",
|
15
|
+
hasInlineTemplate: false
|
16
|
+
};
|
17
|
+
|
18
|
+
class TimestampError extends Error {
|
19
|
+
constructor(state, message) {
|
20
|
+
super();
|
21
|
+
|
22
|
+
this.state = state;
|
23
|
+
this.message = message;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
function start(args) {
|
28
|
+
const result = {}
|
29
|
+
|
30
|
+
try {
|
31
|
+
const options = Array.isArray(args) ? parseArguments(args) : args;
|
32
|
+
|
33
|
+
if (args.length !== 0) {
|
34
|
+
result.state = validateOptions(Object.assign(default_options, options));
|
35
|
+
} else {
|
36
|
+
result.state = "successful";
|
37
|
+
}
|
38
|
+
|
39
|
+
if (result.state === "successful") {
|
40
|
+
result.options = Object.assign(default_options, options);
|
41
|
+
|
42
|
+
const ts = generateTimestamp(options.locale, options.format);
|
43
|
+
const data = generateData(ts, result.options);
|
44
|
+
|
45
|
+
writeOutput(data, result.options.outPutFilePath);
|
46
|
+
|
47
|
+
result.success = true;
|
48
|
+
}
|
49
|
+
} catch (ex) {
|
50
|
+
if (ex instanceof TimestampError) {
|
51
|
+
result.state = ex.state;
|
52
|
+
}
|
53
|
+
|
54
|
+
result.err = ex;
|
55
|
+
result.success = false;
|
56
|
+
}
|
57
|
+
|
58
|
+
return result;
|
59
|
+
}
|
60
|
+
|
61
|
+
function parseArguments(args) {
|
62
|
+
if (args.length === 0) {
|
63
|
+
return default_options;
|
64
|
+
}
|
65
|
+
|
66
|
+
let i = 0;
|
67
|
+
|
68
|
+
do {
|
69
|
+
switch (args[i]) {
|
70
|
+
case '-o':
|
71
|
+
default_options.outputFileName = args[i + 1];
|
72
|
+
default_options.outPutFilePath = default_options.outputFileName
|
73
|
+
? path.isAbsolute(default_options.outputFileName)
|
74
|
+
? default_options.outputFileName
|
75
|
+
: path.join(process.cwd(), default_options.outputFileName)
|
76
|
+
: undefined;
|
77
|
+
i += 2;
|
78
|
+
break;
|
79
|
+
case '-t':
|
80
|
+
default_options.template = args[i + 1];
|
81
|
+
default_options.templatePath = default_options.template
|
82
|
+
? path.isAbsolute(default_options.template)
|
83
|
+
? default_options.template
|
84
|
+
: path.join(process.cwd(), default_options.template)
|
85
|
+
: undefined;
|
86
|
+
i += 2;
|
87
|
+
break;
|
88
|
+
case '-l':
|
89
|
+
default_options.locale = args[i + 1];
|
90
|
+
i += 2;
|
91
|
+
break;
|
92
|
+
case '-f':
|
93
|
+
default_options.format = args[i + 1];
|
94
|
+
i += 2;
|
95
|
+
break;
|
96
|
+
case '-i':
|
97
|
+
default_options.inlineTemplate = args[i + 1];
|
98
|
+
default_options.template = default_options.inlineTemplate;
|
99
|
+
default_options.hasInlineTemplate = true;
|
100
|
+
i += 2;
|
101
|
+
break;
|
102
|
+
default:
|
103
|
+
throw new Error(`Invalid argument provided: ${args[i]}`);
|
104
|
+
}
|
105
|
+
} while (i < args.length);
|
106
|
+
|
107
|
+
return default_options;
|
108
|
+
}
|
109
|
+
|
110
|
+
function validateOptions(options) {
|
111
|
+
const fileRegex = /^[\w,-]+\.[A-Za-z]{1,15}$/;
|
112
|
+
|
113
|
+
Object.entries(options).forEach(([key, value]) => {
|
114
|
+
if (value === undefined) {
|
115
|
+
throw new TimestampError(`${key}_required`, `${key} is required after -${key.slice(0, 1)}`);
|
116
|
+
}
|
117
|
+
});
|
118
|
+
|
119
|
+
if (!fileRegex.test(path.basename(options.outPutFilePath))) {
|
120
|
+
throw new TimestampError("invalid_filename", `Please enter a valid file name.`);
|
121
|
+
}
|
122
|
+
|
123
|
+
if (options.templatePath && !fs.existsSync(options.templatePath)) {
|
124
|
+
throw new TimestampError("template_not_exists", `Template file does not exist.`);
|
125
|
+
}
|
126
|
+
|
127
|
+
if (!isValidDateFormat(options.format)) {
|
128
|
+
|
129
|
+
throw new TimestampError("invalid_format", `Please enter a valid format.`);
|
130
|
+
}
|
131
|
+
|
132
|
+
if (options.inlineTemplate !== "") {
|
133
|
+
options.hasInlineTemplate = true;
|
134
|
+
}
|
135
|
+
|
136
|
+
if (options.hasInlineTemplate && options.inlineTemplate === "") {
|
137
|
+
throw new TimestampError("invalid_inline_template", `Please provide a valid inline template.`);
|
138
|
+
}
|
139
|
+
|
140
|
+
if (options.templatePath && options.inlineTemplate != "") {
|
141
|
+
throw new TimestampError("extra_template", `You can use only one template.`);
|
142
|
+
}
|
143
|
+
|
144
|
+
return "successful";
|
145
|
+
}
|
146
|
+
|
147
|
+
function generateTimestamp(locale, format) {
|
148
|
+
return moment().locale(locale).format(format);
|
149
|
+
}
|
150
|
+
|
151
|
+
function generateData(ts, {template, templatePath, inlineTemplate, hasInlineTemplate}) {
|
152
|
+
let data;
|
153
|
+
|
154
|
+
if (hasInlineTemplate) {
|
155
|
+
data = inlineTemplate;
|
156
|
+
} else if (templatePath) {
|
157
|
+
try {
|
158
|
+
data = fs.readFileSync(templatePath, { encoding: "utf8" });
|
159
|
+
} catch (error) {
|
160
|
+
throw new TimestampError("failed_to_read_file", `Failed to read template file at ${templatePath}`);
|
161
|
+
}
|
162
|
+
} else {
|
163
|
+
data = template;
|
164
|
+
}
|
165
|
+
|
166
|
+
if (!data.includes("{ts}")) {
|
167
|
+
throw new TimestampError("{ts}_placeholder_not_found", `Template does not contain {ts} placeholder.`);
|
168
|
+
}
|
169
|
+
|
170
|
+
return data.replace(/{ts}/g, ts);
|
171
|
+
}
|
172
|
+
|
173
|
+
function writeOutput(data, outPutFilePath) {
|
174
|
+
fs.writeFileSync(outPutFilePath, data);
|
175
|
+
}
|
176
|
+
|
177
|
+
function isValidDateFormat(format) {
|
178
|
+
try {
|
179
|
+
moment().format(format);
|
180
|
+
return true;
|
181
|
+
} catch {
|
182
|
+
return false;
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
186
|
+
module.exports.ts = start;
|
187
|
+
module.exports.version = version;
|
188
|
+
module.exports.TimestampError = TimestampError;
|
@@ -0,0 +1,47 @@
|
|
1
|
+
const { ts, version, TimestampError } = require("./Timestamper");
|
2
|
+
|
3
|
+
function showHelp() {
|
4
|
+
console.log(`
|
5
|
+
Timestamper v${version}
|
6
|
+
Usage: ts [options]
|
7
|
+
|
8
|
+
Options:
|
9
|
+
-v --version version
|
10
|
+
-l --locale locale to use for formatting the date/time. e.g. 'en' or 'fa' (default = en).
|
11
|
+
-o --output output file name where the result will be saved. default is info.json.
|
12
|
+
-t --template template file.
|
13
|
+
-f --format format string to use for formatting the date/time. default is "YYYYMMDDHHmm".
|
14
|
+
-i --inline-template inline template string.
|
15
|
+
|
16
|
+
Examples:
|
17
|
+
ts
|
18
|
+
ts -l en -o result.json -t template.txt -f YYYYMMDDHHmmss
|
19
|
+
ts -l fa -o result.json -i "{ hash: '{ts}' }"
|
20
|
+
`);
|
21
|
+
}
|
22
|
+
|
23
|
+
function TimestamperCLI(args) {
|
24
|
+
try {
|
25
|
+
if (args.includes("--help") || args.includes("-?") || args.includes("/?")) {
|
26
|
+
showHelp();
|
27
|
+
|
28
|
+
return;
|
29
|
+
}
|
30
|
+
|
31
|
+
const result = ts(args);
|
32
|
+
|
33
|
+
if (result.success) {
|
34
|
+
console.log(`File ${result.options.outputFileName} generated at ${result.options.outPutFilePath}`);
|
35
|
+
} else {
|
36
|
+
if (result.err) {
|
37
|
+
throw result.err;
|
38
|
+
} else {
|
39
|
+
throw new TimestampError(result.state, result.message);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
} catch (error) {
|
43
|
+
console.error(`Error: ${error.message}`);
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
module.exports = TimestamperCLI;
|
package/bin/ts
ADDED
package/index.js
ADDED
package/package.json
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
{
|
2
|
+
"name": "@puya/ts",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "This library provides timestamp and supports custom templates for its output file.",
|
5
|
+
"main": "index.js",
|
6
|
+
"bin": {
|
7
|
+
"ts": "bin/ts"
|
8
|
+
},
|
9
|
+
"scripts": {
|
10
|
+
"test": "node test.js"
|
11
|
+
},
|
12
|
+
"repository": {
|
13
|
+
"type": "git",
|
14
|
+
"url": "git+https://github.com/puyacodes/ts.git"
|
15
|
+
},
|
16
|
+
"keywords": [
|
17
|
+
"puya",
|
18
|
+
"ts",
|
19
|
+
"timestamp",
|
20
|
+
"puyacodes",
|
21
|
+
"puyasoft"
|
22
|
+
],
|
23
|
+
"author": "PuyaSoft",
|
24
|
+
"license": "MIT",
|
25
|
+
"bugs": {
|
26
|
+
"url": "https://github.com/puyacodes/ts/issues"
|
27
|
+
},
|
28
|
+
"homepage": "https://github.com/puyacodes/ts#readme",
|
29
|
+
"dependencies": {
|
30
|
+
"jalali-moment": "^3.3.11"
|
31
|
+
},
|
32
|
+
"files": [
|
33
|
+
"test.js",
|
34
|
+
"Timestamper.js",
|
35
|
+
"TimestamperCLI.js",
|
36
|
+
"bin/ts"
|
37
|
+
]
|
38
|
+
}
|
package/test.js
ADDED