@ya-modbus/cli 0.7.1 → 0.9.0
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/src/commands/discover.d.ts +3 -0
- package/dist/cjs/src/commands/discover.d.ts.map +1 -1
- package/dist/cjs/src/commands/discover.js +29 -0
- 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 +54 -27
- package/dist/cjs/src/discovery/parameter-generator-utils.js.map +1 -1
- package/dist/cjs/src/discovery/parameter-generator.d.ts +6 -0
- package/dist/cjs/src/discovery/parameter-generator.d.ts.map +1 -1
- package/dist/cjs/src/discovery/parameter-generator.js +43 -17
- 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 +3 -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 +13 -0
- package/dist/cjs/src/utils/parse-id-range.d.ts.map +1 -0
- package/dist/cjs/src/utils/parse-id-range.js +49 -0
- package/dist/cjs/src/utils/parse-id-range.js.map +1 -0
- 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/src/commands/discover.d.ts +3 -0
- package/dist/esm/src/commands/discover.d.ts.map +1 -1
- package/dist/esm/src/commands/discover.js +29 -0
- 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 +54 -27
- package/dist/esm/src/discovery/parameter-generator-utils.js.map +1 -1
- package/dist/esm/src/discovery/parameter-generator.d.ts +6 -0
- package/dist/esm/src/discovery/parameter-generator.d.ts.map +1 -1
- package/dist/esm/src/discovery/parameter-generator.js +43 -17
- 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 +3 -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 +13 -0
- package/dist/esm/src/utils/parse-id-range.d.ts.map +1 -0
- package/dist/esm/src/utils/parse-id-range.js +46 -0
- package/dist/esm/src/utils/parse-id-range.js.map +1 -0
- 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 +2 -2
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergeSpecs = mergeSpecs;
|
|
4
|
+
/**
|
|
5
|
+
* Merges multiple specification strings (from repeated CLI flags) into a
|
|
6
|
+
* single deduplicated, sorted array.
|
|
7
|
+
*
|
|
8
|
+
* Handles:
|
|
9
|
+
* - Single string or array of strings
|
|
10
|
+
* - Deduplication across all specifications
|
|
11
|
+
* - Custom sorting
|
|
12
|
+
*
|
|
13
|
+
* @param specs - Single spec string, array of spec strings, or undefined
|
|
14
|
+
* @param parser - Function that parses a single spec string
|
|
15
|
+
* @param sorter - Optional function to sort the final array
|
|
16
|
+
* @returns Merged and sorted array, or undefined if specs is undefined
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // Merge multiple --id specifications
|
|
20
|
+
* const ids = mergeSpecs(
|
|
21
|
+
* ['1,2', '3-5'],
|
|
22
|
+
* parseIdRange,
|
|
23
|
+
* (items) => items.sort((a, b) => a - b)
|
|
24
|
+
* )
|
|
25
|
+
* // Result: [1, 2, 3, 4, 5]
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // Merge multiple --parity specifications
|
|
29
|
+
* const parities = mergeSpecs(
|
|
30
|
+
* ['none', 'even,odd'],
|
|
31
|
+
* parseParity,
|
|
32
|
+
* sortParitiesInStandardOrder
|
|
33
|
+
* )
|
|
34
|
+
* // Result: ['none', 'even', 'odd']
|
|
35
|
+
*/
|
|
36
|
+
function mergeSpecs(specs, parser, sorter) {
|
|
37
|
+
if (specs === undefined) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
// Normalize to array
|
|
41
|
+
const specArray = Array.isArray(specs) ? specs : [specs];
|
|
42
|
+
// Parse and merge into Set for deduplication
|
|
43
|
+
const allValues = new Set();
|
|
44
|
+
for (const spec of specArray) {
|
|
45
|
+
const values = parser(spec);
|
|
46
|
+
values.forEach((value) => allValues.add(value));
|
|
47
|
+
}
|
|
48
|
+
// Convert to array
|
|
49
|
+
const result = Array.from(allValues);
|
|
50
|
+
// Apply custom sorter if provided, otherwise return unsorted
|
|
51
|
+
return sorter ? sorter(result) : result;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=merge-specs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-specs.js","sourceRoot":"","sources":["../../../../src/utils/merge-specs.ts"],"names":[],"mappings":";;AAgCA,gCAwBC;AAxDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,SAAgB,UAAU,CACxB,KAAoC,EACpC,MAA6B,EAC7B,MAA4B;IAE5B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,qBAAqB;IACrB,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;IAExD,6CAA6C;IAC7C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAK,CAAA;IAC9B,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;QAC3B,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;IACjD,CAAC;IAED,mBAAmB;IACnB,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IAEpC,6DAA6D;IAC7D,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;AACzC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { BaudRate } from '@ya-modbus/driver-types';
|
|
2
|
+
/**
|
|
3
|
+
* Parses a comma-separated list of baud rates and ranges into a sorted array of unique baud rates.
|
|
4
|
+
*
|
|
5
|
+
* @param spec - Baud rate specification string (e.g., "9600,19200" or "9600-38400")
|
|
6
|
+
* @returns Sorted array of unique baud rates from STANDARD_BAUD_RATES
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* parseBaudRate("9600,19200") // [9600, 19200]
|
|
10
|
+
* parseBaudRate("9600-19200") // [9600, 14400, 19200]
|
|
11
|
+
* parseBaudRate("19200,9600") // [9600, 19200]
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseBaudRate(spec: string): BaudRate[];
|
|
14
|
+
//# sourceMappingURL=parse-baud-rate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-baud-rate.d.ts","sourceRoot":"","sources":["../../../../src/utils/parse-baud-rate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAOvD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CA2BtD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseBaudRate = parseBaudRate;
|
|
4
|
+
const constants_js_1 = require("../discovery/constants.js");
|
|
5
|
+
const parse_integer_js_1 = require("./parse-integer.js");
|
|
6
|
+
const parse_spec_js_1 = require("./parse-spec.js");
|
|
7
|
+
/**
|
|
8
|
+
* Parses a comma-separated list of baud rates and ranges into a sorted array of unique baud rates.
|
|
9
|
+
*
|
|
10
|
+
* @param spec - Baud rate specification string (e.g., "9600,19200" or "9600-38400")
|
|
11
|
+
* @returns Sorted array of unique baud rates from STANDARD_BAUD_RATES
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* parseBaudRate("9600,19200") // [9600, 19200]
|
|
15
|
+
* parseBaudRate("9600-19200") // [9600, 14400, 19200]
|
|
16
|
+
* parseBaudRate("19200,9600") // [9600, 19200]
|
|
17
|
+
*/
|
|
18
|
+
function parseBaudRate(spec) {
|
|
19
|
+
return (0, parse_spec_js_1.parseSpec)({
|
|
20
|
+
spec,
|
|
21
|
+
label: 'baud rate',
|
|
22
|
+
formatExamples: ['"9600,19200"', '"9600-19200"'],
|
|
23
|
+
skipEmptyParts: true,
|
|
24
|
+
parseSingle: (value, context) => {
|
|
25
|
+
const rate = (0, parse_integer_js_1.parseInteger)(value, context, 'baud rate');
|
|
26
|
+
validateBaudRate(rate, context);
|
|
27
|
+
return rate;
|
|
28
|
+
},
|
|
29
|
+
parseRange: (start, end, context) => {
|
|
30
|
+
const startRate = (0, parse_integer_js_1.parseInteger)(start, context, 'baud rate');
|
|
31
|
+
const endRate = (0, parse_integer_js_1.parseInteger)(end, context, 'baud rate');
|
|
32
|
+
if (startRate > endRate) {
|
|
33
|
+
throw new Error(`Invalid range: "${context}". Start must be less than or equal to end`);
|
|
34
|
+
}
|
|
35
|
+
validateBaudRate(startRate, context);
|
|
36
|
+
validateBaudRate(endRate, context);
|
|
37
|
+
// Extract baud rates between start and end from STANDARD_BAUD_RATES
|
|
38
|
+
return constants_js_1.STANDARD_BAUD_RATES.filter((rate) => rate >= startRate && rate <= endRate);
|
|
39
|
+
},
|
|
40
|
+
sortItems: (items) => items.sort((a, b) => a - b),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Validates that a number is a supported baud rate.
|
|
45
|
+
*/
|
|
46
|
+
function validateBaudRate(rate, context) {
|
|
47
|
+
if (!constants_js_1.STANDARD_BAUD_RATES.includes(rate)) {
|
|
48
|
+
throw new Error(`Unsupported baud rate: ${rate} in "${context}". ` +
|
|
49
|
+
`Supported rates are: ${constants_js_1.STANDARD_BAUD_RATES.join(', ')}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=parse-baud-rate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-baud-rate.js","sourceRoot":"","sources":["../../../../src/utils/parse-baud-rate.ts"],"names":[],"mappings":";;AAkBA,sCA2BC;AA3CD,4DAA+D;AAE/D,yDAAiD;AACjD,mDAA2C;AAE3C;;;;;;;;;;GAUG;AACH,SAAgB,aAAa,CAAC,IAAY;IACxC,OAAO,IAAA,yBAAS,EAAC;QACf,IAAI;QACJ,KAAK,EAAE,WAAW;QAClB,cAAc,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC;QAChD,cAAc,EAAE,IAAI;QACpB,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC9B,MAAM,IAAI,GAAG,IAAA,+BAAY,EAAC,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,CAAA;YACtD,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YAC/B,OAAO,IAAI,CAAA;QACb,CAAC;QACD,UAAU,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;YAClC,MAAM,SAAS,GAAG,IAAA,+BAAY,EAAC,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,CAAA;YAC3D,MAAM,OAAO,GAAG,IAAA,+BAAY,EAAC,GAAG,EAAE,OAAO,EAAE,WAAW,CAAC,CAAA;YAEvD,IAAI,SAAS,GAAG,OAAO,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,4CAA4C,CAAC,CAAA;YACzF,CAAC;YAED,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;YACpC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YAElC,oEAAoE;YACpE,OAAO,kCAAmB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,OAAO,CAAC,CAAA;QACnF,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,gBAAgB,CAAC,IAAY,EAAE,OAAe;IACrD,IAAI,CAAC,kCAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CACb,0BAA0B,IAAI,QAAQ,OAAO,KAAK;YAChD,wBAAwB,kCAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3D,CAAA;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses a comma-separated list of IDs and ranges into a sorted array of unique IDs.
|
|
3
|
+
*
|
|
4
|
+
* @param spec - ID specification string (e.g., "1,2,3-5")
|
|
5
|
+
* @returns Sorted array of unique Modbus slave IDs (1-247)
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* parseIdRange("1,2,3-5") // [1, 2, 3, 4, 5]
|
|
9
|
+
* parseIdRange("5,1,3") // [1, 3, 5]
|
|
10
|
+
* parseIdRange("1-3,2-4") // [1, 2, 3, 4]
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseIdRange(spec: string): number[];
|
|
13
|
+
//# sourceMappingURL=parse-id-range.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-id-range.d.ts","sourceRoot":"","sources":["../../../../src/utils/parse-id-range.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CA0BnD"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseIdRange = parseIdRange;
|
|
4
|
+
const parse_integer_js_1 = require("./parse-integer.js");
|
|
5
|
+
const parse_spec_js_1 = require("./parse-spec.js");
|
|
6
|
+
/**
|
|
7
|
+
* Parses a comma-separated list of IDs and ranges into a sorted array of unique IDs.
|
|
8
|
+
*
|
|
9
|
+
* @param spec - ID specification string (e.g., "1,2,3-5")
|
|
10
|
+
* @returns Sorted array of unique Modbus slave IDs (1-247)
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* parseIdRange("1,2,3-5") // [1, 2, 3, 4, 5]
|
|
14
|
+
* parseIdRange("5,1,3") // [1, 3, 5]
|
|
15
|
+
* parseIdRange("1-3,2-4") // [1, 2, 3, 4]
|
|
16
|
+
*/
|
|
17
|
+
function parseIdRange(spec) {
|
|
18
|
+
return (0, parse_spec_js_1.parseSpec)({
|
|
19
|
+
spec,
|
|
20
|
+
label: 'ID',
|
|
21
|
+
formatExamples: ['"1,2,3"', '"1-5"'],
|
|
22
|
+
skipEmptyParts: true,
|
|
23
|
+
parseSingle: (value, context) => {
|
|
24
|
+
const id = (0, parse_integer_js_1.parseInteger)(value, context, 'ID');
|
|
25
|
+
validateModbusAddress(id, context);
|
|
26
|
+
return id;
|
|
27
|
+
},
|
|
28
|
+
parseRange: (start, end, context) => {
|
|
29
|
+
const startId = (0, parse_integer_js_1.parseInteger)(start, context, 'ID');
|
|
30
|
+
const endId = (0, parse_integer_js_1.parseInteger)(end, context, 'ID');
|
|
31
|
+
if (startId > endId) {
|
|
32
|
+
throw new Error(`Invalid range: "${context}". Start must be less than or equal to end`);
|
|
33
|
+
}
|
|
34
|
+
validateModbusAddress(startId, context);
|
|
35
|
+
validateModbusAddress(endId, context);
|
|
36
|
+
return Array.from({ length: endId - startId + 1 }, (_, i) => startId + i);
|
|
37
|
+
},
|
|
38
|
+
sortItems: (items) => items.sort((a, b) => a - b),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Validates that a number is a valid Modbus slave address (1-247).
|
|
43
|
+
*/
|
|
44
|
+
function validateModbusAddress(id, context) {
|
|
45
|
+
if (id < 1 || id > 247) {
|
|
46
|
+
throw new Error(`Invalid Modbus slave address: ${id} in "${context}". ` + `Valid addresses are 1-247`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=parse-id-range.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-id-range.js","sourceRoot":"","sources":["../../../../src/utils/parse-id-range.ts"],"names":[],"mappings":";;AAcA,oCA0BC;AAxCD,yDAAiD;AACjD,mDAA2C;AAE3C;;;;;;;;;;GAUG;AACH,SAAgB,YAAY,CAAC,IAAY;IACvC,OAAO,IAAA,yBAAS,EAAC;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,IAAA,+BAAY,EAAC,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,IAAA,+BAAY,EAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;YAClD,MAAM,KAAK,GAAG,IAAA,+BAAY,EAAC,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,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseInteger = parseInteger;
|
|
4
|
+
/**
|
|
5
|
+
* Parses a string to an integer with validation.
|
|
6
|
+
* Rejects decimal numbers explicitly.
|
|
7
|
+
*
|
|
8
|
+
* @param str - String to parse
|
|
9
|
+
* @param context - Context string for error messages
|
|
10
|
+
* @param label - Label for the value type (e.g., "ID", "baud rate")
|
|
11
|
+
* @returns Parsed integer
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* parseInteger("123", "1-5", "ID") // 123
|
|
15
|
+
* parseInteger("12.5", "1-5", "ID") // throws Error
|
|
16
|
+
*/
|
|
17
|
+
function parseInteger(str, context, label) {
|
|
18
|
+
if (str.includes('.')) {
|
|
19
|
+
throw new Error(`Invalid ${label} format: "${context}". Decimal numbers not allowed, expected whole numbers only`);
|
|
20
|
+
}
|
|
21
|
+
const num = parseInt(str, 10);
|
|
22
|
+
if (isNaN(num)) {
|
|
23
|
+
throw new Error(`Invalid ${label} format: "${context}". Expected a number`);
|
|
24
|
+
}
|
|
25
|
+
return num;
|
|
26
|
+
}
|
|
27
|
+
//# 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,oCAaC;AA1BD;;;;;;;;;;;;GAYG;AACH,SAAgB,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,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseParity = parseParity;
|
|
4
|
+
exports.sortParitiesInStandardOrder = sortParitiesInStandardOrder;
|
|
5
|
+
const constants_js_1 = require("../discovery/constants.js");
|
|
6
|
+
const parse_spec_js_1 = require("./parse-spec.js");
|
|
7
|
+
/**
|
|
8
|
+
* Parses a comma-separated list of parity values into a sorted array of unique parities.
|
|
9
|
+
*
|
|
10
|
+
* @param spec - Parity specification string (e.g., "none,even,odd")
|
|
11
|
+
* @returns Sorted array of unique parity values in standard order (none, even, odd)
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* parseParity("none,even") // ["none", "even"]
|
|
15
|
+
* parseParity("odd,none") // ["none", "odd"]
|
|
16
|
+
* parseParity("even,even") // ["even"]
|
|
17
|
+
*/
|
|
18
|
+
function parseParity(spec) {
|
|
19
|
+
return (0, parse_spec_js_1.parseSpec)({
|
|
20
|
+
spec,
|
|
21
|
+
label: 'parity',
|
|
22
|
+
formatExamples: ['"none,even,odd"'],
|
|
23
|
+
skipEmptyParts: false, // Throw error on empty parts for explicit validation
|
|
24
|
+
parseSingle: (value, context) => {
|
|
25
|
+
const normalized = value.toLowerCase();
|
|
26
|
+
if (!isValidParity(normalized)) {
|
|
27
|
+
throw new Error(`Invalid parity value: "${value}" in "${context}". Valid values are: ${constants_js_1.STANDARD_PARITY.join(', ')}`);
|
|
28
|
+
}
|
|
29
|
+
return normalized;
|
|
30
|
+
},
|
|
31
|
+
sortItems: (items) => sortParitiesInStandardOrder(items),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Sorts parities in standard order (none, even, odd)
|
|
36
|
+
*/
|
|
37
|
+
function sortParitiesInStandardOrder(parities) {
|
|
38
|
+
return constants_js_1.STANDARD_PARITY.filter((p) => parities.includes(p));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Type guard to check if a string is a valid parity value.
|
|
42
|
+
*/
|
|
43
|
+
function isValidParity(value) {
|
|
44
|
+
return constants_js_1.STANDARD_PARITY.includes(value);
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=parse-parity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-parity.js","sourceRoot":"","sources":["../../../../src/utils/parse-parity.ts"],"names":[],"mappings":";;AAiBA,kCAmBC;AAKD,kEAEC;AAzCD,4DAA2D;AAE3D,mDAA2C;AAE3C;;;;;;;;;;GAUG;AACH,SAAgB,WAAW,CAAC,IAAY;IACtC,OAAO,IAAA,yBAAS,EAAC;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,8BAAe,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,SAAgB,2BAA2B,CAAC,QAAkB;IAC5D,OAAO,8BAAe,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,8BAAe,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,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseSpec = parseSpec;
|
|
4
|
+
/**
|
|
5
|
+
* Generic parser for comma-separated specification strings
|
|
6
|
+
*
|
|
7
|
+
* @param options - Parsing options
|
|
8
|
+
* @returns Sorted array of unique values
|
|
9
|
+
*
|
|
10
|
+
* @throws Error if spec is empty or contains invalid values
|
|
11
|
+
*/
|
|
12
|
+
function parseSpec(options) {
|
|
13
|
+
const { spec, label, formatExamples, parseSingle, parseRange, sortItems, skipEmptyParts = false, } = options;
|
|
14
|
+
const trimmed = spec.trim();
|
|
15
|
+
if (!trimmed) {
|
|
16
|
+
throw new Error(`Invalid ${label} specification: empty string. Expected format: ${formatExamples.join(' or ')}`);
|
|
17
|
+
}
|
|
18
|
+
const items = new Set();
|
|
19
|
+
const parts = trimmed.split(',');
|
|
20
|
+
for (const part of parts) {
|
|
21
|
+
const normalized = part.trim();
|
|
22
|
+
if (!normalized) {
|
|
23
|
+
if (skipEmptyParts) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
throw new Error(`Invalid ${label} specification: empty value in "${spec}". Expected format: ${formatExamples.join(' or ')}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// Check if it's a range (contains hyphen)
|
|
31
|
+
if (normalized.includes('-') && parseRange) {
|
|
32
|
+
const rangeParts = normalized.split('-').map((s) => s.trim());
|
|
33
|
+
if (rangeParts.length !== 2 || !rangeParts[0] || !rangeParts[1]) {
|
|
34
|
+
throw new Error(`Invalid range format: "${part}". Expected format: "start-end"`);
|
|
35
|
+
}
|
|
36
|
+
const rangeValues = parseRange(rangeParts[0], rangeParts[1], part);
|
|
37
|
+
rangeValues.forEach((value) => items.add(value));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
// Single value
|
|
41
|
+
const value = parseSingle(normalized, part);
|
|
42
|
+
items.add(value);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return sortItems(Array.from(items));
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=parse-spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-spec.js","sourceRoot":"","sources":["../../../../src/utils/parse-spec.ts"],"names":[],"mappings":";;AA8EA,8BAoDC;AA5DD;;;;;;;GAOG;AACH,SAAgB,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"}
|