@asymmetric-effort/jsonlint 0.0.2 → 0.0.3

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/bin/jsonlint CHANGED
Binary file
package/build/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export type { ParseErrorHash } from "./parser.js";
5
5
  export { formatJson } from "./formatter.js";
6
6
  export { SchemaValidator } from "./schema.js";
7
7
  export type { JsonSchema, SchemaError } from "./schema.js";
8
+ export { main } from "./cli.js";
8
9
  import { JsonParser } from "./parser.js";
9
10
  export declare const parser: JsonParser;
10
11
  import { formatJson } from "./formatter.js";
package/build/index.js CHANGED
@@ -876,12 +876,248 @@ class SchemaValidator {
876
876
  }
877
877
  }
878
878
  }
879
+ // src/cli.ts
880
+ import { readFileSync, writeFileSync } from "fs";
881
+
882
+ // src/version.ts
883
+ var VERSION = "0.0.3";
884
+
885
+ // src/cli.ts
886
+ function printVersion() {
887
+ process.stdout.write(`${VERSION}
888
+ `);
889
+ }
890
+ function printUsage() {
891
+ process.stdout.write(`Usage: jsonlint [OPTIONS] [FILE]
892
+
893
+ Options:
894
+ -v, --version Print version and exit
895
+ -s, --sort-keys Sort object keys in output
896
+ -i, --in-place Overwrite the input file with formatted output
897
+ -t, --indent CHAR Character(s) to use for indentation (default: " ")
898
+ -c, --compact Compact error display
899
+ -V, --validate FILE Validate against a JSON Schema file
900
+ -e, --environment ENV JSON Schema spec version (default: json-schema-draft-03)
901
+ -q, --quiet Do not print parsed JSON to stdout
902
+ -p, --pretty-print Force pretty printing (even if invalid)
903
+ -h, --help Show this help message
904
+
905
+ If FILE is omitted, reads from stdin.
906
+ `);
907
+ }
908
+ function parseArgs(args) {
909
+ const opts = {
910
+ file: null,
911
+ sortKeys: false,
912
+ inPlace: false,
913
+ indent: " ",
914
+ compact: false,
915
+ validate: null,
916
+ environment: "json-schema-draft-03",
917
+ quiet: false,
918
+ prettyPrint: false,
919
+ version: false
920
+ };
921
+ let i = 0;
922
+ while (i < args.length) {
923
+ const arg = args[i];
924
+ switch (arg) {
925
+ case "-v":
926
+ case "--version":
927
+ opts.version = true;
928
+ break;
929
+ case "-s":
930
+ case "--sort-keys":
931
+ opts.sortKeys = true;
932
+ break;
933
+ case "-i":
934
+ case "--in-place":
935
+ opts.inPlace = true;
936
+ break;
937
+ case "-t":
938
+ case "--indent":
939
+ i++;
940
+ opts.indent = args[i] ?? " ";
941
+ break;
942
+ case "-c":
943
+ case "--compact":
944
+ opts.compact = true;
945
+ break;
946
+ case "-V":
947
+ case "--validate":
948
+ i++;
949
+ opts.validate = args[i] ?? null;
950
+ break;
951
+ case "-e":
952
+ case "--environment":
953
+ i++;
954
+ opts.environment = args[i] ?? "json-schema-draft-03";
955
+ break;
956
+ case "-q":
957
+ case "--quiet":
958
+ opts.quiet = true;
959
+ break;
960
+ case "-p":
961
+ case "--pretty-print":
962
+ opts.prettyPrint = true;
963
+ break;
964
+ case "-h":
965
+ case "--help":
966
+ printUsage();
967
+ process.exit(0);
968
+ break;
969
+ default:
970
+ if (arg.startsWith("-")) {
971
+ process.stderr.write(`Unknown option: ${arg}
972
+ `);
973
+ process.exit(1);
974
+ }
975
+ opts.file = arg;
976
+ break;
977
+ }
978
+ i++;
979
+ }
980
+ return opts;
981
+ }
982
+ function sortObject(obj) {
983
+ if (Array.isArray(obj)) {
984
+ return obj.map(sortObject);
985
+ }
986
+ if (obj !== null && typeof obj === "object") {
987
+ const sorted = {};
988
+ const keys = Object.keys(obj).sort();
989
+ for (const key of keys) {
990
+ sorted[key] = sortObject(obj[key]);
991
+ }
992
+ return sorted;
993
+ }
994
+ return obj;
995
+ }
996
+ function readStdin() {
997
+ try {
998
+ return readFileSync("/dev/stdin", "utf-8");
999
+ } catch {
1000
+ process.stderr.write(`Error reading from stdin
1001
+ `);
1002
+ process.exit(1);
1003
+ }
1004
+ }
1005
+ function main(args) {
1006
+ const cliArgs = args ?? process.argv.slice(2);
1007
+ const opts = parseArgs(cliArgs);
1008
+ if (opts.version) {
1009
+ printVersion();
1010
+ return;
1011
+ }
1012
+ let input;
1013
+ let filename;
1014
+ if (opts.file) {
1015
+ try {
1016
+ input = readFileSync(opts.file, "utf-8");
1017
+ } catch {
1018
+ process.stderr.write(`Error: could not open file '${opts.file}'
1019
+ `);
1020
+ process.exit(1);
1021
+ return;
1022
+ }
1023
+ filename = opts.file;
1024
+ } else {
1025
+ input = readStdin();
1026
+ filename = "<stdin>";
1027
+ }
1028
+ const parser = new JsonParser;
1029
+ if (opts.compact) {
1030
+ parser.parseError = (str, hash) => {
1031
+ const line = hash.line;
1032
+ const col = hash.loc.last_column;
1033
+ const found = hash.token === "EOF" ? "EOF" : hash.text || hash.token;
1034
+ const expected = hash.expected.join(", ");
1035
+ const msg = `${filename}: line ${line}, col ${col}, found: '${found}' - expected: ${expected}.`;
1036
+ throw new ParseError(msg, hash);
1037
+ };
1038
+ }
1039
+ function formatCompactError(e) {
1040
+ if (opts.compact && e instanceof LexerError) {
1041
+ return `${filename}: line ${e.line}, col ${e.column}, ${e.message.split(`
1042
+ `)[0]}`;
1043
+ }
1044
+ return e instanceof Error ? e.message : String(e);
1045
+ }
1046
+ let parsed;
1047
+ try {
1048
+ parsed = parser.parse(input);
1049
+ } catch (e) {
1050
+ if (opts.prettyPrint) {
1051
+ const formatted = formatJson(input, opts.indent);
1052
+ process.stdout.write(formatted + `
1053
+ `);
1054
+ try {
1055
+ const reformatParser = new JsonParser;
1056
+ if (opts.compact) {
1057
+ reformatParser.parseError = parser.parseError;
1058
+ }
1059
+ reformatParser.parse(formatted);
1060
+ } catch (e2) {
1061
+ process.stderr.write(formatCompactError(e2) + `
1062
+ `);
1063
+ }
1064
+ process.exit(1);
1065
+ return;
1066
+ }
1067
+ process.stderr.write(formatCompactError(e) + `
1068
+ `);
1069
+ process.exit(1);
1070
+ return;
1071
+ }
1072
+ if (opts.validate) {
1073
+ let schemaInput;
1074
+ try {
1075
+ schemaInput = readFileSync(opts.validate, "utf-8");
1076
+ } catch {
1077
+ process.stderr.write(`Error: could not open schema file '${opts.validate}'
1078
+ `);
1079
+ process.exit(1);
1080
+ return;
1081
+ }
1082
+ let schema;
1083
+ try {
1084
+ schema = JSON.parse(schemaInput);
1085
+ } catch {
1086
+ process.stderr.write(`Error: invalid JSON in schema file '${opts.validate}'
1087
+ `);
1088
+ process.exit(1);
1089
+ return;
1090
+ }
1091
+ const validator = new SchemaValidator;
1092
+ const errors = validator.validate(parsed, schema);
1093
+ if (errors.length > 0) {
1094
+ for (const err of errors) {
1095
+ process.stderr.write(`Schema validation error: property '${err.property}': ${err.message}
1096
+ `);
1097
+ }
1098
+ process.exit(1);
1099
+ return;
1100
+ }
1101
+ }
1102
+ if (opts.sortKeys) {
1103
+ parsed = sortObject(parsed);
1104
+ }
1105
+ const output = JSON.stringify(parsed, null, opts.indent);
1106
+ if (opts.inPlace && opts.file) {
1107
+ writeFileSync(opts.file, output + `
1108
+ `, "utf-8");
1109
+ } else if (!opts.quiet) {
1110
+ process.stdout.write(output + `
1111
+ `);
1112
+ }
1113
+ }
879
1114
  // src/index.ts
880
1115
  var parser = new JsonParser;
881
1116
  var formatter = { formatJson };
882
1117
  export {
883
1118
  parser,
884
1119
  parse,
1120
+ main,
885
1121
  formatter,
886
1122
  formatJson,
887
1123
  TokenType,
@@ -1 +1 @@
1
- export declare const VERSION = "0.0.2";
1
+ export declare const VERSION = "0.0.3";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asymmetric-effort/jsonlint",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "A pure JavaScript/TypeScript JSON parser and validator with detailed error reporting — zero dependencies",
5
5
  "type": "module",
6
6
  "main": "build/index.js",