Comparing version 1.0.0-beta.6 to 1.0.0-beta.7
161
lib/index.js
@@ -7,4 +7,2 @@ "use strict"; | ||
const isSymbol = sym => typeof sym === "symbol"; | ||
const isNil = o => o === null || o === undefined; | ||
const debug = require("debug")("pg-sql2"); | ||
@@ -43,8 +41,18 @@ | ||
function makeRawNode(text /*: string */) /*: SQLRawNode */{ | ||
// $FlowFixMe | ||
if (typeof text !== "string") { | ||
throw new Error("Invalid argument to makeRawNode - expected string"); | ||
} | ||
// $FlowFixMe: flow doesn't like symbols | ||
return { type: "RAW", text, [$$trusted]: true }; | ||
} | ||
function makeIdentifierNode(names /*: Array<mixed> */ | ||
function isStringOrSymbol(val) { | ||
return typeof val === "string" || typeof val === "symbol"; | ||
} | ||
function makeIdentifierNode(names /*: Array<string | Symbol> */ | ||
) /*: SQLIdentifierNode */{ | ||
if (!Array.isArray(names) || !names.every(isStringOrSymbol)) { | ||
throw new Error("Invalid argument to makeIdentifierNode - expected array of strings/symbols"); | ||
} | ||
// $FlowFixMe | ||
@@ -59,3 +67,4 @@ return { type: "IDENTIFIER", names, [$$trusted]: true }; | ||
function ensureNonEmptyArray(array, allowZeroLength = false) { | ||
function ensureNonEmptyArray /*:: <T>*/(array /*: Array<T>*/ | ||
, allowZeroLength = false) /*: Array<T> */{ | ||
if (!Array.isArray(array)) { | ||
@@ -92,6 +101,10 @@ throw debugError(new Error("Expected array")); | ||
for (const rawItem of items) { | ||
for (let i = 0, l = items.length; i < l; i++) { | ||
const rawItem = items[i]; | ||
const item /*: SQLNode */ = enforceValidNode(rawItem); | ||
switch (item.type) { | ||
case "RAW": | ||
if (typeof item.text !== "string") { | ||
throw new Error("RAW node expected string"); | ||
} | ||
sqlFragments.push(item.text); | ||
@@ -106,20 +119,21 @@ break; | ||
return escapeSqlIdentifier(name); | ||
} | ||
if (!isSymbol(rawName)) { | ||
throw debugError(new Error(`Expected string or symbol, received '${String(rawName)}'`)); | ||
} | ||
const name /*: Symbol */ = /*:: (*/rawName /*: any) */; | ||
// $FlowFixMe: flow doesn't like symbols | ||
} else if (typeof rawName === "symbol") { | ||
const name /*: Symbol */ = /*:: (*/rawName /*: any) */; | ||
// Get the correct identifier string for this symbol. | ||
let identifier = symbolToIdentifier.get(name); | ||
// Get the correct identifier string for this symbol. | ||
let identifier = symbolToIdentifier.get(name); | ||
// If there is no identifier, create one and set it. | ||
if (!identifier) { | ||
identifier = `__local_${nextSymbolId++}__`; | ||
symbolToIdentifier.set(name, identifier); | ||
// If there is no identifier, create one and set it. | ||
if (!identifier) { | ||
identifier = `__local_${nextSymbolId++}__`; | ||
symbolToIdentifier.set(name, identifier); | ||
} | ||
// Return the identifier. Since we create it, we won’t have to | ||
// escape it because we know all of the characters are safe. | ||
return identifier; | ||
} else { | ||
throw debugError(new Error(`Expected string or symbol, received '${String(rawName)}'`)); | ||
} | ||
// Return the identifier. Since we create it, we won’t have to | ||
// escape it because we know all of the characters are safe. | ||
return identifier; | ||
}).join(".")); | ||
@@ -143,13 +157,6 @@ break; | ||
function enforceValidNode(node /*: mixed */) /*: SQLNode */{ | ||
if (node != null && typeof node === "object") { | ||
const isRaw = node.type === "RAW" && typeof node.text === "string"; | ||
const isIdentifier = node.type === "IDENTIFIER" && Array.isArray(node.names) && node.names.every(name => typeof name === "string" || typeof name === "symbol"); | ||
const isValue = node.type === "VALUE"; | ||
// $FlowFixMe: flow doesn't like symbols here? | ||
const isTrusted = node[$$trusted] === true; | ||
if ((isRaw || isIdentifier || isValue) && isTrusted) { | ||
// $FlowFixMe: this has been validated | ||
return node; | ||
} | ||
// $FlowFixMe: flow doesn't like symbols | ||
if (node !== null && typeof node === "object" && node[$$trusted] === true) { | ||
// $FlowFixMe: this has been validated | ||
return node; | ||
} | ||
@@ -167,4 +174,4 @@ throw new Error(`Expected SQL item, instead received '${String(node)}'.`); | ||
*/ | ||
function query(strings /*: mixed */ | ||
, ...values /*: Array<mixed> */ | ||
function query(strings /*: Array<string> */ | ||
, ...values /*: Array<SQL> */ | ||
) /*: SQLQuery */{ | ||
@@ -180,3 +187,3 @@ if (!Array.isArray(strings)) { | ||
} | ||
if (text.length) { | ||
if (text.length > 0) { | ||
items.push(makeRawNode(text)); | ||
@@ -203,3 +210,5 @@ } | ||
*/ | ||
const raw = (text /*: mixed */) => makeRawNode(String(text)); | ||
function raw(text /*: string */) /*: SQLNode */{ | ||
return makeRawNode(String(text)); | ||
} | ||
@@ -211,3 +220,5 @@ /** | ||
*/ | ||
const identifier = (...names /*: Array<mixed> */) => makeIdentifierNode(ensureNonEmptyArray(names)); | ||
function identifier(...names /*: Array<string | Symbol> */) /*: SQLNode */{ | ||
return makeIdentifierNode(ensureNonEmptyArray(names)); | ||
} | ||
@@ -218,4 +229,10 @@ /** | ||
*/ | ||
const value = (val /*: mixed */) => makeValueNode(val); | ||
function value(val /*: mixed */) /*: SQLNode */{ | ||
return makeValueNode(val); | ||
} | ||
const trueNode = raw(`TRUE`); | ||
const falseNode = raw(`FALSE`); | ||
const nullNode = raw(`NULL`); | ||
/** | ||
@@ -225,3 +242,3 @@ * If the value is simple will inline it into the query, otherwise will defer | ||
*/ | ||
const literal = (val /*: mixed */) => { | ||
function literal(val /*: mixed */) /*: SQLNode */{ | ||
if (typeof val === "string" && val.match(/^[a-zA-Z0-9_-]*$/)) { | ||
@@ -236,13 +253,9 @@ return raw(`'${val}'`); | ||
} else if (typeof val === "boolean") { | ||
if (val) { | ||
return raw(`TRUE`); | ||
} else { | ||
return raw(`FALSE`); | ||
} | ||
} else if (isNil(val)) { | ||
return raw(`NULL`); | ||
return val ? trueNode : falseNode; | ||
} else if (val == null) { | ||
return nullNode; | ||
} else { | ||
return makeValueNode(val); | ||
} | ||
}; | ||
} | ||
@@ -253,7 +266,5 @@ /** | ||
*/ | ||
const join = (rawItems /*: mixed */, rawSeparator /*: mixed */ = "") => { | ||
if (!Array.isArray(rawItems)) { | ||
throw new Error("Items to join must be an array"); | ||
} | ||
const items = rawItems; | ||
function join(items /*: Array<SQL> */ | ||
, rawSeparator /*: string */ = "") /*: SQLQuery */{ | ||
ensureNonEmptyArray(items, true); | ||
if (typeof rawSeparator !== "string") { | ||
@@ -264,5 +275,5 @@ throw new Error("Invalid separator - must be a string"); | ||
const currentItems = []; | ||
ensureNonEmptyArray(items, true); | ||
const sepNode = makeRawNode(separator); | ||
for (let i = 0, l = items.length; i < l; i++) { | ||
const rawItem = items[i]; | ||
const rawItem /*: SQL */ = items[i]; | ||
let itemsToAppend /*: SQLNode | SQLQuery */; | ||
@@ -277,7 +288,7 @@ if (Array.isArray(rawItem)) { | ||
} else { | ||
currentItems.push(makeRawNode(separator), ...itemsToAppend); | ||
currentItems.push(sepNode, ...itemsToAppend); | ||
} | ||
} | ||
return currentItems; | ||
}; | ||
} | ||
@@ -289,3 +300,3 @@ // Copied from https://github.com/brianc/node-postgres/blob/860cccd53105f7bc32fed8b1de69805f0ecd12eb/lib/client.js#L285-L302 | ||
for (var i = 0; i < str.length; i++) { | ||
for (var i = 0, l = str.length; i < l; i++) { | ||
var c = str[i]; | ||
@@ -304,39 +315,19 @@ if (c === '"') { | ||
// The types we export are stricter so people get the right hinting | ||
exports.query = query; | ||
exports.query = function sqlQuery(strings /*: string[] */ | ||
, ...values /*: Array<SQL> */ | ||
) /*: SQLQuery */{ | ||
return query(strings, ...values); | ||
}; | ||
exports.fragment = exports.query; | ||
exports.raw = function sqlRaw(text /*: string */) /*: SQLNode */{ | ||
return raw(text); | ||
}; | ||
exports.raw = raw; | ||
exports.identifier = function sqlIdentifier(...names /*: Array<string | Symbol> */ | ||
) /*: SQLNode */{ | ||
return identifier(...names); | ||
}; | ||
exports.identifier = identifier; | ||
exports.value = function sqlValue(val /*: mixed */) /*: SQLNode */{ | ||
return value(val); | ||
}; | ||
exports.value = value; | ||
exports.literal = function sqlLiteral(val /*: mixed */) /*: SQLNode */{ | ||
return literal(val); | ||
}; | ||
exports.literal = literal; | ||
exports.join = function sqlJoin(items /*: Array<SQL> */ | ||
, separator /*: string */ = "") /*: SQLQuery */{ | ||
return join(items, separator); | ||
}; | ||
exports.join = join; | ||
exports.compile = function sqlCompile(sql /*: SQLQuery */) /*: QueryConfig */{ | ||
return compile(sql); | ||
}; | ||
exports.compile = compile; | ||
exports.null = exports.literal(null); | ||
exports.null = nullNode; | ||
exports.blank = exports.query``; |
{ | ||
"name": "pg-sql2", | ||
"version": "1.0.0-beta.6", | ||
"version": "1.0.0-beta.7", | ||
"description": "Generate safe Postgres-compliant SQL with tagged template literals", | ||
@@ -44,7 +44,7 @@ "main": "lib/index.js", | ||
"eslint-plugin-jest": "^20.0.3", | ||
"eslint-plugin-prettier": "^2.1.2", | ||
"flow-bin": "^0.52.0", | ||
"eslint-plugin-prettier": "2.6.0", | ||
"flow-bin": "0.66.0", | ||
"jest": "20.0.4", | ||
"markdown-doctest": "^0.9.1", | ||
"prettier": "^1.5.3" | ||
"prettier": "1.11.0" | ||
}, | ||
@@ -51,0 +51,0 @@ "jest": { |
179
src/index.js
@@ -10,4 +10,2 @@ "use strict"; | ||
const isSymbol = sym => typeof sym === "symbol"; | ||
const isNil = o => o === null || o === undefined; | ||
const debug = require("debug")("pg-sql2"); | ||
@@ -46,9 +44,21 @@ | ||
function makeRawNode(text /*: string */) /*: SQLRawNode */ { | ||
// $FlowFixMe | ||
if (typeof text !== "string") { | ||
throw new Error("Invalid argument to makeRawNode - expected string"); | ||
} | ||
// $FlowFixMe: flow doesn't like symbols | ||
return { type: "RAW", text, [$$trusted]: true }; | ||
} | ||
function isStringOrSymbol(val) { | ||
return typeof val === "string" || typeof val === "symbol"; | ||
} | ||
function makeIdentifierNode( | ||
names /*: Array<mixed> */ | ||
names /*: Array<string | Symbol> */ | ||
) /*: SQLIdentifierNode */ { | ||
if (!Array.isArray(names) || !names.every(isStringOrSymbol)) { | ||
throw new Error( | ||
"Invalid argument to makeIdentifierNode - expected array of strings/symbols" | ||
); | ||
} | ||
// $FlowFixMe | ||
@@ -63,3 +73,6 @@ return { type: "IDENTIFIER", names, [$$trusted]: true }; | ||
function ensureNonEmptyArray(array, allowZeroLength = false) { | ||
function ensureNonEmptyArray /*:: <T>*/( | ||
array /*: Array<T>*/, | ||
allowZeroLength = false | ||
) /*: Array<T> */ { | ||
if (!Array.isArray(array)) { | ||
@@ -98,6 +111,10 @@ throw debugError(new Error("Expected array")); | ||
for (const rawItem of items) { | ||
for (let i = 0, l = items.length; i < l; i++) { | ||
const rawItem = items[i]; | ||
const item /*: SQLNode */ = enforceValidNode(rawItem); | ||
switch (item.type) { | ||
case "RAW": | ||
if (typeof item.text !== "string") { | ||
throw new Error("RAW node expected string"); | ||
} | ||
sqlFragments.push(item.text); | ||
@@ -115,4 +132,19 @@ break; | ||
return escapeSqlIdentifier(name); | ||
} | ||
if (!isSymbol(rawName)) { | ||
// $FlowFixMe: flow doesn't like symbols | ||
} else if (typeof rawName === "symbol") { | ||
const name /*: Symbol */ = /*:: (*/ rawName /*: any) */; | ||
// Get the correct identifier string for this symbol. | ||
let identifier = symbolToIdentifier.get(name); | ||
// If there is no identifier, create one and set it. | ||
if (!identifier) { | ||
identifier = `__local_${nextSymbolId++}__`; | ||
symbolToIdentifier.set(name, identifier); | ||
} | ||
// Return the identifier. Since we create it, we won’t have to | ||
// escape it because we know all of the characters are safe. | ||
return identifier; | ||
} else { | ||
throw debugError( | ||
@@ -124,16 +156,2 @@ new Error( | ||
} | ||
const name /*: Symbol */ = /*:: (*/ rawName /*: any) */; | ||
// Get the correct identifier string for this symbol. | ||
let identifier = symbolToIdentifier.get(name); | ||
// If there is no identifier, create one and set it. | ||
if (!identifier) { | ||
identifier = `__local_${nextSymbolId++}__`; | ||
symbolToIdentifier.set(name, identifier); | ||
} | ||
// Return the identifier. Since we create it, we won’t have to | ||
// escape it because we know all of the characters are safe. | ||
return identifier; | ||
}) | ||
@@ -159,18 +177,6 @@ .join(".") | ||
function enforceValidNode(node /*: mixed */) /*: SQLNode */ { | ||
if (node != null && typeof node === "object") { | ||
const isRaw = node.type === "RAW" && typeof node.text === "string"; | ||
const isIdentifier = | ||
node.type === "IDENTIFIER" && | ||
Array.isArray(node.names) && | ||
node.names.every( | ||
name => typeof name === "string" || typeof name === "symbol" | ||
); | ||
const isValue = node.type === "VALUE"; | ||
// $FlowFixMe: flow doesn't like symbols here? | ||
const isTrusted = node[$$trusted] === true; | ||
if ((isRaw || isIdentifier || isValue) && isTrusted) { | ||
// $FlowFixMe: this has been validated | ||
return node; | ||
} | ||
// $FlowFixMe: flow doesn't like symbols | ||
if (node !== null && typeof node === "object" && node[$$trusted] === true) { | ||
// $FlowFixMe: this has been validated | ||
return node; | ||
} | ||
@@ -189,4 +195,4 @@ throw new Error(`Expected SQL item, instead received '${String(node)}'.`); | ||
function query( | ||
strings /*: mixed */, | ||
...values /*: Array<mixed> */ | ||
strings /*: Array<string> */, | ||
...values /*: Array<SQL> */ | ||
) /*: SQLQuery */ { | ||
@@ -206,3 +212,3 @@ if (!Array.isArray(strings)) { | ||
} | ||
if (text.length) { | ||
if (text.length > 0) { | ||
items.push(makeRawNode(text)); | ||
@@ -229,3 +235,5 @@ } | ||
*/ | ||
const raw = (text /*: mixed */) => makeRawNode(String(text)); | ||
function raw(text /*: string */) /*: SQLNode */ { | ||
return makeRawNode(String(text)); | ||
} | ||
@@ -237,4 +245,5 @@ /** | ||
*/ | ||
const identifier = (...names /*: Array<mixed> */) => | ||
makeIdentifierNode(ensureNonEmptyArray(names)); | ||
function identifier(...names /*: Array<string | Symbol> */) /*: SQLNode */ { | ||
return makeIdentifierNode(ensureNonEmptyArray(names)); | ||
} | ||
@@ -245,4 +254,10 @@ /** | ||
*/ | ||
const value = (val /*: mixed */) => makeValueNode(val); | ||
function value(val /*: mixed */) /*: SQLNode */ { | ||
return makeValueNode(val); | ||
} | ||
const trueNode = raw(`TRUE`); | ||
const falseNode = raw(`FALSE`); | ||
const nullNode = raw(`NULL`); | ||
/** | ||
@@ -252,3 +267,3 @@ * If the value is simple will inline it into the query, otherwise will defer | ||
*/ | ||
const literal = (val /*: mixed */) => { | ||
function literal(val /*: mixed */) /*: SQLNode */ { | ||
if (typeof val === "string" && val.match(/^[a-zA-Z0-9_-]*$/)) { | ||
@@ -263,13 +278,9 @@ return raw(`'${val}'`); | ||
} else if (typeof val === "boolean") { | ||
if (val) { | ||
return raw(`TRUE`); | ||
} else { | ||
return raw(`FALSE`); | ||
} | ||
} else if (isNil(val)) { | ||
return raw(`NULL`); | ||
return val ? trueNode : falseNode; | ||
} else if (val == null) { | ||
return nullNode; | ||
} else { | ||
return makeValueNode(val); | ||
} | ||
}; | ||
} | ||
@@ -280,7 +291,7 @@ /** | ||
*/ | ||
const join = (rawItems /*: mixed */, rawSeparator /*: mixed */ = "") => { | ||
if (!Array.isArray(rawItems)) { | ||
throw new Error("Items to join must be an array"); | ||
} | ||
const items = rawItems; | ||
function join( | ||
items /*: Array<SQL> */, | ||
rawSeparator /*: string */ = "" | ||
) /*: SQLQuery */ { | ||
ensureNonEmptyArray(items, true); | ||
if (typeof rawSeparator !== "string") { | ||
@@ -291,5 +302,5 @@ throw new Error("Invalid separator - must be a string"); | ||
const currentItems = []; | ||
ensureNonEmptyArray(items, true); | ||
const sepNode = makeRawNode(separator); | ||
for (let i = 0, l = items.length; i < l; i++) { | ||
const rawItem = items[i]; | ||
const rawItem /*: SQL */ = items[i]; | ||
let itemsToAppend /*: SQLNode | SQLQuery */; | ||
@@ -304,7 +315,7 @@ if (Array.isArray(rawItem)) { | ||
} else { | ||
currentItems.push(makeRawNode(separator), ...itemsToAppend); | ||
currentItems.push(sepNode, ...itemsToAppend); | ||
} | ||
} | ||
return currentItems; | ||
}; | ||
} | ||
@@ -316,3 +327,3 @@ // Copied from https://github.com/brianc/node-postgres/blob/860cccd53105f7bc32fed8b1de69805f0ecd12eb/lib/client.js#L285-L302 | ||
for (var i = 0; i < str.length; i++) { | ||
for (var i = 0, l = str.length; i < l; i++) { | ||
var c = str[i]; | ||
@@ -331,43 +342,19 @@ if (c === '"') { | ||
// The types we export are stricter so people get the right hinting | ||
exports.query = query; | ||
exports.query = function sqlQuery( | ||
strings /*: string[] */, | ||
...values /*: Array<SQL> */ | ||
) /*: SQLQuery */ { | ||
return query(strings, ...values); | ||
}; | ||
exports.fragment = exports.query; | ||
exports.raw = function sqlRaw(text /*: string */) /*: SQLNode */ { | ||
return raw(text); | ||
}; | ||
exports.raw = raw; | ||
exports.identifier = function sqlIdentifier( | ||
...names /*: Array<string | Symbol> */ | ||
) /*: SQLNode */ { | ||
return identifier(...names); | ||
}; | ||
exports.identifier = identifier; | ||
exports.value = function sqlValue(val /*: mixed */) /*: SQLNode */ { | ||
return value(val); | ||
}; | ||
exports.value = value; | ||
exports.literal = function sqlLiteral(val /*: mixed */) /*: SQLNode */ { | ||
return literal(val); | ||
}; | ||
exports.literal = literal; | ||
exports.join = function sqlJoin( | ||
items /*: Array<SQL> */, | ||
separator /*: string */ = "" | ||
) /*: SQLQuery */ { | ||
return join(items, separator); | ||
}; | ||
exports.join = join; | ||
exports.compile = function sqlCompile(sql /*: SQLQuery */) /*: QueryConfig */ { | ||
return compile(sql); | ||
}; | ||
exports.compile = compile; | ||
exports.null = exports.literal(null); | ||
exports.null = nullNode; | ||
exports.blank = exports.query``; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
26913
571