Comparing version 1.0.19 to 1.0.22
@@ -7,3 +7,3 @@ export interface error_type { | ||
additional_info?: Record<string, any>; | ||
stack_trace: any; | ||
stack_trace?: any; | ||
} |
declare type type_string = 'Object' | 'Number' | 'Boolean' | 'String' | 'Null' | 'Array' | 'RegExp' | 'Function' | 'Undefined'; | ||
export declare const type: (value: any) => type_string; | ||
export declare const drop: (num: any, arr: any) => any; | ||
export declare const drop: (num: number, arr: any[]) => any[]; | ||
export declare const last: <T>(array: T[]) => T; | ||
@@ -5,0 +5,0 @@ export declare const deep_set: (path_array: (string | number)[], value: any, obj: any) => void; |
@@ -164,2 +164,3 @@ "use strict"; | ||
var is_array = typeof item === 'object' && Array.isArray(item); | ||
var is_primitive = !is_object && !is_array; | ||
if (is_object) { | ||
@@ -177,2 +178,5 @@ processor(item, current_path); | ||
} | ||
if (is_primitive) { | ||
processor(item, current_path); | ||
} | ||
}; | ||
@@ -179,0 +183,0 @@ exports.deep_for_each = deep_for_each; |
@@ -5,4 +5,4 @@ /** | ||
*/ | ||
import { orma_schema } from '../introspector/introspector'; | ||
export interface edge { | ||
import { orma_field_schema, orma_schema } from '../introspector/introspector'; | ||
export declare type edge = { | ||
from_entity: string; | ||
@@ -12,3 +12,3 @@ from_field: string; | ||
to_field: string; | ||
} | ||
}; | ||
/** | ||
@@ -63,1 +63,2 @@ * @returns a list of entities specified in the schema | ||
export declare const get_unique_fields: (entity_name: string, orma_schema: orma_schema) => string[]; | ||
export declare const field_exists: (entity: string, field: string | number, schema: orma_schema) => string | orma_field_schema; |
@@ -39,3 +39,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.get_unique_fields = exports.get_primary_keys = exports.is_parent_entity = exports.get_edge_path = exports.get_direct_edge = exports.get_direct_edges = exports.is_reserved_keyword = exports.get_all_edges = exports.get_child_edges = exports.reverse_edge = exports.get_parent_edges = exports.get_field_names = exports.get_entity_names = void 0; | ||
exports.field_exists = exports.get_unique_fields = exports.get_primary_keys = exports.is_parent_entity = exports.get_edge_path = exports.get_direct_edge = exports.get_direct_edges = exports.is_reserved_keyword = exports.get_all_edges = exports.get_child_edges = exports.reverse_edge = exports.get_parent_edges = exports.get_field_names = exports.get_entity_names = void 0; | ||
/** | ||
@@ -252,1 +252,6 @@ * @returns a list of entities specified in the schema | ||
exports.get_unique_fields = get_unique_fields; | ||
var field_exists = function (entity, field, schema) { | ||
var _a; | ||
return (_a = schema[entity]) === null || _a === void 0 ? void 0 : _a[field]; | ||
}; | ||
exports.field_exists = field_exists; |
/** | ||
* These functions are used to introspect the schema of a mysql database, and from it create a JSON schema compatible with orma. | ||
* @module | ||
*/ | ||
*/ | ||
export interface mysql_table { | ||
@@ -59,3 +59,3 @@ table_name: string; | ||
*/ | ||
export declare const get_introspect_sqls: (database_name: any) => string[]; | ||
export declare const get_introspect_sqls: (database_name: string) => string[]; | ||
/** | ||
@@ -118,2 +118,3 @@ * Takes the results of running the queries from {@link get_introspect_sqls `get_introspect_sqls`} and makes a JSON schema for orma. | ||
export declare const generate_field_schema: (mysql_column: mysql_column) => orma_field_schema; | ||
export declare const introspector: (db: string, fn: (s: string[]) => Promise<any[]>) => Promise<orma_schema>; | ||
export {}; |
@@ -5,3 +5,39 @@ "use strict"; | ||
* @module | ||
*/ | ||
*/ | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __values = (this && this.__values) || function(o) { | ||
@@ -18,4 +54,20 @@ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
}; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.generate_field_schema = exports.generate_database_schema = exports.get_introspect_sqls = void 0; | ||
exports.introspector = exports.generate_field_schema = exports.generate_database_schema = exports.get_introspect_sqls = void 0; | ||
var helpers_1 = require("../helpers/helpers"); | ||
@@ -66,3 +118,3 @@ /** | ||
database_schema[mysql_table.table_name] = { | ||
$comment: mysql_table.table_comment, | ||
$comment: mysql_table.table_comment | ||
}; | ||
@@ -96,3 +148,9 @@ } | ||
var table_name = mysql_foreign_key.table_name, column_name = mysql_foreign_key.column_name, referenced_table_name = mysql_foreign_key.referenced_table_name, referenced_column_name = mysql_foreign_key.referenced_column_name, constraint_name = mysql_foreign_key.constraint_name; | ||
var reference_path = [table_name, column_name, 'references', referenced_table_name, referenced_column_name]; | ||
var reference_path = [ | ||
table_name, | ||
column_name, | ||
'references', | ||
referenced_table_name, | ||
referenced_column_name | ||
]; | ||
helpers_1.deep_set(reference_path, {}, database_schema); | ||
@@ -112,31 +170,31 @@ } | ||
var mysql_to_simple_types = { | ||
bigint: "number", | ||
binary: "string", | ||
bit: "not_supported", | ||
blob: "not_supported", | ||
bool: "boolean", | ||
boolean: "boolean", | ||
char: "string", | ||
date: "data", | ||
datetime: "data", | ||
decimal: "number", | ||
double: "number", | ||
enum: "enum", | ||
float: "number", | ||
int: "number", | ||
longblob: "not_supported", | ||
longtext: "string", | ||
mediumblob: "not_supported", | ||
mediumint: "number", | ||
mediumtext: "string", | ||
set: "not_supported", | ||
smallint: "number", | ||
text: "string", | ||
time: "data", | ||
timestamp: "data", | ||
tinyblob: "not_supported", | ||
tinyint: "boolean", | ||
tinytext: "string", | ||
varbinary: "string", | ||
varchar: "string" | ||
bigint: 'number', | ||
binary: 'string', | ||
bit: 'not_supported', | ||
blob: 'not_supported', | ||
bool: 'boolean', | ||
boolean: 'boolean', | ||
char: 'string', | ||
date: 'data', | ||
datetime: 'data', | ||
decimal: 'number', | ||
double: 'number', | ||
enum: 'enum', | ||
float: 'number', | ||
int: 'number', | ||
longblob: 'not_supported', | ||
longtext: 'string', | ||
mediumblob: 'not_supported', | ||
mediumint: 'number', | ||
mediumtext: 'string', | ||
set: 'not_supported', | ||
smallint: 'number', | ||
text: 'string', | ||
time: 'data', | ||
timestamp: 'data', | ||
tinyblob: 'not_supported', | ||
tinyint: 'boolean', | ||
tinytext: 'string', | ||
varbinary: 'string', | ||
varchar: 'string' | ||
}; | ||
@@ -189,1 +247,26 @@ var generate_field_schema = function (mysql_column) { | ||
exports.generate_field_schema = generate_field_schema; | ||
var introspector = function (db, fn) { return __awaiter(void 0, void 0, void 0, function () { | ||
var sql_strings, _a, mysql_tables, mysql_columns, mysql_foreign_keys, transform_keys_to_lower, orma_schema; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
sql_strings = exports.get_introspect_sqls(db); | ||
return [4 /*yield*/, fn(sql_strings) | ||
// TODO: to be removed when orma lowercase bug fixed | ||
]; | ||
case 1: | ||
_a = __read.apply(void 0, [_b.sent() | ||
// TODO: to be removed when orma lowercase bug fixed | ||
, 3]), mysql_tables = _a[0], mysql_columns = _a[1], mysql_foreign_keys = _a[2]; | ||
transform_keys_to_lower = function (obj) { | ||
return Object.entries(obj).reduce(function (acc, val) { | ||
acc[val[0].toLowerCase()] = val[1]; | ||
return acc; | ||
}, {}); | ||
}; | ||
orma_schema = exports.generate_database_schema(mysql_tables.map(transform_keys_to_lower), mysql_columns.map(transform_keys_to_lower), mysql_foreign_keys.map(transform_keys_to_lower)); | ||
return [2 /*return*/, orma_schema]; | ||
} | ||
}); | ||
}); }; | ||
exports.introspector = introspector; |
@@ -25,4 +25,4 @@ "use strict"; | ||
chai_1.expect(field_schema).to.deep.equal({ | ||
data_type: "number", | ||
default: "auto_increment", | ||
data_type: 'number', | ||
default: 'auto_increment', | ||
indexed: true, | ||
@@ -46,3 +46,3 @@ ordinal_position: 1, | ||
chai_1.expect(field_schema).to.deep.equal({ | ||
data_type: "string", | ||
data_type: 'string', | ||
indexed: true, | ||
@@ -66,3 +66,3 @@ ordinal_position: 2, | ||
chai_1.expect(field_schema).to.deep.equal({ | ||
data_type: "number", | ||
data_type: 'number', | ||
ordinal_position: 3, | ||
@@ -75,10 +75,14 @@ character_count: 4, | ||
mocha_1.test('entity relationships', function () { | ||
var mysql_tables = [{ | ||
var mysql_tables = [ | ||
{ | ||
table_name: 'users', | ||
table_comment: 'table of users' | ||
}, { | ||
}, | ||
{ | ||
table_name: 'posts', | ||
table_comment: 'user posts' | ||
}]; | ||
var mysql_columns = [{ | ||
} | ||
]; | ||
var mysql_columns = [ | ||
{ | ||
table_name: 'users', | ||
@@ -88,3 +92,4 @@ column_name: 'id', | ||
data_type: 'int' | ||
}, { | ||
}, | ||
{ | ||
table_name: 'posts', | ||
@@ -94,4 +99,6 @@ column_name: 'user_id', | ||
data_type: 'int' | ||
}]; | ||
var mysql_foreign_keys = [{ | ||
} | ||
]; | ||
var mysql_foreign_keys = [ | ||
{ | ||
table_name: 'posts', | ||
@@ -102,9 +109,10 @@ column_name: 'user_id', | ||
constraint_name: 'user_post_constraint' | ||
}]; | ||
} | ||
]; | ||
var database_schema = introspector_1.generate_database_schema(mysql_tables, mysql_columns, mysql_foreign_keys); | ||
chai_1.expect(database_schema).to.deep.equal({ | ||
posts: { | ||
$comment: "user posts", | ||
$comment: 'user posts', | ||
user_id: { | ||
data_type: "number", | ||
data_type: 'number', | ||
ordinal_position: 1, | ||
@@ -119,5 +127,5 @@ references: { | ||
users: { | ||
$comment: "table of users", | ||
$comment: 'table of users', | ||
id: { | ||
data_type: "number", | ||
data_type: 'number', | ||
ordinal_position: 1 | ||
@@ -128,2 +136,8 @@ } | ||
}); | ||
mocha_1.test('Should allow UPPERCASE mysql responses', function () { | ||
chai_1.expect(1).to.equal(2); | ||
}); | ||
mocha_1.test('Should date types be called date? or data...', function () { | ||
chai_1.expect(1).to.equal(2); | ||
}); | ||
}); |
@@ -9,2 +9,4 @@ import { orma_schema } from '../introspector/introspector'; | ||
export declare const is_subquery: (subquery: any) => boolean; | ||
export declare const get_real_parent_name: (path: (string | number)[], query: any) => any; | ||
export declare const get_real_entity_name: (path: (string | number)[], query: any) => any; | ||
export declare const get_subquery_sql: (query: any, subquery_path: string[], previous_results: (string[] | Record<string, unknown>[])[][], orma_schema: orma_schema) => string; | ||
@@ -40,3 +42,3 @@ /** | ||
export declare const orma_nester: (results: [string[], Record<string, unknown>[]][], orma_schema: orma_schema) => {}; | ||
export declare const orma_query: (raw_query: any, orma_schema: orma_schema, query_function: (sql_string: string) => Record<string, unknown>[]) => Promise<{}>; | ||
export declare const orma_query: (raw_query: any, orma_schema: any, query_function: (sql_string: string) => Promise<Record<string, unknown>[]>) => Promise<{}>; | ||
export {}; |
@@ -71,3 +71,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.orma_query = exports.orma_nester = exports.convert_any_path_macro = exports.combine_where_clauses = exports.having_to_json_sql = exports.where_to_json_sql = exports.select_to_json_sql = exports.query_to_json_sql = exports.get_subquery_sql = exports.is_subquery = exports.get_query_plan = exports.json_to_sql = void 0; | ||
exports.orma_query = exports.orma_nester = exports.convert_any_path_macro = exports.combine_where_clauses = exports.having_to_json_sql = exports.where_to_json_sql = exports.select_to_json_sql = exports.query_to_json_sql = exports.get_subquery_sql = exports.get_real_entity_name = exports.get_real_parent_name = exports.is_subquery = exports.get_query_plan = exports.json_to_sql = void 0; | ||
var helpers_1 = require("../helpers/helpers"); | ||
@@ -245,2 +245,14 @@ var nester_1 = require("../helpers/nester"); | ||
exports.is_subquery = is_subquery; | ||
// This function will default to the from clause | ||
var get_real_parent_name = function (path, query) { | ||
if (path.length < 2) | ||
return null; | ||
return helpers_1.deep_get(__spreadArray(__spreadArray([], __read(helpers_1.drop(1, path))), ['$from']), query, null) || path[path.length - 2]; | ||
}; | ||
exports.get_real_parent_name = get_real_parent_name; | ||
// This function will default to the from clause | ||
var get_real_entity_name = function (path, query) { | ||
return helpers_1.deep_get(__spreadArray(__spreadArray([], __read(path)), ['$from']), query, null) || helpers_1.last(path); | ||
}; | ||
exports.get_real_entity_name = get_real_entity_name; | ||
var get_subquery_sql = function (query, subquery_path, previous_results, orma_schema) { | ||
@@ -495,2 +507,3 @@ var json_sql = exports.query_to_json_sql(query, subquery_path, previous_results, orma_schema); | ||
exports.orma_nester = orma_nester; | ||
// export const orma_query = async <schema>(raw_query: validate_query<schema>, orma_schema: validate_orma_schema<schema>, query_function: (sql_string: string) => Promise<Record<string, unknown>[]>) => { | ||
var orma_query = function (raw_query, orma_schema, query_function) { return __awaiter(void 0, void 0, void 0, function () { | ||
@@ -550,2 +563,86 @@ var query, query_plan, results, _loop_1, i, output; | ||
exports.orma_query = orma_query; | ||
// ///-------------type-fest--------------- | ||
// type Without<FirstType, SecondType> = { [KeyType in Exclude<keyof FirstType, keyof SecondType>]?: never }; | ||
// type RequireExactlyOne<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> = | ||
// { [Key in KeysType]: ( | ||
// Required<Pick<ObjectType, Key>> & | ||
// Partial<Record<Exclude<KeysType, Key>, never>> | ||
// ) }[KeysType] & _Omit<ObjectType, KeysType>; | ||
// type _Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>; | ||
// type MergeExclusive<FirstType, SecondType> = | ||
// (FirstType | SecondType) extends object ? | ||
// (Without<FirstType, SecondType> & SecondType) | (Without<SecondType, FirstType> & FirstType) : | ||
// FirstType | SecondType; | ||
// type RequireAtLeastOne< | ||
// ObjectType, | ||
// KeysType extends keyof ObjectType = keyof ObjectType | ||
// > = { | ||
// // For each `Key` in `KeysType` make a mapped type: | ||
// [Key in KeysType]-?: Required<Pick<ObjectType, Key>> & // 1. Make `Key`'s type required | ||
// // 2. Make all other keys in `KeysType` optional | ||
// Partial<Pick<ObjectType, Exclude<KeysType, Key>>>; | ||
// }[KeysType] & | ||
// // 3. Add the remaining keys not in `KeysType` | ||
// Except<ObjectType, KeysType>; | ||
// type Except<ObjectType, KeysType extends keyof ObjectType> = Pick<ObjectType, Exclude<keyof ObjectType, KeysType>>; | ||
// ///---------------------------- | ||
// type validate_orma_schema<schema> = { | ||
// [entity in keyof schema]: | ||
// entity_schema<entity, schema> | ||
// } | ||
// type entity_schema<entity extends keyof schema, schema> = | ||
// // keyof schema[entity] extends keyof schema ? | ||
// { $comment?: string } | ||
// & { [field: string]: field_schema<entity, schema> } | ||
// // : never | ||
// type field_schema<parent extends keyof schema, schema> = { | ||
// references?: | ||
// { [entity in keyof schema]?: | ||
// {} | ||
// // boolean | ||
// // {[k in keyof schema[entity]]: boolean} | ||
// // RequireExactlyOne<{[field in keyof schema[entity]]: {}}> | ||
// } //{ products: { id: {} } } | { variants: { id: {} } } | ||
// } | ||
// const test = orma_query({}, { | ||
// products: { id: {} }, | ||
// variants: { | ||
// id: {}, | ||
// product_id: { | ||
// // references: { products: { id: {} } } | ||
// references: { products: {id: {}} } | ||
// } | ||
// }, | ||
// images: { | ||
// id: {}, | ||
// variant_id: { | ||
// references: { variants: { id8: {} }, hi: {} } | ||
// } | ||
// }, | ||
// images2: { | ||
// id: {}, | ||
// variant_id: { | ||
// // @ts-expect-error | ||
// references: { oops: { id: {} } } | ||
// } | ||
// }, | ||
// images3: { | ||
// id: {}, | ||
// variant_id: { | ||
// // @ts-expect-error | ||
// references: { variants: { id: {} }, hi: {}, } | ||
// } | ||
// } | ||
// }, (s) => ([{ a: 'hi' }])) | ||
// type validate_query<schema> = { | ||
// [entity in keyof schema]: boolean | ||
// } | ||
// const test2 = orma_query({ | ||
// variants: true, | ||
// products: true, | ||
// poop: true, | ||
// }, { | ||
// variants: {id: {}}, | ||
// products: {id: {}}, | ||
// }, (s) => Promise.resolve([{}])) | ||
/* | ||
@@ -552,0 +649,0 @@ |
@@ -1,18 +0,2 @@ | ||
import { orma_schema } from "../introspector/introspector"; | ||
interface validation_response { | ||
query: any; | ||
errors: validation_error[]; | ||
} | ||
interface validation_error { | ||
path: (string | number)[]; | ||
message: any; | ||
additional_info?: {}; | ||
recommendation?: string; | ||
} | ||
export declare const validator: (query: any, schema: any) => validation_response; | ||
export declare const validate_function_fields: (query: any, subquery_path: string[], orma_schema: orma_schema) => void; | ||
export declare const validate_where: (query: any, subquery_path: string[], orma_schema: orma_schema) => void; | ||
export declare const validate_group_by: (query: any, subquery_path: string[], orma_schema: orma_schema) => void; | ||
export declare const validate_order_by: (query: any, subquery_path: string[], orma_schema: orma_schema) => void; | ||
export declare const validate_pagination: (query: any, subquery_path: string[], orma_schema: orma_schema) => void; | ||
export {}; | ||
import { error_type } from "../helpers/error_handling"; | ||
export declare const validator: (query: any, schema: any) => error_type[]; |
"use strict"; | ||
/* | ||
query { | ||
meta: { | ||
where | ||
having | ||
from // valid child | ||
limit // number | ||
offset // number | ||
group_by // array of valid field names | ||
order_by: ({ asc: field_name } | { desc: field_name}) [] | ||
using? | ||
} | ||
[keys]: { query object } | true | 'string' | ||
shmu: 'sku' // renamed field | ||
sku: false // not included | ||
sku: true // included | ||
// subquery | ||
variants: { | ||
...fields | ||
} | ||
// renamed subquery | ||
my_variants: { | ||
meta: { | ||
from: 'variants' | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.validator = void 0; | ||
var helpers_1 = require("../helpers/helpers"); | ||
var schema_helpers_1 = require("../helpers/schema_helpers"); | ||
var query_1 = require("./query"); | ||
var validator = function (query, schema) { | ||
var errors = []; | ||
// Walk the query | ||
helpers_1.deep_for_each(query, function (val, path) { | ||
var is_boolean_resolver = val === true; | ||
var is_virtual_column_resolver = typeof val === 'object' && !query_1.is_subquery(val); | ||
var is_subquery_resolver = typeof val === 'object' && query_1.is_subquery(val); | ||
if (is_boolean_resolver) { | ||
var error = validate_field_exists(val, path, schema, query); | ||
if (error) | ||
errors.push(error); | ||
} | ||
} | ||
variants: { | ||
id: true | ||
} | ||
variants: { | ||
$id: {} | ||
} | ||
variants: { | ||
sum: 'id' | ||
} | ||
// function field | ||
total_quantity: { | ||
sum: 'quantity' | ||
} | ||
total_quantity: { | ||
fn: ['sum', 'quantity'] | ||
} | ||
{ | ||
and: [{}, {}, {}] | ||
} | ||
{ | ||
fn: ['and', {}, {}] | ||
} | ||
} | ||
{ | ||
function_name: [arguments] | ||
} | ||
{ | ||
key_in_the_response_object: what_it_is | ||
} | ||
?? way to indicate/validate array subqueries, object subqueries or single-value field subqueries | ||
cant nest things on to a parent with group_by if the nesting field is not included in the group_by | ||
{ | ||
any: ['variants', { query object on variants}] | ||
} | ||
-> | ||
{ | ||
in: { | ||
where: { | ||
in: ... | ||
} | ||
} | ||
} | ||
{ | ||
$any | ||
} | ||
{ | ||
$descends | ||
} | ||
{ | ||
where: { | ||
$and: [{ | ||
$any: | ||
}] | ||
} | ||
} | ||
{ | ||
$path: [['variants', '*', 'vendors'], { | ||
where clause, but its a where clause for vendors | ||
}] | ||
} // tbd based on implementation | ||
{ | ||
products: { | ||
variants: { | ||
select: [] | ||
from: 'variants' | ||
where: { | ||
in: ['product_id', ${ the parent id }] | ||
if (is_virtual_column_resolver) { | ||
var is_renamed_field = '$field' in val; | ||
var is_eq = '$eq' in val; | ||
if (is_renamed_field) { | ||
if (!is_exclusive_key('$field', val)) { | ||
var error = { | ||
message: "$field must be the only key when renaming a field", | ||
original_data: query, | ||
path: path | ||
}; | ||
errors.push(error); | ||
} | ||
var error2 = ensure_field_exists(val, path, query, schema); | ||
if (error2) | ||
errors.push(error2); | ||
} | ||
if (is_eq) { | ||
if (!last_path_equals('$where', path)) { | ||
var error_1 = { | ||
message: "$eq can only be used in $where", | ||
original_data: query, | ||
path: path, | ||
}; | ||
errors.push(error_1); | ||
} | ||
if (!is_exclusive_key('$eq', val)) { | ||
var error_2 = { | ||
message: "$eq can only be used in $where", | ||
original_data: query, | ||
path: path, | ||
}; | ||
errors.push(error_2); | ||
} | ||
var error = ensure_valid_eq(val, path, query, schema); | ||
if (error) { | ||
errors.push(error); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
{ | ||
$and: [{ where clause }] | ||
$or: [{ where clause }] | ||
} | ||
{ | ||
$eq: ['id', 'sku'] | ||
} | ||
{ | ||
$eq: ['id', { sku: true }] | ||
} | ||
{ | ||
$gt | ||
$lt | ||
$gte | ||
$lte | ||
$like: ['id', '%asd'] | ||
} | ||
{ | ||
} | ||
= | ||
*/ | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.validate_pagination = exports.validate_order_by = exports.validate_group_by = exports.validate_where = exports.validate_function_fields = exports.validator = void 0; | ||
var validator = function (query, schema) { | ||
if (is_subquery_resolver) { | ||
var error = validate_edges(path, query, schema); | ||
if (error) | ||
errors.push(error); | ||
} | ||
}); | ||
// check the keys of a query/subquery - including making sure each field has a place to take its data from | ||
@@ -164,29 +68,95 @@ // e.g. products: { sku: true } is invalid but products: { sku: 'title' } is fine | ||
// also function like { $sum: 'quantity' }, so quantity needs to be valid | ||
return; | ||
return errors; | ||
}; | ||
exports.validator = validator; | ||
var validate_function_fields = function (query, subquery_path, orma_schema) { | ||
// recursively check valid sql functions like $sum or $avg | ||
// check function parameters are good (e.g. field names are real field names in $sum: 'quantity') | ||
var ensure_valid_eq = function (val, path, query, schema) { | ||
var args = val['$eq']; | ||
if (!Array.isArray(args) || args.length !== 2) { | ||
var error = { | ||
message: "$eq must be an array of length 2", | ||
original_data: query, | ||
path: path, | ||
}; | ||
return error; | ||
} | ||
// First val must be a valid column name | ||
var first_arg = args[0]; | ||
var parent_entity = query_1.get_real_parent_name(path, query); | ||
if (typeof first_arg !== 'string' || !schema[parent_entity][first_arg]) { | ||
var error = { | ||
message: "First argument to $eq must be string and be a valid column name from " + parent_entity, | ||
path: path, | ||
original_data: query | ||
}; | ||
return error; | ||
} | ||
return val['$eq']; | ||
}; | ||
exports.validate_function_fields = validate_function_fields; | ||
var validate_where = function (query, subquery_path, orma_schema) { | ||
// allowed keys (but only one), e.g. $eq, $and, $any | ||
// correct parameters ($and gets infinite where clauses as parameters, $eq gets first column name then primitive value or { $field: field_name }) | ||
// subqueries change | ||
// also $having is the same | ||
var is_exclusive_key = function (key, obj) { | ||
return Object.keys(obj).length == 1 && Object.keys(obj)[0] === key; | ||
}; | ||
exports.validate_where = validate_where; | ||
var validate_group_by = function (query, subquery_path, orma_schema) { | ||
// valid keys | ||
var last_path_equals = function (desired_key, path) { | ||
var is_valid = helpers_1.last(path) === desired_key; | ||
return is_valid; | ||
}; | ||
exports.validate_group_by = validate_group_by; | ||
var validate_order_by = function (query, subquery_path, orma_schema) { | ||
// valid keys | ||
var validate_edges = function (path, query, schema) { | ||
if (path.length > 1) { | ||
var parent_name = query_1.get_real_parent_name(path, query); | ||
var entity_name = query_1.get_real_entity_name(path, query); | ||
var direct_edges = schema_helpers_1.get_direct_edges(parent_name, entity_name, schema); | ||
if (direct_edges.length === 0) { | ||
var error = { | ||
message: parent_name + " is not connected to " + entity_name + ".", | ||
path: path, | ||
original_data: query, | ||
}; | ||
return error; | ||
} | ||
} | ||
}; | ||
exports.validate_order_by = validate_order_by; | ||
var validate_pagination = function (query, subquery_path, orma_schema) { | ||
// limit and offset are positive numbers | ||
var ensure_field_exists = function (val, path, query, schema) { | ||
var parent_entity = query_1.get_real_parent_name(path, query); | ||
var original_field = val['$field']; | ||
if (typeof original_field !== 'string' || !schema[parent_entity][original_field]) { | ||
var error = { | ||
message: "$field must be a string which exists in " + parent_entity, | ||
original_data: query, | ||
path: path | ||
}; | ||
return error; | ||
} | ||
}; | ||
exports.validate_pagination = validate_pagination; | ||
var validate_field_exists = function (val, path, schema, query) { | ||
// User is requesting a specific field be in the response | ||
var parent_entity = query_1.get_real_parent_name(path, query); | ||
var requested_field = helpers_1.last(path); | ||
if (!schema_helpers_1.field_exists(parent_entity, requested_field, schema)) { | ||
var error = { | ||
message: "Field " + requested_field + " does not exist on entity " + parent_entity, | ||
path: path, | ||
original_data: query, | ||
}; | ||
return error; | ||
} | ||
return; | ||
}; | ||
// export const validate_function_fields = (query, subquery_path: string[], orma_schema: orma_schema) => { | ||
// // recursively check valid sql functions like $sum or $avg | ||
// // check function parameters are good (e.g. field names are real field names in $sum: 'quantity') | ||
// } | ||
// export const validate_where = (query, subquery_path: string[], orma_schema: orma_schema) => { | ||
// // allowed keys (but only one), e.g. $eq, $and, $any | ||
// // correct parameters ($and gets infinite where clauses as parameters, $eq gets first field name then primitive value or { $field: field_name }) | ||
// // subqueries change | ||
// // also $having is the same | ||
// } | ||
// export const validate_group_by = (query, subquery_path: string[], orma_schema: orma_schema) => { | ||
// // valid keys | ||
// } | ||
// export const validate_order_by = (query, subquery_path: string[], orma_schema: orma_schema) => { | ||
// // valid keys | ||
// } | ||
// export const validate_pagination = (query, subquery_path: string[], orma_schema: orma_schema) => { | ||
// // limit and offset are positive numbers | ||
// } | ||
/* | ||
@@ -193,0 +163,0 @@ |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var chai_1 = require("chai"); | ||
var mocha_1 = require("mocha"); | ||
@@ -8,6 +9,7 @@ var validate_query_1 = require("./validate_query"); | ||
id: {}, | ||
name: {}, | ||
grand_parent_column: {}, | ||
}, | ||
parent: { | ||
id: {}, | ||
parent_column: {}, | ||
grand_parent_id: { | ||
@@ -20,6 +22,6 @@ references: { | ||
}, | ||
name: {} | ||
}, | ||
child: { | ||
id: {}, | ||
child_column: {}, | ||
parent_id: { | ||
@@ -32,3 +34,2 @@ references: { | ||
}, | ||
child_name: {} | ||
} | ||
@@ -53,14 +54,14 @@ }; | ||
*/ | ||
mocha_1.describe.skip('validate_query.ts', function () { | ||
mocha_1.describe('field resolvers', function () { | ||
mocha_1.test('Allows valid keys', function () { | ||
var data = { | ||
mocha_1.describe('validate_query.ts', function () { | ||
mocha_1.describe('boolean resolver', function () { | ||
mocha_1.test('validates boolean resolver column names', function () { | ||
var query = { | ||
grand_parent: { | ||
id: true, | ||
grand_parent_column1: true, | ||
grand_parent_column: true, | ||
parent: { | ||
parent_column1: true, | ||
parent_column: true, | ||
child: { | ||
id: true, | ||
child_column1: true | ||
child_column_oops: true | ||
} | ||
@@ -70,79 +71,61 @@ } | ||
}; | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(0); | ||
var errors = validate_query_1.validator(query, schema); | ||
chai_1.expect(errors.length).to.deep.equal(1); | ||
chai_1.expect(errors[0].path).to.deep.equal(['grand_parent', 'parent', 'child', 'child_column_oops']); | ||
}); | ||
mocha_1.test('Rejects invalid types as the column resolver', function () { | ||
var data = { | ||
}); | ||
mocha_1.describe('virtual columns', function () { | ||
mocha_1.test('validates $field virtual column', function () { | ||
var query = { | ||
parent: { | ||
id: [], | ||
my_name: 'name' | ||
custom_name: { $field: 'parent_column' }, | ||
custom_name2: { $field: 'oops' } | ||
} | ||
}; | ||
// 2 errors | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(2); | ||
var errors = validate_query_1.validator(query, schema); | ||
chai_1.expect(errors[0].path).to.deep.equal(['parent', 'custom_name2']); | ||
chai_1.expect(errors.length).to.deep.equal(1); | ||
}); | ||
mocha_1.test('Rejects field with invalid source', function () { | ||
}); | ||
mocha_1.describe('subqueries', function () { | ||
mocha_1.test('validates the from clause', function () { | ||
var data = { | ||
parent: { | ||
hi: { | ||
$field: 'bye' | ||
good: { | ||
$from: 'child', | ||
id: true | ||
}, | ||
subq: { | ||
bad: { | ||
$from: 'oops', | ||
id: true | ||
}, | ||
hi2: true | ||
} | ||
}; | ||
// 3 errors | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(3); | ||
}); | ||
mocha_1.test('Allows function resolvers', function () { | ||
var data = { | ||
parent: { | ||
hi: { | ||
$field: 'id' | ||
} | ||
} | ||
}; | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(0); | ||
var errors = validate_query_1.validator(data, schema); | ||
var from_clause_errors = errors.filter(function (err) { | ||
return JSON.stringify(err.path) === | ||
JSON.stringify(['parent', 'bad', 'id']); | ||
}); | ||
chai_1.expect(from_clause_errors.length).to.equal(1); | ||
}); | ||
mocha_1.test('Respects from clause', function () { | ||
mocha_1.test('validates subquery connections', function () { | ||
var data = { | ||
parent: { | ||
hi: { | ||
grand_parent: { | ||
john: { | ||
$from: 'parent', | ||
id: true | ||
child: { | ||
id: true, | ||
grand_parent: { | ||
id: true | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(0); | ||
var errors = validate_query_1.validator(data, schema); | ||
chai_1.expect(errors.length).to.equal(1); | ||
chai_1.expect(errors[0].path).to.deep.equal(['grand_parent', 'john', 'child', 'grand_parent']); | ||
}); | ||
mocha_1.test('Does subqueries', function () { | ||
var data = { | ||
parent: { | ||
child: { | ||
id: true | ||
} | ||
} | ||
}; | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(0); | ||
}); | ||
mocha_1.test('Does backwards nesting subqueries', function () { | ||
var data = { | ||
child: { | ||
parent: { | ||
id: true | ||
} | ||
} | ||
}; | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(0); | ||
}); | ||
}); | ||
mocha_1.describe('Where/having clauses', function () { | ||
mocha_1.describe.skip('clauses', function () { | ||
mocha_1.test('Requires $eq to have valid field name', function () { | ||
@@ -159,4 +142,5 @@ var data = { | ||
}; | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(1); | ||
var errors = validate_query_1.validator(data, schema); | ||
chai_1.expect(errors.length).to.equal(1); | ||
chai_1.expect(errors[0].path).to.deep.equal(['parent', '$where']); | ||
}); | ||
@@ -174,4 +158,4 @@ mocha_1.test('Lets $having have aliased fields', function () { | ||
}; | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(0); | ||
var errors = validate_query_1.validator(data, schema); | ||
chai_1.expect(errors.length).to.equal(0); | ||
}); | ||
@@ -187,4 +171,4 @@ mocha_1.test('Lets operators have functions', function () { | ||
}; | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(0); | ||
var errors = validate_query_1.validator(data, schema); | ||
chai_1.expect(errors.length).to.equal(0); | ||
}); | ||
@@ -200,4 +184,4 @@ mocha_1.test('Lets operators have functions', function () { | ||
}; | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(0); | ||
var errors = validate_query_1.validator(data, schema); | ||
chai_1.expect(errors.length).to.equal(0); | ||
}); | ||
@@ -215,4 +199,4 @@ mocha_1.test('Lets $and', function () { | ||
}; | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(0); | ||
var errors = validate_query_1.validator(data, schema); | ||
chai_1.expect(errors.length).to.equal(0); | ||
}); | ||
@@ -234,4 +218,4 @@ mocha_1.test('Changes scope for subqueries', function () { | ||
}; | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(1); | ||
var errors = validate_query_1.validator(data, schema); | ||
chai_1.expect(errors.length).to.equal(1); | ||
}); | ||
@@ -250,4 +234,4 @@ mocha_1.test('Requires subqueries to have valid fields', function () { | ||
}; | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(1); | ||
var errors = validate_query_1.validator(data, schema); | ||
chai_1.expect(errors.length).to.equal(1); | ||
}); | ||
@@ -266,8 +250,6 @@ mocha_1.test('Requires subqueries to have valid fields', function () { | ||
}; | ||
var errors = validate_query_1.validator(data, schema).errors; | ||
mocha_1.expect(errors.length).to.equal(1); | ||
var errors = validate_query_1.validator(data, schema); | ||
chai_1.expect(errors.length).to.equal(1); | ||
}); | ||
}); | ||
mocha_1.test('', function () { | ||
}); | ||
}); |
{ | ||
"name": "orma", | ||
"version": "1.0.19", | ||
"version": "1.0.22", | ||
"description": "A declarative relational syncronous orm", | ||
@@ -10,3 +10,4 @@ "main": "build/index.js", | ||
"test": "mocha --package package.json", | ||
"nt": "nodemon --exec npm run test" | ||
"nt": "nodemon --exec nyc --reporter html npm run test", | ||
"coverage-watch": "live-server coverage" | ||
}, | ||
@@ -46,6 +47,8 @@ "files": [ | ||
"@jsdevtools/npm-publish": "^1.4.3", | ||
"@types/chai": "^4.2.19", | ||
"@types/mocha": "^8.2.3", | ||
"@types/node": "^16.3.2", | ||
"chai": "^4.3.4", | ||
"live-server": "^1.2.1", | ||
"mocha": "^9.0.1", | ||
"nyc": "^15.1.0", | ||
"sql-formatter": "^4.0.2", | ||
@@ -52,0 +55,0 @@ "sucrase": "^3.19.0", |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
249111
64
5789
0
11