@ygracs/xepg-lib-js 0.0.19 → 0.0.21
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/CHANGELOG.md +26 -76
- package/LICENSE +1 -1
- package/README.md +10 -8
- package/doc/xepgdoc-lib.md +332 -83
- package/doc/xepgdoc-spec-draft.dtd +65 -0
- package/index.js +5 -2
- package/lib/dts-helper.js +81 -32
- package/lib/file-helper.js +278 -0
- package/lib/xepgdoc-lib.js +580 -301
- package/package.json +7 -5
package/lib/dts-helper.js
CHANGED
|
@@ -1,32 +1,52 @@
|
|
|
1
|
-
// [v0.1.
|
|
1
|
+
// [v0.1.047-20250225]
|
|
2
2
|
|
|
3
3
|
// === module init block ===
|
|
4
4
|
|
|
5
5
|
const {
|
|
6
|
-
valueToIndex,
|
|
7
|
-
isDateObject,
|
|
6
|
+
valueToIndex,
|
|
8
7
|
} = require('@ygracs/bsfoc-lib-js');
|
|
9
8
|
|
|
10
9
|
const {
|
|
11
10
|
convDTValueToISO8601,
|
|
12
11
|
convDTValueToXMLTV, convXMLTVToDTValue,
|
|
13
12
|
convDTValueToDateString,
|
|
13
|
+
tryDTValue,
|
|
14
14
|
} = require('@ygracs/dtf-lib-js');
|
|
15
15
|
|
|
16
|
+
// === module extra block (helper functions) ===
|
|
17
|
+
|
|
18
|
+
// === module main block ===
|
|
19
|
+
|
|
20
|
+
/***
|
|
21
|
+
* (* constant definitions *)
|
|
22
|
+
*/
|
|
23
|
+
|
|
16
24
|
const def_dts_param = [
|
|
17
25
|
'default', 'iso8601', 'xmltv', 'timestamp', 'utc',
|
|
18
26
|
];
|
|
19
27
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
28
|
+
/***
|
|
29
|
+
* (* function definitions *)
|
|
30
|
+
*/
|
|
23
31
|
|
|
24
|
-
|
|
32
|
+
/**
|
|
33
|
+
* @function chkDTSysID
|
|
34
|
+
* @param {(number|string)} value - value to verify
|
|
35
|
+
* @returns {boolean}
|
|
36
|
+
* @description Checs if a given value is a valid dtstype ID
|
|
37
|
+
*/
|
|
38
|
+
function chkDTSysID(value) {
|
|
25
39
|
const _value = valueToIndex(value);
|
|
26
40
|
return _value !== -1 && def_dts_param[_value] ? true : false;
|
|
27
41
|
};
|
|
28
42
|
|
|
29
|
-
|
|
43
|
+
/**
|
|
44
|
+
* @function getDTSysName
|
|
45
|
+
* @param {(number|string)} value - DTS-type identifier
|
|
46
|
+
* @returns {string}
|
|
47
|
+
* @description Returns a dtstype name by a given dtstype ID
|
|
48
|
+
*/
|
|
49
|
+
function getDTSysName(value) {
|
|
30
50
|
let result = 'undefined';
|
|
31
51
|
if (chkDTSysID(value)) {
|
|
32
52
|
result = def_dts_param[Number(value)];
|
|
@@ -34,7 +54,20 @@ function getDTSysName(value){
|
|
|
34
54
|
return result;
|
|
35
55
|
};
|
|
36
56
|
|
|
37
|
-
|
|
57
|
+
/**
|
|
58
|
+
* @typedef {Object} DTSysDescr
|
|
59
|
+
* @property {number} index - dtstype ID
|
|
60
|
+
* @property {string} name - dtstype name
|
|
61
|
+
* @description A DTS-type descriptor
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @function getDTSysDescr
|
|
66
|
+
* @param {(number|string)} value - DTS-type identifier
|
|
67
|
+
* @returns {DTSysDescr}
|
|
68
|
+
* @description Returns a dtstype description for a given dtstype ID
|
|
69
|
+
*/
|
|
70
|
+
function getDTSysDescr(value) {
|
|
38
71
|
let index = valueToIndex(value);
|
|
39
72
|
let name = 'undefined';
|
|
40
73
|
if (index !== -1) {
|
|
@@ -50,15 +83,24 @@ function getDTSysDescr(value){
|
|
|
50
83
|
return { index, name };
|
|
51
84
|
};
|
|
52
85
|
|
|
53
|
-
|
|
86
|
+
/**
|
|
87
|
+
* @function convStringToDTValue
|
|
88
|
+
* @param {string} value - some value
|
|
89
|
+
* @param {(number|string)} [dts_id=0] - DTS-type identifier
|
|
90
|
+
* @param {(number|string)} [tz] - <*reserved*>
|
|
91
|
+
* @returns {number}
|
|
92
|
+
* @description Tries to convert a given string to timestamp
|
|
93
|
+
* @todo check TZ
|
|
94
|
+
*/
|
|
95
|
+
function convStringToDTValue(value, dts_id = 0, tz) {
|
|
96
|
+
const dtstype = getDTSysName(dts_id);
|
|
54
97
|
let result = 0;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (chkDTSysID(dtstype)) {
|
|
58
|
-
switch (getDTSysName(dtstype)) {
|
|
98
|
+
if (dtstype !== 'undefined') {
|
|
99
|
+
switch (dtstype) {
|
|
59
100
|
case 'default': {
|
|
60
101
|
// TODO: check TZ
|
|
61
102
|
//console.log('convStringToDTValue => dtstype:[default]');
|
|
103
|
+
let dt_str = typeof value === 'string' ? value : '';
|
|
62
104
|
result = (new Date(dt_str)).getTime();
|
|
63
105
|
//console.log('convStringToDTValue => value:['+value+']');
|
|
64
106
|
//console.log('convStringToDTValue => result:['+result+']');
|
|
@@ -67,7 +109,8 @@ function convStringToDTValue(value, dts_id, tz){
|
|
|
67
109
|
case 'iso8601': {
|
|
68
110
|
// TODO: check TZ
|
|
69
111
|
//console.log('convStringToDTValue => dtstype:[iso8601]');
|
|
70
|
-
|
|
112
|
+
let dtStr = typeof value === 'string' ? value : '';
|
|
113
|
+
if (dtStr !== '') result = (new Date(dtStr)).getTime();
|
|
71
114
|
//console.log('convStringToDTValue => value:['+value+']');
|
|
72
115
|
//console.log('convStringToDTValue => result:['+result+']');
|
|
73
116
|
break;
|
|
@@ -75,7 +118,8 @@ function convStringToDTValue(value, dts_id, tz){
|
|
|
75
118
|
case 'xmltv': {
|
|
76
119
|
// TODO: check TZ
|
|
77
120
|
//console.log('convStringToDTValue => dtstype:[xmltv]');
|
|
78
|
-
|
|
121
|
+
const dtValue = convXMLTVToDTValue(value, true);
|
|
122
|
+
if (dtValue !== null) result = dtValue;
|
|
79
123
|
//console.log('convStringToDTValue => value:['+value+']');
|
|
80
124
|
//console.log('convStringToDTValue => result:['+result+']');
|
|
81
125
|
break;
|
|
@@ -83,7 +127,8 @@ function convStringToDTValue(value, dts_id, tz){
|
|
|
83
127
|
case 'timestamp': {
|
|
84
128
|
// TODO: check TZ
|
|
85
129
|
//console.log('convStringToDTValue => dtstype:[timestamp]');
|
|
86
|
-
|
|
130
|
+
const { isSucceed, value: dtValue } = tryDTValue(value);
|
|
131
|
+
if (isSucceed) result = dtValue.getTime();
|
|
87
132
|
//console.log('convStringToDTValue => value:['+value+']');
|
|
88
133
|
//console.log('convStringToDTValue => result:['+result+']');
|
|
89
134
|
break;
|
|
@@ -91,28 +136,32 @@ function convStringToDTValue(value, dts_id, tz){
|
|
|
91
136
|
case 'utc': {
|
|
92
137
|
// TODO: check TZ
|
|
93
138
|
//console.log('convStringToDTValue => dtstype:[utc]');
|
|
94
|
-
|
|
139
|
+
let dtStr = typeof value === 'string' ? value : '';
|
|
140
|
+
if (dtStr !== '') result = (new Date(Date.UTC(dtStr))).getTime();
|
|
95
141
|
//console.log('convStringToDTValue => value:['+value+']');
|
|
96
142
|
//console.log('convStringToDTValue => result:['+result+']');
|
|
97
143
|
break;
|
|
98
144
|
}
|
|
99
|
-
default: {
|
|
100
|
-
break;
|
|
101
|
-
}
|
|
145
|
+
default: {}
|
|
102
146
|
};
|
|
103
147
|
if (Number.isNaN(result)) result = 0;
|
|
104
148
|
};
|
|
105
149
|
return result;
|
|
106
150
|
};
|
|
107
151
|
|
|
108
|
-
|
|
152
|
+
/**
|
|
153
|
+
* @function convDTValueToString
|
|
154
|
+
* @param {(number|string|Date)} value - some value
|
|
155
|
+
* @param {(number|string)} [dts_id=0] - DTS-type identifier
|
|
156
|
+
* @param {(number|string)} [tz] - <*reserved*>
|
|
157
|
+
* @returns {string}
|
|
158
|
+
* @description Tries to convert a given value to its string representation
|
|
159
|
+
* @todo check TZ
|
|
160
|
+
*/
|
|
161
|
+
function convDTValueToString(value, dts_id, tz) {
|
|
162
|
+
let { isSucceed, value: dtValue } = tryDTValue(value);
|
|
163
|
+
let dt_val = isSucceed ? dtValue.getTime() : new Date(0);
|
|
109
164
|
let result = '';
|
|
110
|
-
let dt_val = (
|
|
111
|
-
isDateObject(value)
|
|
112
|
-
? value
|
|
113
|
-
: (new Date(readAsNumberEx(value, 0)))
|
|
114
|
-
).getTime();
|
|
115
|
-
if (Number.isNaN(dt_val)) dt_val = new Date(0);
|
|
116
165
|
let dtstype = valueToIndex(dts_id);
|
|
117
166
|
if (!chkDTSysID(dtstype)) dtstype = 0;
|
|
118
167
|
switch (getDTSysName(dtstype)) {
|
|
@@ -156,14 +205,14 @@ function convDTValueToString(value, dts_id, tz){
|
|
|
156
205
|
//console.log('convDTValueToString => result:['+result+']');
|
|
157
206
|
break;
|
|
158
207
|
}
|
|
159
|
-
default: {
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
208
|
+
default: {}
|
|
162
209
|
};
|
|
163
210
|
return result;
|
|
164
211
|
};
|
|
165
212
|
|
|
166
|
-
|
|
213
|
+
/***
|
|
214
|
+
* (* class definitions *)
|
|
215
|
+
*/
|
|
167
216
|
|
|
168
217
|
// === module exports block ===
|
|
169
218
|
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
// [v0.1.030-20241029]
|
|
2
|
+
|
|
3
|
+
// === module init block ===
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const fse = require('fs').promises;
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
isPlainObject,
|
|
10
|
+
} = require('@ygracs/bsfoc-lib-js');
|
|
11
|
+
|
|
12
|
+
// === module extra block (helper functions) ===
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {Object} fsoDescr
|
|
16
|
+
* @property {boolean} isERR - flag
|
|
17
|
+
* @property {number|undefined} errCode - error code
|
|
18
|
+
* @property {string} errEvent - event ID
|
|
19
|
+
* @property {string} errMsg - event message
|
|
20
|
+
* @property {string} source - path to file
|
|
21
|
+
* @property {any} content - file content
|
|
22
|
+
* @description A fs ops description.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {Object} VCOR_evalerrfs
|
|
27
|
+
* @property {boolean} isSucceed - ops flag
|
|
28
|
+
* @property {fsoDescr} descr - description
|
|
29
|
+
* @description A result of an error check ops.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @function checkFsError
|
|
34
|
+
* @param {fsoDescr} descr
|
|
35
|
+
* @param {Error} err
|
|
36
|
+
* @returns {VCOR_evalerrfs}
|
|
37
|
+
* @inner
|
|
38
|
+
* @description Checks an error code of a fs ops and sets descr info if succeed
|
|
39
|
+
*/
|
|
40
|
+
function checkFsError(descr, err) {
|
|
41
|
+
let isSucceed = false;
|
|
42
|
+
if (isPlainObject(err) && isPlainObject(descr)) {
|
|
43
|
+
switch (err.code) {
|
|
44
|
+
case 'ENOENT':
|
|
45
|
+
case 'EISDIR':
|
|
46
|
+
case 'ENOTDIR':
|
|
47
|
+
case 'EPERM': {
|
|
48
|
+
descr.errCode = err.errno;
|
|
49
|
+
descr.errEvent = err.code;
|
|
50
|
+
descr.errMsg = `ERR_FILE_${err.code}`;
|
|
51
|
+
isSucceed = true;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
default: {}
|
|
55
|
+
};
|
|
56
|
+
if (isSucceed) descr.isERR = true;
|
|
57
|
+
};
|
|
58
|
+
return { isSucceed, descr };
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// === module main block ===
|
|
62
|
+
|
|
63
|
+
/***
|
|
64
|
+
* (* constant definitions *)
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
/***
|
|
68
|
+
* (* function definitions *)
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @function loadFileSync
|
|
73
|
+
* @param {string} src - a path to some file
|
|
74
|
+
* @returns {fsoDescr}
|
|
75
|
+
* @inner
|
|
76
|
+
* @description Loads file by a given path
|
|
77
|
+
*/
|
|
78
|
+
function loadFileSync(src) {
|
|
79
|
+
/** @type {fsoDescr} */
|
|
80
|
+
const data = {
|
|
81
|
+
isERR: false,
|
|
82
|
+
errCode: 0,
|
|
83
|
+
errEvent: '',
|
|
84
|
+
errMsg: '',
|
|
85
|
+
source: '',
|
|
86
|
+
content: '',
|
|
87
|
+
};
|
|
88
|
+
if (typeof src !== 'string') {
|
|
89
|
+
if (src !== undefined) {
|
|
90
|
+
data.isERR = true;
|
|
91
|
+
data.errEvent = 'ERR_INVARG';
|
|
92
|
+
data.errMsg = 'The "source" argument must be a string';
|
|
93
|
+
};
|
|
94
|
+
} else {
|
|
95
|
+
const srcPath = src.trim();
|
|
96
|
+
if (srcPath !== '') {
|
|
97
|
+
data.source = srcPath;
|
|
98
|
+
try {
|
|
99
|
+
data.content = fs.readFileSync(srcPath, 'utf8');
|
|
100
|
+
} catch (err) {
|
|
101
|
+
const { isSucceed } = checkFsError(data, err);
|
|
102
|
+
if (!isSucceed) {
|
|
103
|
+
// // TODO: [?] consider check others
|
|
104
|
+
//console.log(`TEST_ERR-MSG:loadFileSync: ${err}`);
|
|
105
|
+
//throw err;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
return data;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @function loadFile
|
|
115
|
+
* @param {string} src - a path to some file
|
|
116
|
+
* @returns {Promise<fsoDescr, Error>}
|
|
117
|
+
* @async
|
|
118
|
+
* @inner
|
|
119
|
+
* @description Loads file by a given path
|
|
120
|
+
*/
|
|
121
|
+
function loadFile(src) {
|
|
122
|
+
/**/// main part that return promise as a result
|
|
123
|
+
return new Promise((resolve, reject) => {
|
|
124
|
+
/** @type {fsoDescr} */
|
|
125
|
+
const data = {
|
|
126
|
+
isERR: false,
|
|
127
|
+
errCode: 0,
|
|
128
|
+
errEvent: '',
|
|
129
|
+
errMsg: '',
|
|
130
|
+
source: '',
|
|
131
|
+
content: '',
|
|
132
|
+
};
|
|
133
|
+
if (typeof src !== 'string') {
|
|
134
|
+
if (src !== undefined) {
|
|
135
|
+
data.isERR = true;
|
|
136
|
+
data.errEvent = 'ERR_INVARG';
|
|
137
|
+
data.errMsg = 'The "source" argument must be a string';
|
|
138
|
+
};
|
|
139
|
+
resolve(data);
|
|
140
|
+
} else {
|
|
141
|
+
const srcPath = src.trim();
|
|
142
|
+
if (srcPath === '') resolve(data);
|
|
143
|
+
data.source = srcPath;
|
|
144
|
+
fse.readFile(srcPath, 'utf8').then(result => {
|
|
145
|
+
data.content = result;
|
|
146
|
+
resolve(data);
|
|
147
|
+
}).catch(err => {
|
|
148
|
+
let { isSucceed } = checkFsError(data, err);
|
|
149
|
+
if (isSucceed) {
|
|
150
|
+
data.content = '';
|
|
151
|
+
resolve(data);
|
|
152
|
+
} else {
|
|
153
|
+
//console.log('CHECK: loadFile() => Error => '+err);
|
|
154
|
+
//console.log('CHECK: loadFile() => Error => '+err.code);
|
|
155
|
+
reject(err);
|
|
156
|
+
};
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @function saveToFileSync
|
|
164
|
+
* @param {string} src - a path to some file
|
|
165
|
+
* @param {string} content - some file content
|
|
166
|
+
* @param {any} [opt] - <reserved>
|
|
167
|
+
* @returns {fsoDescr}
|
|
168
|
+
* @inner
|
|
169
|
+
* @description Saves a content to a file
|
|
170
|
+
*/
|
|
171
|
+
function saveToFileSync(src, content = '', opt) {
|
|
172
|
+
/** @type {fsoDescr} */
|
|
173
|
+
const data = {
|
|
174
|
+
isERR: false,
|
|
175
|
+
errCode: 0,
|
|
176
|
+
errEvent: '',
|
|
177
|
+
errMsg: '',
|
|
178
|
+
source: '',
|
|
179
|
+
content: '',
|
|
180
|
+
};
|
|
181
|
+
if (typeof src !== 'string') {
|
|
182
|
+
data.isERR = true;
|
|
183
|
+
data.errEvent = src === undefined ? 'ERR_NOSRC' : 'ERR_INVARG';
|
|
184
|
+
data.errMsg = 'The "source" argument must be a string';
|
|
185
|
+
} else if (typeof content === 'string') {
|
|
186
|
+
const srcPath = src.trim();
|
|
187
|
+
if (srcPath === '') {
|
|
188
|
+
data.isERR = true;
|
|
189
|
+
data.errEvent = 'ERR_NOSRC';
|
|
190
|
+
data.errMsg = 'No "source" path given';
|
|
191
|
+
} else {
|
|
192
|
+
data.source = srcPath;
|
|
193
|
+
try {
|
|
194
|
+
fs.writeFileSync(srcPath, content, 'utf8');
|
|
195
|
+
} catch (err) {
|
|
196
|
+
const { isSucceed } = checkFsError(data, err);
|
|
197
|
+
if (!isSucceed) {
|
|
198
|
+
// // TODO: [?] consider check others
|
|
199
|
+
//console.log(`TEST_ERR-MSG:saveToFileSync: ${err}`);
|
|
200
|
+
//throw err;
|
|
201
|
+
};
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
} else {
|
|
205
|
+
data.isERR = true;
|
|
206
|
+
data.errEvent = 'ERR_INVARG';
|
|
207
|
+
data.errMsg = 'The "content" argument must be a string';
|
|
208
|
+
};
|
|
209
|
+
return data;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @function saveToFile
|
|
214
|
+
* @param {string} src - a path to some file
|
|
215
|
+
* @param {string} content - some file content
|
|
216
|
+
* @param {any} [opt] - <reserved>
|
|
217
|
+
* @returns {Promise<fsoDescr, Error>}
|
|
218
|
+
* @async
|
|
219
|
+
* @inner
|
|
220
|
+
* @description Saves a content to a file
|
|
221
|
+
*/
|
|
222
|
+
function saveToFile(src, content = '', opt) {
|
|
223
|
+
/**/// main part that return promise as a result
|
|
224
|
+
return new Promise((resolve, reject) => {
|
|
225
|
+
/** @type {fsoDescr} */
|
|
226
|
+
const data = {
|
|
227
|
+
isERR: false,
|
|
228
|
+
errCode: 0,
|
|
229
|
+
errEvent: '',
|
|
230
|
+
errMsg: '',
|
|
231
|
+
source: '',
|
|
232
|
+
content: '',
|
|
233
|
+
};
|
|
234
|
+
if (typeof src !== 'string') {
|
|
235
|
+
data.isERR = true;
|
|
236
|
+
data.errEvent = src === undefined ? 'ERR_NOSRC' : 'ERR_INVARG';
|
|
237
|
+
data.errMsg = 'The "source" argument must be a string';
|
|
238
|
+
resolve(data);
|
|
239
|
+
} else if (typeof content === 'string') {
|
|
240
|
+
const srcPath = src.trim();
|
|
241
|
+
if (srcPath === '') {
|
|
242
|
+
data.isERR = true;
|
|
243
|
+
data.errEvent = 'ERR_NOSRC';
|
|
244
|
+
data.errMsg = 'No "source" path given';
|
|
245
|
+
resolve(data);
|
|
246
|
+
} else {
|
|
247
|
+
data.source = srcPath;
|
|
248
|
+
fse.writeFile(srcPath, content, 'utf8').then(result => {
|
|
249
|
+
resolve(data);
|
|
250
|
+
}).catch(err => {
|
|
251
|
+
const { isSucceed } = checkFsError(data, err);
|
|
252
|
+
if (isSucceed) resolve(data);
|
|
253
|
+
// // TODO: [?] consider check others
|
|
254
|
+
//console.log('CHECK: TXEpgContentProvider.saveToFile() => Error => '+err);
|
|
255
|
+
//console.log('CHECK: TXEpgContentProvider.saveToFile() => Error => '+err.code);
|
|
256
|
+
reject(err);
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
} else {
|
|
260
|
+
data.isERR = true;
|
|
261
|
+
data.errEvent = 'ERR_INVARG';
|
|
262
|
+
data.errMsg = 'The "content" argument must be a string';
|
|
263
|
+
resolve(data);
|
|
264
|
+
};
|
|
265
|
+
});
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
/***
|
|
269
|
+
* (* class definitions *)
|
|
270
|
+
*/
|
|
271
|
+
|
|
272
|
+
// === module exports block ===
|
|
273
|
+
|
|
274
|
+
module.exports.checkFsError = checkFsError;
|
|
275
|
+
module.exports.loadFile = loadFile;
|
|
276
|
+
module.exports.loadFileSync = loadFileSync;
|
|
277
|
+
module.exports.saveToFile = saveToFile;
|
|
278
|
+
module.exports.saveToFileSync = saveToFileSync;
|