simple-ascii-chart-cli 2.2.0 → 3.0.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/README.md +108 -23
- package/dist/cli.js +621 -63
- package/dist/index.d.ts +2 -0
- package/dist/index.js +23 -0
- package/dist/options.d.ts +28 -0
- package/dist/options.js +59 -0
- package/dist/validators.d.ts +2 -2
- package/dist/validators.js +164 -84
- package/package.json +5 -4
- package/dist/tests/cli.test.d.ts +0 -1
- package/dist/tests/cli.test.js +0 -39
- package/dist/tests/validators.test.d.ts +0 -1
- package/dist/tests/validators.test.js +0 -105
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.plot = void 0;
|
|
21
|
+
var simple_ascii_chart_1 = require("simple-ascii-chart");
|
|
22
|
+
Object.defineProperty(exports, "plot", { enumerable: true, get: function () { return __importDefault(simple_ascii_chart_1).default; } });
|
|
23
|
+
__exportStar(require("simple-ascii-chart"), exports);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Settings } from 'simple-ascii-chart';
|
|
2
|
+
export declare const GRAPH_MODES: readonly ["line", "point", "bar", "horizontalBar"];
|
|
3
|
+
export type CliGraphMode = (typeof GRAPH_MODES)[number];
|
|
4
|
+
export type CliSettingsInput = {
|
|
5
|
+
options?: string;
|
|
6
|
+
title?: string;
|
|
7
|
+
xLabel?: string;
|
|
8
|
+
yLabel?: string;
|
|
9
|
+
width?: number;
|
|
10
|
+
height?: number;
|
|
11
|
+
fillArea?: boolean;
|
|
12
|
+
hideYAxis?: boolean;
|
|
13
|
+
hideXAxis?: boolean;
|
|
14
|
+
color?: (string | number)[] | string;
|
|
15
|
+
axisCenter?: (string | number)[];
|
|
16
|
+
yRange?: (string | number)[];
|
|
17
|
+
showTickLabel?: boolean;
|
|
18
|
+
thresholds?: unknown;
|
|
19
|
+
points?: unknown;
|
|
20
|
+
legend?: string;
|
|
21
|
+
formatter?: string;
|
|
22
|
+
lineFormatter?: string;
|
|
23
|
+
symbols?: string;
|
|
24
|
+
mode?: CliGraphMode;
|
|
25
|
+
debugMode?: boolean;
|
|
26
|
+
onWarning?: (message: string) => void;
|
|
27
|
+
};
|
|
28
|
+
export declare const preparePlotOptions: ({ options, width, height, hideYAxis, hideXAxis, fillArea, title, xLabel, yLabel, color, axisCenter, yRange, showTickLabel, thresholds, points, legend, formatter, lineFormatter, symbols, mode, debugMode, onWarning, }: CliSettingsInput) => Settings;
|
package/dist/options.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.preparePlotOptions = exports.GRAPH_MODES = void 0;
|
|
4
|
+
const validators_1 = require("./validators");
|
|
5
|
+
exports.GRAPH_MODES = ['line', 'point', 'bar', 'horizontalBar'];
|
|
6
|
+
const preparePlotOptions = ({ options, width, height, hideYAxis, hideXAxis, fillArea, title, xLabel, yLabel, color, axisCenter, yRange, showTickLabel, thresholds, points, legend, formatter, lineFormatter, symbols, mode, debugMode, onWarning, }) => {
|
|
7
|
+
let currentOptions = {};
|
|
8
|
+
if (options) {
|
|
9
|
+
try {
|
|
10
|
+
currentOptions = JSON.parse(options);
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
const details = error instanceof Error ? error.message : String(error);
|
|
14
|
+
throw new Error(`Invalid --options JSON: ${details}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const mergedOptions = {
|
|
18
|
+
...currentOptions,
|
|
19
|
+
};
|
|
20
|
+
const assignIfDefined = (key, value) => {
|
|
21
|
+
if (value !== undefined) {
|
|
22
|
+
mergedOptions[key] = value;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
assignIfDefined('width', width);
|
|
26
|
+
assignIfDefined('height', height);
|
|
27
|
+
assignIfDefined('hideYAxis', hideYAxis);
|
|
28
|
+
assignIfDefined('hideXAxis', hideXAxis);
|
|
29
|
+
assignIfDefined('title', title);
|
|
30
|
+
assignIfDefined('xLabel', xLabel);
|
|
31
|
+
assignIfDefined('yLabel', yLabel);
|
|
32
|
+
assignIfDefined('fillArea', fillArea);
|
|
33
|
+
assignIfDefined('mode', mode);
|
|
34
|
+
assignIfDefined('debugMode', debugMode);
|
|
35
|
+
assignIfDefined('color', color ? (0, validators_1.validateColors)(color) : undefined);
|
|
36
|
+
assignIfDefined('axisCenter', (0, validators_1.validateAxisCenter)(axisCenter));
|
|
37
|
+
assignIfDefined('yRange', (0, validators_1.validateYRange)(yRange));
|
|
38
|
+
assignIfDefined('showTickLabel', showTickLabel);
|
|
39
|
+
const parsedThresholds = (0, validators_1.validateThresholds)(thresholds);
|
|
40
|
+
if (thresholds !== undefined && parsedThresholds === undefined && onWarning) {
|
|
41
|
+
onWarning('Ignoring invalid --thresholds payload. Use JSON object/array (e.g. {"y":2} or [{"y":2}]).');
|
|
42
|
+
}
|
|
43
|
+
assignIfDefined('thresholds', parsedThresholds);
|
|
44
|
+
const parsedPoints = (0, validators_1.validatePoints)(points);
|
|
45
|
+
if (points !== undefined && parsedPoints === undefined && onWarning) {
|
|
46
|
+
onWarning('Ignoring invalid --points payload. Use JSON object/array (e.g. {"x":1,"y":2} or [{"x":1,"y":2}]).');
|
|
47
|
+
}
|
|
48
|
+
assignIfDefined('points', parsedPoints);
|
|
49
|
+
const parsedLegend = (0, validators_1.validateLegend)(legend);
|
|
50
|
+
if (legend !== undefined && parsedLegend === undefined) {
|
|
51
|
+
throw new Error('Invalid --legend JSON: expected an object with optional position (left|right|top|bottom) and string/string[] labels for series/points/thresholds');
|
|
52
|
+
}
|
|
53
|
+
assignIfDefined('legend', parsedLegend);
|
|
54
|
+
assignIfDefined('formatter', (0, validators_1.validateFormatter)(formatter));
|
|
55
|
+
assignIfDefined('lineFormatter', (0, validators_1.validateLineFormatter)(lineFormatter));
|
|
56
|
+
assignIfDefined('symbols', (0, validators_1.validateSymbols)(symbols));
|
|
57
|
+
return mergedOptions;
|
|
58
|
+
};
|
|
59
|
+
exports.preparePlotOptions = preparePlotOptions;
|
package/dist/validators.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { Colors, CustomSymbol, Formatter, GraphPoint, Legend, LineFormatterArgs,
|
|
|
2
2
|
export declare const validateAxisCenter: (axisCenter: (string | number)[] | undefined) => MaybePoint;
|
|
3
3
|
export declare const validateColors: (colors: (string | number)[] | string | undefined) => Colors | undefined;
|
|
4
4
|
export declare const validateYRange: (yRange: (string | number)[] | undefined) => [number, number] | undefined;
|
|
5
|
-
export declare const validateThresholds: (thresholds:
|
|
6
|
-
export declare const validatePoints: (points:
|
|
5
|
+
export declare const validateThresholds: (thresholds: unknown) => Threshold[] | undefined;
|
|
6
|
+
export declare const validatePoints: (points: unknown) => GraphPoint[] | undefined;
|
|
7
7
|
export declare const validateLegend: (legend: string | undefined) => Legend | undefined;
|
|
8
8
|
export declare const validateFormatter: (formatter: string | undefined) => Formatter | undefined;
|
|
9
9
|
export declare const validateLineFormatter: (lineFormatter: string | undefined) => ((args: LineFormatterArgs) => CustomSymbol | CustomSymbol[]) | undefined;
|
package/dist/validators.js
CHANGED
|
@@ -1,25 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __read = (this && this.__read) || function (o, n) {
|
|
3
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
4
|
-
if (!m) return o;
|
|
5
|
-
var i = m.call(o), r, ar = [], e;
|
|
6
|
-
try {
|
|
7
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
8
|
-
}
|
|
9
|
-
catch (error) { e = { error: error }; }
|
|
10
|
-
finally {
|
|
11
|
-
try {
|
|
12
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
13
|
-
}
|
|
14
|
-
finally { if (e) throw e.error; }
|
|
15
|
-
}
|
|
16
|
-
return ar;
|
|
17
|
-
};
|
|
18
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
3
|
exports.validateSymbols = exports.validateLineFormatter = exports.validateFormatter = exports.validateLegend = exports.validatePoints = exports.validateThresholds = exports.validateYRange = exports.validateColors = exports.validateAxisCenter = void 0;
|
|
20
4
|
// Prepares parameters by parsing JSON inputs and merging with optional settings
|
|
21
5
|
// Define ANSI color types for validation
|
|
22
|
-
|
|
6
|
+
const ANSI_COLORS = new Set([
|
|
23
7
|
'ansiRed',
|
|
24
8
|
'ansiGreen',
|
|
25
9
|
'ansiBlack',
|
|
@@ -29,20 +13,60 @@ var ANSI_COLORS = new Set([
|
|
|
29
13
|
'ansiCyan',
|
|
30
14
|
'ansiWhite',
|
|
31
15
|
]);
|
|
16
|
+
const LEGEND_POSITIONS = new Set(['left', 'right', 'top', 'bottom']);
|
|
32
17
|
// Type guard to check if a value is a valid ANSI color
|
|
33
|
-
|
|
18
|
+
const isAnsiColor = (value) => ANSI_COLORS.has(value);
|
|
19
|
+
const toFiniteNumber = (value) => {
|
|
20
|
+
if (typeof value === 'number') {
|
|
21
|
+
return Number.isFinite(value) ? value : undefined;
|
|
22
|
+
}
|
|
23
|
+
if (typeof value === 'string') {
|
|
24
|
+
const parsed = Number(value.trim());
|
|
25
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
};
|
|
29
|
+
const parseJsonFragment = (value) => {
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(value);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const isStringOrStringArray = (value) => {
|
|
38
|
+
return typeof value === 'string' || (Array.isArray(value) && value.every((item) => typeof item === 'string'));
|
|
39
|
+
};
|
|
40
|
+
const collectObjectCandidates = (value) => {
|
|
41
|
+
if (value === undefined || value === null) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
if (Array.isArray(value)) {
|
|
45
|
+
return value.flatMap((item) => collectObjectCandidates(item));
|
|
46
|
+
}
|
|
47
|
+
if (typeof value === 'string') {
|
|
48
|
+
const parsed = parseJsonFragment(value.trim());
|
|
49
|
+
return parsed === undefined ? [] : collectObjectCandidates(parsed);
|
|
50
|
+
}
|
|
51
|
+
if (typeof value === 'object') {
|
|
52
|
+
return [value];
|
|
53
|
+
}
|
|
54
|
+
return [];
|
|
55
|
+
};
|
|
34
56
|
// Helper function to validate and format axisCenter as MaybePoint
|
|
35
|
-
|
|
57
|
+
const validateAxisCenter = (axisCenter) => {
|
|
36
58
|
if (!axisCenter || axisCenter.length !== 2)
|
|
37
59
|
return undefined;
|
|
38
|
-
|
|
39
|
-
|
|
60
|
+
const [x, y] = axisCenter;
|
|
61
|
+
const xNumber = toFiniteNumber(x);
|
|
62
|
+
const yNumber = toFiniteNumber(y);
|
|
63
|
+
return xNumber !== undefined && yNumber !== undefined ? [xNumber, yNumber] : undefined;
|
|
40
64
|
};
|
|
41
65
|
exports.validateAxisCenter = validateAxisCenter;
|
|
42
66
|
// Helper function to validate and map colors to the Colors type
|
|
43
|
-
|
|
67
|
+
const validateColors = (colors) => {
|
|
44
68
|
if (Array.isArray(colors)) {
|
|
45
|
-
|
|
69
|
+
const filteredColors = colors.filter(isAnsiColor);
|
|
46
70
|
return filteredColors.length > 0 ? filteredColors : undefined;
|
|
47
71
|
}
|
|
48
72
|
else if (typeof colors === 'string' && isAnsiColor(colors)) {
|
|
@@ -53,123 +77,179 @@ var validateColors = function (colors) {
|
|
|
53
77
|
exports.validateColors = validateColors;
|
|
54
78
|
// Updated prepareParams function with validated colors and axisCenter handling
|
|
55
79
|
// Helper function to validate and format yRange as [number, number]
|
|
56
|
-
|
|
80
|
+
const validateYRange = (yRange) => {
|
|
57
81
|
if (Array.isArray(yRange) && yRange.length === 2) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
82
|
+
const [min, max] = yRange;
|
|
83
|
+
const minNumber = toFiniteNumber(min);
|
|
84
|
+
const maxNumber = toFiniteNumber(max);
|
|
85
|
+
if (minNumber !== undefined && maxNumber !== undefined) {
|
|
86
|
+
return [minNumber, maxNumber];
|
|
62
87
|
}
|
|
63
88
|
}
|
|
64
89
|
return undefined; // Return undefined if the format is incorrect
|
|
65
90
|
};
|
|
66
91
|
exports.validateYRange = validateYRange;
|
|
67
92
|
// Helper function to validate and format thresholds as Threshold[]
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
var color = typeof threshold.color === 'string' ? threshold.color : undefined;
|
|
78
|
-
return x !== undefined || y !== undefined ? { x: x, y: y, color: color } : undefined;
|
|
79
|
-
}
|
|
80
|
-
return undefined;
|
|
93
|
+
const validateThresholds = (thresholds) => {
|
|
94
|
+
const candidates = collectObjectCandidates(thresholds);
|
|
95
|
+
const validated = candidates
|
|
96
|
+
.map((item) => {
|
|
97
|
+
const threshold = item;
|
|
98
|
+
const x = toFiniteNumber(threshold.x);
|
|
99
|
+
const y = toFiniteNumber(threshold.y);
|
|
100
|
+
const color = typeof threshold.color === 'string' ? threshold.color : undefined;
|
|
101
|
+
return x !== undefined || y !== undefined ? { x, y, color } : undefined;
|
|
81
102
|
})
|
|
82
|
-
.filter(
|
|
103
|
+
.filter((threshold) => threshold !== undefined);
|
|
104
|
+
return validated.length > 0 ? validated : undefined;
|
|
83
105
|
};
|
|
84
106
|
exports.validateThresholds = validateThresholds;
|
|
85
107
|
// Helper function to validate and format thresholds as Threshold[]
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
var color = typeof point.color === 'string' ? point.color : undefined;
|
|
96
|
-
return x !== undefined && y !== undefined ? { x: x, y: y, color: color } : undefined;
|
|
97
|
-
}
|
|
98
|
-
return undefined;
|
|
108
|
+
const validatePoints = (points) => {
|
|
109
|
+
const candidates = collectObjectCandidates(points);
|
|
110
|
+
const validated = candidates
|
|
111
|
+
.map((item) => {
|
|
112
|
+
const point = item;
|
|
113
|
+
const x = toFiniteNumber(point.x);
|
|
114
|
+
const y = toFiniteNumber(point.y);
|
|
115
|
+
const color = typeof point.color === 'string' ? point.color : undefined;
|
|
116
|
+
return x !== undefined && y !== undefined ? { x, y, color } : undefined;
|
|
99
117
|
})
|
|
100
|
-
.filter(
|
|
118
|
+
.filter((point) => point !== undefined);
|
|
119
|
+
return validated.length > 0 ? validated : undefined;
|
|
101
120
|
};
|
|
102
121
|
exports.validatePoints = validatePoints;
|
|
103
122
|
// Helper function to validate and parse legend as Legend
|
|
104
|
-
|
|
123
|
+
const validateLegend = (legend) => {
|
|
105
124
|
if (!legend)
|
|
106
125
|
return undefined;
|
|
107
126
|
try {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
127
|
+
const parsedLegend = JSON.parse(legend);
|
|
128
|
+
if (typeof parsedLegend !== 'object' || parsedLegend === null || Array.isArray(parsedLegend)) {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
const candidate = parsedLegend;
|
|
132
|
+
const normalized = {};
|
|
133
|
+
if (candidate.position !== undefined) {
|
|
134
|
+
if (typeof candidate.position !== 'string' || !LEGEND_POSITIONS.has(candidate.position)) {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
normalized.position = candidate.position;
|
|
138
|
+
}
|
|
139
|
+
if (candidate.series !== undefined) {
|
|
140
|
+
if (!isStringOrStringArray(candidate.series)) {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
normalized.series = candidate.series;
|
|
144
|
+
}
|
|
145
|
+
if (candidate.points !== undefined) {
|
|
146
|
+
if (!isStringOrStringArray(candidate.points)) {
|
|
147
|
+
return undefined;
|
|
148
|
+
}
|
|
149
|
+
normalized.points = candidate.points;
|
|
115
150
|
}
|
|
151
|
+
if (candidate.thresholds !== undefined) {
|
|
152
|
+
if (!isStringOrStringArray(candidate.thresholds)) {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
normalized.thresholds = candidate.thresholds;
|
|
156
|
+
}
|
|
157
|
+
return Object.keys(normalized).length > 0 ? normalized : undefined;
|
|
116
158
|
}
|
|
117
|
-
catch
|
|
159
|
+
catch {
|
|
118
160
|
// Ignore JSON parsing errors and return undefined
|
|
119
161
|
}
|
|
120
162
|
return undefined;
|
|
121
163
|
};
|
|
122
164
|
exports.validateLegend = validateLegend;
|
|
123
165
|
// Helper function to parse a formatter string into a function of type Formatter
|
|
124
|
-
|
|
166
|
+
const validateFormatter = (formatter) => {
|
|
125
167
|
if (!formatter)
|
|
126
168
|
return undefined;
|
|
127
169
|
try {
|
|
128
170
|
// Create a function from the formatter string; it should accept (value, helpers) parameters
|
|
129
171
|
// Using `new Function` to construct a function from the string (in the form "value => { ... }")
|
|
130
|
-
return new Function('value', 'helpers',
|
|
172
|
+
return new Function('value', 'helpers', `return (${formatter})(value, helpers);`);
|
|
131
173
|
}
|
|
132
|
-
catch
|
|
174
|
+
catch {
|
|
133
175
|
// Return undefined if the formatter string cannot be parsed as a function
|
|
134
176
|
return undefined;
|
|
135
177
|
}
|
|
136
178
|
};
|
|
137
179
|
exports.validateFormatter = validateFormatter;
|
|
138
180
|
// Helper function to parse lineFormatter string into a function of type (args: LineFormatterArgs) => CustomSymbol | CustomSymbol[]
|
|
139
|
-
|
|
181
|
+
const validateLineFormatter = (lineFormatter) => {
|
|
140
182
|
if (!lineFormatter)
|
|
141
183
|
return undefined;
|
|
142
184
|
try {
|
|
143
185
|
// Using `new Function` to construct a function from the lineFormatter string
|
|
144
|
-
return new Function('args',
|
|
186
|
+
return new Function('args', `return (${lineFormatter})(args);`);
|
|
145
187
|
}
|
|
146
|
-
catch
|
|
188
|
+
catch {
|
|
147
189
|
// Return undefined if the lineFormatter string cannot be parsed as a function
|
|
148
190
|
return undefined;
|
|
149
191
|
}
|
|
150
192
|
};
|
|
151
193
|
exports.validateLineFormatter = validateLineFormatter;
|
|
152
194
|
// Helper function to parse and validate symbols as Symbols type
|
|
153
|
-
|
|
195
|
+
const validateSymbols = (symbols) => {
|
|
154
196
|
if (!symbols)
|
|
155
197
|
return undefined;
|
|
156
198
|
try {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
199
|
+
const parsedSymbols = JSON.parse(symbols);
|
|
200
|
+
if (typeof parsedSymbols !== 'object' || parsedSymbols === null || Array.isArray(parsedSymbols)) {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
const candidate = parsedSymbols;
|
|
204
|
+
const normalized = {};
|
|
205
|
+
const isObjectCandidate = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
206
|
+
if (candidate.axis !== undefined) {
|
|
207
|
+
if (!isObjectCandidate(candidate.axis)) {
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
normalized.axis = candidate.axis;
|
|
211
|
+
}
|
|
212
|
+
if (candidate.chart !== undefined) {
|
|
213
|
+
if (!isObjectCandidate(candidate.chart)) {
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
normalized.chart = candidate.chart;
|
|
217
|
+
}
|
|
218
|
+
if (candidate.thresholds !== undefined) {
|
|
219
|
+
if (!isObjectCandidate(candidate.thresholds)) {
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
normalized.thresholds = candidate.thresholds;
|
|
223
|
+
}
|
|
224
|
+
if (candidate.empty !== undefined) {
|
|
225
|
+
if (typeof candidate.empty !== 'string') {
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
normalized.empty = candidate.empty;
|
|
167
229
|
}
|
|
230
|
+
if (candidate.background !== undefined) {
|
|
231
|
+
if (typeof candidate.background !== 'string') {
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
normalized.background = candidate.background;
|
|
235
|
+
}
|
|
236
|
+
if (candidate.border !== undefined) {
|
|
237
|
+
if (typeof candidate.border !== 'string') {
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
normalized.border = candidate.border;
|
|
241
|
+
}
|
|
242
|
+
if (candidate.point !== undefined) {
|
|
243
|
+
if (typeof candidate.point !== 'string') {
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
normalized.point = candidate.point;
|
|
247
|
+
}
|
|
248
|
+
return Object.keys(normalized).length > 0 ? normalized : undefined;
|
|
168
249
|
}
|
|
169
|
-
catch
|
|
250
|
+
catch {
|
|
170
251
|
// Return undefined if symbols string cannot be parsed
|
|
171
252
|
return undefined;
|
|
172
253
|
}
|
|
173
|
-
return undefined;
|
|
174
254
|
};
|
|
175
255
|
exports.validateSymbols = validateSymbols;
|
package/package.json
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "simple-ascii-chart-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Simple ascii chart generator CLI",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"bin": {
|
|
8
|
-
"simple-ascii-chart": "dist/cli.js"
|
|
8
|
+
"simple-ascii-chart": "dist/cli.js",
|
|
9
|
+
"simple-ascii-chart-cli": "dist/cli.js"
|
|
9
10
|
},
|
|
10
11
|
"scripts": {
|
|
11
|
-
"start": "tsc-watch -p tsconfig.json --preserveWatchOutput -w --onSuccess 'node ./dist/
|
|
12
|
+
"start": "tsc-watch -p tsconfig.json --preserveWatchOutput -w --onSuccess 'node ./dist/cli.js --help'",
|
|
12
13
|
"lint": "eslint .",
|
|
13
14
|
"lint:fix": "eslint . --fix",
|
|
14
15
|
"test": "jest --coverage",
|
|
15
16
|
"test:watch": "jest --watch",
|
|
16
|
-
"build": "tsc -p tsconfig.build.json",
|
|
17
|
+
"build": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\" && tsc -p tsconfig.build.json",
|
|
17
18
|
"build:watch": "tsc -p tsconfig.build.json -w",
|
|
18
19
|
"prepare": "npm run lint && npm run build && npm test"
|
|
19
20
|
},
|
package/dist/tests/cli.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/tests/cli.test.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
var child_process_1 = require("child_process");
|
|
7
|
-
var path_1 = __importDefault(require("path"));
|
|
8
|
-
var cliPath = path_1.default.resolve(__dirname, '../../dist/cli.js'); // <-- LOCAL build output
|
|
9
|
-
function execPlotterScript(args, callback) {
|
|
10
|
-
(0, child_process_1.exec)("node ".concat(cliPath, " ").concat(args), callback);
|
|
11
|
-
}
|
|
12
|
-
describe('plotter script', function () {
|
|
13
|
-
it('should require the --input option', function (done) {
|
|
14
|
-
execPlotterScript('', function (error, stdout, stderr) {
|
|
15
|
-
expect(stderr).toContain('Missing required argument: input');
|
|
16
|
-
done();
|
|
17
|
-
});
|
|
18
|
-
});
|
|
19
|
-
it('should output a plot when given valid input', function (done) {
|
|
20
|
-
var validInput = JSON.stringify([
|
|
21
|
-
[1, 1],
|
|
22
|
-
[2, 2],
|
|
23
|
-
[3, 3],
|
|
24
|
-
]);
|
|
25
|
-
execPlotterScript("--input '".concat(validInput, "'"), function (error, stdout, stderr) {
|
|
26
|
-
expect(error).toBeNull();
|
|
27
|
-
expect(stderr).toBe('');
|
|
28
|
-
expect(stdout).toContain("\n \u25B2 \n3\u2524 \u250F\u2501 \n2\u2524\u250F\u251B \n1\u2524\u251B \n \u2514\u252C\u252C\u252C\u25B6\n 123 \n");
|
|
29
|
-
done();
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
it('should handle invalid JSON input gracefully', function (done) {
|
|
33
|
-
var invalidInput = '[ invalid json';
|
|
34
|
-
execPlotterScript("--input '".concat(invalidInput, "'"), function (error, stdout, stderr) {
|
|
35
|
-
expect(stderr).toContain('Oops! Something went wrong!');
|
|
36
|
-
done();
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
var validators_1 = require("../validators");
|
|
4
|
-
describe('Utility Functions Tests', function () {
|
|
5
|
-
describe('validateAxisCenter', function () {
|
|
6
|
-
it('returns valid MaybePoint when given two numbers', function () {
|
|
7
|
-
expect((0, validators_1.validateAxisCenter)([1, 2])).toEqual([1, 2]);
|
|
8
|
-
});
|
|
9
|
-
it('returns undefined for invalid input', function () {
|
|
10
|
-
expect((0, validators_1.validateAxisCenter)([1])).toBeUndefined();
|
|
11
|
-
expect((0, validators_1.validateAxisCenter)(['a', 'b'])).toBeUndefined();
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
describe('validateColors', function () {
|
|
15
|
-
it('filters valid ANSI colors from an array', function () {
|
|
16
|
-
expect((0, validators_1.validateColors)(['ansiRed', 'ansiGreen', 'ansiBlue'])).toEqual([
|
|
17
|
-
'ansiRed',
|
|
18
|
-
'ansiGreen',
|
|
19
|
-
'ansiBlue',
|
|
20
|
-
]);
|
|
21
|
-
});
|
|
22
|
-
it('returns undefined for unsupported color strings', function () {
|
|
23
|
-
expect((0, validators_1.validateColors)(['red', 'green'])).toBeUndefined();
|
|
24
|
-
});
|
|
25
|
-
it('returns a single ANSI color if input is a valid ANSI color string', function () {
|
|
26
|
-
expect((0, validators_1.validateColors)('ansiRed')).toEqual('ansiRed');
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
describe('validateYRange', function () {
|
|
30
|
-
it('returns a valid [number, number] tuple for valid input', function () {
|
|
31
|
-
expect((0, validators_1.validateYRange)([10, 20])).toEqual([10, 20]);
|
|
32
|
-
});
|
|
33
|
-
it('returns undefined for invalid ranges', function () {
|
|
34
|
-
expect((0, validators_1.validateYRange)([10])).toBeUndefined();
|
|
35
|
-
expect((0, validators_1.validateYRange)(['a', 'b'])).toBeUndefined();
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
describe('validateThresholds', function () {
|
|
39
|
-
it('returns a valid array of Thresholds when given correct input', function () {
|
|
40
|
-
expect((0, validators_1.validateThresholds)([{ x: 10, y: 20, color: 'ansiRed' }])).toEqual([
|
|
41
|
-
{ x: 10, y: 20, color: 'ansiRed' },
|
|
42
|
-
]);
|
|
43
|
-
});
|
|
44
|
-
it('ignores invalid items in the array', function () {
|
|
45
|
-
expect((0, validators_1.validateThresholds)([
|
|
46
|
-
{ x: 10, y: 20, color: 'ansiRed' },
|
|
47
|
-
{ x: 'a', y: 'b' },
|
|
48
|
-
])).toEqual([{ x: 10, y: 20, color: 'ansiRed' }]);
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
describe('validateLegend', function () {
|
|
52
|
-
it('returns a valid Legend object for correct JSON string input', function () {
|
|
53
|
-
var legend = { position: 'top', series: ['series1'] };
|
|
54
|
-
expect((0, validators_1.validateLegend)(JSON.stringify(legend))).toEqual(legend);
|
|
55
|
-
});
|
|
56
|
-
it('returns undefined for invalid JSON or unsupported structure', function () {
|
|
57
|
-
expect((0, validators_1.validateLegend)('{"position": "middle"}')).toBeUndefined();
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
describe('validateFormatter', function () {
|
|
61
|
-
it('returns a valid Formatter function for correct string input', function () {
|
|
62
|
-
var formatterStr = '(value) => value.toFixed(2)';
|
|
63
|
-
var formatter = (0, validators_1.validateFormatter)(formatterStr);
|
|
64
|
-
expect(formatter(10.1234, {})).toBe('10.12');
|
|
65
|
-
});
|
|
66
|
-
it('returns undefined for invalid formatter strings', function () {
|
|
67
|
-
expect((0, validators_1.validateFormatter)('invalid code')).toBeUndefined();
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
describe('validateLineFormatter', function () {
|
|
71
|
-
it('returns a valid LineFormatter function for correct string input', function () {
|
|
72
|
-
var lineFormatterStr = '(args) => ({ x: args.x, y: args.y, symbol: "*" })';
|
|
73
|
-
var lineFormatter = (0, validators_1.validateLineFormatter)(lineFormatterStr);
|
|
74
|
-
expect(lineFormatter({
|
|
75
|
-
x: 1,
|
|
76
|
-
y: 2,
|
|
77
|
-
plotX: 1,
|
|
78
|
-
plotY: 2,
|
|
79
|
-
input: [],
|
|
80
|
-
index: 0,
|
|
81
|
-
minX: 0,
|
|
82
|
-
minY: 0,
|
|
83
|
-
expansionX: [0, 0],
|
|
84
|
-
expansionY: [0, 0],
|
|
85
|
-
toPlotCoordinates: function () { return [0, 0]; },
|
|
86
|
-
})).toEqual({
|
|
87
|
-
x: 1,
|
|
88
|
-
y: 2,
|
|
89
|
-
symbol: '*',
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
it('returns undefined for invalid lineFormatter strings', function () {
|
|
93
|
-
expect((0, validators_1.validateLineFormatter)('invalid code')).toBeUndefined();
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
describe('validateSymbols', function () {
|
|
97
|
-
it('returns valid Symbols object for correct JSON string input', function () {
|
|
98
|
-
var symbols = { axis: { x: '-', y: '|' }, empty: ' ' };
|
|
99
|
-
expect((0, validators_1.validateSymbols)(JSON.stringify(symbols))).toEqual(symbols);
|
|
100
|
-
});
|
|
101
|
-
it('returns undefined for invalid JSON or unsupported structure', function () {
|
|
102
|
-
expect((0, validators_1.validateSymbols)('{"invalidKey": "-"}')).toBeUndefined();
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
});
|