+39
-23
@@ -6,6 +6,7 @@ "use strict"; | ||
| exports.fetchNJSON = fetchNJSON; | ||
| /* eslint-disable @typescript-eslint/no-unnecessary-condition */ | ||
| const parser_1 = require("./parser"); | ||
| function parse(text, options) { | ||
| try { | ||
| const result = (0, parser_1.parse)(text, { grammarSource: "", offset: 0, ...options }); | ||
| const result = (0, parser_1.parse)(text, { grammarSource: "", offset: 0, ...(typeof options === "function" ? undefined : options) }); | ||
| if (typeof options === "function") | ||
@@ -20,3 +21,3 @@ options = { reviver: options }; | ||
| function revive(context, key, value, skip, skipNext) { | ||
| if (value && typeof value === "object" && !(value instanceof Date) && !(value instanceof RegExp) && !(value instanceof URL) && !ArrayBuffer.isView(value) && references.indexOf(value) === -1) { | ||
| if (value && typeof value === "object" && !(value instanceof Date) && !(value instanceof RegExp) && !(value instanceof URL) && !ArrayBuffer.isView(value) && !references.includes(value)) { | ||
| references.push(value); | ||
@@ -182,3 +183,2 @@ if (value instanceof Array) | ||
| const indent = space; | ||
| const twoIndent = indent + indent; | ||
| function getIdentifier() { | ||
@@ -231,21 +231,30 @@ const { length } = letters; | ||
| if (value instanceof Array) { | ||
| let args = []; | ||
| const elements = []; | ||
| let elems = elements; | ||
| let push = -1; | ||
| for (const [i, _] of value.entries()) | ||
| elements.push(replace(value, numberKey ? i : i.toString(), _, skipNext)); | ||
| function stringify(currIndent, body, first) { | ||
| if (this.identifier && body) | ||
| if (this.already && this.identifier && body) | ||
| return this.identifier; | ||
| if (first) { | ||
| const push = elements.findIndex(_ => !_.argument()); | ||
| push = elements.findIndex(_ => !_.argument()); | ||
| if (push !== -1) { | ||
| elems = elements.slice(0, push); | ||
| const args = elements.slice(push, elements.length); | ||
| this.statement = function () { | ||
| return `${indent}${this.identifier}.push(${newLine}${args.map(_ => twoIndent + _.stringify(twoIndent, true)).join("," + newLine)}${newLine}${indent})`; | ||
| }; | ||
| args = elements.slice(push, elements.length); | ||
| } | ||
| } | ||
| const nextIndent = currIndent + indent; | ||
| return elems.length ? `[${newLine}${elems.map(_ => nextIndent + _.stringify(nextIndent, body)).join("," + newLine)}${newLine}${currIndent}]` : "[]"; | ||
| if (!this.already && this.identifier && body) { | ||
| this.already = true; | ||
| if (args.length) { | ||
| const nextNextIndent = nextIndent + indent; | ||
| return `Object.assign(${newLine}${nextIndent}${this.identifier},${newLine}${nextIndent}{${newLine}${args | ||
| .map((_, i) => `${nextNextIndent}"${i + push}":${separator}${_.stringify(nextNextIndent, true)}`) | ||
| .join(`,${newLine}`)}${newLine}${nextIndent}}${newLine}${currIndent})`; | ||
| } | ||
| return this.identifier; | ||
| } | ||
| return elems.length ? `[${newLine}${elems.map(_ => nextIndent + _.stringify(nextIndent, body)).join(`,${newLine}`)}${newLine}${currIndent}]` : "[]"; | ||
| } | ||
@@ -290,3 +299,3 @@ rest = { argument, elements, stringify }; | ||
| } | ||
| return elems.length ? `new Map([${newLine}${elems.map(_ => nextIndent + _.stringify(nextIndent, body)).join("," + newLine)}${newLine}${currIndent}])` : "new Map()"; | ||
| return elems.length ? `new Map([${newLine}${elems.map(_ => nextIndent + _.stringify(nextIndent, body)).join(`,${newLine}`)}${newLine}${currIndent}])` : "new Map()"; | ||
| } | ||
@@ -322,3 +331,3 @@ rest = { argument, elements, stringify }; | ||
| } | ||
| return elems.length ? `new Set([${newLine}${elems.map(_ => nextIndent + _.stringify(nextIndent, body)).join("," + newLine)}${newLine}${currIndent}])` : "new Set()"; | ||
| return elems.length ? `new Set([${newLine}${elems.map(_ => nextIndent + _.stringify(nextIndent, body)).join(`,${newLine}`)}${newLine}${currIndent}])` : "new Set()"; | ||
| } | ||
@@ -332,8 +341,11 @@ rest = { argument, elements, stringify }; | ||
| } | ||
| // eslint-disable-next-line no-case-declarations | ||
| const id = typedArrays.findIndex(_ => value instanceof _); | ||
| if (id !== -1) { | ||
| const { name, prototype: { toString } } = typedArrays[id]; | ||
| const { name, | ||
| // eslint-disable-next-line @typescript-eslint/unbound-method | ||
| prototype: { toString } } = typedArrays[id]; | ||
| const bigint = value instanceof BigInt64Array || value instanceof BigUint64Array; | ||
| const stringified = toString.call(value); | ||
| rest = nativeRef(stringified.length ? `new ${name}([${bigint ? stringified.replace(/,/g, "n,") + "n" : stringified}])` : `new ${name}()`); | ||
| rest = nativeRef(stringified.length ? `new ${name}([${bigint ? `${stringified.replace(/,/g, "n,")}n` : stringified}])` : `new ${name}()`); | ||
| } | ||
@@ -369,3 +381,3 @@ else { | ||
| for (const [key, val] of entries) { | ||
| if (["cause", "message", "name", "stack"].indexOf(key) === -1) { | ||
| if (!["cause", "message", "name", "stack"].includes(key)) { | ||
| const replaced = replace(value, key, val); | ||
@@ -394,3 +406,3 @@ if (!replaced.exclude) | ||
| .map(_ => `${nextNextIndent}${JSON.stringify(_[0])}:${separator}${_[1].stringify(nextNextIndent, body)}`) | ||
| .join("," + newLine)}${newLine}${nextIndent}}${newLine}${currIndent})`; | ||
| .join(`,${newLine}`)}${newLine}${nextIndent}}${newLine}${currIndent})`; | ||
| if (!this.already && this.identifier && body) { | ||
@@ -425,8 +437,11 @@ this.already = true; | ||
| .map(_ => `${nextNextIndent}${JSON.stringify(_[0])}:${separator}${_[1].stringify(nextNextIndent, true)}`) | ||
| .join("," + newLine)}${newLine}${nextIndent}}${newLine}${currIndent})`; | ||
| .join(`,${newLine}`)}${newLine}${nextIndent}}${newLine}${currIndent})`; | ||
| } | ||
| return this.identifier; | ||
| } | ||
| const wrapped = this.main && body; | ||
| const open = wrapped ? "(" : ""; | ||
| const close = wrapped ? ")" : ""; | ||
| return elems.length | ||
| ? `{${newLine}${elems.map(_ => `${nextIndent}${JSON.stringify(_[0])}:${separator}${_[1].stringify(nextIndent, body)}`).join("," + newLine)}${newLine}${currIndent}}` | ||
| ? `${open}{${newLine}${elems.map(_ => `${nextIndent}${JSON.stringify(_[0])}:${separator}${_[1].stringify(nextIndent, body)}`).join(`,${newLine}`)}${newLine}${currIndent}}${close}` | ||
| : "{}"; | ||
@@ -449,3 +464,3 @@ } | ||
| case "bigint": | ||
| return nativeRef(value.toString() + "n"); | ||
| return nativeRef(`${value.toString()}n`); | ||
| case "boolean": | ||
@@ -467,2 +482,3 @@ case "number": | ||
| return undefined; | ||
| replaced.main = true; | ||
| const identifiers = Array.from(references.values()) | ||
@@ -474,5 +490,3 @@ .filter(_ => _.identifier) | ||
| const args = identifiers.map(_ => _.stringify(indent, false, true)); | ||
| const statements = identifiers.filter(_ => _.statement).map(_ => _.statement()); | ||
| statements.push(`${indent}return ${replaced.stringify(indent, true)}`); | ||
| return (`((${identifiers.map(_ => _.identifier).join("," + separator)})${separator}=>${separator}{${newLine}${statements.join(";" + newLine)}${newLine}})` + | ||
| return (`((${identifiers.map(_ => _.identifier).join(`,${separator}`)})${separator}=>${newLine}${indent}${replaced.stringify(indent, true)}${newLine})` + | ||
| `(${newLine}${indent}${args.join(`,${newLine}${indent}`)}${newLine})`); | ||
@@ -496,2 +510,3 @@ } | ||
| }; | ||
| // eslint-disable-next-line @typescript-eslint/no-unsafe-return | ||
| if (req._body || req.headers["content-type"] !== "application/njson") | ||
@@ -503,2 +518,3 @@ return next(); | ||
| try { | ||
| // eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
| req.body = exports.NJSON.parse(Buffer.concat(chunks).toString(req.headers["content-encoding"] || "utf8"), parse); | ||
@@ -521,3 +537,3 @@ req._body = true; | ||
| const _options = options; | ||
| if (Response && Response.prototype) { | ||
| if (Response === null || Response === void 0 ? void 0 : Response.prototype) { | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
@@ -524,0 +540,0 @@ Response.prototype.njson = async function njson(options) { |
+39
-23
@@ -0,5 +1,6 @@ | ||
| /* eslint-disable @typescript-eslint/no-unnecessary-condition */ | ||
| import { NJSONError, parse as parser } from "./parser.js"; | ||
| function parse(text, options) { | ||
| try { | ||
| const result = parser(text, { grammarSource: "", offset: 0, ...options }); | ||
| const result = parser(text, { grammarSource: "", offset: 0, ...(typeof options === "function" ? undefined : options) }); | ||
| if (typeof options === "function") | ||
@@ -14,3 +15,3 @@ options = { reviver: options }; | ||
| function revive(context, key, value, skip, skipNext) { | ||
| if (value && typeof value === "object" && !(value instanceof Date) && !(value instanceof RegExp) && !(value instanceof URL) && !ArrayBuffer.isView(value) && references.indexOf(value) === -1) { | ||
| if (value && typeof value === "object" && !(value instanceof Date) && !(value instanceof RegExp) && !(value instanceof URL) && !ArrayBuffer.isView(value) && !references.includes(value)) { | ||
| references.push(value); | ||
@@ -176,3 +177,2 @@ if (value instanceof Array) | ||
| const indent = space; | ||
| const twoIndent = indent + indent; | ||
| function getIdentifier() { | ||
@@ -225,21 +225,30 @@ const { length } = letters; | ||
| if (value instanceof Array) { | ||
| let args = []; | ||
| const elements = []; | ||
| let elems = elements; | ||
| let push = -1; | ||
| for (const [i, _] of value.entries()) | ||
| elements.push(replace(value, numberKey ? i : i.toString(), _, skipNext)); | ||
| function stringify(currIndent, body, first) { | ||
| if (this.identifier && body) | ||
| if (this.already && this.identifier && body) | ||
| return this.identifier; | ||
| if (first) { | ||
| const push = elements.findIndex(_ => !_.argument()); | ||
| push = elements.findIndex(_ => !_.argument()); | ||
| if (push !== -1) { | ||
| elems = elements.slice(0, push); | ||
| const args = elements.slice(push, elements.length); | ||
| this.statement = function () { | ||
| return `${indent}${this.identifier}.push(${newLine}${args.map(_ => twoIndent + _.stringify(twoIndent, true)).join("," + newLine)}${newLine}${indent})`; | ||
| }; | ||
| args = elements.slice(push, elements.length); | ||
| } | ||
| } | ||
| const nextIndent = currIndent + indent; | ||
| return elems.length ? `[${newLine}${elems.map(_ => nextIndent + _.stringify(nextIndent, body)).join("," + newLine)}${newLine}${currIndent}]` : "[]"; | ||
| if (!this.already && this.identifier && body) { | ||
| this.already = true; | ||
| if (args.length) { | ||
| const nextNextIndent = nextIndent + indent; | ||
| return `Object.assign(${newLine}${nextIndent}${this.identifier},${newLine}${nextIndent}{${newLine}${args | ||
| .map((_, i) => `${nextNextIndent}"${i + push}":${separator}${_.stringify(nextNextIndent, true)}`) | ||
| .join(`,${newLine}`)}${newLine}${nextIndent}}${newLine}${currIndent})`; | ||
| } | ||
| return this.identifier; | ||
| } | ||
| return elems.length ? `[${newLine}${elems.map(_ => nextIndent + _.stringify(nextIndent, body)).join(`,${newLine}`)}${newLine}${currIndent}]` : "[]"; | ||
| } | ||
@@ -284,3 +293,3 @@ rest = { argument, elements, stringify }; | ||
| } | ||
| return elems.length ? `new Map([${newLine}${elems.map(_ => nextIndent + _.stringify(nextIndent, body)).join("," + newLine)}${newLine}${currIndent}])` : "new Map()"; | ||
| return elems.length ? `new Map([${newLine}${elems.map(_ => nextIndent + _.stringify(nextIndent, body)).join(`,${newLine}`)}${newLine}${currIndent}])` : "new Map()"; | ||
| } | ||
@@ -316,3 +325,3 @@ rest = { argument, elements, stringify }; | ||
| } | ||
| return elems.length ? `new Set([${newLine}${elems.map(_ => nextIndent + _.stringify(nextIndent, body)).join("," + newLine)}${newLine}${currIndent}])` : "new Set()"; | ||
| return elems.length ? `new Set([${newLine}${elems.map(_ => nextIndent + _.stringify(nextIndent, body)).join(`,${newLine}`)}${newLine}${currIndent}])` : "new Set()"; | ||
| } | ||
@@ -326,8 +335,11 @@ rest = { argument, elements, stringify }; | ||
| } | ||
| // eslint-disable-next-line no-case-declarations | ||
| const id = typedArrays.findIndex(_ => value instanceof _); | ||
| if (id !== -1) { | ||
| const { name, prototype: { toString } } = typedArrays[id]; | ||
| const { name, | ||
| // eslint-disable-next-line @typescript-eslint/unbound-method | ||
| prototype: { toString } } = typedArrays[id]; | ||
| const bigint = value instanceof BigInt64Array || value instanceof BigUint64Array; | ||
| const stringified = toString.call(value); | ||
| rest = nativeRef(stringified.length ? `new ${name}([${bigint ? stringified.replace(/,/g, "n,") + "n" : stringified}])` : `new ${name}()`); | ||
| rest = nativeRef(stringified.length ? `new ${name}([${bigint ? `${stringified.replace(/,/g, "n,")}n` : stringified}])` : `new ${name}()`); | ||
| } | ||
@@ -363,3 +375,3 @@ else { | ||
| for (const [key, val] of entries) { | ||
| if (["cause", "message", "name", "stack"].indexOf(key) === -1) { | ||
| if (!["cause", "message", "name", "stack"].includes(key)) { | ||
| const replaced = replace(value, key, val); | ||
@@ -388,3 +400,3 @@ if (!replaced.exclude) | ||
| .map(_ => `${nextNextIndent}${JSON.stringify(_[0])}:${separator}${_[1].stringify(nextNextIndent, body)}`) | ||
| .join("," + newLine)}${newLine}${nextIndent}}${newLine}${currIndent})`; | ||
| .join(`,${newLine}`)}${newLine}${nextIndent}}${newLine}${currIndent})`; | ||
| if (!this.already && this.identifier && body) { | ||
@@ -419,8 +431,11 @@ this.already = true; | ||
| .map(_ => `${nextNextIndent}${JSON.stringify(_[0])}:${separator}${_[1].stringify(nextNextIndent, true)}`) | ||
| .join("," + newLine)}${newLine}${nextIndent}}${newLine}${currIndent})`; | ||
| .join(`,${newLine}`)}${newLine}${nextIndent}}${newLine}${currIndent})`; | ||
| } | ||
| return this.identifier; | ||
| } | ||
| const wrapped = this.main && body; | ||
| const open = wrapped ? "(" : ""; | ||
| const close = wrapped ? ")" : ""; | ||
| return elems.length | ||
| ? `{${newLine}${elems.map(_ => `${nextIndent}${JSON.stringify(_[0])}:${separator}${_[1].stringify(nextIndent, body)}`).join("," + newLine)}${newLine}${currIndent}}` | ||
| ? `${open}{${newLine}${elems.map(_ => `${nextIndent}${JSON.stringify(_[0])}:${separator}${_[1].stringify(nextIndent, body)}`).join(`,${newLine}`)}${newLine}${currIndent}}${close}` | ||
| : "{}"; | ||
@@ -443,3 +458,3 @@ } | ||
| case "bigint": | ||
| return nativeRef(value.toString() + "n"); | ||
| return nativeRef(`${value.toString()}n`); | ||
| case "boolean": | ||
@@ -461,2 +476,3 @@ case "number": | ||
| return undefined; | ||
| replaced.main = true; | ||
| const identifiers = Array.from(references.values()) | ||
@@ -468,5 +484,3 @@ .filter(_ => _.identifier) | ||
| const args = identifiers.map(_ => _.stringify(indent, false, true)); | ||
| const statements = identifiers.filter(_ => _.statement).map(_ => _.statement()); | ||
| statements.push(`${indent}return ${replaced.stringify(indent, true)}`); | ||
| return (`((${identifiers.map(_ => _.identifier).join("," + separator)})${separator}=>${separator}{${newLine}${statements.join(";" + newLine)}${newLine}})` + | ||
| return (`((${identifiers.map(_ => _.identifier).join(`,${separator}`)})${separator}=>${newLine}${indent}${replaced.stringify(indent, true)}${newLine})` + | ||
| `(${newLine}${indent}${args.join(`,${newLine}${indent}`)}${newLine})`); | ||
@@ -490,2 +504,3 @@ } | ||
| }; | ||
| // eslint-disable-next-line @typescript-eslint/no-unsafe-return | ||
| if (req._body || req.headers["content-type"] !== "application/njson") | ||
@@ -497,2 +512,3 @@ return next(); | ||
| try { | ||
| // eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
| req.body = NJSON.parse(Buffer.concat(chunks).toString(req.headers["content-encoding"] || "utf8"), parse); | ||
@@ -515,3 +531,3 @@ req._body = true; | ||
| const _options = options; | ||
| if (Response && Response.prototype) { | ||
| if (Response?.prototype) { | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
@@ -518,0 +534,0 @@ Response.prototype.njson = async function njson(options) { |
@@ -9,3 +9,6 @@ /** A function which can be used as `replacer` or `reviver`. */ | ||
| numberKey?: boolean; | ||
| /** A function that transforms the results. This function is called for each member of the object. If a member contains nested objects, the nested objects are transformed before the parent object is. */ | ||
| /** | ||
| * A function that transforms the results. This function is called for each member of the object. | ||
| * If a member contains nested objects, the nested objects are transformed before the parent object is. | ||
| */ | ||
| reviver?: NjsonFunction; | ||
@@ -43,3 +46,4 @@ } | ||
| * @param text A valid NJSON string. | ||
| * @param reviver A function that transforms the results. This function is called for each member of the object. If a member contains nested objects, the nested objects are transformed before the parent object is. | ||
| * @param reviver A function that transforms the results. This function is called for each member of the object. | ||
| * If a member contains nested objects, the nested objects are transformed before the parent object is. | ||
| */ | ||
@@ -46,0 +50,0 @@ declare function parse<T = unknown>(text: string, reviver?: NjsonFunction): T; |
+58
-42
@@ -1,8 +0,3 @@ | ||
| import path from "node:path"; | ||
| import { fileURLToPath } from "node:url"; | ||
| import { fixupPluginRules } from "@eslint/compat"; | ||
| import { FlatCompat } from "@eslint/eslintrc"; | ||
| import js from "@eslint/js"; | ||
| import tsParser from "@typescript-eslint/parser"; | ||
| import stylistic from "@stylistic/eslint-plugin"; | ||
| import _import from "eslint-plugin-import"; | ||
@@ -12,42 +7,63 @@ import simpleImportSort from "eslint-plugin-simple-import-sort"; | ||
| import globals from "globals"; | ||
| import tsEslint from "typescript-eslint"; | ||
| const __filename = fileURLToPath(import.meta.url); | ||
| const __dirname = path.dirname(__filename); | ||
| const compat = new FlatCompat({ allConfig: js.configs.all, baseDirectory: __dirname, recommendedConfig: js.configs.recommended }); | ||
| const overrides = { for: { after: false }, if: { after: false }, switch: { after: false }, while: { after: false } }; | ||
| const unusedVarsOptions = { argsIgnorePattern: "^_", caughtErrors: "none", ignoreRestSiblings: true }; | ||
| export default [ | ||
| ...compat.extends("plugin:@typescript-eslint/recommended"), | ||
| export default tsEslint.config( | ||
| { ignores: ["coverage", "dist", "parser.ts"] }, | ||
| { | ||
| languageOptions: { ecmaVersion: 9, globals: { ...globals.amd, ...globals.browser, ...globals.jquery, ...globals.node }, parser: tsParser, sourceType: "module" }, | ||
| plugins: { import: fixupPluginRules(_import), "simple-import-sort": simpleImportSort, "sort-keys": sortKeys }, | ||
| rules: { | ||
| "@typescript-eslint/no-empty-function": "off", | ||
| "@typescript-eslint/no-empty-interface": "off", | ||
| "@typescript-eslint/no-non-null-assertion": "off", | ||
| "arrow-body-style": ["error", "as-needed"], | ||
| "arrow-parens": ["error", "as-needed"], | ||
| "arrow-spacing": "error", | ||
| "brace-style": ["error", "1tbs", { allowSingleLine: true }], | ||
| curly: ["error", "multi-or-nest"], | ||
| eqeqeq: ["error"], | ||
| "import/first": "error", | ||
| "import/newline-after-import": "error", | ||
| "import/no-duplicates": "error", | ||
| indent: ["error", 2], | ||
| "key-spacing": ["error", { align: { afterColon: true, beforeColon: false, on: "value" } }], | ||
| "keyword-spacing": ["error", { before: true, overrides: { catch: { after: false }, for: { after: false }, if: { after: false }, switch: { after: false }, while: { after: false } } }], | ||
| "linebreak-style": ["error", "unix"], | ||
| "no-console": "warn", | ||
| "no-mixed-spaces-and-tabs": ["error", "smart-tabs"], | ||
| "nonblock-statement-body-position": ["error", "beside"], | ||
| "prefer-const": ["error", { destructuring: "all" }], | ||
| semi: ["error", "always"], | ||
| "simple-import-sort/exports": "error", | ||
| "simple-import-sort/imports": "error", | ||
| "sort-keys": "off", | ||
| "sort-keys/sort-keys-fix": "error", | ||
| "space-before-function-paren": ["error", { anonymous: "never", asyncArrow: "always", named: "never" }], | ||
| "space-unary-ops": ["error", { nonwords: false, overrides: { "!": true }, words: true }] | ||
| extends: [js.configs.recommended, ...tsEslint.configs.strictTypeChecked, ...tsEslint.configs.recommendedTypeChecked, ...tsEslint.configs.stylisticTypeChecked], | ||
| files: ["**/*.{cjs,js,mjs,ts}"], | ||
| languageOptions: { | ||
| ecmaVersion: 2020, | ||
| globals: globals.browser, | ||
| parserOptions: { | ||
| projectService: { allowDefaultProject: ["eslint.config.mjs", "jest.config.cjs"], defaultProject: "tsconfig.json" }, | ||
| tsconfigRootDir: import.meta.dirname | ||
| } | ||
| }, | ||
| plugins: { "@stylistic": stylistic, import: _import, "simple-import-sort": simpleImportSort, "sort-keys": sortKeys }, | ||
| rules: { | ||
| "@stylistic/keyword-spacing": ["error", { after: true, before: true, overrides }], | ||
| "@stylistic/space-before-function-paren": ["error", { anonymous: "never", asyncArrow: "always", catch: "never", named: "never" }], | ||
| "@typescript-eslint/consistent-type-definitions": "off", | ||
| "@typescript-eslint/no-confusing-void-expression": "off", | ||
| "@typescript-eslint/no-dynamic-delete": "off", | ||
| "@typescript-eslint/no-empty-function": "off", | ||
| "@typescript-eslint/no-empty-interface": "off", | ||
| "@typescript-eslint/no-extraneous-class": "off", | ||
| "@typescript-eslint/no-namespace": "off", | ||
| "@typescript-eslint/no-non-null-assertion": "off", | ||
| "@typescript-eslint/no-unused-vars": ["error", unusedVarsOptions], | ||
| "@typescript-eslint/prefer-nullish-coalescing": "off", | ||
| "@typescript-eslint/prefer-regexp-exec": "off", | ||
| "@typescript-eslint/restrict-template-expressions": ["error", { allowNumber: true }], | ||
| "@typescript-eslint/use-unknown-in-catch-callback-variable": "off", | ||
| "arrow-body-style": ["error", "as-needed"], | ||
| "arrow-parens": ["error", "as-needed"], | ||
| "arrow-spacing": "error", | ||
| "brace-style": ["error", "1tbs", { allowSingleLine: true }], | ||
| curly: ["error", "multi-or-nest"], | ||
| eqeqeq: ["error"], | ||
| "import/first": "error", | ||
| "import/newline-after-import": "error", | ||
| "import/no-duplicates": "error", | ||
| indent: ["error", 2], | ||
| "key-spacing": ["error", { align: { afterColon: true, beforeColon: false, on: "value" } }], | ||
| "linebreak-style": ["error", "unix"], | ||
| "max-len": ["error", { code: 200, ignoreStrings: true }], | ||
| "no-console": "warn", | ||
| "no-mixed-spaces-and-tabs": ["error", "smart-tabs"], | ||
| "prefer-const": ["error", { destructuring: "all" }], | ||
| "prefer-template": "error", | ||
| quotes: ["error", "double", { avoidEscape: true }], | ||
| semi: ["error", "always"], | ||
| "simple-import-sort/exports": "error", | ||
| "simple-import-sort/imports": "error", | ||
| "sort-keys": "off", | ||
| "sort-keys/sort-keys-fix": "error", | ||
| "space-unary-ops": ["error", { nonwords: false, overrides: { "!": true }, words: true }] | ||
| } | ||
| } | ||
| ]; | ||
| ); |
+22
-14
@@ -9,21 +9,20 @@ { | ||
| "devDependencies": { | ||
| "@eslint/compat": "1.2.2", | ||
| "@types/express": "5.0.0", | ||
| "@stylistic/eslint-plugin": "5.2.3", | ||
| "@types/express": "5.0.3", | ||
| "@types/jest": "29.5.14", | ||
| "@types/node": "22.9.0", | ||
| "@typescript-eslint/eslint-plugin": "8.14.0", | ||
| "@typescript-eslint/parser": "8.14.0", | ||
| "eslint": "9.14.0", | ||
| "eslint-plugin-import": "2.31.0", | ||
| "@types/node": "24.3.0", | ||
| "eslint": "9.34.0", | ||
| "eslint-plugin-import": "2.32.0", | ||
| "eslint-plugin-simple-import-sort": "12.1.1", | ||
| "eslint-plugin-sort-keys": "2.3.5", | ||
| "express": "4.21.1", | ||
| "express": "5.1.0", | ||
| "jest": "29.7.0", | ||
| "jest-environment-node-single-context": "29.4.0", | ||
| "peggy": "4.1.1", | ||
| "prettier": "3.3.3", | ||
| "ts-jest": "29.2.5", | ||
| "peggy": "5.0.6", | ||
| "prettier": "3.6.2", | ||
| "ts-jest": "29.4.1", | ||
| "ts-pegjs": "4.2.1", | ||
| "tsx": "4.19.2", | ||
| "typescript": "5.6.3" | ||
| "tsx": "4.20.5", | ||
| "typescript": "5.9.2", | ||
| "typescript-eslint": "8.41.0" | ||
| }, | ||
@@ -47,4 +46,9 @@ "engines": { | ||
| "buffer", | ||
| "circular", | ||
| "circular-reference", | ||
| "custom-json", | ||
| "date", | ||
| "deserialize", | ||
| "eval", | ||
| "extended-json", | ||
| "infinity", | ||
@@ -57,2 +61,5 @@ "javascript", | ||
| "regexp", | ||
| "repeated", | ||
| "repeated-reference", | ||
| "serialize", | ||
| "set", | ||
@@ -80,2 +87,3 @@ "stringify", | ||
| "deploy": "make deploy", | ||
| "lint": "eslint . --report-unused-disable-directives --max-warnings 0", | ||
| "parser": "typescript", | ||
@@ -89,3 +97,3 @@ "precoverage": "make", | ||
| "types": "./dist/types/index.d.ts", | ||
| "version": "0.4.0" | ||
| "version": "0.5.0" | ||
| } |
+91
-39
@@ -51,5 +51,6 @@ # NJSON - next-json | ||
| - doesn't support `undefined` values, | ||
| - doesn't support `BigInt` numbers, | ||
| - doesn't support many other features... | ||
| - ❌ loses `undefined`, `NaN`, `Infinity`, `-0` | ||
| - ❌ throws `TypeError` serializing circular references | ||
| - ❌ cannot handle `BigInt`, `Date`, `Error`, `Map`, `RegExp`, `Set`, `URL` | ||
| - ❌ doesn't support many other features... | ||
@@ -60,18 +61,67 @@ This package is intended to offer something as great as JSON... trying to add something more. | ||
| - ☑ extends JSON | ||
| - ☑ supports C style comments | ||
| - ☑ supports escaped new line in strings | ||
| - ☑ supports trailing commas | ||
| - ☑ supports circular and repeated references | ||
| - ☑ supports `undefined` | ||
| - ☑ supports `-0`, `NaN` and `Infinity` | ||
| - ☑ supports `BigInt` | ||
| - ☑ supports `Date` | ||
| - ☑ supports `Error` (with [exception](#the-error-exception)) | ||
| - ☑ supports `Map` | ||
| - ☑ supports `RegExp` | ||
| - ☑ supports `Set` | ||
| - ☑ supports `TypedArray`s (but `Float16Array`) | ||
| - ☑ supports `URL` | ||
| - ✔ extends JSON | ||
| - ✔ safe parser: doesn't use `eval` | ||
| - ✔ JavaScript compatible: same result from `parse` and `eval` | ||
| - ✔ includes TypeScript types | ||
| - ✔ supports C style comments | ||
| - ✔ supports escaped new line in strings | ||
| - ✔ supports trailing commas | ||
| - ✔ supports circular and repeated references | ||
| - ✔ supports `undefined` | ||
| - ✔ supports `-0`, `NaN` and `Infinity` | ||
| - ✔ supports `BigInt` | ||
| - ✔ supports `Date` | ||
| - ✔ supports `Error` (with [exception](#the-error-exception)) | ||
| - ✔ supports `Map` | ||
| - ✔ supports `RegExp` | ||
| - ✔ supports `Set` | ||
| - ✔ supports `TypedArray`s (but `Float16Array`) | ||
| - ✔ supports `URL` | ||
| # Example | ||
| <!-- prettier-ignore-start --> | ||
| ```javascript | ||
| const set = new Set(); | ||
| const arr = [set]; | ||
| const obj = { arr, nan: NaN, set }; | ||
| arr.push(arr, obj); | ||
| obj.obj = obj; | ||
| set.add(arr).add(obj); | ||
| const serialized = NJSON.stringify(obj); | ||
| const parsed = NJSON.parse(serialized); | ||
| console.log(parsed === parsed.obj); // true | ||
| console.log(parsed.arr === parsed.arr[1]); // true | ||
| console.log(isNaN(parsed.nan)); // true | ||
| console.log(parsed.set instanceof Set); // true | ||
| console.log(parsed === [...parsed.set][1]); // true | ||
| console.log(serialized); | ||
| // ((A,B,C)=>Object.assign(B,{"arr":Object.assign(A,{"0":C.add(A).add(B),"1":A,"2":B}),"set":C,"obj":B}))([],{"nan":NaN},new Set()) | ||
| ``` | ||
| <!-- prettier-ignore-end --> | ||
| ## Comparison with alternatives | ||
| | Feature | JSON | flatted | devalue | superjson | **NJSON** | | ||
| | ------------------------ | -------- | -------- | -------- | --------- | --------- | | ||
| | Safe: no `eval` use | ✔ | ✔ | ✔ | ✔ | ✔ | | ||
| | `eval` compliant \* | ✔ | ❌ | ❌ | ❌ | ✔ | | ||
| | Circular / repeated refs | ❌ | ✔ | ✔ | ✔ | ✔ | | ||
| | `Map` / `Set` | ❌ | ❌ | ✔ | ✔ | ✔ | | ||
| | `BigInt` | ❌ | ❌ | ✔ | ✔ | ✔ | | ||
| | `Date` | ❌ | ❌ | ✔ | ✔ | ✔ | | ||
| | `RegExp` | ❌ | ❌ | ✔ | ✔ | ✔ | | ||
| | `TypedArray`s | ❌ | ❌ | ✔ | ❌ | ✔ | | ||
| | Preserves `undefined` | ❌ | ❌ | ✔ | ✔ | ✔ | | ||
| > \* This is the main reason why `NJSON` was born. The string produced by any other option strictly requires its own | ||
| > parser to be converted back to the original value. As with `JSON`, the string produced by `NJSON` can be cut / pasted | ||
| > in any JavaScript environment - without the need of any additional library - to reproduce the original value; a very | ||
| > powerful feature while debugging / developing. | ||
| ## NJSON extends JSON | ||
@@ -138,3 +188,2 @@ | ||
| - `cause`: | ||
| - through `NJSON.parse` the result is **a not enumerable** property; | ||
@@ -145,5 +194,3 @@ - through `eval` the result may be **an enumerable** or **a not enumerable** property depending on the running | ||
| - `stack`: | ||
| - if absent: | ||
| - through `NJSON.parse` the result is **a not enumerable** property with value a _pseudo-stack_; | ||
@@ -153,3 +200,2 @@ - through `eval` the result is the standard `stack` property for the running JavaScript engine; | ||
| - if present: | ||
| - through `NJSON.parse` the result is **a not enumerable** property; | ||
@@ -191,19 +237,2 @@ - through `eval` the result may be **an enumerable** or **a not enumerable** property depending on the running | ||
| # Example | ||
| ```javascript | ||
| const obj = { test: Infinity }; | ||
| const set = new Set(); | ||
| const arr = [NaN, obj, set]; | ||
| arr.push(arr); | ||
| arr.push(obj); | ||
| obj.arr = arr; | ||
| set.add(obj); | ||
| set.add(arr); | ||
| console.log(NJSON.stringify(arr)); | ||
| // ((A,B)=>{B.push(Object.assign(A,{"arr":B}),new Set([A,B]),B,A);return B})({"test":Infinity},[NaN]) | ||
| ``` | ||
| # Polyfill | ||
@@ -473,2 +502,25 @@ | ||
| # Version 0.5.0 | ||
| `v0.5.0` changes the stringification of `Array`s from the use of `push` to the use `Object.assign` with some | ||
| advantages: | ||
| - enables the support of _sparse arrays_, next item in the TODO list; | ||
| - enables the use of _body-less functions_ rather than _functions_ which makes the parser thinner; | ||
| and one disadvantage: | ||
| - breaks the compatibility with previous versions stringification. | ||
| To make the change as smooth as possible, `v0.5.0` still supports the deserialization of previous versions | ||
| stringification: support for parsing `push` will be removed in some later version TBD. | ||
| > If `NJSON` is used to produce volatile values through `stringify` that are immediately parsed and discarded, no | ||
| > actions are required. | ||
| > | ||
| > If some values stringified using `NJSON.version` < `v0.5.0` are stored (in some DBs or in some files), it is | ||
| > recommended to convert them serialization to the newer format (just parse and re-stringify them using `v0.5.0` <= | ||
| > `NJSON.version` < `TBD`). | ||
| # Compatibility | ||
@@ -475,0 +527,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
642322
1.65%18
-5.26%15699
0.8%0
-100%568
10.08%