@puya/ts 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,8 @@
1
+ # Timestamper
2
+ This library provides timestamp and supports custom templates for its output file.
3
+
4
+ # Install
5
+
6
+ ```
7
+ npm i @puya/ts
8
+ ```
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
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ var path = require('path');
4
+ var fs = require('fs');
5
+ require(path.join(path.dirname(fs.realpathSync(__filename)), '../test'));
package/index.js ADDED
@@ -0,0 +1,4 @@
1
+ const { ts } = require('./Timestamper')
2
+ //const cli = require('./TimestamperCLI');
3
+
4
+ module.exports = ts;
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
@@ -0,0 +1,3 @@
1
+ const cli = require('./TimestamperCLI');
2
+
3
+ cli(process.argv.slice(2))