feat(map2tree): convert to TypeScript (#638)

* map2tree

* Fix build
This commit is contained in:
Nathan Bierema 2020-09-19 19:56:40 -04:00 committed by GitHub
parent f9f15a41de
commit 3b027f400e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 191 additions and 126 deletions

View File

@ -1,3 +1,4 @@
{
"presets": ["@babel/preset-env"]
"presets": ["@babel/preset-env", "@babel/preset-typescript"],
"plugins": ["@babel/plugin-proposal-class-properties"]
}

View File

@ -0,0 +1,3 @@
examples
lib
dist

View File

@ -0,0 +1,29 @@
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'],
},
},
{
files: ['webpack.config.umd.ts'],
extends: '../../eslintrc.ts.base.json',
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.webpack.json'],
},
},
],
};

View File

@ -0,0 +1,3 @@
module.exports = {
preset: 'ts-jest',
};

View File

@ -2,20 +2,6 @@
"name": "map2tree",
"version": "1.4.2",
"description": "Utility for mapping maps to trees",
"main": "lib/index.js",
"scripts": {
"clean": "rimraf lib dist",
"build": "babel src --out-dir lib",
"build:umd": "webpack --progress --config webpack.config.umd.js",
"build:umd:min": "webpack --env.production --progress --config webpack.config.umd.js",
"test": "jest",
"prepare": "npm run build && npm run build:umd",
"prepublishOnly": "npm run test && npm run clean && npm run build && npm run build:umd && npm run build:umd:min"
},
"repository": {
"type": "git",
"url": "https://github.com/reduxjs/redux-devtools.git"
},
"keywords": [
"map2tree",
"map-to-tree",
@ -23,38 +9,43 @@
"map",
"tree"
],
"author": "romseguy",
"license": "MIT",
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/map2tree",
"bugs": {
"url": "https://github.com/reduxjs/redux-devtools/issues"
},
"homepage": "https://github.com/reduxjs/redux-devtools",
"devDependencies": {
"@babel/cli": "^7.10.5",
"@babel/core": "^7.11.1",
"@babel/preset-env": "^7.11.0",
"babel-loader": "^8.1.0",
"immutable": "^4.0.0-rc.12",
"jest": "^26.2.2",
"rimraf": "^3.0.2",
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12"
},
"dependencies": {
"lodash": "^4.17.19"
},
"npmName": "map2tree",
"license": "MIT",
"author": "romseguy",
"files": [
"lib",
"dist",
"src"
],
"npmFileMap": [
{
"basePath": "/dist/",
"files": [
"*.js"
]
}
]
"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 && npm run build:umd && npm run build:umd:min",
"build:types": "tsc --emitDeclarationOnly",
"build:js": "babel src --out-dir lib --extensions \".ts\" --source-maps inline",
"build:umd": "webpack --progress --config webpack.config.umd.ts",
"build:umd:min": "webpack --env.production --progress --config webpack.config.umd.ts",
"clean": "rimraf lib dist",
"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": {
"lodash": "^4.17.19"
},
"devDependencies": {
"@types/lodash": "^4.14.159",
"immutable": "^4.0.0-rc.12"
}
}

View File

@ -1,79 +0,0 @@
import isArray from 'lodash/isArray';
import isPlainObject from 'lodash/isPlainObject';
import mapValues from 'lodash/mapValues';
function visit(parent, visitFn, childrenFn) {
if (!parent) return;
visitFn(parent);
const children = childrenFn(parent);
if (children) {
const count = children.length;
for (let i = 0; i < count; i++) {
visit(children[i], visitFn, childrenFn);
}
}
}
function getNode(tree, key) {
let node = null;
visit(
tree,
(d) => {
if (d.name === key) {
node = d;
}
},
(d) => d.children
);
return node;
}
export default function map2tree(
root,
options = {},
tree = { name: options.key || 'state', children: [] }
) {
if (!isPlainObject(root) && root && !root.toJS) {
return {};
}
const { key: rootNodeKey = 'state', pushMethod = 'push' } = options;
const currentNode = getNode(tree, rootNodeKey);
if (currentNode === null) {
return {};
}
mapValues(root && root.toJS ? root.toJS() : root, (maybeImmutable, key) => {
const value =
maybeImmutable && maybeImmutable.toJS
? maybeImmutable.toJS()
: maybeImmutable;
let newNode = { name: key };
if (isArray(value)) {
newNode.children = [];
for (let i = 0; i < value.length; i++) {
newNode.children[pushMethod]({
name: `${key}[${i}]`,
[isPlainObject(value[i]) ? 'object' : 'value']: value[i],
});
}
} else if (isPlainObject(value)) {
newNode.children = [];
} else {
newNode.value = value;
}
currentNode.children[pushMethod](newNode);
map2tree(value, { key, pushMethod }, tree);
});
return tree;
}

