Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Adds some neatness to Knex library. Utilities for tables, joins, transactions and other.
There're three ways to work with relational DB on an application side: raw SQL, query builders, ORMs.
I prefer query builders over other two and find it a perfect balance.
The lead query builder in JS ecosystem is Knex. I don't like it much for poor code style & architecture, not so good API. Yes, Knex is not perfect, however this is the leading project in this area and it tends to stay so. It working, it will receive updates, fixes and improves. I decided to build a better abstractions over it with composability and much more JS/Lispy-crazy-science-style in mind. The only restriction is not to fall into ORM-ish style. So this library contains only simple helpers and composable abstractions. Feel free to use another good solutions (like Bluebird's Promise extensions which is built-in for Knex, Lodash/fp, Ramda & lenses etc) along the way.
Import / require modules you need explicitly. Most of functionality is accessible from the root of the package, like require('knexed/one')
, require('knexed/exists')
. Some utilities are bundled into groups by usage, like require('knexed/table/table')
, require('knexed/table/join')
. The group of utility is mentioned in the braces below.
knex('table').select()
/* build query … */
/* then use one of utilities: */
.then(one) // pick exact 1 row
.then(one.maybe) // pick 0..1 rows
.then(exists) // true/false depending on rows existence
.then(exists.not) // negated true/false on existence
.then(count) // pick rows count
.then(project('id')) // compose object with rows by ids
table/table
)/* create init point for this table queries: */
var accounts = table(knex, 'accounts')
/* `accounts()` creates new query at every invocation */
accounts().select()
accounts(trx).select() /* as a part of transaction `trx` */
accounts.as('alias').select() /* with alias */
accounts.as('alias', trx).select()
/* … then build query … */
tx/method
)/* create method */
var create = method(knex, (trx, name) =>
{
return accounts(trx).insert({ name })
})
/* then use it */
create(trx, 'Name') /* as a part of transaction `trx` */
create('Name') /* new transaction will be started */
create(method.NOTX, 'Name') /* if you don't need transaction at all */
table/join
)Use join
helper for symmetric-looking joins. table
is used as basis.
/* prepare two tables: */
var accounts = table(knex, 'accounts')
var messages = table(knex, 'messages')
/* join by accounts.id = messages.user_id: */
var accounts$messages = join(accounts, messages, [ 'id', 'user_id' ])
/* `accounts$messages()` creates new query at every invocation */
/* then use as simple table */
accounts$messages()
.select('user_id', 'text')
.where('user_id', user_id)
/* as a part of transaction `trx` */
accounts$messages(trx).select()
/* supported join types: */
join.left(accounts, messages, [ 'id', 'user_id' ])
join.right(messages, accounts, [ 'id', 'user_id' ])
join.full(table_a, table_b, [ 'id', 'user_id' ])
join.cross(table_a, table_b)
/* pick predicate: */
join(accounts, messages, [ 'id', '=', 'user_id' ])
join.left(accounts, messages, [ 'id', '<>', 'user_id' ])
/* join by accounts.id = messages.id, like NATURAL JOIN: */
join(accounts, messages, 'id')
/* join with aliases */
/* accounts as A, messages as M,
this will also pick proper aliases on join predicate
*/
join([ accounts, 'A' ], [ messages, 'M' ], [ 'id', 'user_id' ])
query
)This helpers transform generated query.
var accounts = table(knex, 'accounts')
var q = accounts().where('id', '>', 1000)
/* `query/count` transforms query into COUNT() one */
var qc = count(q) // returning `number`
/* `query/exists` transforms query into EXISTS(SELECT …) */
var qe = exists(q) // returning `boolean`
Note that count
& exists
from dataset helpers works on returning
dataset, which means streaming potentially large amount of redundant data from
database driver to client. In contrast query/count
& query/exists
works on driver's side, sending to client only simple scalars.
catch/constraint
)Catch constraints and rethrow them as your model-specific constraint errors.
var accounts = table(knex, 'accounts')
function AlreadyExists ()
{
return new TypeError('account_already_exists')
}
accounts()
.insert({ id: 1, name: 'account' })
.catch(...catch_constraint({ constraint: 'accounts_pkey' }, AlreadyExists))
var accounts = table(knex, 'accounts')
function AlreadyExists (data)
{
return { error: 'account_already_exists', conflict: data }
}
var id = 1
accounts()
.insert({ id, name: 'account' })
.catch(...catch_constraint({ constraint: 'accounts_pkey' }, { id }, AlreadyExists))
updated
)Will throw is zero or more than one row had been updated.
var accounts = table(knex, 'accounts')
/* preventing too many (or zero) rows deletion */
accounts()
.delete()
.then(updated)
var accounts = table(knex, 'accounts')
/* guarantee one and only one row modification */
accounts()
.where('name', 'not found')
.update('name', 'Not Found')
.then(updated)
We're providing built-in Flow type definitions.
MIT. © Strider, 2016 — 2018.
FAQs
Knex utilities
The npm package knexed receives a total of 5 weekly downloads. As such, knexed popularity was classified as not popular.
We found that knexed demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.