Skip to content

Commit

Permalink
chore(deps): nuke taffydb from orbit
Browse files Browse the repository at this point in the history
Even as a dev dependency, used solely to verify the correctness of its replacement, `@jsdoc/salty`, it was triggering bogus security warnings.

Fixes jsdoc#2041.
  • Loading branch information
hegemonic committed Mar 1, 2023
1 parent 0662bc7 commit 1192486
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 155 deletions.
1 change: 0 additions & 1 deletion .renovaterc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"extends": ["config:base"],
"statusCheckVerify": true,
"ignoreDeps": ["taffydb"],
"automerge": true,
"automergeType": "branch",
"rangeStrategy": "bump",
Expand Down
4 changes: 2 additions & 2 deletions js-green-licenses.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"packageAllowlist": [
"argparse", // Python-2.0 licensed, which is fine but not on js-green-licenses default list
"taffydb" // MIT licensed, per its source code
// Python-2.0 licensed, which is fine but not on js-green-licenses default list
"argparse"
]
}
15 changes: 1 addition & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@
"license-check-and-add": "^4.0.5",
"lodash": "^4.17.21",
"mock-fs": "^5.2.0",
"prettier": "^2.8.4",
"taffydb": "2.6.2"
"prettier": "^2.8.4"
},
"type": "module",
"engines": {
Expand Down
223 changes: 87 additions & 136 deletions packages/jsdoc-salty/test/specs/lib/salty.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
describe('@jsdoc/salty/lib/salty', () => {
const _ = require('lodash');
const Salty = require('../../../lib/salty');
const { taffy } = require('taffydb');

const data = [
{ a: 2, b: undefined, c: true },
Expand All @@ -29,20 +28,12 @@ describe('@jsdoc/salty/lib/salty', () => {
{ a: 17, b: 0, c: false },
{ a: 66, c: true },
];
let saltyDB;
let taffyDB;
let db;

beforeEach(() => {
saltyDB = new Salty(_.cloneDeep(data));
taffyDB = taffy(_.cloneDeep(data));
db = new Salty(_.cloneDeep(data));
});

// To confirm that TaffyDB and Salty have equivalent behavior, run the same test for both.
function validate(f) {
f(saltyDB);
f(taffyDB);
}

it('is a constructor that returns a function', () => {
expect(new Salty()).toBeFunction();
});
Expand All @@ -56,9 +47,9 @@ describe('@jsdoc/salty/lib/salty', () => {
it('sorts by a single key', () => {
// TaffyDB sorts things strangely when null or undefined values are present. Salty doesn't
// attempt to match that behavior, so we just verify that Salty does what it's supposed to.
saltyDB.sort('b');
db.sort('b');

expect(saltyDB().get()).toMatchArrayOfObjects([
expect(db().get()).toMatchArrayOfObjects([
{ a: 7, b: 'goodbye', c: false },
{ a: 100, b: 'hello', c: true },
{ a: 17, b: 0, c: false },
Expand All @@ -72,208 +63,168 @@ describe('@jsdoc/salty/lib/salty', () => {
});

it('sorts by multiple keys', () => {
validate((db) => {
db.sort('a, b');

expect(db().get()).toMatchArrayOfObjects([
{ a: 2, b: undefined, c: true },
{ a: 7, b: 'goodbye', c: false },
{ a: 17, b: 0, c: false },
{ a: 22, b: null, c: true },
{ a: 35, b: undefined, c: true },
{ a: 42, b: 8, c: null },
{ a: 47, b: null, c: true },
{ a: 66, c: true },
{ a: 100, b: 'hello', c: true },
]);
});
db.sort('a, b');

expect(db().get()).toMatchArrayOfObjects([
{ a: 2, b: undefined, c: true },
{ a: 7, b: 'goodbye', c: false },
{ a: 17, b: 0, c: false },
{ a: 22, b: null, c: true },
{ a: 35, b: undefined, c: true },
{ a: 42, b: 8, c: null },
{ a: 47, b: null, c: true },
{ a: 66, c: true },
{ a: 100, b: 'hello', c: true },
]);
});

it('has no effect when called with a nonexistent key', () => {
validate((db) => {
db.sort('q');
db.sort('q');

expect(db().get()).toMatchArrayOfObjects(data);
});
expect(db().get()).toMatchArrayOfObjects(data);
});

it('returns true', () => {
validate((db) => {
expect(db.sort('a')).toBeTrue();
});
expect(db.sort('a')).toBeTrue();
});
});
});

describe('queries', () => {
it('returns an object with the expected methods after a query', () => {
validate((db) => {
const query = db();
const query = db();

expect(query.each).toBeFunction();
expect(query.get).toBeFunction();
expect(query.remove).toBeFunction();
});
expect(query.each).toBeFunction();
expect(query.get).toBeFunction();
expect(query.remove).toBeFunction();
});

describe('each', () => {
it('calls the function on each item if there is no selection', () => {
validate((db) => {
const result = [];
const result = [];

db().each((item) => result.push(item.a));
db().each((item) => result.push(item.a));

expect(result).toEqual([2, 47, 100, 7, 42, 35, 22, 17, 66]);
});
expect(result).toEqual([2, 47, 100, 7, 42, 35, 22, 17, 66]);
});

it('calls the function on selected items if there is a selection', () => {
validate((db) => {
const result = [];
const result = [];

db({ c: false }).each((item) => result.push(item.a));
db({ c: false }).each((item) => result.push(item.a));

expect(result).toEqual([7, 17]);
});
expect(result).toEqual([7, 17]);
});

it('does not call the function if the selection is empty', () => {
validate((db) => {
const fn = jasmine.createSpy();
const fn = jasmine.createSpy();

db({ a: 1000000000 }).each(fn);
db({ a: 1000000000 }).each(fn);

expect(fn).not.toHaveBeenCalled();
});
expect(fn).not.toHaveBeenCalled();
});

it('returns an object with the expected methods', () => {
validate((db) => {
const query = db().each(() => true);
const query = db().each(() => true);

expect(query.each).toBeFunction();
expect(query.get).toBeFunction();
expect(query.remove).toBeFunction();
});
expect(query.each).toBeFunction();
expect(query.get).toBeFunction();
expect(query.remove).toBeFunction();
});
});

describe('get', () => {
it('returns all items if there is no selection', () => {
validate((db) => {
expect(db().get()).toMatchArrayOfObjects(data);
});
expect(db().get()).toMatchArrayOfObjects(data);
});

it('returns the selected items when one matcher is provided', () => {
validate((db) => {
const result = db({ c: false }).get();

expect(result).toMatchArrayOfObjects([
{ a: 7, b: 'goodbye', c: false },
{ a: 17, b: 0, c: false },
]);
});
const result = db({ c: false }).get();

expect(result).toMatchArrayOfObjects([
{ a: 7, b: 'goodbye', c: false },
{ a: 17, b: 0, c: false },
]);
});

it('returns the selected items when multiple matchers are provided', () => {
validate((db) => {
const result = db({ c: false }, { b: 0 }).get();
const result = db({ c: false }, { b: 0 }).get();

expect(result).toMatchArrayOfObjects([{ a: 17, b: 0, c: false }]);
});
expect(result).toMatchArrayOfObjects([{ a: 17, b: 0, c: false }]);
});

it('returns the selected items when the matcher contains an array of values', () => {
validate((db) => {
const result = db({ a: [2, 47] }).get();

expect(result).toMatchArrayOfObjects([
{ a: 2, b: undefined, c: true },
{ a: 47, b: null, c: true },
]);
});
const result = db({ a: [2, 47] }).get();

expect(result).toMatchArrayOfObjects([
{ a: 2, b: undefined, c: true },
{ a: 47, b: null, c: true },
]);
});

it('returns the correct items with the special matcher for undefined values', () => {
validate((db) => {
const result = db({ b: { isUndefined: true } }).get();

expect(result).toMatchArrayOfObjects([
{ a: 2, b: undefined, c: true },
{ a: 35, b: undefined, c: true },
{ a: 66, c: true },
]);
});
const result = db({ b: { isUndefined: true } }).get();

expect(result).toMatchArrayOfObjects([
{ a: 2, b: undefined, c: true },
{ a: 35, b: undefined, c: true },
{ a: 66, c: true },
]);
});

it('returns no items if the selection is empty', () => {
validate((db) => {
expect(db({ a: 1000000000 }).get()).toBeEmptyArray();
});
expect(db({ a: 1000000000 }).get()).toBeEmptyArray();
});

it('returns the correct items with a custom matcher function', () => {
validate((db) => {
function matcher() {
return this.a > 20; // eslint-disable-line
}

expect(db(matcher).get()).toMatchArrayOfObjects([
{ a: 47, b: null, c: true },
{ a: 100, b: 'hello', c: true },
{ a: 42, b: 8, c: null },
{ a: 35, b: undefined, c: true },
{ a: 22, b: null, c: true },
{ a: 66, c: true },
]);
});
function matcher() {
return this.a > 20; // eslint-disable-line
}

expect(db(matcher).get()).toMatchArrayOfObjects([
{ a: 47, b: null, c: true },
{ a: 100, b: 'hello', c: true },
{ a: 42, b: 8, c: null },
{ a: 35, b: undefined, c: true },
{ a: 22, b: null, c: true },
{ a: 66, c: true },
]);
});
});

describe('remove', () => {
it('deletes everything if there is no selection', () => {
validate((db) => {
db().remove();
db().remove();

expect(db().get()).toBeEmptyArray();
});
expect(db().get()).toBeEmptyArray();
});

it('deletes the selected items if there is a selection', () => {
validate((db) => {
db({ c: true }).remove();

expect(db().get()).toMatchArrayOfObjects([
{ a: 7, b: 'goodbye', c: false },
{ a: 42, b: 8, c: null },
{ a: 17, b: 0, c: false },
]);
});
db({ c: true }).remove();

expect(db().get()).toMatchArrayOfObjects([
{ a: 7, b: 'goodbye', c: false },
{ a: 42, b: 8, c: null },
{ a: 17, b: 0, c: false },
]);
});

it('deletes nothing if the selection is empty', () => {
validate((db) => {
db({ a: 846 }).remove();
db({ a: 846 }).remove();

expect(db().get()).toMatchArrayOfObjects(data);
});
expect(db().get()).toMatchArrayOfObjects(data);
});

it('removes the selected items from the active selection', () => {
validate((db) => {
const db2 = db({ a: 7 });
const db2 = db({ a: 7 });

db2.remove();
db2.remove();

expect(db2.get()).toBeEmptyArray();
});
expect(db2.get()).toBeEmptyArray();
});

it('returns the number of removed items', () => {
validate((db) => {
expect(db({ c: true }).remove()).toBe(6);
});
expect(db({ c: true }).remove()).toBe(6);
});
});
});
Expand Down

0 comments on commit 1192486

Please sign in to comment.