View File

@ -0,0 +1,99 @@
import isArray from 'lodash/isArray';
import isPlainObject from 'lodash/isPlainObject';
import mapValues from 'lodash/mapValues';
interface Node {
name: string;
children?: Node[];
value?: unknown;
}
function visit(
parent: Node,
visitFn: (parent: Node) => void,
childrenFn: (parent: Node) => Node[] | undefined
) {
if (!parent) return;
visitFn(parent);
const children = childrenFn(parent);
if (children) {
const count = children.length;
for (let i = 0; i < count; i++) {
visit(children[i], visitFn, childrenFn);
}
}
}
function getNode(tree: Node, key: string): Node | null {
let node = null;
visit(
tree,
(d) => {
if (d.name === key) {
node = d;
}
},
(d) => d.children
);
return node;
}
export default function map2tree(
// eslint-disable-next-line @typescript-eslint/ban-types
root: {},
options: { key?: string; pushMethod?: 'push' | 'unshift' } = {},
tree: Node = { name: options.key || 'state', children: [] }
): Node {
// eslint-disable-next-line @typescript-eslint/ban-types
if (!isPlainObject(root) && root && !(root as { toJS: () => {} }).toJS) {
return {} as Node;
}
const { key: rootNodeKey = 'state', pushMethod = 'push' } = options;
const currentNode = getNode(tree, rootNodeKey);
if (currentNode === null) {
return {} as Node;
}
mapValues(
// eslint-disable-next-line @typescript-eslint/ban-types
root && (root as { toJS: () => {} }).toJS
? // eslint-disable-next-line @typescript-eslint/ban-types
(root as { toJS: () => {} }).toJS()
: root,
// eslint-disable-next-line @typescript-eslint/ban-types
(maybeImmutable: { toJS?: () => {} }, key) => {
const value =
maybeImmutable && maybeImmutable.toJS
? maybeImmutable.toJS()
: maybeImmutable;
const newNode: Node = { name: key };
if (isArray(value)) {
newNode.children = [];
for (let i = 0; i < value.length; i++) {
newNode.children[pushMethod]({
name: `${key}[${i}]`,
[isPlainObject(value[i]) ? 'object' : 'value']: value[i],
});
}
} else if (isPlainObject(value)) {
newNode.children = [];
} else {
newNode.value = value;
}
currentNode.children![pushMethod](newNode);
map2tree(value, { key, pushMethod }, tree);
}
);
return tree;
}

View File

@ -1,5 +1,5 @@
import map2tree from '../src';
import immutable from 'immutable';
import * as immutable from 'immutable';
test('# rootNodeKey', () => {
const map = {};
@ -151,7 +151,7 @@ describe('# array map', () => {
});
test('## unshift', () => {
const options = { pushMethod: 'unshift' };
const options = { pushMethod: 'unshift' as const };
const expected = {
name: 'state',
children: [

View File

@ -0,0 +1,4 @@
{
"extends": "../../../tsconfig.base.json",
"include": ["../src", "."]
}

View File

@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.react.base.json",
"compilerOptions": {
"outDir": "lib"
},
"include": ["src"]
}

View File

@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.base.json",
"include": ["webpack.config.umd.ts"]
}

View File

@ -1,9 +1,9 @@
const path = require('path');
import * as path from 'path';
module.exports = (env = {}) => ({
module.exports = (env: { production?: boolean } = {}) => ({
mode: env.production ? 'production' : 'development',
entry: {
app: ['./src/index.js'],
app: ['./src/index'],
},
output: {
library: 'd3tooltip',
@ -14,10 +14,13 @@ module.exports = (env = {}) => ({
module: {
rules: [
{
test: /\.js$/,
test: /\.(js|ts)$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
});