New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@directus/data-sql

Package Overview
Dependencies
Maintainers
2
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@directus/data-sql - npm Package Compare versions

Comparing version 0.2.1 to 0.3.0

readme.md

288

dist/index.d.ts

@@ -1,86 +0,264 @@

import { AbstractQueryNodeSortTargets, AbstractQuery } from '@directus/data';
import { ExtractFn, ArrayFn, AbstractQueryNodeSortTargets, AbstractQuery } from '@directus/data';
import { GeoJSONGeometry } from 'wellknown';
import { TransformStream } from 'node:stream/web';
interface SqlStatementColumn {
type: 'primitive';
/**
* Used pass a single value.
*/
interface ValueNode {
type: 'value';
parameterIndex: number;
}
/**
* Used pass an arbitrary amount of values.
*/
interface ValuesNode {
type: 'values';
parameterIndexes: number[];
}
/**
* An actual vendor specific SQL statement with its parameters.
* @example
* ```
* {
* statement: 'SELECT * FROM "articles" WHERE "articles"."id" = $1;',
* values: [99],
* }
* ```
*/
interface ParameterizedSqlStatement {
statement: string;
parameters: ParameterTypes[];
}
type ParameterTypes = string | boolean | number | GeoJSONGeometry;
interface AbstractSqlQueryColumn {
table: string;
column: string;
}
interface SqlStatementSelectColumn extends SqlStatementColumn {
/**
* Used to select a specific column from a table.
*/
interface AbstractSqlQuerySelectNode extends AbstractSqlQueryColumn {
type: 'primitive';
as?: string;
/**
* The final alias optionally provided by the user which will be returned within the response.
*/
alias?: string;
}
/**
* Used for parameterized queries.
* Condition to filter rows where two columns of different tables are equal.
* Mainly used for JOINs.
*/
type ParameterIndex = {
/** Indicates where the actual value is stored in the parameter array */
parameterIndex: number;
};
interface SqlConditionFieldNode {
type: 'condition-field';
operation: 'eq';
target: AbstractSqlQuerySelectNode;
compareTo: AbstractSqlQuerySelectNode;
}
/**
* This is an abstract SQL query which can be passen to all SQL drivers.
*
* @example
* ```ts
* const query: SqlStatement = {
* select: [id],
* from: 'articles',
* limit: 0,
* parameters: [25],
* };
* ```
* Used to retrieve a set of data, where the column in question stores a geographic value which intersects with another given geographic value.
* Here, the two types `condition-geo` and `condition-geo-bbox` from @directus/data are combined into one type,
* because the compare value is the same for both types - it's the reference to the actual value stored in the list of parameters.
* That also why the operations got merged together.
*/
interface AbstractSqlQuery {
select: SqlStatementSelectColumn[];
from: string;
limit?: ParameterIndex;
offset?: ParameterIndex;
order?: AbstractSqlQueryOrderNode[];
where?: AbstractSqlQueryWhereConditionNode | AbstractSqlQueryWhereLogicalNode;
intersect?: AbstractSqlQuery;
parameters: (string | boolean | number)[];
interface SqlConditionGeoNode {
type: 'condition-geo';
target: AbstractSqlQuerySelectNode;
/**
* The operation to apply. Get only those rows where the targeting column
* - `intersects`: intersects with the given geo value
* - `intersects_bbox`: intersects with a given bounding box
*/
operation: 'intersects' | 'intersects_bbox';
compareTo: ValueNode;
}
type AbstractSqlQueryOrderNode = {
orderBy: AbstractQueryNodeSortTargets;
direction: 'ASC' | 'DESC';
};
/**
* An abstract WHERE clause.
* Used to apply a function to a column.
* Currently we support various EXTRACT functions to extract specific parts out of a data/time value.
*/
interface AbstractSqlQueryWhereConditionNode {
interface AbstractSqlQueryFnNode extends AbstractSqlQueryColumn {
type: 'fn';
/**
* A list of supported functions. Those are the same as the abstract query.
*/
fn: ExtractFn | ArrayFn;
arguments?: ValuesNode;
as?: string;
alias?: string;
}
/**
* Filter rows where a numeric column is equal, greater than, less than, etc. other given number.
*/
interface SqlConditionNumberNode {
type: 'condition-number';
target: AbstractSqlQuerySelectNode | AbstractSqlQueryFnNode;
operation: 'eq' | 'lt' | 'lte' | 'gt' | 'gte';
compareTo: ValueNode;
}
interface SqlConditionSetNode {
type: 'condition-set';
operation: 'in';
target: AbstractSqlQuerySelectNode;
compareTo: ValuesNode;
}
/**
* Condition to filter rows where a string column value contains, starts with, ends with, or is equal to another given string.
*/
interface SqlConditionStringNode {
type: 'condition-string';
target: AbstractSqlQuerySelectNode;
operation: 'contains' | 'starts_with' | 'ends_with' | 'eq';
compareTo: ValueNode;
}
/**
* Condition to filter rows.
* Various condition types are supported, each depending on a specific datatype.
* The condition can also be negated on this level.
*/
interface AbstractSqlQueryConditionNode {
type: 'condition';
target: SqlStatementColumn;
operation: 'eq' | 'lt' | 'lte' | 'gt' | 'gte' | 'in' | 'contains' | 'starts_with' | 'ends_with' | 'intersects';
condition: SqlConditionStringNode | SqlConditionNumberNode | SqlConditionGeoNode | SqlConditionSetNode | SqlConditionFieldNode;
negate: boolean;
compareTo: CompareValueNode;
}
interface AbstractSqlQueryWhereLogicalNode {
type SqlConditionType = 'condition-string' | 'condition-number' | 'condition-geo' | 'condition-set' | 'condition-field';
/**
* A wrapper to add multiple conditions at once.
*/
interface AbstractSqlQueryLogicalNode {
type: 'logical';
operator: 'and' | 'or';
negate: boolean;
childNodes: (AbstractSqlQueryWhereConditionNode | AbstractSqlQueryWhereLogicalNode)[];
childNodes: (AbstractSqlQueryConditionNode | AbstractSqlQueryLogicalNode)[];
}
interface CompareValueNode {
type: 'value';
parameterIndexes: number[];
/**
* Used to join another table, regardless of the type of relation.
*/
interface AbstractSqlQueryJoinNode {
type: 'join';
table: string;
on: AbstractSqlQueryConditionNode | AbstractSqlQueryLogicalNode;
as: string;
alias?: string;
}
interface AbstractSqlQueryOrderNode {
type: 'order';
orderBy: AbstractQueryNodeSortTargets;
direction: 'ASC' | 'DESC';
}
interface AbstractSqlClauses {
select: (AbstractSqlQuerySelectNode | AbstractSqlQueryFnNode)[];
from: string;
joins?: AbstractSqlQueryJoinNode[];
where?: AbstractSqlQueryWhereNode;
limit?: ValueNode;
offset?: ValueNode;
order?: AbstractSqlQueryOrderNode[];
}
type AbstractSqlQueryWhereNode = AbstractSqlQueryConditionNode | AbstractSqlQueryLogicalNode;
type WhereUnion = {
where: AbstractSqlQueryWhereNode;
parameters: ParameterTypes[];
};
/**
* An actual vendor specific SQL statement with its parameters.
* A set of types which form the abstract SQL query.
* It's still neutral to concrete SQL dialects and databases but provides to SQL drivers with a query type that they can more easy work with.
*
* How the abstract SQL query types differ from the abstract query.
* - In the abstract query the user input values are put directly within the query directly.
* The abstract SQL however stores the user input values in a list of parameters, so that the SQL driver always perform parameterized queries.
* That way we prevent SQL injection.
* Moving the user input values into a list of parameters and replace the input value with the index of the value from the list, is a big part of the converter.
* - Instead of a wrapper for negation, here the negation is a property on the type.
* So the abstract SQL does not have a node of type 'negate' but instead the nodes have a property called 'negate'.
*
* @module
*/
/**
* This is an abstract SQL query which can be passed to all SQL drivers.
*
* @example
* The following query gets the title of all articles and limits the result to 25 rows.
* ```ts
* const query: SqlStatement = {
* select: [title],
* from: 'articles',
* limit: 0, // this is the index of the parameter
* parameters: [25],
* };
* ```
* {
* statement: 'SELECT * FROM "articles" WHERE "articles"."id" = $1;',
* values: [99],
* }
* ```
*/
interface ParameterizedSQLStatement {
statement: string;
parameters: (string | number | boolean)[];
interface AbstractSqlQuery {
clauses: AbstractSqlClauses;
parameters: ParameterTypes[];
aliasMapping: Map<string, string[]>;
}
/**
* Converts an abstract query to the abstract SQL query ({@link AbstractSqlClauses}).
* This converter is used as the first action within the SQL drivers.
*
* @module
*/
/**
* Here the abstract query gets converted into the abstract SQL query.
* It calls all related conversion functions and takes care of the parameter index.
* This process, is also part of the ORM since here the aliases get generated and the mapping of aliases to the original fields is created.
*
* @param abstractQuery the abstract query to convert
* @returns a format very close to actual SQL but without making assumptions about the actual SQL dialect
* @returns the abstract sql query
*/
declare const convertAbstractQueryToAbstractSqlQuery: (abstractQuery: AbstractQuery) => AbstractSqlQuery;
declare const convertQuery: (abstractQuery: AbstractQuery) => AbstractSqlQuery;
export { AbstractSqlQuery, AbstractSqlQueryOrderNode, AbstractSqlQueryWhereConditionNode, AbstractSqlQueryWhereLogicalNode, CompareValueNode, ParameterizedSQLStatement, SqlStatementSelectColumn, convertAbstractQueryToAbstractSqlQuery };
/**
* Converts the receiving chunks from the database into a nested structure
* based on the result from the database.
*/
declare const getOrmTransformer: (paths: Map<string, string[]>) => TransformStream;
/**
* It takes the chunk from the stream and transforms the
* flat result from the database (basically a two dimensional matrix)
* into to proper nested javascript object.
*
* @param chunk one row of the database response
* @param paths the lookup map from the aliases to the nested path
* @returns an object which reflects the hierarchy from the initial query
*/
declare function transformChunk(chunk: Record<string, any>, paths: Map<string, string[]>): Record<string, any>;
/**
* Appends a pseudo-random value to the end of a given identifier to make sure it's unique within the
* context of the current query. The generated identifier is used as an alias to select columns and to join tables.
*
* @remarks
* The uniqueness of a table or column within the schema is not enough for us, since f.e. the same table can be joined multiple times
* and only with some randomness added, we can ensure that the ORM does the nesting correctly.
*
* @todo OracleDB has a max length of 30 characters for identifiers. Is this the right spot to
* ensure that, or should that be on the DB level?
*/
declare const createUniqueAlias: (identifier: string) => string;
/**
* @param operation
* @param negate
* @returns
*/
declare function convertNumericOperators(operation: string, negate: boolean): string;
export { AbstractSqlClauses, AbstractSqlQuery, AbstractSqlQueryColumn, AbstractSqlQueryConditionNode, AbstractSqlQueryFnNode, AbstractSqlQueryJoinNode, AbstractSqlQueryLogicalNode, AbstractSqlQueryOrderNode, AbstractSqlQuerySelectNode, AbstractSqlQueryWhereNode, ParameterTypes, ParameterizedSqlStatement, SqlConditionFieldNode, SqlConditionGeoNode, SqlConditionNumberNode, SqlConditionSetNode, SqlConditionStringNode, SqlConditionType, ValueNode, ValuesNode, WhereUnion, convertNumericOperators, convertQuery, createUniqueAlias, getOrmTransformer, transformChunk };

@@ -1,119 +0,432 @@

// src/converter/convert-primitive.ts
var convertPrimitive = (abstractPrimitive, collection) => {
const statement = {
// src/query-converter/param-index-generator.ts
function* parameterIndexGenerator() {
let index = 0;
while (true) {
yield index++;
}
}
// src/query-converter/fields/create-primitive-select.ts
var createPrimitiveSelect = (collection, abstractPrimitive, generatedAlias) => {
const primitive = {
type: "primitive",
table: collection,
column: abstractPrimitive.field
column: abstractPrimitive.field,
as: generatedAlias
};
if (abstractPrimitive.alias) {
statement.as = abstractPrimitive.alias;
primitive.alias = abstractPrimitive.alias;
}
return statement;
return primitive;
};
// src/utils/param-index-generator.ts
function* parameterIndexGenerator() {
let index = 0;
while (true) {
yield index++;
// src/query-converter/fields/create-join.ts
var createJoin = (currentCollection, relationalField, externalCollectionAlias, fieldAlias) => {
let on;
if (relationalField.join.current.fields.length > 1) {
on = {
type: "logical",
operator: "and",
negate: false,
childNodes: relationalField.join.current.fields.map((currentField, index) => {
const externalField = relationalField.join.external.fields[index];
if (!externalField) {
throw new Error(`Missing related foreign key join column for current context column "${currentField}"`);
}
return getJoinCondition(currentCollection, currentField, externalCollectionAlias, externalField);
})
};
} else {
on = getJoinCondition(
currentCollection,
relationalField.join.current.fields[0],
externalCollectionAlias,
relationalField.join.external.fields[0]
);
}
const result = {
type: "join",
table: relationalField.join.external.collection,
as: externalCollectionAlias,
on
};
if (fieldAlias) {
result.alias = fieldAlias;
}
return result;
};
function getJoinCondition(table1, column1, table2, column2) {
return {
type: "condition",
negate: false,
condition: {
type: "condition-field",
target: {
type: "primitive",
table: table1,
column: column1
},
operation: "eq",
compareTo: {
type: "primitive",
table: table2,
column: column2
}
}
};
}
// src/converter/convert-sort.ts
var convertSort = (abstractSorts) => {
return abstractSorts.map((abstractSort) => {
return {
orderBy: abstractSort.target,
direction: abstractSort.direction === "descending" ? "DESC" : "ASC"
// src/query-converter/functions.ts
function convertFn(collection, abstractFunction, idxGenerator, generatedAlias) {
const fn = {
type: "fn",
fn: abstractFunction.fn,
table: collection,
column: abstractFunction.field
};
if (abstractFunction.alias) {
fn.alias = abstractFunction.alias;
}
if (generatedAlias) {
fn.as = generatedAlias;
}
if (abstractFunction.args && abstractFunction.args?.length > 0) {
fn.arguments = {
type: "values",
parameterIndexes: abstractFunction.args.map(() => idxGenerator.next().value)
};
});
}
return {
fn,
parameters: abstractFunction.args ?? []
};
}
// src/orm/create-unique-alias.ts
import { randomBytes } from "crypto";
var createUniqueAlias = (identifier) => {
const random = randomBytes(3).toString("hex");
return `${identifier}_${random}`;
};
// src/converter/convert-filter.ts
var convertFilter = (filter, collection, generator) => {
return convertFilterWithNegate(filter, collection, generator, false);
};
var convertFilterWithNegate = (filter, collection, generator, negate) => {
if (filter.type === "condition") {
if (filter.target.type !== "primitive") {
throw new Error("Only primitives are currently supported.");
// src/query-converter/fields/fields.ts
var convertFieldNodes = (collection, abstractFields, idxGenerator, currentPath = []) => {
const select = [];
const joins = [];
const parameters = [];
const aliasRelationalMapping = /* @__PURE__ */ new Map();
for (const abstractField of abstractFields) {
if (abstractField.type === "primitive") {
const generatedAlias = createUniqueAlias(abstractField.field);
aliasRelationalMapping.set(generatedAlias, [...currentPath, abstractField.alias ?? abstractField.field]);
const selectNode = createPrimitiveSelect(collection, abstractField, generatedAlias);
select.push(selectNode);
continue;
}
if (filter.operation === "intersects" || filter.operation === "intersects_bounding_box") {
throw new Error("The intersects operators are not yet supported.");
if (abstractField.type === "nested-one") {
if (abstractField.meta.type === "m2o") {
const externalCollectionAlias = createUniqueAlias(abstractField.meta.join.external.collection);
const sqlJoinNode = createJoin(collection, abstractField.meta, externalCollectionAlias, abstractField.alias);
const nestedOutput = convertFieldNodes(externalCollectionAlias, abstractField.fields, idxGenerator, [
...currentPath,
abstractField.meta.join.external.collection
]);
nestedOutput.aliasMapping.forEach((value, key) => aliasRelationalMapping.set(key, value));
joins.push(sqlJoinNode);
select.push(...nestedOutput.clauses.select);
}
continue;
}
return {
where: {
type: "condition",
negate,
operation: filter.operation,
target: {
column: filter.target.field,
table: collection,
type: "primitive"
},
if (abstractField.type === "fn") {
const fnField = abstractField;
const generatedAlias = createUniqueAlias(`${fnField.fn.fn}_${fnField.field}`);
aliasRelationalMapping.set(generatedAlias, [...currentPath, abstractField.alias ?? abstractField.field]);
const fn = convertFn(collection, fnField, idxGenerator, generatedAlias);
select.push(fn.fn);
parameters.push(...fn.parameters);
continue;
}
}
return { clauses: { select, joins }, parameters, aliasMapping: aliasRelationalMapping };
};
// src/query-converter/modifiers/filter/logical.ts
function convertLogical(children, operator, negate) {
const childNodes = children.map((child) => child.where);
const parameters = children.flatMap((child) => child.parameters);
return {
where: {
type: "logical",
negate,
operator,
childNodes
},
parameters
};
}
// src/query-converter/modifiers/filter/conditions/utils.ts
function convertPrimitive(collection, primitiveNode) {
return {
type: "primitive",
table: collection,
column: primitiveNode.field
};
}
function convertTarget(condition, collection, generator) {
let target;
const parameters = [];
if (condition.target.type === "primitive") {
target = {
type: "primitive",
table: collection,
column: condition.target.field
};
} else if (condition.target.type === "fn") {
const convertedFn = convertFn(collection, condition.target, generator);
target = convertedFn.fn;
parameters.push(...convertedFn.parameters);
} else {
throw new Error("The related field types are not yet supported.");
}
return target;
}
// src/query-converter/modifiers/filter/conditions/field.ts
function convertFieldCondition(node, collection, negate) {
return {
where: {
type: "condition",
negate,
condition: {
type: "condition-field",
operation: node.operation,
target: convertPrimitive(collection, node.target),
compareTo: convertPrimitive(node.compareTo.collection, node.compareTo)
}
},
parameters: []
};
}
// src/query-converter/modifiers/filter/conditions/geo.ts
function convertGeoCondition(node, collection, generator, negate) {
return {
where: {
type: "condition",
negate,
condition: {
type: "condition-geo",
operation: node.operation,
target: convertPrimitive(collection, node.target),
compareTo: {
type: "value",
parameterIndexes: [generator.next().value]
parameterIndex: generator.next().value
}
},
parameters: [filter.compareTo.value]
};
}
},
parameters: [node.compareTo]
};
}
// src/query-converter/modifiers/filter/conditions/string.ts
function convertStringNode(node, collection, generator, negate) {
return {
where: {
type: "condition",
negate,
condition: {
type: node.type,
operation: node.operation,
target: convertPrimitive(collection, node.target),
compareTo: {
type: "value",
parameterIndex: generator.next().value
}
}
},
parameters: [node.compareTo]
};
}
// src/query-converter/modifiers/filter/conditions/number.ts
function convertNumberNode(node, collection, generator, negate) {
return {
where: {
type: "condition",
negate,
condition: {
type: node.type,
operation: node.operation,
target: convertTarget(node, collection, generator),
compareTo: {
type: "value",
parameterIndex: generator.next().value
}
}
},
parameters: [node.compareTo]
};
}
// src/query-converter/modifiers/filter/conditions/set.ts
function convertSetCondition(node, collection, generator, negate) {
return {
where: {
type: "condition",
negate,
condition: {
type: "condition-set",
operation: node.operation,
target: convertPrimitive(collection, node.target),
compareTo: {
type: "values",
parameterIndexes: Array.from(node.compareTo).map(() => generator.next().value)
}
}
},
parameters: [...node.compareTo]
};
}
// src/query-converter/modifiers/filter/conditions/conditions.ts
function convertCondition(condition, collection, generator, negate) {
switch (condition.condition.type) {
case "condition-string":
return convertStringNode(condition.condition, collection, generator, negate);
case "condition-number":
return convertNumberNode(condition.condition, collection, generator, negate);
case "condition-geo-intersects":
case "condition-geo-intersects-bbox":
return convertGeoCondition(condition.condition, collection, generator, negate);
case "condition-set":
return convertSetCondition(condition.condition, collection, generator, negate);
case "condition-field":
return convertFieldCondition(condition.condition, collection, negate);
}
}
// src/query-converter/modifiers/filter/filter.ts
var convertFilter = (filter, collection, generator, negate = false) => {
if (filter.type === "condition") {
return convertCondition(filter, collection, generator, negate);
} else if (filter.type === "negate") {
return convertFilterWithNegate(filter.childNode, collection, generator, !negate);
return convertFilter(filter.childNode, collection, generator, !negate);
} else if (filter.type === "logical") {
const children = filter.childNodes.map((childNode) => convertFilter(childNode, collection, generator, false));
return convertLogical(children, filter.operator, negate);
} else {
const children = filter.childNodes.map(
(childNode) => convertFilterWithNegate(childNode, collection, generator, false)
);
throw new Error(`Unknown filter type`);
}
};
// src/query-converter/modifiers/sort.ts
var convertSort = (abstractSorts) => {
return abstractSorts.map((abstractSort) => {
return {
where: {
type: "logical",
negate,
operator: filter.operator,
childNodes: children.map((child) => child.where)
},
parameters: children.flatMap((child) => child.parameters)
type: "order",
orderBy: abstractSort.target,
direction: abstractSort.direction === "descending" ? "DESC" : "ASC"
};
}
});
};
// src/converter/index.ts
var convertAbstractQueryToAbstractSqlQuery = (abstractQuery) => {
const statement = {
select: abstractQuery.nodes.map((abstractNode) => {
switch (abstractNode.type) {
case "primitive":
return convertPrimitive(abstractNode, abstractQuery.collection);
case "fn":
case "m2o":
case "o2m":
case "a2o":
case "o2a":
default:
throw new Error(`Type ${abstractNode.type} hasn't been implemented yet`);
}
}),
from: abstractQuery.collection,
// src/query-converter/modifiers/modifiers.ts
var convertModifiers = (modifiers, collection, idxGenerator) => {
const result = {
clauses: {},
parameters: []
};
const idGen = parameterIndexGenerator();
if (abstractQuery.modifiers?.filter) {
const convertedFilter = convertFilter(abstractQuery.modifiers.filter, abstractQuery.collection, idGen);
statement.where = convertedFilter.where;
statement.parameters.push(...convertedFilter.parameters);
if (modifiers?.filter) {
const convertedFilter = convertFilter(modifiers.filter, collection, idxGenerator);
result.clauses.where = convertedFilter.where;
result.parameters.push(...convertedFilter.parameters);
}
if (abstractQuery.modifiers?.limit) {
statement.limit = { parameterIndex: idGen.next().value };
statement.parameters.push(abstractQuery.modifiers.limit.value);
if (modifiers?.limit) {
result.clauses.limit = { type: "value", parameterIndex: idxGenerator.next().value };
result.parameters.push(modifiers.limit.value);
}
if (abstractQuery.modifiers?.offset) {
statement.offset = { parameterIndex: idGen.next().value };
statement.parameters.push(abstractQuery.modifiers.offset.value);
if (modifiers?.offset) {
result.clauses.offset = { type: "value", parameterIndex: idxGenerator.next().value };
result.parameters.push(modifiers.offset.value);
}
if (abstractQuery.modifiers?.sort) {
statement.order = convertSort(abstractQuery.modifiers.sort);
if (modifiers?.sort) {
result.clauses.order = convertSort(modifiers.sort);
}
return statement;
return result;
};
// src/query-converter/converter.ts
var convertQuery = (abstractQuery) => {
const idGen = parameterIndexGenerator();
const parameters = [];
const convertedFieldNodes = convertFieldNodes(abstractQuery.collection, abstractQuery.fields, idGen);
let clauses = { ...convertedFieldNodes.clauses, from: abstractQuery.collection };
parameters.push(...convertedFieldNodes.parameters);
const convertedModifiers = convertModifiers(abstractQuery.modifiers, abstractQuery.collection, idGen);
clauses = Object.assign(clauses, convertedModifiers.clauses);
parameters.push(...convertedModifiers.parameters);
return {
clauses,
parameters,
aliasMapping: convertedFieldNodes.aliasMapping
};
};
// src/orm/expand.ts
import { set } from "lodash-es";
import { TransformStream } from "stream/web";
var getOrmTransformer = (paths) => {
return new TransformStream({
transform(chunk, controller) {
if (chunk?.constructor !== Object) {
throw new Error(`Can't expand a non-object chunk`);
}
const outputChunk = transformChunk(chunk, paths);
controller.enqueue(outputChunk);
}
});
};
function transformChunk(chunk, paths) {
const result = {};
for (const [key, value] of Object.entries(chunk)) {
const path = paths.get(key);
if (!path) {
throw new Error(`No path available for dot-notated key ${key}`);
}
set(result, path, value);
}
return result;
}
// src/utils/numeric-operator-conversion.ts
function convertNumericOperators(operation, negate) {
let result = "";
switch (operation) {
case "eq":
result = `${negate ? "!=" : "="}`;
break;
case "gt":
result = `${negate ? "<=" : ">"}`;
break;
case "gte":
result = `${negate ? "<" : ">="}`;
break;
case "lt":
result = `${negate ? ">=" : "<"}`;
break;
case "lte":
result = `${negate ? ">" : "<="}`;
break;
default:
throw new Error(`Unknown numeric operator: ${operation}`);
}
return result;
}
export {
convertAbstractQueryToAbstractSqlQuery
convertNumericOperators,
convertQuery,
createUniqueAlias,
getOrmTransformer,
transformChunk
};

23

package.json
{
"name": "@directus/data-sql",
"version": "0.2.1",
"version": "0.3.0",
"type": "module",

@@ -24,17 +24,24 @@ "sideEffects": false,

"devDependencies": {
"@types/lodash-es": "4.17.7",
"@types/node": "18.16.12",
"@types/wellknown": "0.5.4",
"@vitest/coverage-c8": "0.31.1",
"tsup": "6.7.0",
"typescript": "5.0.4",
"dependency-cruiser": "13.1.4",
"tsup": "7.2.0",
"typescript": "5.2.2",
"vitest": "0.31.1",
"@directus/data": "0.2.1",
"@directus/random": "0.2.2",
"@directus/tsconfig": "1.0.0",
"@directus/types": "10.1.3"
"@directus/data": "0.3.0",
"@directus/tsconfig": "1.0.1",
"@directus/random": "0.2.3",
"@directus/types": "11.0.0"
},
"dependencies": {
"lodash-es": "4.17.21"
},
"scripts": {
"build": "tsup src/index.ts --format=esm --dts",
"dev": "tsup src/index.ts --format=esm --dts --watch",
"test": "vitest --watch=false"
"test": "vitest --watch=false",
"depcruise": "depcruise src --include-only '^src' -x test.ts --output-type dot | dot -T svg > dependency-graph.svg"
}
}
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