@ya-modbus/cli 0.8.0 → 0.9.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/CHANGELOG.md +12 -0
- package/README.md +85 -0
- package/dist/cjs/bin/ya-modbus.js +0 -0
- package/dist/cjs/src/commands/discover.d.ts +2 -0
- package/dist/cjs/src/commands/discover.d.ts.map +1 -1
- package/dist/cjs/src/commands/discover.js +19 -11
- package/dist/cjs/src/commands/discover.js.map +1 -1
- package/dist/cjs/src/discovery/parameter-generator-utils.d.ts +5 -2
- package/dist/cjs/src/discovery/parameter-generator-utils.d.ts.map +1 -1
- package/dist/cjs/src/discovery/parameter-generator-utils.js +46 -25
- package/dist/cjs/src/discovery/parameter-generator-utils.js.map +1 -1
- package/dist/cjs/src/discovery/parameter-generator.d.ts +4 -0
- package/dist/cjs/src/discovery/parameter-generator.d.ts.map +1 -1
- package/dist/cjs/src/discovery/parameter-generator.js +20 -8
- package/dist/cjs/src/discovery/parameter-generator.js.map +1 -1
- package/dist/cjs/src/index.d.ts.map +1 -1
- package/dist/cjs/src/index.js +2 -0
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/cjs/src/utils/merge-specs.d.ts +34 -0
- package/dist/cjs/src/utils/merge-specs.d.ts.map +1 -0
- package/dist/cjs/src/utils/merge-specs.js +53 -0
- package/dist/cjs/src/utils/merge-specs.js.map +1 -0
- package/dist/cjs/src/utils/parse-baud-rate.d.ts +14 -0
- package/dist/cjs/src/utils/parse-baud-rate.d.ts.map +1 -0
- package/dist/cjs/src/utils/parse-baud-rate.js +52 -0
- package/dist/cjs/src/utils/parse-baud-rate.js.map +1 -0
- package/dist/cjs/src/utils/parse-id-range.d.ts.map +1 -1
- package/dist/cjs/src/utils/parse-id-range.js +23 -48
- package/dist/cjs/src/utils/parse-id-range.js.map +1 -1
- package/dist/cjs/src/utils/parse-integer.d.ts +15 -0
- package/dist/cjs/src/utils/parse-integer.d.ts.map +1 -0
- package/dist/cjs/src/utils/parse-integer.js +27 -0
- package/dist/cjs/src/utils/parse-integer.js.map +1 -0
- package/dist/cjs/src/utils/parse-parity.d.ts +18 -0
- package/dist/cjs/src/utils/parse-parity.d.ts.map +1 -0
- package/dist/cjs/src/utils/parse-parity.js +46 -0
- package/dist/cjs/src/utils/parse-parity.js.map +1 -0
- package/dist/cjs/src/utils/parse-spec.d.ts +73 -0
- package/dist/cjs/src/utils/parse-spec.d.ts.map +1 -0
- package/dist/cjs/src/utils/parse-spec.js +47 -0
- package/dist/cjs/src/utils/parse-spec.js.map +1 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/bin/ya-modbus.js +0 -0
- package/dist/esm/src/commands/discover.d.ts +2 -0
- package/dist/esm/src/commands/discover.d.ts.map +1 -1
- package/dist/esm/src/commands/discover.js +19 -11
- package/dist/esm/src/commands/discover.js.map +1 -1
- package/dist/esm/src/discovery/parameter-generator-utils.d.ts +5 -2
- package/dist/esm/src/discovery/parameter-generator-utils.d.ts.map +1 -1
- package/dist/esm/src/discovery/parameter-generator-utils.js +46 -25
- package/dist/esm/src/discovery/parameter-generator-utils.js.map +1 -1
- package/dist/esm/src/discovery/parameter-generator.d.ts +4 -0
- package/dist/esm/src/discovery/parameter-generator.d.ts.map +1 -1
- package/dist/esm/src/discovery/parameter-generator.js +20 -8
- package/dist/esm/src/discovery/parameter-generator.js.map +1 -1
- package/dist/esm/src/index.d.ts.map +1 -1
- package/dist/esm/src/index.js +2 -0
- package/dist/esm/src/index.js.map +1 -1
- package/dist/esm/src/utils/merge-specs.d.ts +34 -0
- package/dist/esm/src/utils/merge-specs.d.ts.map +1 -0
- package/dist/esm/src/utils/merge-specs.js +50 -0
- package/dist/esm/src/utils/merge-specs.js.map +1 -0
- package/dist/esm/src/utils/parse-baud-rate.d.ts +14 -0
- package/dist/esm/src/utils/parse-baud-rate.d.ts.map +1 -0
- package/dist/esm/src/utils/parse-baud-rate.js +49 -0
- package/dist/esm/src/utils/parse-baud-rate.js.map +1 -0
- package/dist/esm/src/utils/parse-id-range.d.ts.map +1 -1
- package/dist/esm/src/utils/parse-id-range.js +23 -48
- package/dist/esm/src/utils/parse-id-range.js.map +1 -1
- package/dist/esm/src/utils/parse-integer.d.ts +15 -0
- package/dist/esm/src/utils/parse-integer.d.ts.map +1 -0
- package/dist/esm/src/utils/parse-integer.js +24 -0
- package/dist/esm/src/utils/parse-integer.js.map +1 -0
- package/dist/esm/src/utils/parse-parity.d.ts +18 -0
- package/dist/esm/src/utils/parse-parity.d.ts.map +1 -0
- package/dist/esm/src/utils/parse-parity.js +42 -0
- package/dist/esm/src/utils/parse-parity.js.map +1 -0
- package/dist/esm/src/utils/parse-spec.d.ts +73 -0
- package/dist/esm/src/utils/parse-spec.d.ts.map +1 -0
- package/dist/esm/src/utils/parse-spec.js +44 -0
- package/dist/esm/src/utils/parse-spec.js.map +1 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +3 -3
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { parseInteger } from './parse-integer.js';
|
|
2
|
+
import { parseSpec } from './parse-spec.js';
|
|
1
3
|
/**
|
|
2
4
|
* Parses a comma-separated list of IDs and ranges into a sorted array of unique IDs.
|
|
3
5
|
*
|
|
@@ -10,41 +12,28 @@
|
|
|
10
12
|
* parseIdRange("1-3,2-4") // [1, 2, 3, 4]
|
|
11
13
|
*/
|
|
12
14
|
export function parseIdRange(spec) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
if (
|
|
27
|
-
throw new Error(`Invalid range
|
|
28
|
-
}
|
|
29
|
-
const start = parseInteger(rangeParts[0], part);
|
|
30
|
-
const end = parseInteger(rangeParts[1], part);
|
|
31
|
-
if (start > end) {
|
|
32
|
-
throw new Error(`Invalid range: "${part}". Start must be less than or equal to end`);
|
|
33
|
-
}
|
|
34
|
-
validateModbusAddress(start, part);
|
|
35
|
-
validateModbusAddress(end, part);
|
|
36
|
-
for (let i = start; i <= end; i++) {
|
|
37
|
-
ids.add(i);
|
|
15
|
+
return parseSpec({
|
|
16
|
+
spec,
|
|
17
|
+
label: 'ID',
|
|
18
|
+
formatExamples: ['"1,2,3"', '"1-5"'],
|
|
19
|
+
skipEmptyParts: true,
|
|
20
|
+
parseSingle: (value, context) => {
|
|
21
|
+
const id = parseInteger(value, context, 'ID');
|
|
22
|
+
validateModbusAddress(id, context);
|
|
23
|
+
return id;
|
|
24
|
+
},
|
|
25
|
+
parseRange: (start, end, context) => {
|
|
26
|
+
const startId = parseInteger(start, context, 'ID');
|
|
27
|
+
const endId = parseInteger(end, context, 'ID');
|
|
28
|
+
if (startId > endId) {
|
|
29
|
+
throw new Error(`Invalid range: "${context}". Start must be less than or equal to end`);
|
|
38
30
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return Array.from(ids).sort((a, b) => a - b);
|
|
31
|
+
validateModbusAddress(startId, context);
|
|
32
|
+
validateModbusAddress(endId, context);
|
|
33
|
+
return Array.from({ length: endId - startId + 1 }, (_, i) => startId + i);
|
|
34
|
+
},
|
|
35
|
+
sortItems: (items) => items.sort((a, b) => a - b),
|
|
36
|
+
});
|
|
48
37
|
}
|
|
49
38
|
/**
|
|
50
39
|
* Validates that a number is a valid Modbus slave address (1-247).
|
|
@@ -54,18 +43,4 @@ function validateModbusAddress(id, context) {
|
|
|
54
43
|
throw new Error(`Invalid Modbus slave address: ${id} in "${context}". ` + `Valid addresses are 1-247`);
|
|
55
44
|
}
|
|
56
45
|
}
|
|
57
|
-
/**
|
|
58
|
-
* Parses a string to an integer with validation.
|
|
59
|
-
* Rejects decimal numbers explicitly.
|
|
60
|
-
*/
|
|
61
|
-
function parseInteger(str, context) {
|
|
62
|
-
if (str.includes('.')) {
|
|
63
|
-
throw new Error(`Invalid ID format: "${context}". Decimal numbers not allowed, expected whole numbers only`);
|
|
64
|
-
}
|
|
65
|
-
const num = parseInt(str, 10);
|
|
66
|
-
if (isNaN(num)) {
|
|
67
|
-
throw new Error(`Invalid ID format: "${context}". Expected a number`);
|
|
68
|
-
}
|
|
69
|
-
return num;
|
|
70
|
-
}
|
|
71
46
|
//# sourceMappingURL=parse-id-range.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-id-range.js","sourceRoot":"","sources":["../../../../src/utils/parse-id-range.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"parse-id-range.js","sourceRoot":"","sources":["../../../../src/utils/parse-id-range.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,SAAS,CAAC;QACf,IAAI;QACJ,KAAK,EAAE,IAAI;QACX,cAAc,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC;QACpC,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC9B,MAAM,EAAE,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;YAC7C,qBAAqB,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;YAClC,OAAO,EAAE,CAAA;QACX,CAAC;QACD,UAAU,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;YAClC,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;YAClD,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;YAE9C,IAAI,OAAO,GAAG,KAAK,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,4CAA4C,CAAC,CAAA;YACzF,CAAC;YAED,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YACvC,qBAAqB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;YAErC,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,GAAG,OAAO,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,GAAG,CAAC,CAAC,CAAA;QAC3E,CAAC;QACD,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;KAClD,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,qBAAqB,CAAC,EAAU,EAAE,OAAe;IACxD,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,iCAAiC,EAAE,QAAQ,OAAO,KAAK,GAAG,2BAA2B,CACtF,CAAA;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a string to an integer with validation.
|
|
3
|
+
* Rejects decimal numbers explicitly.
|
|
4
|
+
*
|
|
5
|
+
* @param str - String to parse
|
|
6
|
+
* @param context - Context string for error messages
|
|
7
|
+
* @param label - Label for the value type (e.g., "ID", "baud rate")
|
|
8
|
+
* @returns Parsed integer
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* parseInteger("123", "1-5", "ID") // 123
|
|
12
|
+
* parseInteger("12.5", "1-5", "ID") // throws Error
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseInteger(str: string, context: string, label: string): number;
|
|
15
|
+
//# sourceMappingURL=parse-integer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-integer.d.ts","sourceRoot":"","sources":["../../../../src/utils/parse-integer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAahF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a string to an integer with validation.
|
|
3
|
+
* Rejects decimal numbers explicitly.
|
|
4
|
+
*
|
|
5
|
+
* @param str - String to parse
|
|
6
|
+
* @param context - Context string for error messages
|
|
7
|
+
* @param label - Label for the value type (e.g., "ID", "baud rate")
|
|
8
|
+
* @returns Parsed integer
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* parseInteger("123", "1-5", "ID") // 123
|
|
12
|
+
* parseInteger("12.5", "1-5", "ID") // throws Error
|
|
13
|
+
*/
|
|
14
|
+
export function parseInteger(str, context, label) {
|
|
15
|
+
if (str.includes('.')) {
|
|
16
|
+
throw new Error(`Invalid ${label} format: "${context}". Decimal numbers not allowed, expected whole numbers only`);
|
|
17
|
+
}
|
|
18
|
+
const num = parseInt(str, 10);
|
|
19
|
+
if (isNaN(num)) {
|
|
20
|
+
throw new Error(`Invalid ${label} format: "${context}". Expected a number`);
|
|
21
|
+
}
|
|
22
|
+
return num;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=parse-integer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-integer.js","sourceRoot":"","sources":["../../../../src/utils/parse-integer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,OAAe,EAAE,KAAa;IACtE,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,WAAW,KAAK,aAAa,OAAO,6DAA6D,CAClG,CAAA;IACH,CAAC;IAED,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IAC7B,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,WAAW,KAAK,aAAa,OAAO,sBAAsB,CAAC,CAAA;IAC7E,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Parity } from '@ya-modbus/driver-types';
|
|
2
|
+
/**
|
|
3
|
+
* Parses a comma-separated list of parity values into a sorted array of unique parities.
|
|
4
|
+
*
|
|
5
|
+
* @param spec - Parity specification string (e.g., "none,even,odd")
|
|
6
|
+
* @returns Sorted array of unique parity values in standard order (none, even, odd)
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* parseParity("none,even") // ["none", "even"]
|
|
10
|
+
* parseParity("odd,none") // ["none", "odd"]
|
|
11
|
+
* parseParity("even,even") // ["even"]
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseParity(spec: string): Parity[];
|
|
14
|
+
/**
|
|
15
|
+
* Sorts parities in standard order (none, even, odd)
|
|
16
|
+
*/
|
|
17
|
+
export declare function sortParitiesInStandardOrder(parities: Parity[]): Parity[];
|
|
18
|
+
//# sourceMappingURL=parse-parity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-parity.d.ts","sourceRoot":"","sources":["../../../../src/utils/parse-parity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAMrD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAmBlD;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAExE"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { STANDARD_PARITY } from '../discovery/constants.js';
|
|
2
|
+
import { parseSpec } from './parse-spec.js';
|
|
3
|
+
/**
|
|
4
|
+
* Parses a comma-separated list of parity values into a sorted array of unique parities.
|
|
5
|
+
*
|
|
6
|
+
* @param spec - Parity specification string (e.g., "none,even,odd")
|
|
7
|
+
* @returns Sorted array of unique parity values in standard order (none, even, odd)
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* parseParity("none,even") // ["none", "even"]
|
|
11
|
+
* parseParity("odd,none") // ["none", "odd"]
|
|
12
|
+
* parseParity("even,even") // ["even"]
|
|
13
|
+
*/
|
|
14
|
+
export function parseParity(spec) {
|
|
15
|
+
return parseSpec({
|
|
16
|
+
spec,
|
|
17
|
+
label: 'parity',
|
|
18
|
+
formatExamples: ['"none,even,odd"'],
|
|
19
|
+
skipEmptyParts: false, // Throw error on empty parts for explicit validation
|
|
20
|
+
parseSingle: (value, context) => {
|
|
21
|
+
const normalized = value.toLowerCase();
|
|
22
|
+
if (!isValidParity(normalized)) {
|
|
23
|
+
throw new Error(`Invalid parity value: "${value}" in "${context}". Valid values are: ${STANDARD_PARITY.join(', ')}`);
|
|
24
|
+
}
|
|
25
|
+
return normalized;
|
|
26
|
+
},
|
|
27
|
+
sortItems: (items) => sortParitiesInStandardOrder(items),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Sorts parities in standard order (none, even, odd)
|
|
32
|
+
*/
|
|
33
|
+
export function sortParitiesInStandardOrder(parities) {
|
|
34
|
+
return STANDARD_PARITY.filter((p) => parities.includes(p));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Type guard to check if a string is a valid parity value.
|
|
38
|
+
*/
|
|
39
|
+
function isValidParity(value) {
|
|
40
|
+
return STANDARD_PARITY.includes(value);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=parse-parity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-parity.js","sourceRoot":"","sources":["../../../../src/utils/parse-parity.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAE3D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,SAAS,CAAC;QACf,IAAI;QACJ,KAAK,EAAE,QAAQ;QACf,cAAc,EAAE,CAAC,iBAAiB,CAAC;QACnC,cAAc,EAAE,KAAK,EAAE,qDAAqD;QAC5E,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAA;YAEtC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CACb,0BAA0B,KAAK,SAAS,OAAO,wBAAwB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACpG,CAAA;YACH,CAAC;YAED,OAAO,UAAU,CAAA;QACnB,CAAC;QACD,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,2BAA2B,CAAC,KAAK,CAAC;KACzD,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,2BAA2B,CAAC,QAAkB;IAC5D,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;AAC5D,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,eAAe,CAAC,QAAQ,CAAC,KAAe,CAAC,CAAA;AAClD,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic utility for parsing comma-separated specification strings
|
|
3
|
+
* with optional range support.
|
|
4
|
+
*
|
|
5
|
+
* Handles:
|
|
6
|
+
* - Empty string validation
|
|
7
|
+
* - Comma-separated list parsing
|
|
8
|
+
* - Optional range expansion (e.g., "1-5")
|
|
9
|
+
* - Deduplication via Set
|
|
10
|
+
* - Custom sorting/ordering
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const parseIds = (spec: string) => parseSpec({
|
|
14
|
+
* spec,
|
|
15
|
+
* label: 'ID',
|
|
16
|
+
* formatExamples: ['"1,2,3"', '"1-5"'],
|
|
17
|
+
* parseSingle: (value, context) => {
|
|
18
|
+
* const id = parseInteger(value, context, 'ID')
|
|
19
|
+
* if (id < 1 || id > 247) throw new Error(...)
|
|
20
|
+
* return id
|
|
21
|
+
* },
|
|
22
|
+
* parseRange: (start, end, context) => {
|
|
23
|
+
* const startId = parseInteger(start, context, 'ID')
|
|
24
|
+
* const endId = parseInteger(end, context, 'ID')
|
|
25
|
+
* return Array.from({length: endId - startId + 1}, (_, i) => startId + i)
|
|
26
|
+
* },
|
|
27
|
+
* sortItems: (items) => items.sort((a, b) => a - b)
|
|
28
|
+
* })
|
|
29
|
+
*/
|
|
30
|
+
export interface ParseSpecOptions<T> {
|
|
31
|
+
/** The specification string to parse (e.g., "1,2,3" or "none,even") */
|
|
32
|
+
spec: string;
|
|
33
|
+
/** Label for the value type (e.g., "ID", "parity", "baud rate") */
|
|
34
|
+
label: string;
|
|
35
|
+
/** Example formats to show in error messages (e.g., ['"1,2,3"', '"1-5"']) */
|
|
36
|
+
formatExamples: string[];
|
|
37
|
+
/**
|
|
38
|
+
* Parse a single value from the spec
|
|
39
|
+
* @param value - The trimmed value to parse
|
|
40
|
+
* @param context - The original part for error context
|
|
41
|
+
* @returns The parsed value
|
|
42
|
+
*/
|
|
43
|
+
parseSingle: (value: string, context: string) => T;
|
|
44
|
+
/**
|
|
45
|
+
* Optional: Parse a range (e.g., "1-5")
|
|
46
|
+
* @param start - The start value string
|
|
47
|
+
* @param end - The end value string
|
|
48
|
+
* @param context - The original range string for error context
|
|
49
|
+
* @returns Array of values in the range
|
|
50
|
+
*/
|
|
51
|
+
parseRange?: (start: string, end: string, context: string) => T[];
|
|
52
|
+
/**
|
|
53
|
+
* Sort/order the final array of values
|
|
54
|
+
* @param items - Deduplicated array of items
|
|
55
|
+
* @returns Sorted array
|
|
56
|
+
*/
|
|
57
|
+
sortItems: (items: T[]) => T[];
|
|
58
|
+
/**
|
|
59
|
+
* Optional: Skip empty parts in comma-separated list instead of throwing error
|
|
60
|
+
* Default: false (throw error on empty parts)
|
|
61
|
+
*/
|
|
62
|
+
skipEmptyParts?: boolean;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Generic parser for comma-separated specification strings
|
|
66
|
+
*
|
|
67
|
+
* @param options - Parsing options
|
|
68
|
+
* @returns Sorted array of unique values
|
|
69
|
+
*
|
|
70
|
+
* @throws Error if spec is empty or contains invalid values
|
|
71
|
+
*/
|
|
72
|
+
export declare function parseSpec<T>(options: ParseSpecOptions<T>): T[];
|
|
73
|
+
//# sourceMappingURL=parse-spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-spec.d.ts","sourceRoot":"","sources":["../../../../src/utils/parse-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAA;IAEZ,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAA;IAEb,6EAA6E;IAC7E,cAAc,EAAE,MAAM,EAAE,CAAA;IAExB;;;;;OAKG;IACH,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC,CAAA;IAElD;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC,EAAE,CAAA;IAEjE;;;;OAIG;IACH,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAA;IAE9B;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAoD9D"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic parser for comma-separated specification strings
|
|
3
|
+
*
|
|
4
|
+
* @param options - Parsing options
|
|
5
|
+
* @returns Sorted array of unique values
|
|
6
|
+
*
|
|
7
|
+
* @throws Error if spec is empty or contains invalid values
|
|
8
|
+
*/
|
|
9
|
+
export function parseSpec(options) {
|
|
10
|
+
const { spec, label, formatExamples, parseSingle, parseRange, sortItems, skipEmptyParts = false, } = options;
|
|
11
|
+
const trimmed = spec.trim();
|
|
12
|
+
if (!trimmed) {
|
|
13
|
+
throw new Error(`Invalid ${label} specification: empty string. Expected format: ${formatExamples.join(' or ')}`);
|
|
14
|
+
}
|
|
15
|
+
const items = new Set();
|
|
16
|
+
const parts = trimmed.split(',');
|
|
17
|
+
for (const part of parts) {
|
|
18
|
+
const normalized = part.trim();
|
|
19
|
+
if (!normalized) {
|
|
20
|
+
if (skipEmptyParts) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
throw new Error(`Invalid ${label} specification: empty value in "${spec}". Expected format: ${formatExamples.join(' or ')}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// Check if it's a range (contains hyphen)
|
|
28
|
+
if (normalized.includes('-') && parseRange) {
|
|
29
|
+
const rangeParts = normalized.split('-').map((s) => s.trim());
|
|
30
|
+
if (rangeParts.length !== 2 || !rangeParts[0] || !rangeParts[1]) {
|
|
31
|
+
throw new Error(`Invalid range format: "${part}". Expected format: "start-end"`);
|
|
32
|
+
}
|
|
33
|
+
const rangeValues = parseRange(rangeParts[0], rangeParts[1], part);
|
|
34
|
+
rangeValues.forEach((value) => items.add(value));
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// Single value
|
|
38
|
+
const value = parseSingle(normalized, part);
|
|
39
|
+
items.add(value);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return sortItems(Array.from(items));
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=parse-spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-spec.js","sourceRoot":"","sources":["../../../../src/utils/parse-spec.ts"],"names":[],"mappings":"AAsEA;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAI,OAA4B;IACvD,MAAM,EACJ,IAAI,EACJ,KAAK,EACL,cAAc,EACd,WAAW,EACX,UAAU,EACV,SAAS,EACT,cAAc,GAAG,KAAK,GACvB,GAAG,OAAO,CAAA;IAEX,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IAC3B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,WAAW,KAAK,kDAAkD,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAChG,CAAA;IACH,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,GAAG,EAAK,CAAA;IAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAEhC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;QAE9B,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,IAAI,cAAc,EAAE,CAAC;gBACnB,SAAQ;YACV,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CACb,WAAW,KAAK,mCAAmC,IAAI,uBAAuB,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAC5G,CAAA;YACH,CAAC;QACH,CAAC;QAED,0CAA0C;QAC1C,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3C,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;YAE7D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChE,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,iCAAiC,CAAC,CAAA;YAClF,CAAC;YAED,MAAM,WAAW,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;YAClE,WAAW,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;QAClD,CAAC;aAAM,CAAC;YACN,eAAe;YACf,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;YAC3C,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAClB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;AACrC,CAAC"}
|