Socket
Socket
Sign inDemoInstall

slonik

Package Overview
Dependencies
Maintainers
1
Versions
395
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

slonik - npm Package Compare versions

Comparing version 13.1.1 to 14.0.0

64

dist/templateTags/sql.js

@@ -44,3 +44,3 @@ "use strict";

for (const fragmentValue of fragmentValues) {
(0, _invariant.default)((0, _isPrimitiveValueExpression.default)(fragmentValue), 'Unexpected set member type.');
(0, _invariant.default)((0, _isPrimitiveValueExpression.default)(fragmentValue), 'Unexpected value binding type.');
bindings.push(fragmentValue);

@@ -60,38 +60,49 @@ }

continue;
} else if (value && value.type === 'SET' && Array.isArray(value.members)) {
} else if (value && value.type === 'VALUE_LIST' && Array.isArray(value.values)) {
const placeholders = [];
let placeholderIndex = bindings.length;
for (const member of value.members) {
for (const listValue of value.values) {
placeholders.push('$' + ++placeholderIndex);
(0, _invariant.default)((0, _isPrimitiveValueExpression.default)(member), 'Unexpected set member type.');
bindings.push(member);
(0, _invariant.default)((0, _isPrimitiveValueExpression.default)(listValue), 'Unexpected value list member type.');
bindings.push(listValue);
}
raw += placeholders.join(', ');
} else if (value && value.type === 'TUPLE' && Array.isArray(value.values)) {
const placeholders = [];
let placeholderIndex = bindings.length;
for (const tupleValue of value.values) {
placeholders.push('$' + ++placeholderIndex);
(0, _invariant.default)((0, _isPrimitiveValueExpression.default)(tupleValue), 'Unexpected tuple member type.');
bindings.push(tupleValue);
}
raw += '(' + placeholders.join(', ') + ')';
} else if (value && value.type === 'MULTISET' && Array.isArray(value.sets)) {
} else if (value && value.type === 'TUPLE_LIST' && Array.isArray(value.tuples)) {
let placeholderIndex = bindings.length;
const multisetMemberSql = [];
let lastSetSize;
const tupleListMemberSql = [];
let lastTupleSize;
for (const set of value.sets) {
for (const tuple of value.tuples) {
const placeholders = [];
(0, _invariant.default)(Array.isArray(set), 'Unexpected set shape.');
(0, _invariant.default)(Array.isArray(tuple), 'Unexpected tuple shape.');
if (typeof lastSetSize === 'number' && lastSetSize !== set.length) {
throw new Error('Each set in a collection of sets must have an equal number of members.');
if (typeof lastTupleSize === 'number' && lastTupleSize !== tuple.length) {
throw new Error('Each tuple in a list of tuples must have an equal number of members.');
}
lastSetSize = set.length;
lastTupleSize = tuple.length;
for (const member of set) {
for (const member of tuple) {
placeholders.push('$' + ++placeholderIndex);
(0, _invariant.default)((0, _isPrimitiveValueExpression.default)(member), 'Unexpected set member type.');
(0, _invariant.default)((0, _isPrimitiveValueExpression.default)(member), 'Unexpected tuple member type.');
bindings.push(member);
}
multisetMemberSql.push('(' + placeholders.join(', ') + ')');
tupleListMemberSql.push('(' + placeholders.join(', ') + ')');
}
raw += multisetMemberSql.join(', ');
raw += tupleListMemberSql.join(', ');
} else if ((0, _isPrimitiveValueExpression.default)(value)) {

@@ -132,18 +143,25 @@ raw += '$' + (bindings.length + 1);

sql.set = members => {
sql.valueList = values => {
return {
members,
type: 'SET'
type: 'VALUE_LIST',
values
};
};
sql.multiset = sets => {
sql.tuple = values => {
return {
sets,
type: 'MULTISET'
type: 'TUPLE',
values
};
};
sql.tupleList = tuples => {
return {
tuples,
type: 'TUPLE_LIST'
};
};
var _default = sql;
exports.default = _default;
//# sourceMappingURL=sql.js.map

@@ -96,3 +96,3 @@ {

},
"version": "13.1.1"
"version": "14.0.0"
}

@@ -18,3 +18,3 @@ <a name="slonik"></a>

* [SQL injection guarding](#slonik-value-placeholders-tagged-template-literals).
* [Set interpolation](#slonik-value-placeholders-sql-set).
* [Value and tuple interpolation](#slonik-value-placeholders-sql-valuelist).
* Detail [logging](#slonik-debugging).

@@ -30,4 +30,18 @@ * [Parsing and logging of the auto_explain logs](#logging-auto_explain).

---
<a name="slonik-battle-tested"></a>
## Battle-Tested
Slonik began as a collection of utilities designed for working with [`node-postgres`](https://github.com/brianc/node-postgres). We continue to use `node-postgres` as it provides a robust foundation for interacting with PostgreSQL. However, what once was a collection of utilities has since grown into a framework that abstracts repeating code patterns, protects against unsafe connection handling and value interpolation, and provides rich debugging experience.
Slonik has been [battle-tested](https://medium.com/@gajus/lessons-learned-scaling-postgresql-database-to-1-2bn-records-month-edc5449b3067) with large data volumes and queries ranging from simple CRUD operations to data-warehousing needs.
<a name="slonik-origin-of-the-name"></a>
## Origin of the name
![Slonik](./.README/postgresql-elephant.png)
The name of the elephant depicted in the official PostgreSQL logo is Slonik. The name itself is derived from the Russian word for "little elephant".
Read: [The History of Slonik, the PostgreSQL Elephant Logo](https://www.vertabelo.com/blog/notes-from-the-lab/the-history-of-slonik-the-postgresql-elephant-logo)
<a name="slonik-documentation"></a>

@@ -38,2 +52,4 @@ ## Documentation

* [Features](#slonik-features)
* [Battle-Tested](#slonik-battle-tested)
* [Origin of the name](#slonik-origin-of-the-name)
* [Documentation](#slonik-documentation)

@@ -51,4 +67,2 @@ * [Usage](#slonik-usage)

* [Using `sql.raw` to generate dynamic queries](#slonik-recipes-using-sql-raw-to-generate-dynamic-queries)
* [Battle-Tested](#slonik-battle-tested)
* [Origin of the name](#slonik-origin-of-the-name)
* [Conventions](#slonik-conventions)

@@ -58,4 +72,5 @@ * [No multiline values](#slonik-conventions-no-multiline-values)

* [Tagged template literals](#slonik-value-placeholders-tagged-template-literals)
* [`sql.set`](#slonik-value-placeholders-sql-set)
* [`sql.multiset`](#slonik-value-placeholders-sql-multiset)
* [`sql.valueList`](#slonik-value-placeholders-sql-valuelist)
* [`sql.tuple`](#slonik-value-placeholders-sql-tuple)
* [`sql.tupleList`](#slonik-value-placeholders-sql-tuplelist)
* [`sql.identifier`](#slonik-value-placeholders-sql-identifier)

@@ -574,18 +589,2 @@ * [`sql.raw`](#slonik-value-placeholders-sql-raw)

<a name="slonik-battle-tested"></a>
## Battle-Tested
Slonik began as a collection of utilities designed for working with [`node-postgres`](https://github.com/brianc/node-postgres). We continue to use `node-postgres` as it provides a robust foundation for interacting with PostgreSQL. However, what once was a collection of utilities has since grown into a framework that abstracts repeating code patterns, protects against unsafe connection handling and value interpolation, and provides rich debugging experience.
Slonik has been [battle-tested](https://medium.com/@gajus/lessons-learned-scaling-postgresql-database-to-1-2bn-records-month-edc5449b3067) with large data volumes and queries ranging from simple CRUD operations to data-warehousing needs.
<a name="slonik-origin-of-the-name"></a>
## Origin of the name
![Slonik](./.README/postgresql-elephant.png)
The name of the elephant depicted in the official PostgreSQL logo is Slonik. The name itself is derived from the Russian word for "little elephant".
Read: [The History of Slonik, the PostgreSQL Elephant Logo](https://www.vertabelo.com/blog/notes-from-the-lab/the-history-of-slonik-the-postgresql-elephant-logo)
<a name="slonik-conventions"></a>

@@ -648,15 +647,15 @@ ## Conventions

<a name="slonik-value-placeholders-sql-set"></a>
### <code>sql.set</code>
<a name="slonik-value-placeholders-sql-valuelist"></a>
### <code>sql.valueList</code>
```js
(members: $ReadOnlyArray<PrimitiveValueExpressionType>) => SetSqlTokenType;
(values: $ReadOnlyArray<PrimitiveValueExpressionType>) => ValueListSqlTokenType;
```
`sql.set` is used to create a typed row construct (or a set, depending on the context), e.g.
Creates a list of values, e.g.
```js
await connection.query(sql`
SELECT ${sql.set([1, 2, 3])}
SELECT (${sql.valueList([1, 2, 3])})
`);

@@ -680,15 +679,48 @@

<a name="slonik-value-placeholders-sql-multiset"></a>
### <code>sql.multiset</code>
<a name="slonik-value-placeholders-sql-tuple"></a>
### <code>sql.tuple</code>
```js
(sets: $ReadOnlyArray<$ReadOnlyArray<PrimitiveValueExpressionType>>) => MultisetSqlTokenType;
(values: $ReadOnlyArray<PrimitiveValueExpressionType>) => TupleSqlTokenType;
```
`sql.multiset` is used to create a comma-separated list of typed row constructs, e.g.
Creates a tuple (typed row construct), e.g.
```js
await connection.query(sql`
SELECT ${sql.multiset([
INSERT INTO (foo, bar, baz)
VALUES ${sql.tuple([1, 2, 3])}
`);
```
Produces:
```js
{
sql: 'INSERT INTO (foo, bar, baz) VALUES ($1, $2, $3)',
values: [
1,
2,
3
]
}
```
<a name="slonik-value-placeholders-sql-tuplelist"></a>
### <code>sql.tupleList</code>
```js
(tuples: $ReadOnlyArray<$ReadOnlyArray<PrimitiveValueExpressionType>>) => TupleListSqlTokenType;
```
Creates a list of tuples (typed row constructs), e.g.
```js
await connection.query(sql`
INSERT INTO (foo, bar, baz)
VALUES ${sql.tupleList([
[1, 2, 3],

@@ -705,3 +737,3 @@ [4, 5, 6]

{
sql: 'SELECT ($1, $2, $3), ($4, $5, $6)',
sql: 'INSERT INTO (foo, bar, baz) VALUES ($1, $2, $3), ($4, $5, $6)',
values: [

@@ -708,0 +740,0 @@ 1,

@@ -6,8 +6,9 @@ // @flow

IdentifierTokenType,
MultisetSqlTokenType,
PrimitiveValueExpressionType,
RawSqlTokenType,
SetSqlTokenType,
TaggledTemplateLiteralInvocationType,
ValueExpressionType
TupleListSqlTokenType,
TupleSqlTokenType,
ValueExpressionType,
ValueListSqlTokenType
} from '../types';

@@ -50,3 +51,3 @@ import {

for (const fragmentValue of fragmentValues) {
invariant(isPrimitiveValueExpression(fragmentValue), 'Unexpected set member type.');
invariant(isPrimitiveValueExpression(fragmentValue), 'Unexpected value binding type.');

@@ -70,3 +71,3 @@ bindings.push(fragmentValue);

continue;
} else if (value && value.type === 'SET' && Array.isArray(value.members)) {
} else if (value && value.type === 'VALUE_LIST' && Array.isArray(value.values)) {
const placeholders = [];

@@ -76,33 +77,47 @@

for (const member of value.members) {
for (const listValue of value.values) {
placeholders.push('$' + ++placeholderIndex);
invariant(isPrimitiveValueExpression(member), 'Unexpected set member type.');
invariant(isPrimitiveValueExpression(listValue), 'Unexpected value list member type.');
bindings.push(member);
bindings.push(listValue);
}
raw += placeholders.join(', ');
} else if (value && value.type === 'TUPLE' && Array.isArray(value.values)) {
const placeholders = [];
let placeholderIndex = bindings.length;
for (const tupleValue of value.values) {
placeholders.push('$' + ++placeholderIndex);
invariant(isPrimitiveValueExpression(tupleValue), 'Unexpected tuple member type.');
bindings.push(tupleValue);
}
raw += '(' + placeholders.join(', ') + ')';
} else if (value && value.type === 'MULTISET' && Array.isArray(value.sets)) {
} else if (value && value.type === 'TUPLE_LIST' && Array.isArray(value.tuples)) {
let placeholderIndex = bindings.length;
const multisetMemberSql = [];
const tupleListMemberSql = [];
let lastSetSize;
let lastTupleSize;
for (const set of value.sets) {
for (const tuple of value.tuples) {
const placeholders = [];
invariant(Array.isArray(set), 'Unexpected set shape.');
invariant(Array.isArray(tuple), 'Unexpected tuple shape.');
if (typeof lastSetSize === 'number' && lastSetSize !== set.length) {
throw new Error('Each set in a collection of sets must have an equal number of members.');
if (typeof lastTupleSize === 'number' && lastTupleSize !== tuple.length) {
throw new Error('Each tuple in a list of tuples must have an equal number of members.');
}
lastSetSize = set.length;
lastTupleSize = tuple.length;
for (const member of set) {
for (const member of tuple) {
placeholders.push('$' + ++placeholderIndex);
invariant(isPrimitiveValueExpression(member), 'Unexpected set member type.');
invariant(isPrimitiveValueExpression(member), 'Unexpected tuple member type.');

@@ -112,6 +127,6 @@ bindings.push(member);

multisetMemberSql.push('(' + placeholders.join(', ') + ')');
tupleListMemberSql.push('(' + placeholders.join(', ') + ')');
}
raw += multisetMemberSql.join(', ');
raw += tupleListMemberSql.join(', ');
} else if (isPrimitiveValueExpression(value)) {

@@ -154,16 +169,23 @@ raw += '$' + (bindings.length + 1);

sql.set = (members: $ReadOnlyArray<PrimitiveValueExpressionType>): SetSqlTokenType => {
sql.valueList = (values: $ReadOnlyArray<PrimitiveValueExpressionType>): ValueListSqlTokenType => {
return {
members,
type: 'SET'
type: 'VALUE_LIST',
values
};
};
sql.multiset = (sets: $ReadOnlyArray<$ReadOnlyArray<PrimitiveValueExpressionType>>): MultisetSqlTokenType => {
sql.tuple = (values: $ReadOnlyArray<PrimitiveValueExpressionType>): TupleSqlTokenType => {
return {
sets,
type: 'MULTISET'
type: 'TUPLE',
values
};
};
sql.tupleList = (tuples: $ReadOnlyArray<$ReadOnlyArray<PrimitiveValueExpressionType>>): TupleListSqlTokenType => {
return {
tuples,
type: 'TUPLE_LIST'
};
};
export default sql;

@@ -144,12 +144,17 @@ // @flow

export type SetSqlTokenType = {|
members: $ReadOnlyArray<PrimitiveValueExpressionType>,
type: 'SET'
export type ValueListSqlTokenType = {|
values: $ReadOnlyArray<PrimitiveValueExpressionType>,
type: 'VALUE_LIST'
|};
export type MultisetSqlTokenType = {|
sets: $ReadOnlyArray<$ReadOnlyArray<PrimitiveValueExpressionType>>,
type: 'MULTISET'
export type TupleSqlTokenType = {|
values: $ReadOnlyArray<PrimitiveValueExpressionType>,
type: 'TUPLE'
|};
export type TupleListSqlTokenType = {|
tuples: $ReadOnlyArray<$ReadOnlyArray<PrimitiveValueExpressionType>>,
type: 'TUPLE_LIST'
|};
export type PrimitiveValueExpressionType = string | number | boolean | null;

@@ -161,4 +166,5 @@

RawSqlTokenType |
SetSqlTokenType |
MultisetSqlTokenType;
ValueListSqlTokenType |
TupleSqlTokenType |
TupleListSqlTokenType;

@@ -165,0 +171,0 @@ export type TaggledTemplateLiteralInvocationType = {|

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc