Skip to content

Commit

Permalink
Merge 7f33e17 into 36bbee5
Browse files Browse the repository at this point in the history
  • Loading branch information
hibes committed Oct 16, 2020
2 parents 36bbee5 + 7f33e17 commit ef6e804
Show file tree
Hide file tree
Showing 42 changed files with 1,071 additions and 566 deletions.
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{
"name": "@0ti.me/tiny-pfp",
"version": "0.1.13",
"version": "0.1.14",
"description": "A tiny, minimalist lodash alternative library",
"license": "GPL-3.0",
"main": "src/index.js",
"repository": "https://www.github.com/0time/tiny-pfp",
"scripts": {
"generate-lib-index-js": "yarn generate-index --directory=./src/lib --outputFilePath=./src/src/lib/index.js --overwrite=true",
"generate-src-index-js": "yarn generate-index --directory=./src/src --outputFilePath=./src/index.js --overwrite=true",
Expand All @@ -19,14 +20,15 @@
},
"devDependencies": {
"@0ti.me/index-generator": "^0.1.6",
"@0ti.me/test-deps": "0.1.19",
"@0ti.me/test-deps": "0.1.21",
"bluebird": "^3.7.1",
"coveralls": "^3.0.7",
"eslint": "^6.5.1",
"eslint-config-prettier": "^6.4.0",
"eslint-plugin-prettier": "^3.1.1",
"husky": "^4.2.5",
"index-generator": "^1.0.3",
"lint-staged": "^9.4.2",
"lint-staged": "^10.2.11",
"lodash": "^4.17.15",
"mocha": "^6.2.1",
"nyc": "^14.1.1",
Expand Down
5 changes: 4 additions & 1 deletion src/lib/clone.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
const isArray = require('./is-array');
const isObject = require('./is-object');

module.exports = inp =>
typeof inp === 'object' ? Object.assign({}, inp) : inp;
isArray(inp) ? [].concat(inp) : isObject(inp) ? Object.assign({}, inp) : inp;
27 changes: 27 additions & 0 deletions src/lib/get-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const isArray = require('./is-array');
const isBoolean = require('./is-boolean');
const isError = require('./is-error');
const isFunction = require('./is-function');
const isNull = require('./is-null');
const isNumber = require('./is-number');
const isObject = require('./is-object');
const isString = require('./is-string');
const isUndefined = require('./is-undefined');

const associations = [
{ fn: isUndefined, type: 'undefined' },
{ fn: isNull, type: 'null' },
{ fn: isBoolean, type: 'boolean' },
{ fn: isNumber, type: 'number' },
{ fn: isArray, type: 'array' },
{ fn: isFunction, type: 'function' },
{ fn: isError, type: 'error' },
{ fn: isString, type: 'string' },
{ fn: isObject, type: 'object' },
];

module.exports = item =>
associations.reduce(
(acc, { fn, type }) => (acc !== false || !fn(item) ? acc : type),
false,
);
1 change: 1 addition & 0 deletions src/lib/is-array.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = item => Array.isArray(item);
2 changes: 2 additions & 0 deletions src/lib/is-boolean.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module.exports = item =>
item === true || item === false || item instanceof Boolean;
1 change: 1 addition & 0 deletions src/lib/is-error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = item => item instanceof Error;
1 change: 1 addition & 0 deletions src/lib/is-function.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = item => typeof item === 'function';
1 change: 1 addition & 0 deletions src/lib/is-null.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = item => item === null;
1 change: 1 addition & 0 deletions src/lib/is-number.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = item => typeof item === 'number' || item instanceof Number;
5 changes: 5 additions & 0 deletions src/lib/is-object.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = item => {
const type = typeof item;

return item !== null && (type === 'object' || type === 'function');
};
1 change: 1 addition & 0 deletions src/lib/is-undefined.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = item => item === undefined;
26 changes: 13 additions & 13 deletions src/lib/omit.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,23 @@ const fpExcludes = ray => negate(val => ray.includes(val));
const MAX_ITERATIONS = 250;

module.exports = (obj, omitSet) => {
let allKeys = [];
let accKeys = [];
let curr = obj;
let i = 0;
let first = true;
let keys = [];
let key = null;
let newKeys = [];
let objKeys = [];

// eslint-disable-next-line no-constant-condition
while (true) {
while (first || keys.length > 0) {
first = false;

if (keys.length > 0) {
key = keys.pop();
curr = get(obj, key);
}

++i;

if (!isString(curr)) {
Expand All @@ -33,7 +40,7 @@ module.exports = (obj, omitSet) => {

keys = keys.concat(newKeys);

allKeys = allKeys.concat(newKeys);
accKeys = accKeys.concat(newKeys);
}

if (i > MAX_ITERATIONS) {
Expand All @@ -44,19 +51,12 @@ module.exports = (obj, omitSet) => {
`iteration overrun ${i} > ${MAX_ITERATIONS} (i > MAX_ITERATIONS)`,
);
}

if (keys.length === 0) {
break;
}

key = keys.pop();
curr = get(obj, key);
}

allKeys = allKeys.sort((a, b) => (a < b ? 1 : -1));
accKeys = accKeys.sort((a, b) => (a < b ? 1 : -1));

return flow([
reduce((acc, ea) => set(acc, ea, clone(get(obj, ea))), {}),
initialAcc => omitSet.reduce((acc, ea) => unset(acc, ea), initialAcc),
])(allKeys);
])(accKeys);
};
22 changes: 21 additions & 1 deletion src/lib/set.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
const isBoolean = require('./is-boolean');
const isNull = require('./is-null');
const isNumber = require('./is-number');
const isObject = require('./is-object');
const isString = require('./is-string');
const isUndefined = require('./is-undefined');

module.exports = (obj, bigKey, val) => {
if (!isString(bigKey)) {
Expand All @@ -14,8 +19,23 @@ module.exports = (obj, bigKey, val) => {
if (i === keys.length - 1) {
curr[key] = val;
} else {
if (!Object.prototype.hasOwnProperty.call(curr, key)) {
if (
!Object.prototype.hasOwnProperty.call(curr, key) ||
isUndefined(curr[key]) ||
isNull(curr[key])
) {
curr[key] = {};
} else if (!isUndefined(curr[key]) && !isObject(curr[key])) {
// Be sure to use `.valueOf()` to get at the values if you want to use this preserved information...
if (isBoolean(curr[key])) {
curr[key] = new Boolean(curr[key]);
} else if (isNumber(curr[key])) {
curr[key] = new Number(curr[key]);
} else if (isString(curr[key])) {
curr[key] = new String(curr[key]);
} else {
throw new Error('unhandled primitive to object promotion');
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/src/get-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('../lib/get-type');
1 change: 1 addition & 0 deletions src/src/is-array.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('../lib/is-array');
1 change: 1 addition & 0 deletions src/src/is-boolean.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('../lib/is-boolean');
1 change: 1 addition & 0 deletions src/src/is-error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('../lib/is-error');
1 change: 1 addition & 0 deletions src/src/is-function.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('../lib/is-function');
1 change: 1 addition & 0 deletions src/src/is-null.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('../lib/is-null');
1 change: 1 addition & 0 deletions src/src/is-number.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('../lib/is-number');
1 change: 1 addition & 0 deletions src/src/is-object.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('../lib/is-object');
1 change: 1 addition & 0 deletions src/src/is-string.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('../lib/is-string');
1 change: 1 addition & 0 deletions src/src/is-undefined.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('../lib/is-undefined');
19 changes: 19 additions & 0 deletions test/integration/lodash-parity/get.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const runTestCreator = require('../../lib/run-lodash-parity-test-creator');
const runFpTestCreator = require('../../lib/run-lodash-fp-parity-test-creator');

const { d, nextInt } = deps;

const me = __filename;

d(me, () => {
const runTest = runTestCreator('get');
const runFpTest = runFpTestCreator('get');

const obj = { a: undefined, b: null };
const r = () => nextInt();

const setsOfArgs = [[obj, 'a'], [obj, 'b'], [obj, r()]];

setsOfArgs.forEach(args => runTest(...args));
setsOfArgs.forEach(args => runFpTest(...args));
});
57 changes: 0 additions & 57 deletions test/integration/lodash-parity/index.js
Original file line number Diff line number Diff line change
@@ -1,57 +0,0 @@
const lodash = require('lodash');
const lodashFp = require('lodash/fp');
const tinyPfp = require('../../../src/index');

const { d, testRunner } = deps;

const me = __filename;

const logIfTestingVerbose = obj => {
if (process.env.TESTING_VERBOSE !== undefined) {
console.error(obj); // eslint-disable-line no-console
}

return obj;
};

d(me, () => {
const runTestCreator = functionName => (...input) =>
describe(`tinyPfp.${functionName}`, () =>
testRunner(
logIfTestingVerbose({
description: `should perform like lodash.${functionName}`,
expected: lodash[functionName](...input),
functionToTest: () => tinyPfp[functionName](...input),
input: null,
}),
));

const runFpTestCreator = functionName => (...input) =>
describe(`tinyPfp.fp.${functionName}`, () =>
testRunner(
logIfTestingVerbose({
description: `should perform like lodash.fp.${functionName}`,
expected: lodashFp[functionName](...input),
functionToTest: () => tinyPfp.fp[functionName](...input),
input: null,
}),
));

const square = x => x * x;

describe('array functions', () => {
const setsOfArgs = [
[[], square],
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], square],
];

const rotateAToEnd = array => array.slice(1).concat([array[0]]);
const runMapTest = runTestCreator('map');
const runFpMapTest = runFpTestCreator('map');

setsOfArgs.forEach(ea => {
runMapTest(...ea);
runFpMapTest(...rotateAToEnd(ea));
});
});
});
38 changes: 38 additions & 0 deletions test/integration/lodash-parity/is-type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const evaluatedSetOfEverything = require('../../lib/evaluated-set-of-everything');

const { _, d, expect } = deps;

const me = __filename;

d(me, () => {
const tinyPfp = require('../../../src');

it('should have parity for all the `is-?` functions', () =>
[
'isArray',
'isBoolean',
'isError',
'isFunction',
'isNull',
'isNumber',
'isObject',
'isString',
'isUndefined',
]
.map(key =>
Object.assign({
ours: tinyPfp[key],
theirs: _[key],
key,
}),
)
.forEach(({ key, ours, theirs }) =>
evaluatedSetOfEverything().forEach(({ evaluated, text }) => [
expect(ours, key).to.be.a('function'),
expect(theirs, key).to.be.a('function'),
expect(ours(evaluated), `${key} for ${text}`).to.equal(
theirs(evaluated),
),
]),
));
});
25 changes: 25 additions & 0 deletions test/integration/lodash-parity/map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const runTestCreator = require('../../lib/run-lodash-parity-test-creator');
const runFpTestCreator = require('../../lib/run-lodash-fp-parity-test-creator');

const { d } = deps;

const me = __filename;

d(me, () => {
const square = x => x * x;

describe('array functions', () => {
const setsOfArgs = [
[[], square],
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], square],
];

const runMapTest = runTestCreator('map');
const runFpMapTest = runFpTestCreator('map');

setsOfArgs.forEach(ea => {
runMapTest(...ea);
runFpMapTest(...ea);
});
});
});

0 comments on commit ef6e804

Please sign in to comment.