Comparing version 1.0.77 to 1.0.78
@@ -49,3 +49,3 @@ /** | ||
export declare const get_direct_edges: (from_entity: string, to_entity: string, orma_schema: OrmaSchema) => Edge[]; | ||
export declare const get_direct_edge: (from_entity: string, to_entity: string, orma_schema: OrmaSchema) => Edge; | ||
export declare const get_direct_edge: (from_entity: string, to_entity: string, orma_schema: OrmaSchema, foreign_key_override?: string[]) => Edge; | ||
/** | ||
@@ -52,0 +52,0 @@ * returns a list of edges which, when traversed one after the other, connect the first given entity to the last. |
@@ -127,4 +127,12 @@ "use strict"; | ||
*/ | ||
const get_direct_edge = (from_entity, to_entity, orma_schema) => { | ||
const edges = (0, exports.get_direct_edges)(from_entity, to_entity, orma_schema); | ||
const get_direct_edge = (from_entity, to_entity, orma_schema, foreign_key_override = undefined) => { | ||
const parent_edges = (0, exports.get_parent_edges)(from_entity, orma_schema).filter(el => el.to_entity === to_entity); | ||
const child_edges = (0, exports.get_child_edges)(from_entity, orma_schema).filter(el => el.to_entity === to_entity); | ||
const filtered_parent_edges = foreign_key_override | ||
? parent_edges.filter(edge => edge.from_field === foreign_key_override[0]) | ||
: parent_edges; | ||
const filtered_child_edges = foreign_key_override | ||
? child_edges.filter(edge => edge.to_field === foreign_key_override[0]) | ||
: child_edges; | ||
const edges = [...filtered_parent_edges, ...filtered_child_edges]; | ||
if (edges.length !== 1) { | ||
@@ -131,0 +139,0 @@ throw Error(`Did not find exactly one edge from ${from_entity} to ${to_entity}`); |
@@ -28,4 +28,4 @@ "use strict"; | ||
if (ancestor_result === undefined || ancestor_result[1].length === 0) { | ||
// this case where there are no ancestor results can happen if, for example, this is a nested lower entitiy but | ||
// nothing was returned from the higher entitiy. In this case, we want nothing of this entity to be queried | ||
// this case where there are no ancestor results can happen if, for example, this is a nested lower entitiy but | ||
// nothing was returned from the higher entitiy. In this case, we want nothing of this entity to be queried | ||
// so we use an impossible where clause that returns nothing. | ||
@@ -38,3 +38,3 @@ return { | ||
const ancestor_to_entity_path = subquery_path.slice(nesting_ancestor_index + 1, Infinity); | ||
const ancestor_where_clause = get_ancestor_where_clause(ancestor_rows, ancestor_path, ancestor_to_entity_path, query, orma_schema); | ||
const ancestor_where_clause = get_ancestor_where_clause(ancestor_rows, subquery_path, nesting_ancestor_index, query, orma_schema); | ||
return ancestor_where_clause; | ||
@@ -69,26 +69,36 @@ }; | ||
*/ | ||
const get_ancestor_where_clause = (ancestor_rows, ancestor_path, ancestor_to_entity_path, query, orma_schema) => { | ||
const ancestor_name = (0, query_1.get_real_entity_name)(ancestor_path, query); | ||
const under_ancestor_path = [...ancestor_path, ancestor_to_entity_path[0]]; | ||
const entity_under_ancestor = (0, query_1.get_real_entity_name)(under_ancestor_path, query); | ||
const edge_under_ancestor = (0, schema_helpers_1.get_direct_edge)(entity_under_ancestor, ancestor_name, orma_schema); | ||
const get_ancestor_where_clause = (ancestor_rows, entity_path, ancestor_index, query, orma_schema) => { | ||
const ancestor_to_entity_edge_path = get_query_edge_path(query, entity_path, ancestor_index, orma_schema); | ||
const edge_under_ancestor = ancestor_to_entity_edge_path[0]; | ||
if (ancestor_rows === undefined || ancestor_rows.length === 0) { | ||
const ancestor_name = ancestor_to_entity_edge_path[0].from_entity; | ||
throw Error(`No ancestor rows provided for ${ancestor_name}`); | ||
} | ||
const ancestor_foreign_key_values = ancestor_rows.map(row => row[edge_under_ancestor.to_field]); | ||
const entity_to_ancestor_path = ancestor_to_entity_path.slice().reverse(); | ||
const any_path = entity_to_ancestor_path.slice(1, entity_to_ancestor_path.length); | ||
const entity_name = entity_to_ancestor_path[0]; | ||
const ancestor_query = (0, any_path_macro_1.process_any_clause)({ | ||
$any_path: [ | ||
any_path, | ||
{ | ||
$in: [ | ||
edge_under_ancestor.from_field, | ||
ancestor_foreign_key_values, | ||
], | ||
}, | ||
], | ||
}, entity_name, '$where', orma_schema); | ||
const ancestor_foreign_key_values = ancestor_rows.map(row => row[edge_under_ancestor.from_field]); | ||
// reverse the path since we are making the where clause in the entity and want to search based on ancestor | ||
const entity_to_ancestor_edge_path = ancestor_to_entity_edge_path | ||
// exclude the entity closest to the ancestor, since this entity is already accounted for in the final $in clause | ||
.slice(1, Infinity) | ||
// to reverse the path, we have to reverse the order of the edges but also reverse each | ||
// individual edge | ||
.reverse() | ||
.map(edge => (0, schema_helpers_1.reverse_edge)(edge)); | ||
const ancestor_query = (0, any_path_macro_1.edge_path_to_where_ins)(entity_to_ancestor_edge_path, '$where', { | ||
$in: [edge_under_ancestor.to_field, ancestor_foreign_key_values], | ||
}); | ||
return ancestor_query; | ||
}; | ||
const get_query_edge_path = (query, path_to_last_subquery, start_path_index, orma_schema) => { | ||
let edge_path = []; | ||
// dont run the for loop on the last element, since each for loop iteration makes an edge to the | ||
for (let i = start_path_index; i < path_to_last_subquery.length - 1; i++) { | ||
const subquery_path = path_to_last_subquery.slice(0, i + 1); | ||
const subquery = (0, helpers_1.deep_get)(subquery_path, query); | ||
const subquery_entity = (0, query_1.get_real_entity_name)(path_to_last_subquery[i], subquery); | ||
const next_subquery = subquery[path_to_last_subquery[i + 1]]; | ||
const next_subquery_entity = (0, query_1.get_real_entity_name)(path_to_last_subquery[i + 1], next_subquery); | ||
const edge = (0, schema_helpers_1.get_direct_edge)(subquery_entity, next_subquery_entity, orma_schema, next_subquery.$foreign_key); | ||
edge_path.push(edge); | ||
} | ||
return edge_path; | ||
}; |
@@ -21,2 +21,29 @@ "use strict"; | ||
}, | ||
payments: { | ||
id: {}, | ||
from_vendor_id: { | ||
references: { | ||
vendors: { | ||
id: {}, | ||
}, | ||
}, | ||
}, | ||
to_vendor_id: { | ||
references: { | ||
vendors: { | ||
id: {}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
receipts: { | ||
id: {}, | ||
payment_id: { | ||
references: { | ||
payments: { | ||
id: {}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
images: { | ||
@@ -216,7 +243,8 @@ id: {}, | ||
const query = { | ||
products: { | ||
images: { | ||
$where: undefined, | ||
$having: undefined, | ||
image_urls: {}, | ||
vendors: { | ||
payments: { | ||
$foreign_key: ['from_vendor_id'], | ||
receipts: { | ||
id: true | ||
}, | ||
}, | ||
@@ -226,20 +254,19 @@ }, | ||
const previous_results = [ | ||
[['products'], [{ id: 1 }, { id: 2 }]], | ||
// [['products', 'images'], [{ id: 3 }]], | ||
[['vendors'], [{ id: 1 }, { id: 2 }]], | ||
]; | ||
(0, nesting_macro_1.apply_nesting_macro)(query, ['products', 'images', 'image_urls'], previous_results, orma_schema); | ||
(0, nesting_macro_1.apply_nesting_macro)(query, ['vendors', 'payments', 'receipts'], previous_results, orma_schema); | ||
const goal = { | ||
products: { | ||
images: { | ||
$where: undefined, | ||
$having: undefined, | ||
image_urls: { | ||
vendors: { | ||
payments: { | ||
$foreign_key: ['from_vendor_id'], | ||
receipts: { | ||
id: true, | ||
$where: { | ||
$in: [ | ||
'image_id', | ||
'payment_id', | ||
{ | ||
$select: ['id'], | ||
$from: 'images', | ||
$from: 'payments', | ||
$where: { | ||
$in: ['product_id', [1, 2]], | ||
$in: ['from_vendor_id', [1, 2]], | ||
}, | ||
@@ -246,0 +273,0 @@ }, |
@@ -6,2 +6,4 @@ import { OrmaSchema } from '../../introspector/introspector'; | ||
export declare const apply_select_macro: (query: any, orma_schema: OrmaSchema) => void; | ||
export declare const get_select: (subquery: any, subquery_path: string[], orma_schema: OrmaSchema) => any[]; | ||
export declare const get_select: (subquery: any, subquery_path: string[], orma_schema: OrmaSchema) => (string | { | ||
$as: any[]; | ||
})[]; |
@@ -23,3 +23,5 @@ "use strict"; | ||
} | ||
const new_select_names = new_select.map(el => (el === null || el === void 0 ? void 0 : el.$as) ? el.$as[1] : el); | ||
const new_select_names = new_select.map(el => | ||
// @ts-ignore | ||
(el === null || el === void 0 ? void 0 : el.$as) ? el.$as[1] : el); | ||
for (const select of new_select_names) { | ||
@@ -50,4 +52,4 @@ delete value[select]; | ||
const lower_subquery_entity = (_a = lower_subquery.$from) !== null && _a !== void 0 ? _a : key; | ||
const edge_to_lower_table = (0, schema_helpers_1.get_direct_edge)(entity_name, lower_subquery_entity, orma_schema); | ||
return edge_to_lower_table.from_field; | ||
const edges_to_lower_table = (0, schema_helpers_1.get_direct_edges)(entity_name, lower_subquery_entity, orma_schema); | ||
return edges_to_lower_table.map(el => el.from_field); | ||
} | ||
@@ -58,4 +60,4 @@ return []; // subqueries are not handled here | ||
const higher_entity = subquery_path[subquery_path.length - 2]; | ||
const edge_to_higher_entity = (0, schema_helpers_1.get_direct_edge)(entity_name, higher_entity, orma_schema); | ||
$select.push(edge_to_higher_entity.from_field); | ||
const edges_to_higher_entity = (0, schema_helpers_1.get_direct_edges)(entity_name, higher_entity, orma_schema); | ||
$select.push(...edges_to_higher_entity.map(el => el.from_field)); | ||
} | ||
@@ -62,0 +64,0 @@ return [...new Set($select)]; // unique values |
@@ -66,21 +66,21 @@ "use strict"; | ||
let where_clause_locations = []; | ||
(0, query_helpers_1.query_for_each)(query, (subquery, path) => { | ||
(0, query_helpers_1.query_for_each)(query, (subquery, subquery_path) => { | ||
if (subquery.$where) { | ||
(0, helpers_1.deep_for_each)(subquery.$where, (value, path) => { | ||
if (value === null || value === void 0 ? void 0 : value.$from) { | ||
where_clause_locations.push({ value, path }); | ||
(0, helpers_1.deep_for_each)(subquery.$where, (where_clause, where_clause_path) => { | ||
if (where_clause === null || where_clause === void 0 ? void 0 : where_clause.$from) { | ||
where_clause_locations.push({ where_clause, where_clause_path }); | ||
} | ||
}); | ||
} | ||
subquery_locations.push({ value: subquery, path }); | ||
subquery_locations.push({ subquery, subquery_path }); | ||
}); | ||
// generate where clauses for all the paths that we found | ||
where_clause_locations.forEach(({ value, path }) => { | ||
const entity_name = value.$from; | ||
apply_where_connected_to_subquery(connection_edges, query.$where_connected, value, entity_name, undefined); | ||
where_clause_locations.forEach(({ where_clause, where_clause_path }) => { | ||
const entity_name = where_clause.$from; | ||
apply_where_connected_to_subquery(connection_edges, query.$where_connected, where_clause, entity_name, undefined); | ||
}); | ||
subquery_locations.forEach(({ value, path }) => { | ||
const entity_name = (0, query_1.get_real_entity_name)(path, value); | ||
const higher_entity = (0, query_1.get_real_higher_entity_name)(path, value); | ||
apply_where_connected_to_subquery(connection_edges, query.$where_connected, value, entity_name, higher_entity); | ||
subquery_locations.forEach(({ subquery, subquery_path }) => { | ||
const entity_name = (0, query_1.get_real_entity_name)((0, helpers_1.last)(subquery_path), subquery); | ||
const higher_entity = (0, query_1.get_real_higher_entity_name)(subquery_path, subquery); | ||
apply_where_connected_to_subquery(connection_edges, query.$where_connected, subquery, entity_name, higher_entity); | ||
}); | ||
@@ -87,0 +87,0 @@ return query; |
@@ -7,3 +7,3 @@ import { error_type } from '../helpers/error_handling'; | ||
export declare const get_real_higher_entity_name: (path: (string | number)[], query: any) => any; | ||
export declare const get_real_entity_name: (path: (string | number)[], query: any) => any; | ||
export declare const get_real_entity_name: (last_path_item: string, subquery: Record<string, any>) => any; | ||
export declare const having_to_json_sql: (query: any, subquery_path: string[], orma_schema: OrmaSchema) => any; | ||
@@ -10,0 +10,0 @@ export declare const orma_nester: (results: [string[], Record<string, unknown>[]][], query: any, orma_schema: OrmaSchema) => {}; |
@@ -23,4 +23,5 @@ "use strict"; | ||
// This function will default to the from clause | ||
const get_real_entity_name = (path, query) => { | ||
return (0, helpers_1.deep_get)([...path, '$from'], query, null) || (0, helpers_1.last)(path); | ||
const get_real_entity_name = (last_path_item, subquery) => { | ||
var _a; | ||
return (_a = subquery.$from) !== null && _a !== void 0 ? _a : last_path_item; | ||
}; | ||
@@ -83,5 +84,8 @@ exports.get_real_entity_name = get_real_entity_name; | ||
} | ||
const entity = (0, exports.get_real_entity_name)(path, query); | ||
const higher_entity = (0, exports.get_real_entity_name)(path.slice(0, -1), query); | ||
const edge = (0, schema_helpers_1.get_direct_edge)(higher_entity, entity, orma_schema); | ||
const higher_entity_path = path.slice(0, -1); | ||
const higher_entity = (0, helpers_1.deep_get)(higher_entity_path, query); | ||
const entity = higher_entity[(0, helpers_1.last)(path)]; | ||
const entity_name = (0, exports.get_real_entity_name)((0, helpers_1.last)(path), entity); | ||
const higher_entity_name = (0, exports.get_real_entity_name)((0, helpers_1.last)(higher_entity_path), higher_entity); | ||
const edge = (0, schema_helpers_1.get_direct_edge)(higher_entity_name, entity_name, orma_schema, entity.$foreign_key); | ||
return [edge.from_field, edge.to_field]; | ||
@@ -88,0 +92,0 @@ }); |
@@ -1,261 +0,261 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const chai_1 = require("chai"); | ||
const mocha_1 = require("mocha"); | ||
const validate_query_manual_1 = require("./validate_query_manual"); | ||
const schema = { | ||
grand_parent: { | ||
id: {}, | ||
grand_parent_column: {}, | ||
}, | ||
parent: { | ||
id: {}, | ||
parent_column: {}, | ||
grand_parent_id: { | ||
references: { | ||
grand_parent: { | ||
id: {}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
child: { | ||
id: {}, | ||
child_column: {}, | ||
parent_id: { | ||
references: { | ||
parent: { | ||
id: {}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
/* | ||
{ | ||
qty: { | ||
$sum: 'quantity' | ||
}, | ||
inventory_adjustments: { | ||
variants: { | ||
sku: true | ||
} | ||
}, | ||
inventory_adjustments: { | ||
quantity: true | ||
} | ||
} | ||
*/ | ||
(0, mocha_1.describe)('validate_query.ts', () => { | ||
(0, mocha_1.describe)('boolean resolver', () => { | ||
(0, mocha_1.test)('validates boolean resolver column names', () => { | ||
const query = { | ||
grand_parent: { | ||
id: true, | ||
grand_parent_column: true, | ||
parent: { | ||
parent_column: true, | ||
child: { | ||
id: true, | ||
child_column_oops: true, | ||
}, | ||
}, | ||
}, | ||
}; | ||
const errors = (0, validate_query_manual_1.validator)(query, schema); | ||
(0, chai_1.expect)(errors.length).to.deep.equal(1); | ||
(0, chai_1.expect)(errors[0].path).to.deep.equal([ | ||
'grand_parent', | ||
'parent', | ||
'child', | ||
'child_column_oops', | ||
]); | ||
}); | ||
}); | ||
(0, mocha_1.describe)('virtual columns', () => { | ||
(0, mocha_1.test)('validates $field virtual column', () => { | ||
const query = { | ||
parent: { | ||
custom_name: { $field: 'parent_column' }, | ||
custom_name2: { $field: 'oops' }, | ||
}, | ||
}; | ||
const errors = (0, validate_query_manual_1.validator)(query, schema); | ||
(0, chai_1.expect)(errors[0].path).to.deep.equal(['parent', 'custom_name2']); | ||
(0, chai_1.expect)(errors.length).to.deep.equal(1); | ||
}); | ||
}); | ||
(0, mocha_1.describe)('subqueries', () => { | ||
(0, mocha_1.test)('validates the from clause', () => { | ||
const data = { | ||
parent: { | ||
good: { | ||
$from: 'child', | ||
id: true, | ||
}, | ||
bad: { | ||
$from: 'oops', | ||
id: true, | ||
}, | ||
}, | ||
}; | ||
const errors = (0, validate_query_manual_1.validator)(data, schema); | ||
const from_clause_errors = errors.filter(err => JSON.stringify(err.path) === | ||
JSON.stringify(['parent', 'bad', 'id'])); | ||
(0, chai_1.expect)(from_clause_errors.length).to.equal(1); | ||
}); | ||
(0, mocha_1.test)('validates subquery connections', () => { | ||
const data = { | ||
grand_parent: { | ||
john: { | ||
$from: 'parent', | ||
child: { | ||
id: true, | ||
grand_parent: { | ||
id: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
const errors = (0, validate_query_manual_1.validator)(data, schema); | ||
(0, chai_1.expect)(errors.length).to.equal(1); | ||
(0, chai_1.expect)(errors[0].path).to.deep.equal([ | ||
'grand_parent', | ||
'john', | ||
'child', | ||
'grand_parent', | ||
]); | ||
}); | ||
}); | ||
mocha_1.describe.skip('clauses', () => { | ||
(0, mocha_1.test)('Requires $eq to have valid field name', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$eq: ['my_id', 5], | ||
}, | ||
my_id: { | ||
$field: 'id', | ||
}, | ||
}, | ||
}; | ||
const errors = (0, validate_query_manual_1.validator)(data, schema); | ||
(0, chai_1.expect)(errors.length).to.equal(1); | ||
(0, chai_1.expect)(errors[0].path).to.deep.equal(['parent', '$where']); | ||
}); | ||
(0, mocha_1.test)('Lets $having have aliased fields', () => { | ||
const data = { | ||
parent: { | ||
$having: { | ||
$eq: ['my_id', 5], | ||
}, | ||
my_id: { | ||
$field: 'id', | ||
}, | ||
}, | ||
}; | ||
const errors = (0, validate_query_manual_1.validator)(data, schema); | ||
(0, chai_1.expect)(errors.length).to.equal(0); | ||
}); | ||
(0, mocha_1.test)('Lets operators have functions', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$eq: ['name', { $field: 'id' }], | ||
}, | ||
id: 'id', | ||
}, | ||
}; | ||
const errors = (0, validate_query_manual_1.validator)(data, schema); | ||
(0, chai_1.expect)(errors.length).to.equal(0); | ||
}); | ||
(0, mocha_1.test)('Lets operators have functions', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$lte: ['name', { $field: 'id' }], | ||
}, | ||
id: 'id', | ||
}, | ||
}; | ||
const errors = (0, validate_query_manual_1.validator)(data, schema); | ||
(0, chai_1.expect)(errors.length).to.equal(0); | ||
}); | ||
(0, mocha_1.test)('Lets $and', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$and: [ | ||
{ | ||
$eq: ['id', '5'], | ||
}, | ||
], | ||
}, | ||
id: 'id', | ||
}, | ||
}; | ||
const errors = (0, validate_query_manual_1.validator)(data, schema); | ||
(0, chai_1.expect)(errors.length).to.equal(0); | ||
}); | ||
(0, mocha_1.test)('Changes scope for subqueries', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$in: [ | ||
'id', | ||
{ | ||
$select: ['parent_id'], | ||
$from: 'child', | ||
$where: { | ||
$eq: ['name', 3], // invalid because 'name' is a field of parent, not child | ||
}, | ||
}, | ||
], | ||
}, | ||
id: 'id', | ||
}, | ||
}; | ||
const errors = (0, validate_query_manual_1.validator)(data, schema); | ||
(0, chai_1.expect)(errors.length).to.equal(1); | ||
}); | ||
(0, mocha_1.test)('Requires subqueries to have valid fields', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$in: [ | ||
'id', | ||
{ | ||
$select: ['invalid_field'], | ||
$from: 'child', | ||
}, | ||
], | ||
}, | ||
id: 'id', | ||
}, | ||
}; | ||
const errors = (0, validate_query_manual_1.validator)(data, schema); | ||
(0, chai_1.expect)(errors.length).to.equal(1); | ||
}); | ||
(0, mocha_1.test)('Requires subqueries to have valid fields', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$in: [ | ||
'id', | ||
{ | ||
$select: ['name'], | ||
$from: 'fake_table', | ||
}, | ||
], | ||
}, | ||
id: 'id', | ||
}, | ||
}; | ||
const errors = (0, validate_query_manual_1.validator)(data, schema); | ||
(0, chai_1.expect)(errors.length).to.equal(1); | ||
}); | ||
}); | ||
}); | ||
// import { expect } from 'chai' | ||
// import { describe, test } from 'mocha' | ||
// import { OrmaSchema } from '../introspector/introspector' | ||
// import { validator } from './validate_query_manual' | ||
// const schema: OrmaSchema = { | ||
// grand_parent: { | ||
// id: {}, | ||
// grand_parent_column: {}, | ||
// }, | ||
// parent: { | ||
// id: {}, | ||
// parent_column: {}, | ||
// grand_parent_id: { | ||
// references: { | ||
// grand_parent: { | ||
// id: {}, | ||
// }, | ||
// }, | ||
// }, | ||
// }, | ||
// child: { | ||
// id: {}, | ||
// child_column: {}, | ||
// parent_id: { | ||
// references: { | ||
// parent: { | ||
// id: {}, | ||
// }, | ||
// }, | ||
// }, | ||
// }, | ||
// } | ||
// /* | ||
// { | ||
// qty: { | ||
// $sum: 'quantity' | ||
// }, | ||
// inventory_adjustments: { | ||
// variants: { | ||
// sku: true | ||
// } | ||
// }, | ||
// inventory_adjustments: { | ||
// quantity: true | ||
// } | ||
// } | ||
// */ | ||
// describe('validate_query.ts', () => { | ||
// describe('boolean resolver', () => { | ||
// test('validates boolean resolver column names', () => { | ||
// const query = { | ||
// grand_parent: { | ||
// id: true, | ||
// grand_parent_column: true, | ||
// parent: { | ||
// parent_column: true, | ||
// child: { | ||
// id: true, | ||
// child_column_oops: true, | ||
// }, | ||
// }, | ||
// }, | ||
// } | ||
// const errors = validator(query, schema) | ||
// expect(errors.length).to.deep.equal(1) | ||
// expect(errors[0].path).to.deep.equal([ | ||
// 'grand_parent', | ||
// 'parent', | ||
// 'child', | ||
// 'child_column_oops', | ||
// ]) | ||
// }) | ||
// }) | ||
// describe('virtual columns', () => { | ||
// test('validates $field virtual column', () => { | ||
// const query = { | ||
// parent: { | ||
// custom_name: { $field: 'parent_column' }, | ||
// custom_name2: { $field: 'oops' }, | ||
// }, | ||
// } | ||
// const errors = validator(query, schema) | ||
// expect(errors[0].path).to.deep.equal(['parent', 'custom_name2']) | ||
// expect(errors.length).to.deep.equal(1) | ||
// }) | ||
// }) | ||
// describe('subqueries', () => { | ||
// test('validates the from clause', () => { | ||
// const data = { | ||
// parent: { | ||
// good: { | ||
// $from: 'child', | ||
// id: true, | ||
// }, | ||
// bad: { | ||
// $from: 'oops', | ||
// id: true, | ||
// }, | ||
// }, | ||
// } | ||
// const errors = validator(data, schema) | ||
// const from_clause_errors = errors.filter( | ||
// err => | ||
// JSON.stringify(err.path) === | ||
// JSON.stringify(['parent', 'bad', 'id']) | ||
// ) | ||
// expect(from_clause_errors.length).to.equal(1) | ||
// }) | ||
// test('validates subquery connections', () => { | ||
// const data = { | ||
// grand_parent: { | ||
// john: { | ||
// $from: 'parent', | ||
// child: { | ||
// id: true, | ||
// grand_parent: { | ||
// id: true, | ||
// }, | ||
// }, | ||
// }, | ||
// }, | ||
// } | ||
// const errors = validator(data, schema) | ||
// expect(errors.length).to.equal(1) | ||
// expect(errors[0].path).to.deep.equal([ | ||
// 'grand_parent', | ||
// 'john', | ||
// 'child', | ||
// 'grand_parent', | ||
// ]) | ||
// }) | ||
// }) | ||
// describe.skip('clauses', () => { | ||
// test('Requires $eq to have valid field name', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $eq: ['my_id', 5], | ||
// }, | ||
// my_id: { | ||
// $field: 'id', | ||
// }, | ||
// }, | ||
// } | ||
// const errors = validator(data, schema) | ||
// expect(errors.length).to.equal(1) | ||
// expect(errors[0].path).to.deep.equal(['parent', '$where']) | ||
// }) | ||
// test('Lets $having have aliased fields', () => { | ||
// const data = { | ||
// parent: { | ||
// $having: { | ||
// $eq: ['my_id', 5], | ||
// }, | ||
// my_id: { | ||
// $field: 'id', | ||
// }, | ||
// }, | ||
// } | ||
// const errors = validator(data, schema) | ||
// expect(errors.length).to.equal(0) | ||
// }) | ||
// test('Lets operators have functions', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $eq: ['name', { $field: 'id' }], | ||
// }, | ||
// id: 'id', | ||
// }, | ||
// } | ||
// const errors = validator(data, schema) | ||
// expect(errors.length).to.equal(0) | ||
// }) | ||
// test('Lets operators have functions', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $lte: ['name', { $field: 'id' }], | ||
// }, | ||
// id: 'id', | ||
// }, | ||
// } | ||
// const errors = validator(data, schema) | ||
// expect(errors.length).to.equal(0) | ||
// }) | ||
// test('Lets $and', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $and: [ | ||
// { | ||
// $eq: ['id', '5'], | ||
// }, | ||
// ], | ||
// }, | ||
// id: 'id', | ||
// }, | ||
// } | ||
// const errors = validator(data, schema) | ||
// expect(errors.length).to.equal(0) | ||
// }) | ||
// test('Changes scope for subqueries', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $in: [ | ||
// 'id', | ||
// { | ||
// $select: ['parent_id'], | ||
// $from: 'child', | ||
// $where: { | ||
// $eq: ['name', 3], // invalid because 'name' is a field of parent, not child | ||
// }, | ||
// }, | ||
// ], | ||
// }, | ||
// id: 'id', | ||
// }, | ||
// } | ||
// const errors = validator(data, schema) | ||
// expect(errors.length).to.equal(1) | ||
// }) | ||
// test('Requires subqueries to have valid fields', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $in: [ | ||
// 'id', | ||
// { | ||
// $select: ['invalid_field'], | ||
// $from: 'child', | ||
// }, | ||
// ], | ||
// }, | ||
// id: 'id', | ||
// }, | ||
// } | ||
// const errors = validator(data, schema) | ||
// expect(errors.length).to.equal(1) | ||
// }) | ||
// test('Requires subqueries to have valid fields', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $in: [ | ||
// 'id', | ||
// { | ||
// $select: ['name'], | ||
// $from: 'fake_table', | ||
// }, | ||
// ], | ||
// }, | ||
// id: 'id', | ||
// }, | ||
// } | ||
// const errors = validator(data, schema) | ||
// expect(errors.length).to.equal(1) | ||
// }) | ||
// }) | ||
// }) |
{ | ||
"name": "orma", | ||
"version": "1.0.77", | ||
"version": "1.0.78", | ||
"description": "A declarative relational syncronous orm", | ||
@@ -5,0 +5,0 @@ "main": "build/index.js", |
@@ -166,6 +166,26 @@ /** | ||
to_entity: string, | ||
orma_schema: OrmaSchema | ||
orma_schema: OrmaSchema, | ||
foreign_key_override: string[] = undefined | ||
) => { | ||
const edges = get_direct_edges(from_entity, to_entity, orma_schema) | ||
const parent_edges = get_parent_edges(from_entity, orma_schema).filter( | ||
el => el.to_entity === to_entity | ||
) | ||
const child_edges = get_child_edges(from_entity, orma_schema).filter( | ||
el => el.to_entity === to_entity | ||
) | ||
const filtered_parent_edges = foreign_key_override | ||
? parent_edges.filter( | ||
edge => edge.from_field === foreign_key_override[0] | ||
) | ||
: parent_edges | ||
const filtered_child_edges = foreign_key_override | ||
? child_edges.filter( | ||
edge => edge.to_field === foreign_key_override[0] | ||
) | ||
: child_edges | ||
const edges = [...filtered_parent_edges, ...filtered_child_edges] | ||
if (edges.length !== 1) { | ||
@@ -172,0 +192,0 @@ throw Error( |
@@ -21,2 +21,29 @@ import { describe, test } from 'mocha' | ||
}, | ||
payments: { | ||
id: {}, | ||
from_vendor_id: { | ||
references: { | ||
vendors: { | ||
id: {}, | ||
}, | ||
}, | ||
}, | ||
to_vendor_id: { | ||
references: { | ||
vendors: { | ||
id: {}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
receipts: { | ||
id: {}, | ||
payment_id: { | ||
references: { | ||
payments: { | ||
id: {}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
images: { | ||
@@ -31,3 +58,3 @@ id: {}, | ||
}, | ||
}, //TODO: make a table connected with 2 foreign keys | ||
}, | ||
image_urls: { | ||
@@ -266,7 +293,8 @@ image_id: { | ||
const query = { | ||
products: { | ||
images: { | ||
$where: undefined, | ||
$having: undefined, | ||
image_urls: {}, | ||
vendors: { | ||
payments: { | ||
$foreign_key: ['from_vendor_id'], | ||
receipts: { | ||
id: true | ||
}, | ||
}, | ||
@@ -277,8 +305,7 @@ }, | ||
const previous_results = [ | ||
[['products'], [{ id: 1 }, { id: 2 }]], | ||
// [['products', 'images'], [{ id: 3 }]], | ||
[['vendors'], [{ id: 1 }, { id: 2 }]], | ||
] | ||
apply_nesting_macro( | ||
query, | ||
['products', 'images', 'image_urls'], | ||
['vendors', 'payments', 'receipts'], | ||
previous_results, | ||
@@ -289,15 +316,15 @@ orma_schema | ||
const goal = { | ||
products: { | ||
images: { | ||
$where: undefined, | ||
$having: undefined, | ||
image_urls: { | ||
vendors: { | ||
payments: { | ||
$foreign_key: ['from_vendor_id'], | ||
receipts: { | ||
id: true, | ||
$where: { | ||
$in: [ | ||
'image_id', | ||
'payment_id', | ||
{ | ||
$select: ['id'], | ||
$from: 'images', | ||
$from: 'payments', | ||
$where: { | ||
$in: ['product_id', [1, 2]], | ||
$in: ['from_vendor_id', [1, 2]], | ||
}, | ||
@@ -304,0 +331,0 @@ }, |
@@ -1,7 +0,11 @@ | ||
import { deep_get } from '../../helpers/helpers' | ||
import { get_direct_edge } from '../../helpers/schema_helpers' | ||
import { deep_get, last } from '../../helpers/helpers' | ||
import { | ||
Edge, | ||
get_direct_edge, | ||
reverse_edge, | ||
} from '../../helpers/schema_helpers' | ||
import { OrmaSchema } from '../../introspector/introspector' | ||
import { get_real_entity_name } from '../query' | ||
import { combine_wheres } from '../query_helpers' | ||
import { process_any_clause } from './any_path_macro' | ||
import { edge_path_to_where_ins, process_any_clause } from './any_path_macro' | ||
@@ -55,4 +59,4 @@ /** | ||
if (ancestor_result === undefined || ancestor_result[1].length === 0) { | ||
// this case where there are no ancestor results can happen if, for example, this is a nested lower entitiy but | ||
// nothing was returned from the higher entitiy. In this case, we want nothing of this entity to be queried | ||
// this case where there are no ancestor results can happen if, for example, this is a nested lower entitiy but | ||
// nothing was returned from the higher entitiy. In this case, we want nothing of this entity to be queried | ||
// so we use an impossible where clause that returns nothing. | ||
@@ -73,4 +77,4 @@ return { | ||
ancestor_rows, | ||
ancestor_path, | ||
ancestor_to_entity_path, | ||
subquery_path, | ||
nesting_ancestor_index, | ||
query, | ||
@@ -113,22 +117,18 @@ orma_schema | ||
ancestor_rows: Record<string, unknown>[], | ||
ancestor_path: string[], | ||
ancestor_to_entity_path: string[], | ||
entity_path: string[], | ||
ancestor_index: number, | ||
query, | ||
orma_schema: OrmaSchema | ||
) => { | ||
const ancestor_name = get_real_entity_name(ancestor_path, query) | ||
const under_ancestor_path = [...ancestor_path, ancestor_to_entity_path[0]] | ||
const entity_under_ancestor = get_real_entity_name( | ||
under_ancestor_path, | ||
query | ||
) | ||
const edge_under_ancestor = get_direct_edge( | ||
entity_under_ancestor, | ||
ancestor_name, | ||
const ancestor_to_entity_edge_path = get_query_edge_path( | ||
query, | ||
entity_path, | ||
ancestor_index, | ||
orma_schema | ||
) | ||
const edge_under_ancestor = ancestor_to_entity_edge_path[0] | ||
if (ancestor_rows === undefined || ancestor_rows.length === 0) { | ||
const ancestor_name = ancestor_to_entity_edge_path[0].from_entity | ||
throw Error(`No ancestor rows provided for ${ancestor_name}`) | ||
@@ -138,26 +138,19 @@ } | ||
const ancestor_foreign_key_values = ancestor_rows.map( | ||
row => row[edge_under_ancestor.to_field] | ||
row => row[edge_under_ancestor.from_field] | ||
) | ||
const entity_to_ancestor_path = ancestor_to_entity_path.slice().reverse() | ||
const any_path = entity_to_ancestor_path.slice( | ||
1, | ||
entity_to_ancestor_path.length | ||
) | ||
const entity_name = entity_to_ancestor_path[0] | ||
const ancestor_query = process_any_clause( | ||
// reverse the path since we are making the where clause in the entity and want to search based on ancestor | ||
const entity_to_ancestor_edge_path = ancestor_to_entity_edge_path | ||
// exclude the entity closest to the ancestor, since this entity is already accounted for in the final $in clause | ||
.slice(1, Infinity) | ||
// to reverse the path, we have to reverse the order of the edges but also reverse each | ||
// individual edge | ||
.reverse() | ||
.map(edge => reverse_edge(edge)) | ||
const ancestor_query = edge_path_to_where_ins( | ||
entity_to_ancestor_edge_path, | ||
'$where', | ||
{ | ||
$any_path: [ | ||
any_path, | ||
{ | ||
$in: [ | ||
edge_under_ancestor.from_field, | ||
ancestor_foreign_key_values, | ||
], | ||
}, | ||
], | ||
}, | ||
entity_name, | ||
'$where', | ||
orma_schema | ||
$in: [edge_under_ancestor.to_field, ancestor_foreign_key_values], | ||
} | ||
) | ||
@@ -167,1 +160,35 @@ | ||
} | ||
const get_query_edge_path = ( | ||
query: any, | ||
path_to_last_subquery: string[], | ||
start_path_index: number, | ||
orma_schema: OrmaSchema | ||
) => { | ||
let edge_path: Edge[] = [] | ||
// dont run the for loop on the last element, since each for loop iteration makes an edge to the | ||
for (let i = start_path_index; i < path_to_last_subquery.length - 1; i++) { | ||
const subquery_path = path_to_last_subquery.slice(0, i + 1) | ||
const subquery = deep_get(subquery_path, query) | ||
const subquery_entity = get_real_entity_name( | ||
path_to_last_subquery[i], | ||
subquery | ||
) | ||
const next_subquery = subquery[path_to_last_subquery[i + 1]] | ||
const next_subquery_entity = get_real_entity_name( | ||
path_to_last_subquery[i + 1], | ||
next_subquery | ||
) | ||
const edge = get_direct_edge( | ||
subquery_entity, | ||
next_subquery_entity, | ||
orma_schema, | ||
next_subquery.$foreign_key | ||
) | ||
edge_path.push(edge) | ||
} | ||
return edge_path | ||
} |
import { is_simple_object, last } from '../../helpers/helpers' | ||
import { | ||
get_direct_edge, | ||
get_direct_edges, | ||
is_reserved_keyword, | ||
@@ -28,2 +29,3 @@ } from '../../helpers/schema_helpers' | ||
const new_select_names = new_select.map(el => | ||
// @ts-ignore | ||
el?.$as ? el.$as[1] : el | ||
@@ -64,3 +66,3 @@ ) | ||
const lower_subquery_entity = lower_subquery.$from ?? key | ||
const edge_to_lower_table = get_direct_edge( | ||
const edges_to_lower_table = get_direct_edges( | ||
entity_name, | ||
@@ -71,3 +73,3 @@ lower_subquery_entity, | ||
return edge_to_lower_table.from_field | ||
return edges_to_lower_table.map(el => el.from_field) | ||
} | ||
@@ -80,3 +82,3 @@ | ||
const higher_entity = subquery_path[subquery_path.length - 2] | ||
const edge_to_higher_entity = get_direct_edge( | ||
const edges_to_higher_entity = get_direct_edges( | ||
entity_name, | ||
@@ -86,3 +88,3 @@ higher_entity, | ||
) | ||
$select.push(edge_to_higher_entity.from_field) | ||
$select.push(...edges_to_higher_entity.map(el => el.from_field)) | ||
} | ||
@@ -89,0 +91,0 @@ |
@@ -113,9 +113,9 @@ import { orma_escape } from '../../helpers/escape' | ||
// where clauses for | ||
let subquery_locations: { value; path }[] = [] | ||
let where_clause_locations: { value; path }[] = [] | ||
query_for_each(query, (subquery, path) => { | ||
let subquery_locations: { subquery; subquery_path }[] = [] | ||
let where_clause_locations: { where_clause; where_clause_path }[] = [] | ||
query_for_each(query, (subquery, subquery_path) => { | ||
if (subquery.$where) { | ||
deep_for_each(subquery.$where, (value, path) => { | ||
if (value?.$from) { | ||
where_clause_locations.push({ value, path }) | ||
deep_for_each(subquery.$where, (where_clause, where_clause_path) => { | ||
if (where_clause?.$from) { | ||
where_clause_locations.push({ where_clause, where_clause_path }) | ||
} | ||
@@ -125,12 +125,12 @@ }) | ||
subquery_locations.push({ value: subquery, path }) | ||
subquery_locations.push({ subquery, subquery_path }) | ||
}) | ||
// generate where clauses for all the paths that we found | ||
where_clause_locations.forEach(({ value, path }) => { | ||
const entity_name = value.$from | ||
where_clause_locations.forEach(({ where_clause, where_clause_path }) => { | ||
const entity_name = where_clause.$from | ||
apply_where_connected_to_subquery( | ||
connection_edges, | ||
query.$where_connected, | ||
value, | ||
where_clause, | ||
entity_name, | ||
@@ -141,9 +141,9 @@ undefined | ||
subquery_locations.forEach(({ value, path }) => { | ||
const entity_name = get_real_entity_name(path, value) | ||
const higher_entity = get_real_higher_entity_name(path, value) | ||
subquery_locations.forEach(({ subquery, subquery_path }) => { | ||
const entity_name = get_real_entity_name(last(subquery_path), subquery) | ||
const higher_entity = get_real_higher_entity_name(subquery_path, subquery) | ||
apply_where_connected_to_subquery( | ||
connection_edges, | ||
query.$where_connected, | ||
value, | ||
subquery, | ||
entity_name, | ||
@@ -150,0 +150,0 @@ higher_entity |
@@ -22,3 +22,6 @@ import { error_type } from '../helpers/error_handling' | ||
// This function will default to the from clause | ||
export const get_real_higher_entity_name = (path: (string | number)[], query) => { | ||
export const get_real_higher_entity_name = ( | ||
path: (string | number)[], | ||
query | ||
) => { | ||
if (path.length < 2) return null | ||
@@ -33,4 +36,7 @@ | ||
// This function will default to the from clause | ||
export const get_real_entity_name = (path: (string | number)[], query) => { | ||
return deep_get([...path, '$from'], query, null) || last(path) | ||
export const get_real_entity_name = ( | ||
last_path_item: string, | ||
subquery: Record<string, any> | ||
) => { | ||
return subquery.$from ?? last_path_item | ||
} | ||
@@ -109,5 +115,16 @@ | ||
} | ||
const entity = get_real_entity_name(path, query) | ||
const higher_entity = get_real_entity_name(path.slice(0, -1), query) | ||
const edge = get_direct_edge(higher_entity, entity, orma_schema) | ||
const higher_entity_path = path.slice(0, -1) | ||
const higher_entity = deep_get(higher_entity_path, query) | ||
const entity = higher_entity[last(path)] | ||
const entity_name = get_real_entity_name(last(path), entity) | ||
const higher_entity_name = get_real_entity_name( | ||
last(higher_entity_path), | ||
higher_entity | ||
) | ||
const edge = get_direct_edge( | ||
higher_entity_name, | ||
entity_name, | ||
orma_schema, | ||
entity.$foreign_key | ||
) | ||
return [edge.from_field, edge.to_field] | ||
@@ -114,0 +131,0 @@ }) |
@@ -1,293 +0,293 @@ | ||
import { expect } from 'chai' | ||
import { describe, test } from 'mocha' | ||
import { OrmaSchema } from '../introspector/introspector' | ||
import { validator } from './validate_query_manual' | ||
// import { expect } from 'chai' | ||
// import { describe, test } from 'mocha' | ||
// import { OrmaSchema } from '../introspector/introspector' | ||
// import { validator } from './validate_query_manual' | ||
const schema: OrmaSchema = { | ||
grand_parent: { | ||
id: {}, | ||
grand_parent_column: {}, | ||
}, | ||
parent: { | ||
id: {}, | ||
parent_column: {}, | ||
grand_parent_id: { | ||
references: { | ||
grand_parent: { | ||
id: {}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
child: { | ||
id: {}, | ||
child_column: {}, | ||
parent_id: { | ||
references: { | ||
parent: { | ||
id: {}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
// const schema: OrmaSchema = { | ||
// grand_parent: { | ||
// id: {}, | ||
// grand_parent_column: {}, | ||
// }, | ||
// parent: { | ||
// id: {}, | ||
// parent_column: {}, | ||
// grand_parent_id: { | ||
// references: { | ||
// grand_parent: { | ||
// id: {}, | ||
// }, | ||
// }, | ||
// }, | ||
// }, | ||
// child: { | ||
// id: {}, | ||
// child_column: {}, | ||
// parent_id: { | ||
// references: { | ||
// parent: { | ||
// id: {}, | ||
// }, | ||
// }, | ||
// }, | ||
// }, | ||
// } | ||
/* | ||
// /* | ||
{ | ||
qty: { | ||
$sum: 'quantity' | ||
}, | ||
inventory_adjustments: { | ||
variants: { | ||
sku: true | ||
} | ||
}, | ||
inventory_adjustments: { | ||
quantity: true | ||
} | ||
} | ||
// { | ||
// qty: { | ||
// $sum: 'quantity' | ||
// }, | ||
// inventory_adjustments: { | ||
// variants: { | ||
// sku: true | ||
// } | ||
// }, | ||
// inventory_adjustments: { | ||
// quantity: true | ||
// } | ||
// } | ||
*/ | ||
// */ | ||
describe('validate_query.ts', () => { | ||
describe('boolean resolver', () => { | ||
test('validates boolean resolver column names', () => { | ||
const query = { | ||
grand_parent: { | ||
id: true, | ||
grand_parent_column: true, | ||
parent: { | ||
parent_column: true, | ||
child: { | ||
id: true, | ||
child_column_oops: true, | ||
}, | ||
}, | ||
}, | ||
} | ||
// describe('validate_query.ts', () => { | ||
// describe('boolean resolver', () => { | ||
// test('validates boolean resolver column names', () => { | ||
// const query = { | ||
// grand_parent: { | ||
// id: true, | ||
// grand_parent_column: true, | ||
// parent: { | ||
// parent_column: true, | ||
// child: { | ||
// id: true, | ||
// child_column_oops: true, | ||
// }, | ||
// }, | ||
// }, | ||
// } | ||
const errors = validator(query, schema) | ||
// const errors = validator(query, schema) | ||
expect(errors.length).to.deep.equal(1) | ||
expect(errors[0].path).to.deep.equal([ | ||
'grand_parent', | ||
'parent', | ||
'child', | ||
'child_column_oops', | ||
]) | ||
}) | ||
}) | ||
// expect(errors.length).to.deep.equal(1) | ||
// expect(errors[0].path).to.deep.equal([ | ||
// 'grand_parent', | ||
// 'parent', | ||
// 'child', | ||
// 'child_column_oops', | ||
// ]) | ||
// }) | ||
// }) | ||
describe('virtual columns', () => { | ||
test('validates $field virtual column', () => { | ||
const query = { | ||
parent: { | ||
custom_name: { $field: 'parent_column' }, | ||
custom_name2: { $field: 'oops' }, | ||
}, | ||
} | ||
// describe('virtual columns', () => { | ||
// test('validates $field virtual column', () => { | ||
// const query = { | ||
// parent: { | ||
// custom_name: { $field: 'parent_column' }, | ||
// custom_name2: { $field: 'oops' }, | ||
// }, | ||
// } | ||
const errors = validator(query, schema) | ||
// const errors = validator(query, schema) | ||
expect(errors[0].path).to.deep.equal(['parent', 'custom_name2']) | ||
expect(errors.length).to.deep.equal(1) | ||
}) | ||
}) | ||
// expect(errors[0].path).to.deep.equal(['parent', 'custom_name2']) | ||
// expect(errors.length).to.deep.equal(1) | ||
// }) | ||
// }) | ||
describe('subqueries', () => { | ||
test('validates the from clause', () => { | ||
const data = { | ||
parent: { | ||
good: { | ||
$from: 'child', | ||
id: true, | ||
}, | ||
bad: { | ||
$from: 'oops', | ||
id: true, | ||
}, | ||
}, | ||
} | ||
// describe('subqueries', () => { | ||
// test('validates the from clause', () => { | ||
// const data = { | ||
// parent: { | ||
// good: { | ||
// $from: 'child', | ||
// id: true, | ||
// }, | ||
// bad: { | ||
// $from: 'oops', | ||
// id: true, | ||
// }, | ||
// }, | ||
// } | ||
const errors = validator(data, schema) | ||
// const errors = validator(data, schema) | ||
const from_clause_errors = errors.filter( | ||
err => | ||
JSON.stringify(err.path) === | ||
JSON.stringify(['parent', 'bad', 'id']) | ||
) | ||
expect(from_clause_errors.length).to.equal(1) | ||
}) | ||
test('validates subquery connections', () => { | ||
const data = { | ||
grand_parent: { | ||
john: { | ||
$from: 'parent', | ||
child: { | ||
id: true, | ||
grand_parent: { | ||
id: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
// const from_clause_errors = errors.filter( | ||
// err => | ||
// JSON.stringify(err.path) === | ||
// JSON.stringify(['parent', 'bad', 'id']) | ||
// ) | ||
// expect(from_clause_errors.length).to.equal(1) | ||
// }) | ||
// test('validates subquery connections', () => { | ||
// const data = { | ||
// grand_parent: { | ||
// john: { | ||
// $from: 'parent', | ||
// child: { | ||
// id: true, | ||
// grand_parent: { | ||
// id: true, | ||
// }, | ||
// }, | ||
// }, | ||
// }, | ||
// } | ||
const errors = validator(data, schema) | ||
// const errors = validator(data, schema) | ||
expect(errors.length).to.equal(1) | ||
expect(errors[0].path).to.deep.equal([ | ||
'grand_parent', | ||
'john', | ||
'child', | ||
'grand_parent', | ||
]) | ||
}) | ||
}) | ||
// expect(errors.length).to.equal(1) | ||
// expect(errors[0].path).to.deep.equal([ | ||
// 'grand_parent', | ||
// 'john', | ||
// 'child', | ||
// 'grand_parent', | ||
// ]) | ||
// }) | ||
// }) | ||
describe.skip('clauses', () => { | ||
test('Requires $eq to have valid field name', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$eq: ['my_id', 5], | ||
}, | ||
my_id: { | ||
$field: 'id', | ||
}, | ||
}, | ||
} | ||
// describe.skip('clauses', () => { | ||
// test('Requires $eq to have valid field name', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $eq: ['my_id', 5], | ||
// }, | ||
// my_id: { | ||
// $field: 'id', | ||
// }, | ||
// }, | ||
// } | ||
const errors = validator(data, schema) | ||
// const errors = validator(data, schema) | ||
expect(errors.length).to.equal(1) | ||
expect(errors[0].path).to.deep.equal(['parent', '$where']) | ||
}) | ||
test('Lets $having have aliased fields', () => { | ||
const data = { | ||
parent: { | ||
$having: { | ||
$eq: ['my_id', 5], | ||
}, | ||
my_id: { | ||
$field: 'id', | ||
}, | ||
}, | ||
} | ||
// expect(errors.length).to.equal(1) | ||
// expect(errors[0].path).to.deep.equal(['parent', '$where']) | ||
// }) | ||
// test('Lets $having have aliased fields', () => { | ||
// const data = { | ||
// parent: { | ||
// $having: { | ||
// $eq: ['my_id', 5], | ||
// }, | ||
// my_id: { | ||
// $field: 'id', | ||
// }, | ||
// }, | ||
// } | ||
const errors = validator(data, schema) | ||
// const errors = validator(data, schema) | ||
expect(errors.length).to.equal(0) | ||
}) | ||
test('Lets operators have functions', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$eq: ['name', { $field: 'id' }], | ||
}, | ||
id: 'id', | ||
}, | ||
} | ||
// expect(errors.length).to.equal(0) | ||
// }) | ||
// test('Lets operators have functions', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $eq: ['name', { $field: 'id' }], | ||
// }, | ||
// id: 'id', | ||
// }, | ||
// } | ||
const errors = validator(data, schema) | ||
// const errors = validator(data, schema) | ||
expect(errors.length).to.equal(0) | ||
}) | ||
test('Lets operators have functions', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$lte: ['name', { $field: 'id' }], | ||
}, | ||
id: 'id', | ||
}, | ||
} | ||
// expect(errors.length).to.equal(0) | ||
// }) | ||
// test('Lets operators have functions', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $lte: ['name', { $field: 'id' }], | ||
// }, | ||
// id: 'id', | ||
// }, | ||
// } | ||
const errors = validator(data, schema) | ||
// const errors = validator(data, schema) | ||
expect(errors.length).to.equal(0) | ||
}) | ||
test('Lets $and', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$and: [ | ||
{ | ||
$eq: ['id', '5'], | ||
}, | ||
], | ||
}, | ||
id: 'id', | ||
}, | ||
} | ||
// expect(errors.length).to.equal(0) | ||
// }) | ||
// test('Lets $and', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $and: [ | ||
// { | ||
// $eq: ['id', '5'], | ||
// }, | ||
// ], | ||
// }, | ||
// id: 'id', | ||
// }, | ||
// } | ||
const errors = validator(data, schema) | ||
// const errors = validator(data, schema) | ||
expect(errors.length).to.equal(0) | ||
}) | ||
test('Changes scope for subqueries', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$in: [ | ||
'id', | ||
{ | ||
$select: ['parent_id'], | ||
$from: 'child', | ||
$where: { | ||
$eq: ['name', 3], // invalid because 'name' is a field of parent, not child | ||
}, | ||
}, | ||
], | ||
}, | ||
id: 'id', | ||
}, | ||
} | ||
// expect(errors.length).to.equal(0) | ||
// }) | ||
// test('Changes scope for subqueries', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $in: [ | ||
// 'id', | ||
// { | ||
// $select: ['parent_id'], | ||
// $from: 'child', | ||
// $where: { | ||
// $eq: ['name', 3], // invalid because 'name' is a field of parent, not child | ||
// }, | ||
// }, | ||
// ], | ||
// }, | ||
// id: 'id', | ||
// }, | ||
// } | ||
const errors = validator(data, schema) | ||
// const errors = validator(data, schema) | ||
expect(errors.length).to.equal(1) | ||
}) | ||
test('Requires subqueries to have valid fields', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$in: [ | ||
'id', | ||
{ | ||
$select: ['invalid_field'], | ||
$from: 'child', | ||
}, | ||
], | ||
}, | ||
id: 'id', | ||
}, | ||
} | ||
// expect(errors.length).to.equal(1) | ||
// }) | ||
// test('Requires subqueries to have valid fields', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $in: [ | ||
// 'id', | ||
// { | ||
// $select: ['invalid_field'], | ||
// $from: 'child', | ||
// }, | ||
// ], | ||
// }, | ||
// id: 'id', | ||
// }, | ||
// } | ||
const errors = validator(data, schema) | ||
// const errors = validator(data, schema) | ||
expect(errors.length).to.equal(1) | ||
}) | ||
test('Requires subqueries to have valid fields', () => { | ||
const data = { | ||
parent: { | ||
$where: { | ||
$in: [ | ||
'id', | ||
{ | ||
$select: ['name'], | ||
$from: 'fake_table', | ||
}, | ||
], | ||
}, | ||
id: 'id', | ||
}, | ||
} | ||
// expect(errors.length).to.equal(1) | ||
// }) | ||
// test('Requires subqueries to have valid fields', () => { | ||
// const data = { | ||
// parent: { | ||
// $where: { | ||
// $in: [ | ||
// 'id', | ||
// { | ||
// $select: ['name'], | ||
// $from: 'fake_table', | ||
// }, | ||
// ], | ||
// }, | ||
// id: 'id', | ||
// }, | ||
// } | ||
const errors = validator(data, schema) | ||
// const errors = validator(data, schema) | ||
expect(errors.length).to.equal(1) | ||
}) | ||
}) | ||
}) | ||
// expect(errors.length).to.equal(1) | ||
// }) | ||
// }) | ||
// }) |
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
1025862
24818