From d586f1955a3648883107f8c981ee17eeb4c013a3 Mon Sep 17 00:00:00 2001 From: Nathan Bierema Date: Sat, 29 Aug 2020 00:14:49 -0400 Subject: [PATCH] feat(redux-devtools-serialize): convert to TypeScript (#621) * feature(redux-devtools-serialize): convert to TypeScript * unused --- packages/react-base16-styling/.eslintrc.js | 4 +- .../redux-devtools-dock-monitor/package.json | 2 +- .../redux-devtools-instrument/.eslintrc.js | 4 +- .../redux-devtools-instrument/package.json | 4 +- .../redux-devtools-log-monitor/package.json | 2 +- packages/redux-devtools-serialize/.babelrc | 4 + .../redux-devtools-serialize/.eslintignore | 1 + .../redux-devtools-serialize/.eslintrc.js | 21 +++ .../redux-devtools-serialize/helpers/index.js | 32 ---- .../immutable/index.js | 23 --- .../immutable/serialize.js | 87 ---------- .../redux-devtools-serialize/jest.config.js | 3 + .../redux-devtools-serialize/package.json | 41 +++-- .../options.js => src/constants/options.ts} | 2 +- .../src/helpers/index.ts | 54 ++++++ .../src/immutable/index.ts | 37 ++++ .../src/immutable/serialize.ts | 105 ++++++++++++ .../{index.js => src/index.ts} | 2 +- packages/redux-devtools-serialize/src/jsan.ts | 30 ++++ .../redux-devtools-serialize/src/types.ts | 71 ++++++++ ...pers.spec.js.snap => helpers.spec.ts.snap} | 0 ...le.spec.js.snap => immutable.spec.ts.snap} | 2 +- .../test/{helpers.spec.js => helpers.spec.ts} | 11 +- .../test/immutable.spec.js | 148 ---------------- .../test/immutable.spec.ts | 159 ++++++++++++++++++ .../test/tsconfig.json | 4 + .../redux-devtools-serialize/tsconfig.json | 7 + 27 files changed, 538 insertions(+), 322 deletions(-) create mode 100644 packages/redux-devtools-serialize/.babelrc create mode 100644 packages/redux-devtools-serialize/.eslintignore create mode 100644 packages/redux-devtools-serialize/.eslintrc.js delete mode 100644 packages/redux-devtools-serialize/helpers/index.js delete mode 100644 packages/redux-devtools-serialize/immutable/index.js delete mode 100644 packages/redux-devtools-serialize/immutable/serialize.js create mode 100644 packages/redux-devtools-serialize/jest.config.js rename packages/redux-devtools-serialize/{constants/options.js => src/constants/options.ts} (93%) create mode 100644 packages/redux-devtools-serialize/src/helpers/index.ts create mode 100644 packages/redux-devtools-serialize/src/immutable/index.ts create mode 100644 packages/redux-devtools-serialize/src/immutable/serialize.ts rename packages/redux-devtools-serialize/{index.js => src/index.ts} (54%) create mode 100644 packages/redux-devtools-serialize/src/jsan.ts create mode 100644 packages/redux-devtools-serialize/src/types.ts rename packages/redux-devtools-serialize/test/__snapshots__/{helpers.spec.js.snap => helpers.spec.ts.snap} (100%) rename packages/redux-devtools-serialize/test/__snapshots__/{immutable.spec.js.snap => immutable.spec.ts.snap} (65%) rename packages/redux-devtools-serialize/test/{helpers.spec.js => helpers.spec.ts} (61%) delete mode 100644 packages/redux-devtools-serialize/test/immutable.spec.js create mode 100644 packages/redux-devtools-serialize/test/immutable.spec.ts create mode 100644 packages/redux-devtools-serialize/test/tsconfig.json create mode 100644 packages/redux-devtools-serialize/tsconfig.json diff --git a/packages/react-base16-styling/.eslintrc.js b/packages/react-base16-styling/.eslintrc.js index 486b7fd4..fbd5a609 100644 --- a/packages/react-base16-styling/.eslintrc.js +++ b/packages/react-base16-styling/.eslintrc.js @@ -2,7 +2,7 @@ module.exports = { extends: '../../.eslintrc', overrides: [ { - files: ['*.ts', '*.tsx'], + files: ['*.ts'], extends: '../../eslintrc.ts.base.json', parserOptions: { tsconfigRootDir: __dirname, @@ -10,7 +10,7 @@ module.exports = { }, }, { - files: ['test/*.ts', 'test/*.tsx'], + files: ['test/*.ts'], extends: '../../eslintrc.ts.jest.base.json', parserOptions: { tsconfigRootDir: __dirname, diff --git a/packages/redux-devtools-dock-monitor/package.json b/packages/redux-devtools-dock-monitor/package.json index bb54f96d..d64d5b93 100644 --- a/packages/redux-devtools-dock-monitor/package.json +++ b/packages/redux-devtools-dock-monitor/package.json @@ -36,7 +36,7 @@ "lint:fix": "eslint . --ext .ts,.tsx --fix", "type-check": "tsc --noEmit", "type-check:watch": "npm run type-check -- --watch", - "preversion": "npm run type-check && npm run lint && npm run test", + "preversion": "npm run type-check && npm run lint", "prepublishOnly": "npm run clean && npm run build" }, "dependencies": { diff --git a/packages/redux-devtools-instrument/.eslintrc.js b/packages/redux-devtools-instrument/.eslintrc.js index 486b7fd4..fbd5a609 100644 --- a/packages/redux-devtools-instrument/.eslintrc.js +++ b/packages/redux-devtools-instrument/.eslintrc.js @@ -2,7 +2,7 @@ module.exports = { extends: '../../.eslintrc', overrides: [ { - files: ['*.ts', '*.tsx'], + files: ['*.ts'], extends: '../../eslintrc.ts.base.json', parserOptions: { tsconfigRootDir: __dirname, @@ -10,7 +10,7 @@ module.exports = { }, }, { - files: ['test/*.ts', 'test/*.tsx'], + files: ['test/*.ts'], extends: '../../eslintrc.ts.jest.base.json', parserOptions: { tsconfigRootDir: __dirname, diff --git a/packages/redux-devtools-instrument/package.json b/packages/redux-devtools-instrument/package.json index 2d063098..59ef2c37 100644 --- a/packages/redux-devtools-instrument/package.json +++ b/packages/redux-devtools-instrument/package.json @@ -32,8 +32,8 @@ "build:js": "babel src --out-dir lib --extensions \".ts\" --source-maps inline", "clean": "rimraf lib", "test": "jest", - "lint": "eslint . --ext .ts,.tsx", - "lint:fix": "eslint . --ext .ts,.tsx --fix", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", "type-check": "tsc --noEmit", "type-check:watch": "npm run type-check -- --watch", "preversion": "npm run type-check && npm run lint && npm run test", diff --git a/packages/redux-devtools-log-monitor/package.json b/packages/redux-devtools-log-monitor/package.json index a4799c6c..4c1add20 100644 --- a/packages/redux-devtools-log-monitor/package.json +++ b/packages/redux-devtools-log-monitor/package.json @@ -36,7 +36,7 @@ "lint:fix": "eslint . --ext .ts,.tsx --fix", "type-check": "tsc --noEmit", "type-check:watch": "npm run type-check -- --watch", - "preversion": "npm run type-check && npm run lint && npm run test", + "preversion": "npm run type-check && npm run lint", "prepublishOnly": "npm run clean && npm run build" }, "dependencies": { diff --git a/packages/redux-devtools-serialize/.babelrc b/packages/redux-devtools-serialize/.babelrc new file mode 100644 index 00000000..5259cd24 --- /dev/null +++ b/packages/redux-devtools-serialize/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["@babel/preset-env", "@babel/preset-typescript"], + "plugins": ["@babel/plugin-proposal-class-properties"] +} diff --git a/packages/redux-devtools-serialize/.eslintignore b/packages/redux-devtools-serialize/.eslintignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/redux-devtools-serialize/.eslintignore @@ -0,0 +1 @@ +lib diff --git a/packages/redux-devtools-serialize/.eslintrc.js b/packages/redux-devtools-serialize/.eslintrc.js new file mode 100644 index 00000000..fbd5a609 --- /dev/null +++ b/packages/redux-devtools-serialize/.eslintrc.js @@ -0,0 +1,21 @@ +module.exports = { + extends: '../../.eslintrc', + overrides: [ + { + files: ['*.ts'], + extends: '../../eslintrc.ts.base.json', + parserOptions: { + tsconfigRootDir: __dirname, + project: ['./tsconfig.json'], + }, + }, + { + files: ['test/*.ts'], + extends: '../../eslintrc.ts.jest.base.json', + parserOptions: { + tsconfigRootDir: __dirname, + project: ['./test/tsconfig.json'], + }, + }, + ], +}; diff --git a/packages/redux-devtools-serialize/helpers/index.js b/packages/redux-devtools-serialize/helpers/index.js deleted file mode 100644 index b084c7db..00000000 --- a/packages/redux-devtools-serialize/helpers/index.js +++ /dev/null @@ -1,32 +0,0 @@ -function mark(data, type, transformMethod) { - return { - data: transformMethod ? data[transformMethod]() : data, - __serializedType__: type, - }; -} - -function extract(data, type) { - return { - data: Object.assign({}, data), - __serializedType__: type, - }; -} - -function refer(data, type, isArray, refs) { - var r = mark(data, type, isArray); - if (!refs) return r; - for (var i = 0; i < refs.length; i++) { - var ref = refs[i]; - if (typeof ref === 'function' && data instanceof ref) { - r.__serializedRef__ = i; - return r; - } - } - return r; -} - -module.exports = { - mark: mark, - extract: extract, - refer: refer, -}; diff --git a/packages/redux-devtools-serialize/immutable/index.js b/packages/redux-devtools-serialize/immutable/index.js deleted file mode 100644 index 0a9b360d..00000000 --- a/packages/redux-devtools-serialize/immutable/index.js +++ /dev/null @@ -1,23 +0,0 @@ -var jsan = require('jsan'); -var serialize = require('./serialize'); -var options = require('../constants/options'); - -module.exports = function (Immutable, refs, customReplacer, customReviver) { - return { - stringify: function (data) { - return jsan.stringify( - data, - serialize(Immutable, refs, customReplacer, customReviver).replacer, - null, - options - ); - }, - parse: function (data) { - return jsan.parse( - data, - serialize(Immutable, refs, customReplacer, customReviver).reviver - ); - }, - serialize: serialize, - }; -}; diff --git a/packages/redux-devtools-serialize/immutable/serialize.js b/packages/redux-devtools-serialize/immutable/serialize.js deleted file mode 100644 index eef8e8fa..00000000 --- a/packages/redux-devtools-serialize/immutable/serialize.js +++ /dev/null @@ -1,87 +0,0 @@ -var helpers = require('../helpers'); -var mark = helpers.mark; -var extract = helpers.extract; -var refer = helpers.refer; -var options = require('../constants/options'); - -module.exports = function serialize( - Immutable, - refs, - customReplacer, - customReviver -) { - function replacer(key, value) { - if (value instanceof Immutable.Record) - return refer(value, 'ImmutableRecord', 'toObject', refs); - if (value instanceof Immutable.Range) - return extract(value, 'ImmutableRange'); - if (value instanceof Immutable.Repeat) - return extract(value, 'ImmutableRepeat'); - if (Immutable.OrderedMap.isOrderedMap(value)) - return mark(value, 'ImmutableOrderedMap', 'toObject'); - if (Immutable.Map.isMap(value)) - return mark(value, 'ImmutableMap', 'toObject'); - if (Immutable.List.isList(value)) - return mark(value, 'ImmutableList', 'toArray'); - if (Immutable.OrderedSet.isOrderedSet(value)) - return mark(value, 'ImmutableOrderedSet', 'toArray'); - if (Immutable.Set.isSet(value)) - return mark(value, 'ImmutableSet', 'toArray'); - if (Immutable.Seq.isSeq(value)) - return mark(value, 'ImmutableSeq', 'toArray'); - if (Immutable.Stack.isStack(value)) - return mark(value, 'ImmutableStack', 'toArray'); - return value; - } - - function reviver(key, value) { - if ( - typeof value === 'object' && - value !== null && - '__serializedType__' in value - ) { - var data = value.data; - switch (value.__serializedType__) { - case 'ImmutableMap': - return Immutable.Map(data); - case 'ImmutableOrderedMap': - return Immutable.OrderedMap(data); - case 'ImmutableList': - return Immutable.List(data); - case 'ImmutableRange': - return Immutable.Range(data._start, data._end, data._step); - case 'ImmutableRepeat': - return Immutable.Repeat(data._value, data.size); - case 'ImmutableSet': - return Immutable.Set(data); - case 'ImmutableOrderedSet': - return Immutable.OrderedSet(data); - case 'ImmutableSeq': - return Immutable.Seq(data); - case 'ImmutableStack': - return Immutable.Stack(data); - case 'ImmutableRecord': - return refs && refs[value.__serializedRef__] - ? new refs[value.__serializedRef__](data) - : Immutable.Map(data); - default: - return data; - } - } - return value; - } - - return { - replacer: customReplacer - ? function (key, value) { - return customReplacer(key, value, replacer); - } - : replacer, - reviver: customReviver - ? function (key, value) { - return customReviver(key, value, reviver); - } - : reviver, - options: options, - }; -}; diff --git a/packages/redux-devtools-serialize/jest.config.js b/packages/redux-devtools-serialize/jest.config.js new file mode 100644 index 00000000..8824c114 --- /dev/null +++ b/packages/redux-devtools-serialize/jest.config.js @@ -0,0 +1,3 @@ +module.exports = { + preset: 'ts-jest', +}; diff --git a/packages/redux-devtools-serialize/package.json b/packages/redux-devtools-serialize/package.json index 06509e12..9c8e7474 100644 --- a/packages/redux-devtools-serialize/package.json +++ b/packages/redux-devtools-serialize/package.json @@ -2,29 +2,42 @@ "name": "redux-devtools-serialize", "version": "0.1.9", "description": "Serialize unserializable data and parse it back.", - "main": "index.js", - "scripts": { - "test": "jest --no-cache", - "prepublish": "npm run test" - }, - "repository": { - "type": "git", - "url": "https://github.com/reduxjs/redux-devtools.git" - }, "keywords": [ "redux", "devtools" ], - "author": "Mihail Diordiev (https://github.com/zalmoxisus)", - "license": "MIT", + "homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-serialize", "bugs": { "url": "https://github.com/reduxjs/redux-devtools/issues" }, - "homepage": "https://github.com/reduxjs/redux-devtools", - "devDependencies": { - "immutable": "^4.0.0-rc.12" + "license": "MIT", + "author": "Mihail Diordiev (https://github.com/zalmoxisus)", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/reduxjs/redux-devtools.git" + }, + "scripts": { + "build": "npm run build:types && npm run build:js", + "build:types": "tsc --emitDeclarationOnly", + "build:js": "babel src --out-dir lib --extensions \".ts\" --source-maps inline", + "clean": "rimraf lib", + "test": "jest", + "lint": "eslint . --ext .ts", + "lint:fix": "eslint . --ext .ts --fix", + "type-check": "tsc --noEmit", + "type-check:watch": "npm run type-check -- --watch", + "preversion": "npm run type-check && npm run lint && npm run test", + "prepublishOnly": "npm run clean && npm run build" }, "dependencies": { "jsan": "^3.1.13" + }, + "devDependencies": { + "immutable": "^4.0.0-rc.12" + }, + "peerDependencies": { + "immutable": "^4.0.0-rc.12" } } diff --git a/packages/redux-devtools-serialize/constants/options.js b/packages/redux-devtools-serialize/src/constants/options.ts similarity index 93% rename from packages/redux-devtools-serialize/constants/options.js rename to packages/redux-devtools-serialize/src/constants/options.ts index f227a0ce..57a8542d 100644 --- a/packages/redux-devtools-serialize/constants/options.js +++ b/packages/redux-devtools-serialize/src/constants/options.ts @@ -1,6 +1,6 @@ // jsan stringify options -module.exports = { +export default { refs: false, // references can't be resolved on the original Immutable structure date: true, function: true, diff --git a/packages/redux-devtools-serialize/src/helpers/index.ts b/packages/redux-devtools-serialize/src/helpers/index.ts new file mode 100644 index 00000000..99076e3b --- /dev/null +++ b/packages/redux-devtools-serialize/src/helpers/index.ts @@ -0,0 +1,54 @@ +export interface SerializedData { + data: unknown; + __serializedType__: string; + __serializedRef__?: number; +} + +export function mark(data: unknown, type: string): SerializedData; +export function mark( + data: { [key in K]: () => unknown }, + type: string, + transformMethod?: K | false +): SerializedData; +export function mark( + data: any, + type: string, + transformMethod?: 'toString' | false +): SerializedData; +export function mark( + data: { [key in K]: () => unknown } | unknown, + type: string, + transformMethod?: K | false +): SerializedData { + return { + data: transformMethod + ? (data as { [key in K]: () => unknown })[transformMethod]() + : data, + __serializedType__: type, + }; +} + +export function extract(data: unknown, type: string): SerializedData { + return { + data: Object.assign({}, data), + __serializedType__: type, + }; +} + +export function refer( + data: { [key in K]: () => unknown }, + type: string, + transformMethod: K | false, + refs?: (new (data: any) => unknown)[] | null +): SerializedData { + const r = mark(data, type, transformMethod); + if (!refs) return r; + for (let i = 0; i < refs.length; i++) { + const ref = refs[i]; + if (typeof ref === 'function' && data instanceof ref) { + r.__serializedRef__ = i; + return r; + } + } + return r; +} diff --git a/packages/redux-devtools-serialize/src/immutable/index.ts b/packages/redux-devtools-serialize/src/immutable/index.ts new file mode 100644 index 00000000..b8fd874b --- /dev/null +++ b/packages/redux-devtools-serialize/src/immutable/index.ts @@ -0,0 +1,37 @@ +import jsan from 'jsan'; +import Immutable from 'immutable'; +import serialize from './serialize'; +import options from '../constants/options'; + +export default function ( + immutable: typeof Immutable, + refs?: (new (data: any) => unknown)[] | null, + customReplacer?: ( + key: string, + value: unknown, + defaultReplacer: (key: string, value: unknown) => unknown + ) => unknown, + customReviver?: ( + key: string, + value: unknown, + defaultReviver: (key: string, value: unknown) => unknown + ) => unknown +) { + return { + stringify: function (data: unknown) { + return jsan.stringify( + data, + serialize(immutable, refs, customReplacer, customReviver).replacer, + undefined, + options + ); + }, + parse: function (data: string) { + return jsan.parse( + data, + serialize(immutable, refs, customReplacer, customReviver).reviver + ); + }, + serialize: serialize, + }; +} diff --git a/packages/redux-devtools-serialize/src/immutable/serialize.ts b/packages/redux-devtools-serialize/src/immutable/serialize.ts new file mode 100644 index 00000000..22de50f2 --- /dev/null +++ b/packages/redux-devtools-serialize/src/immutable/serialize.ts @@ -0,0 +1,105 @@ +import Immutable, { OrderedSet, Record } from 'immutable'; +import { mark, extract, refer } from '../helpers'; +import options from '../constants/options'; +import { SerializedImmutableData } from '../types'; + +export default function serialize( + immutable: typeof Immutable, + refs?: (new (data: any) => unknown)[] | null, + customReplacer?: ( + key: string, + value: unknown, + defaultReplacer: (key: string, value: unknown) => unknown + ) => unknown, + customReviver?: ( + key: string, + value: unknown, + defaultReviver: (key: string, value: unknown) => unknown + ) => unknown +) { + function replacer(key: string, value: unknown) { + if (value instanceof immutable.Record) + return refer(value as Record, 'ImmutableRecord', 'toObject', refs); + if (value instanceof immutable.Range) + return extract(value, 'ImmutableRange'); + if (value instanceof immutable.Repeat) + return extract(value, 'ImmutableRepeat'); + if (immutable.OrderedMap.isOrderedMap(value)) + return mark(value, 'ImmutableOrderedMap', 'toObject'); + if (immutable.Map.isMap(value)) + return mark(value, 'ImmutableMap', 'toObject'); + if (immutable.List.isList(value)) + return mark(value, 'ImmutableList', 'toArray'); + if (immutable.OrderedSet.isOrderedSet(value)) + return mark( + value as OrderedSet, + 'ImmutableOrderedSet', + 'toArray' + ); + if (immutable.Set.isSet(value)) + return mark(value, 'ImmutableSet', 'toArray'); + if (immutable.Seq.isSeq(value)) + return mark(value, 'ImmutableSeq', 'toArray'); + if (immutable.Stack.isStack(value)) + return mark(value, 'ImmutableStack', 'toArray'); + return value; + } + + function reviver(key: string, value: unknown) { + if ( + typeof value === 'object' && + value !== null && + '__serializedType__' in value + ) { + const immutableValue = value as SerializedImmutableData; + switch (immutableValue.__serializedType__) { + case 'ImmutableMap': + return immutable.Map(immutableValue.data); + case 'ImmutableOrderedMap': + return immutable.OrderedMap(immutableValue.data); + case 'ImmutableList': + return immutable.List(immutableValue.data); + case 'ImmutableRange': + return immutable.Range( + immutableValue.data._start, + immutableValue.data._end, + immutableValue.data._step + ); + case 'ImmutableRepeat': + return immutable.Repeat( + immutableValue.data._value, + immutableValue.data.size + ); + case 'ImmutableSet': + return immutable.Set(immutableValue.data); + case 'ImmutableOrderedSet': + return immutable.OrderedSet(immutableValue.data); + case 'ImmutableSeq': + return immutable.Seq(immutableValue.data); + case 'ImmutableStack': + return immutable.Stack(immutableValue.data); + case 'ImmutableRecord': + return refs && refs[immutableValue.__serializedRef__!] + ? new refs[immutableValue.__serializedRef__!](immutableValue.data) + : immutable.Map(immutableValue.data); + default: + return (immutableValue as { data: unknown }).data; + } + } + return value; + } + + return { + replacer: customReplacer + ? function (key: string, value: unknown) { + return customReplacer(key, value, replacer); + } + : replacer, + reviver: customReviver + ? function (key: string, value: unknown) { + return customReviver(key, value, reviver); + } + : reviver, + options: options, + }; +} diff --git a/packages/redux-devtools-serialize/index.js b/packages/redux-devtools-serialize/src/index.ts similarity index 54% rename from packages/redux-devtools-serialize/index.js rename to packages/redux-devtools-serialize/src/index.ts index 98648dac..600d22c0 100644 --- a/packages/redux-devtools-serialize/index.js +++ b/packages/redux-devtools-serialize/src/index.ts @@ -1,4 +1,4 @@ -var immutable = require('./immutable'); +import immutable from './immutable'; module.exports = { immutable: immutable, diff --git a/packages/redux-devtools-serialize/src/jsan.ts b/packages/redux-devtools-serialize/src/jsan.ts new file mode 100644 index 00000000..9b295e7b --- /dev/null +++ b/packages/redux-devtools-serialize/src/jsan.ts @@ -0,0 +1,30 @@ +declare module 'jsan' { + export interface Options { + date?: boolean; + function?: boolean; + regex?: boolean; + undefined?: boolean; + error?: boolean; + symbol?: boolean; + map?: boolean; + set?: boolean; + nan?: boolean; + infinity?: boolean; + refs?: boolean; + } + + export function stringify( + value: unknown, + replacer?: ( + key: string, + value: unknown + ) => unknown | (number | string)[] | null, + space?: string | number, + _options?: Options | boolean + ): string; + + export function parse( + text: string, + reviver?: (key: string, value: unknown) => unknown + ): unknown; +} diff --git a/packages/redux-devtools-serialize/src/types.ts b/packages/redux-devtools-serialize/src/types.ts new file mode 100644 index 00000000..b30d0a96 --- /dev/null +++ b/packages/redux-devtools-serialize/src/types.ts @@ -0,0 +1,71 @@ +interface SerializedImmutableMap { + data: Record; + __serializedType__: 'ImmutableMap'; +} + +interface SerializedImmutableOrderedMap { + data: Record; + __serializedType__: 'ImmutableOrderedMap'; +} + +interface SerializedImmutableList { + data: unknown[]; + __serializedType__: 'ImmutableList'; +} + +interface SerializedImmutableRangeData { + _start: number | undefined; + _end: number | undefined; + _step: number | undefined; +} +interface SerializedImmutableRange { + data: SerializedImmutableRangeData; + __serializedType__: 'ImmutableRange'; +} + +interface SerializedImmutableRepeatData { + _value: unknown; + size: number | undefined; +} +interface SerializedImmutableRepeat { + data: SerializedImmutableRepeatData; + __serializedType__: 'ImmutableRepeat'; +} + +interface SerializedImmutableSet { + data: unknown[]; + __serializedType__: 'ImmutableSet'; +} + +interface SerializedImmutableOrderedSet { + data: unknown[]; + __serializedType__: 'ImmutableOrderedSet'; +} + +interface SerializedImmutableSeq { + data: unknown[]; + __serializedType__: 'ImmutableSeq'; +} + +interface SerializedImmutableStack { + data: unknown[]; + __serializedType__: 'ImmutableStack'; +} + +interface SerializedImmutableRecord { + data: Record; + __serializedType__: 'ImmutableRecord'; + __serializedRef__?: number; +} + +export type SerializedImmutableData = + | SerializedImmutableMap + | SerializedImmutableOrderedMap + | SerializedImmutableList + | SerializedImmutableRange + | SerializedImmutableRepeat + | SerializedImmutableSet + | SerializedImmutableOrderedSet + | SerializedImmutableSeq + | SerializedImmutableStack + | SerializedImmutableRecord; diff --git a/packages/redux-devtools-serialize/test/__snapshots__/helpers.spec.js.snap b/packages/redux-devtools-serialize/test/__snapshots__/helpers.spec.ts.snap similarity index 100% rename from packages/redux-devtools-serialize/test/__snapshots__/helpers.spec.js.snap rename to packages/redux-devtools-serialize/test/__snapshots__/helpers.spec.ts.snap diff --git a/packages/redux-devtools-serialize/test/__snapshots__/immutable.spec.js.snap b/packages/redux-devtools-serialize/test/__snapshots__/immutable.spec.ts.snap similarity index 65% rename from packages/redux-devtools-serialize/test/__snapshots__/immutable.spec.js.snap rename to packages/redux-devtools-serialize/test/__snapshots__/immutable.spec.ts.snap index 115e2115..4c460e04 100644 --- a/packages/redux-devtools-serialize/test/__snapshots__/immutable.spec.js.snap +++ b/packages/redux-devtools-serialize/test/__snapshots__/immutable.spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Immutable Nested stringify 1`] = `"{\\"data\\":[[\\"map\\",{\\"data\\":{\\"seq\\":{\\"data\\":[1,2,3,4,5,6,7,8],\\"__serializedType__\\":\\"ImmutableSeq\\"},\\"stack\\":{\\"data\\":[\\"a\\",\\"b\\",\\"c\\"],\\"__serializedType__\\":\\"ImmutableStack\\"}},\\"__serializedType__\\":\\"ImmutableOrderedMap\\"}],[\\"repeat\\",{\\"data\\":{\\"_value\\":\\"hi\\",\\"size\\":100},\\"__serializedType__\\":\\"ImmutableRepeat\\"}]],\\"__serializedType__\\":\\"ImmutableSet\\"}"`; +exports[`Immutable Nested stringify 1`] = `"{\\"data\\":[{\\"data\\":{\\"map\\":{\\"data\\":{\\"seq\\":{\\"data\\":[1,2,3,4,5,6,7,8],\\"__serializedType__\\":\\"ImmutableSeq\\"},\\"stack\\":{\\"data\\":[\\"a\\",\\"b\\",\\"c\\"],\\"__serializedType__\\":\\"ImmutableStack\\"}},\\"__serializedType__\\":\\"ImmutableOrderedMap\\"},\\"repeat\\":{\\"data\\":{\\"_value\\":\\"hi\\",\\"size\\":100},\\"__serializedType__\\":\\"ImmutableRepeat\\"}},\\"__serializedType__\\":\\"ImmutableRecord\\",\\"__serializedRef__\\":0},{\\"data\\":[10,9,8,7,6,5,4,3,2,1],\\"__serializedType__\\":\\"ImmutableOrderedSet\\"},{\\"data\\":{\\"_start\\":0,\\"_end\\":7,\\"_step\\":1,\\"size\\":7},\\"__serializedType__\\":\\"ImmutableRange\\"}],\\"__serializedType__\\":\\"ImmutableSet\\"}"`; exports[`Immutable Record stringify 1`] = `"{\\"data\\":{\\"a\\":1,\\"b\\":3},\\"__serializedType__\\":\\"ImmutableRecord\\",\\"__serializedRef__\\":0}"`; diff --git a/packages/redux-devtools-serialize/test/helpers.spec.js b/packages/redux-devtools-serialize/test/helpers.spec.ts similarity index 61% rename from packages/redux-devtools-serialize/test/helpers.spec.js rename to packages/redux-devtools-serialize/test/helpers.spec.ts index 7df2e933..62af59a3 100644 --- a/packages/redux-devtools-serialize/test/helpers.spec.js +++ b/packages/redux-devtools-serialize/test/helpers.spec.ts @@ -1,7 +1,4 @@ -var helpers = require('../helpers'); -var mark = helpers.mark; -var extract = helpers.extract; -var refer = helpers.refer; +import { mark, extract, refer } from '../src/helpers'; describe('Helpers', function () { it('mark', function () { @@ -16,12 +13,12 @@ describe('Helpers', function () { }); it('refer', function () { - var TestClass = function (data) { + const TestClass = function (data: unknown) { return data; }; - var testInstance = new TestClass({ testData: 'test' }); + const testInstance = new (TestClass as any)({ testData: 'test' }); expect( - refer(testInstance, 'testType', false, [TestClass]) + refer(testInstance, 'testType', false, [TestClass as any]) ).toMatchSnapshot(); }); }); diff --git a/packages/redux-devtools-serialize/test/immutable.spec.js b/packages/redux-devtools-serialize/test/immutable.spec.js deleted file mode 100644 index d2959c0d..00000000 --- a/packages/redux-devtools-serialize/test/immutable.spec.js +++ /dev/null @@ -1,148 +0,0 @@ -var Immutable = require('immutable'); -var Serialize = require('../immutable'); -var serialize = Serialize(Immutable); -var stringify = serialize.stringify; -var parse = serialize.parse; - -var data = { - map: Immutable.Map({ a: 1, b: 2, c: 3, d: 4 }), - orderedMap: Immutable.OrderedMap({ b: 2, a: 1, c: 3, d: 4 }), - list: Immutable.List([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), - range: Immutable.Range(0, 7), - repeat: Immutable.Repeat('hi', 100), - set: Immutable.Set([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), - orderedSet: Immutable.OrderedSet([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), - seq: Immutable.Seq([1, 2, 3, 4, 5, 6, 7, 8]), - stack: Immutable.Stack.of('a', 'b', 'c'), -}; - -describe('Immutable', function () { - var stringified = {}; - describe('Stringify', function () { - Object.keys(data).forEach(function (key) { - it(key, function () { - stringified[key] = stringify(data[key]); - expect(stringified[key]).toMatchSnapshot(); - }); - }); - }); - - describe('Parse', function () { - Object.keys(data).forEach(function (key) { - it(key, function () { - expect(parse(stringified[key])).toEqual(data[key]); - }); - }); - }); - - describe('Record', function () { - var ABRecord = Immutable.Record({ a: 1, b: 2 }); - var myRecord = new ABRecord({ b: 3 }); - - var serialize = Serialize(Immutable, [ABRecord]); - var stringify = serialize.stringify; - var parse = serialize.parse; - var stringifiedRecord; - - it('stringify', function () { - stringifiedRecord = stringify(myRecord); - expect(stringifiedRecord).toMatchSnapshot(); - }); - - it('parse', function () { - expect(parse(stringifiedRecord)).toEqual(myRecord); - }); - }); - - describe('Nested', function () { - var ABRecord = Immutable.Record({ - map: Immutable.OrderedMap({ seq: data.seq, stack: data.stack }), - repeat: data.repeat, - }); - var nestedData = Immutable.Set(ABRecord(), data.orderedSet, data.range); - - var serialize = Serialize(Immutable, [ABRecord]); - var stringify = serialize.stringify; - var parse = serialize.parse; - var stringifiedNested; - - it('stringify', function () { - stringifiedNested = stringify(nestedData); - expect(stringifiedNested).toMatchSnapshot(); - }); - - it('parse', function () { - expect(parse(stringifiedNested)).toEqual(nestedData); - }); - }); - describe('With references', function () { - it('serializes and deserializes', function () { - var sharedValue = []; - var record = Immutable.Record({ - prop: sharedValue, - }); - - var refs = [record]; - - var obj = Immutable.Map({ - fst: new record(), - scnd: new record(), - }); - - var serialized = stringify( - obj, - Serialize(Immutable, refs).replacer, - null, - true - ); - var parsed = JSON.parse(serialized); - - var fstProp = parsed.data.fst.data.prop; - var scndProp = parsed.data.scnd.data.prop; - - expect(fstProp).toEqual(scndProp); - expect(Array.isArray(obj.get('fst').get('prop'))); - }); - }); - - describe('Custom replacer and reviver functions', function () { - var customOneRepresentation = 'one'; - - function customReplacer(key, value, defaultReplacer) { - if (value === 1) { - return { data: customOneRepresentation, __serializedType__: 'number' }; - } - return defaultReplacer(key, value); - } - - function customReviver(key, value, defaultReviver) { - if ( - typeof value === 'object' && - value.__serializedType__ === 'number' && - value.data === customOneRepresentation - ) { - return 1; - } - return defaultReviver(key, value); - } - - var serializeCustom = Serialize( - Immutable, - null, - customReplacer, - customReviver - ); - - Object.keys(data).forEach(function (key) { - var stringified = serializeCustom.stringify(data[key]); - it(key, function () { - var deserialized = serializeCustom.parse(stringified); - expect(deserialized).toEqual(data[key]); - if (key === 'map' || key === 'orderedMap') { - var deserializedDefault = parse(stringified); - expect(deserializedDefault.get('a')).toEqual(customOneRepresentation); - } - }); - }); - }); -}); diff --git a/packages/redux-devtools-serialize/test/immutable.spec.ts b/packages/redux-devtools-serialize/test/immutable.spec.ts new file mode 100644 index 00000000..7abee118 --- /dev/null +++ b/packages/redux-devtools-serialize/test/immutable.spec.ts @@ -0,0 +1,159 @@ +import Immutable, { Map, OrderedMap } from 'immutable'; +import Serialize from '../src/immutable'; +import { SerializedData } from '../src/helpers'; +const serialize = Serialize(Immutable); +const stringify = serialize.stringify; +const parse = serialize.parse; + +const data = { + map: Immutable.Map({ a: 1, b: 2, c: 3, d: 4 }), + orderedMap: Immutable.OrderedMap({ b: 2, a: 1, c: 3, d: 4 }), + list: Immutable.List([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), + range: Immutable.Range(0, 7), + repeat: Immutable.Repeat('hi', 100), + set: Immutable.Set([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), + orderedSet: Immutable.OrderedSet([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), + seq: Immutable.Seq([1, 2, 3, 4, 5, 6, 7, 8]), + stack: Immutable.Stack.of('a', 'b', 'c'), +}; + +describe('Immutable', function () { + const stringified: { [key: string]: string } = {}; + describe('Stringify', function () { + Object.keys(data).forEach(function (key) { + it(key, function () { + stringified[key] = stringify(data[key as keyof typeof data]); + expect(stringified[key]).toMatchSnapshot(); + }); + }); + }); + + describe('Parse', function () { + Object.keys(data).forEach(function (key) { + it(key, function () { + expect(parse(stringified[key])).toEqual(data[key as keyof typeof data]); + }); + }); + }); + + describe('Record', function () { + const ABRecord = Immutable.Record({ a: 1, b: 2 }); + const myRecord = new ABRecord({ b: 3 }); + + const serialize = Serialize(Immutable, [ABRecord]); + const stringify = serialize.stringify; + const parse = serialize.parse; + let stringifiedRecord: string; + + it('stringify', function () { + stringifiedRecord = stringify(myRecord); + expect(stringifiedRecord).toMatchSnapshot(); + }); + + it('parse', function () { + expect(parse(stringifiedRecord)).toEqual(myRecord); + }); + }); + + describe('Nested', function () { + const ABRecord = Immutable.Record({ + map: Immutable.OrderedMap({ seq: data.seq, stack: data.stack }), + repeat: data.repeat, + }); + const nestedData = Immutable.Set([ABRecord(), data.orderedSet, data.range]); + + const serialize = Serialize(Immutable, [ABRecord]); + const stringify = serialize.stringify; + const parse = serialize.parse; + let stringifiedNested: string; + + it('stringify', function () { + stringifiedNested = stringify(nestedData); + expect(stringifiedNested).toMatchSnapshot(); + }); + + it('parse', function () { + expect(parse(stringifiedNested)).toEqual(nestedData); + }); + }); + describe('With references', function () { + it('serializes and deserializes', function () { + const sharedValue: unknown[] = []; + const record = Immutable.Record({ + prop: sharedValue, + }); + + const refs = [record]; + + const obj = Immutable.Map({ + fst: new record(), + scnd: new record(), + }); + + const serialize = Serialize(Immutable, refs); + const serialized = serialize.stringify(obj); + const parsed = JSON.parse(serialized); + + const fstProp = parsed.data.fst.data.prop; + const scndProp = parsed.data.scnd.data.prop; + + expect(fstProp).toEqual(scndProp); + expect(Array.isArray(obj.get('fst')!.get('prop'))).toBe(true); + }); + }); + + describe('Custom replacer and reviver functions', function () { + const customOneRepresentation = 'one'; + + function customReplacer( + key: string, + value: unknown, + defaultReplacer: (key: string, value: unknown) => unknown + ) { + if (value === 1) { + return { data: customOneRepresentation, __serializedType__: 'number' }; + } + return defaultReplacer(key, value); + } + + function customReviver( + key: string, + value: unknown, + defaultReviver: (key: string, value: unknown) => unknown + ) { + if ( + typeof value === 'object' && + (value as SerializedData).__serializedType__ === 'number' && + (value as SerializedData).data === customOneRepresentation + ) { + return 1; + } + return defaultReviver(key, value); + } + + const serializeCustom = Serialize( + Immutable, + null, + customReplacer, + customReviver + ); + + Object.keys(data).forEach(function (key) { + const stringified = serializeCustom.stringify( + data[key as keyof typeof data] + ); + it(key, function () { + const deserialized = serializeCustom.parse(stringified); + expect(deserialized).toEqual(data[key as keyof typeof data]); + if (key === 'map' || key === 'orderedMap') { + const deserializedDefault = parse(stringified); + expect( + (deserializedDefault as + | Map + | OrderedMap).get('a') + ).toEqual(customOneRepresentation); + } + }); + }); + }); +}); diff --git a/packages/redux-devtools-serialize/test/tsconfig.json b/packages/redux-devtools-serialize/test/tsconfig.json new file mode 100644 index 00000000..b55532d2 --- /dev/null +++ b/packages/redux-devtools-serialize/test/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../../tsconfig.base.json", + "include": ["../src", "."] +} diff --git a/packages/redux-devtools-serialize/tsconfig.json b/packages/redux-devtools-serialize/tsconfig.json new file mode 100644 index 00000000..84575cb5 --- /dev/null +++ b/packages/redux-devtools-serialize/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["src"] +}