diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..9cf9495 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index df60d14..9198515 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,5 +4,13 @@ node_js: - 10 - 12 - 14 +script: > + node_version="$(node -v)"; + if [ "${node_version:1:1}" -eq 8 ]; then + # tsd test runner doesn't work on node 8 + npm run test:no-types; + else + npm test; + fi after_script: - coveralls < coverage/lcov.info diff --git a/index.d.ts b/index.d.ts index 23e46ca..20fc937 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,4 +1,66 @@ -declare module 'fast-json-stable-stringify' { - function stringify(obj: any): string; - export = stringify; +export = stringify; + +/** + * Deterministic `JSON.stringify()`. + * + * @returns A deterministic stringified string from the object `obj`. + * + * @example + * import stringify = require('fast-json-stable-stringify'); + * + * const obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 }; + * console.log(stringify(obj)); + * // -> {"a":3,"b":[{"x":4,"y":5,"z":6},7],"c":8} + */ +declare function stringify( + obj: any, + options?: stringify.Options | stringify.Comparator +): string; + +declare namespace stringify { + interface Options { + /** + * You can supply a custom comparison function for object keys. + * + * @example + * // For example, to sort on the object key names in reverse order you could write: + * + * import stringify = require('fast-json-stable-stringify'); + * + * const obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 }; + * const s = stringify(obj, (a, b) => { + * return a.key < b.key ? 1 : -1; + * }); + * console.log(s); + * // -> {"c":8,"b":[{"z":6,"y":5,"x":4},7],"a":3} + * + * @example + * // Or if you wanted to sort on the object values in reverse order, you could write: + * + * import stringify = require('fast-json-stable-stringify'); + * + * const obj = { d: 6, c: 5, b: [{z:3,y:2,x:1},9], a: 10 }; + * const s = stringify(obj, (a, b) => { + * return a.value < b.value ? 1 : -1; + * }); + * console.log(s); + * // -> {"d":6,"c":5,"b":[{"z":3,"y":2,"x":1},9],"a":10} + */ + cmp?: Comparator; + + /** + * Pass `true` to stringify circular property as `__cycle__` - the result will not be + * a valid JSON string in this case. + * + * TypeError will be thrown in case of circular object without this option. + */ + cycles?: boolean; + } + + type Comparator = (a: CompareDescriptor, b: CompareDescriptor) => number; + + interface CompareDescriptor { + key: string; + value: any; + } } diff --git a/package.json b/package.json index 754d4d2..a523d83 100644 --- a/package.json +++ b/package.json @@ -14,12 +14,15 @@ "json-stable-stringify": "latest", "nyc": "^14.1.0", "pre-commit": "^1.2.2", - "tape": "^4.11.0" + "tape": "^4.11.0", + "tsd": "^0.16.0" }, "scripts": { "eslint": "eslint index.js test", "test-spec": "tape test/*.js", - "test": "npm run eslint && nyc npm run test-spec" + "test-types": "tsd", + "test": "npm run eslint && nyc npm run test-spec && npm run test-types", + "test:no-types": "npm run eslint && nyc npm run test-spec" }, "repository": { "type": "git", @@ -49,6 +52,9 @@ "text-summary" ] }, + "tsd": { + "directory": "test" + }, "engines": { "node": ">=8" } diff --git a/test/index.test-d.ts b/test/index.test-d.ts new file mode 100644 index 0000000..4184900 --- /dev/null +++ b/test/index.test-d.ts @@ -0,0 +1,28 @@ +import { expectType } from "tsd"; +import stringify = require("../index"); + +// test type exports +type CompareDescriptor = stringify.CompareDescriptor; +type Comparator = stringify.Comparator; +type Options = stringify.Options; + +const obj = { c: 8, b: [{ z: 6, y: 5, x: 4 }, 7], a: 3 }; + +expectType(stringify(obj)); +expectType( + stringify(obj, (a, b) => { + expectType(a); + expectType(b); + return a.key < b.key ? 1 : -1; + }) +); +expectType( + stringify(obj, { + cmp(a, b) { + expectType(a); + expectType(b); + return a.key < b.key ? 1 : -1; + }, + }) +); +expectType(stringify(obj, { cycles: true }));