Comparing version 1.0.35 to 1.0.36
@@ -125,8 +125,2 @@ "use strict"; | ||
let result = nester_1.nester(data, edges); | ||
// let result = {} | ||
// for (let i = 0; i < 10000; i++) { | ||
// result = nester(data, edges) | ||
// } | ||
// await stop_profiler() | ||
// console.timeEnd('t') | ||
chai_1.expect(result).to.deep.equal(goal); | ||
@@ -133,0 +127,0 @@ }); |
export declare const orma_introspect: (db: string, fn: (s: string[]) => Promise<Record<string, unknown>[][]>) => Promise<import("./introspector/introspector").orma_schema>; | ||
export declare const orma_query: (raw_query: any, orma_schema: any, query_function: (sql_string: string[]) => Promise<Record<string, unknown>[][]>) => Promise<{}>; | ||
export declare const orma_mutate: (mutation: any, mutate_functions: import("./mutate/mutate").mutate_functions, orma_schema: import("./introspector/introspector").orma_schema) => Promise<any>; | ||
export declare const orma_mutate: (mutation: any, mutate_fn: import("./mutate/mutate").mutate_fn, escape_fn: import("./mutate/mutate").escape_fn, orma_schema: import("./introspector/introspector").orma_schema) => Promise<any>; |
@@ -109,1 +109,2 @@ // import { orma_schema } from '../introspector/introspector' | ||
// } | ||
// do not allow product_id 5 if nested |
import { orma_schema } from '../introspector/introspector'; | ||
export declare type mutate_function = (sql_strings: string[], sql_jsons: Record<string, unknown>[]) => Promise<Record<string, unknown>[]>; | ||
export declare type operation = 'create' | 'update' | 'delete'; | ||
export interface mutate_functions { | ||
create: mutate_function; | ||
update: mutate_function; | ||
delete: mutate_function; | ||
} | ||
export declare const orma_mutate: (mutation: any, mutate_functions: mutate_functions, orma_schema: orma_schema) => Promise<any>; | ||
export declare type mutate_fn = (sql_strings: string[], sql_jsons: Record<string, unknown>[], operation: operation) => Promise<Record<string, unknown>[]>; | ||
export declare type escape_fn = (string: any) => string; | ||
export declare const orma_mutate: (mutation: any, mutate_fn: mutate_fn, escape_fn: escape_fn, orma_schema: orma_schema) => Promise<any>; | ||
/** | ||
@@ -11,0 +7,0 @@ * Each given path should point to a record in the mutation. |
@@ -8,14 +8,18 @@ "use strict"; | ||
const query_1 = require("../query/query"); | ||
// TODO: comment explaining how to set up mutation functions and what needs to be returned (need to return generated values) | ||
const orma_mutate = async (mutation, mutate_functions, orma_schema) => { | ||
const orma_mutate = async (mutation, mutate_fn, escape_fn, orma_schema) => { | ||
const mutate_plan = exports.get_mutate_plan(mutation, orma_schema); | ||
const mutation_result = helpers_1.clone(mutation); | ||
let mutation_result = helpers_1.clone(mutation); | ||
for (const tier of mutate_plan) { | ||
await Promise.all(tier.map(async ({ operation, paths }) => { | ||
const command_jsons = exports.get_command_jsons(operation, paths, mutation_result, orma_schema); | ||
const command_sqls = command_jsons.map(command_json => query_1.json_to_sql(command_json)); | ||
const mutate_function = mutate_functions[operation]; | ||
const results = await mutate_function(command_sqls, command_jsons); | ||
const escaped_command_jsons = escape_all(command_jsons, escape_fn); | ||
const command_sqls = escaped_command_jsons.map(command_json => query_1.json_to_sql(command_json)); | ||
const results = await mutate_fn(command_sqls, escaped_command_jsons, operation); | ||
paths.forEach((path, i) => { | ||
helpers_1.deep_set(path, results[i], mutation_result); | ||
const original_row = helpers_1.deep_get(path, mutation_result); | ||
const mutation_result_row = results[i]; | ||
// if (original_rows.length !== mutation_result_rows.length) { | ||
// throw new Error('Row count mismatched. Please ensure mutation results has the same length as mutation rows') | ||
// } | ||
helpers_1.deep_set(path, Object.assign(Object.assign({}, original_row), mutation_result_row), mutation_result); | ||
}); | ||
@@ -27,2 +31,6 @@ })); | ||
exports.orma_mutate = orma_mutate; | ||
const escape_all = (command_jsons, escape_fn) => { | ||
// TODO escape create update and delete | ||
return command_jsons; | ||
}; | ||
/* | ||
@@ -77,3 +85,3 @@ | ||
.filter(key => !identifying_keys.includes(key)) | ||
.filter(key => typeof (record[key]) !== 'object') | ||
.filter(key => typeof record[key] !== 'object') | ||
.filter(key => !schema_helpers_1.is_reserved_keyword(key)); | ||
@@ -115,3 +123,3 @@ return { | ||
const keys_to_insert = Object.keys(record) | ||
.filter(key => typeof (record[key]) !== 'object') | ||
.filter(key => typeof record[key] !== 'object') | ||
.filter(key => !schema_helpers_1.is_reserved_keyword(key)); | ||
@@ -130,6 +138,8 @@ keys_to_insert.forEach(key => acc.add(key)); | ||
}); | ||
return [{ | ||
return [ | ||
{ | ||
$insert_into: [entity_name, [...insert_keys]], | ||
$values: values | ||
}]; | ||
} | ||
]; | ||
}; | ||
@@ -140,5 +150,7 @@ const generate_record_where_clause = (identifying_keys, record) => { | ||
})); | ||
const where = where_clauses.length > 1 ? { | ||
and: where_clauses | ||
} : where_clauses === null || where_clauses === void 0 ? void 0 : where_clauses[0]; | ||
const where = where_clauses.length > 1 | ||
? { | ||
and: where_clauses | ||
} | ||
: where_clauses === null || where_clauses === void 0 ? void 0 : where_clauses[0]; | ||
return where; | ||
@@ -170,3 +182,4 @@ }; | ||
const included_unique_keys = unique_keys.filter(unique_key => record[unique_key]); | ||
if (included_unique_keys.length === 1) { // if there are 2 or more unique keys, we cant use them since it would be ambiguous which we choose | ||
if (included_unique_keys.length === 1) { | ||
// if there are 2 or more unique keys, we cant use them since it would be ambiguous which we choose | ||
return included_unique_keys; | ||
@@ -182,3 +195,3 @@ } | ||
original_data: mutation, | ||
stack_trace: (new Error()).stack, | ||
stack_trace: new Error().stack, | ||
additional_info: { | ||
@@ -247,3 +260,3 @@ identifying_columns: identifying_keys !== null && identifying_keys !== void 0 ? identifying_keys : 'none' | ||
// construct a directed acyclic graph reflecting the parent/child relationships of the routes | ||
// we use sets because we need to quickly add items to the graph while avoiding duplicates | ||
// we use sets because we need to quickly add items to the graph while avoiding duplicates | ||
// (one will be added per row in the mutation, so its important that this is O(1)) | ||
@@ -264,3 +277,3 @@ const route_graph = {}; | ||
} | ||
const path_template = path.map(el => typeof el === 'number' ? 0 : el); | ||
const path_template = path.map(el => (typeof el === 'number' ? 0 : el)); | ||
const route = [operation, ...path_template]; | ||
@@ -335,2 +348,2 @@ const route_string = JSON.stringify(route); | ||
*/ | ||
*/ |
@@ -389,2 +389,51 @@ "use strict"; | ||
}); | ||
mocha_1.describe(mutate_1.orma_mutate.name, () => { | ||
mocha_1.test('integrates orma mutation components', async () => { | ||
const mutation = { | ||
parents: [ | ||
{ | ||
$operation: 'create', | ||
unique1: 'test', | ||
grandparent_id: 5, | ||
children: [ | ||
{ | ||
// 'create' operation cascades | ||
} | ||
] | ||
} | ||
] | ||
}; | ||
let call_count = -1; | ||
const mutate_fn = async (sql_strings, sql_jsons, operation) => { | ||
call_count++; | ||
if (call_count === 0) { | ||
return [{ id: 10 }]; | ||
} | ||
if (call_count === 1) { | ||
return [ | ||
{ | ||
id1: 1, | ||
id2: 2 | ||
} | ||
]; | ||
} | ||
}; | ||
const escape_fn = i => i; | ||
// const escape_fn = val => typeof val === 'string' ? `"${val}"` : val | ||
const results = await mutate_1.orma_mutate(mutation, mutate_fn, escape_fn, orma_schema); | ||
const goal = { | ||
parents: [ | ||
{ | ||
$operation: 'create', | ||
unique1: 'test', | ||
grandparent_id: 5, | ||
children: [{ id1: 1, id2: 2, parent_id: 5 }], | ||
id: 10 | ||
} | ||
] | ||
}; | ||
chai_1.expect(results).to.equal(goal); | ||
}); | ||
mocha_1.test('escapes values'); | ||
}); | ||
}); | ||
@@ -391,0 +440,0 @@ /* |
@@ -21,3 +21,4 @@ "use strict"; | ||
}); | ||
const parsed_commands = sorted_commands.map(command => { | ||
const parsed_commands = sorted_commands | ||
.map(command => { | ||
if (expression[command] === undefined) { | ||
@@ -35,21 +36,26 @@ return ''; | ||
return command_parser(parsed_args, path); | ||
}).filter(el => el !== ''); | ||
}) | ||
.filter(el => el !== ''); | ||
return parsed_commands.join(' '); | ||
}; | ||
exports.json_to_sql = json_to_sql; | ||
const command_order = { | ||
$delete_from: -3, | ||
$update: -2, | ||
$set: -1, | ||
$select: 0, | ||
$from: 1, | ||
$where: 2, | ||
$group_by: 3, | ||
$having: 4, | ||
$order_by: 5, | ||
$limit: 6, | ||
$offset: 7, | ||
$insert_into: 8, | ||
$values: 9, | ||
}; | ||
const command_order_array = [ | ||
'$delete_from', | ||
'$update', | ||
'$set', | ||
'$select', | ||
'$from', | ||
'$where', | ||
'$group_by', | ||
'$having', | ||
'$order_by', | ||
'$limit', | ||
'$offset', | ||
'$insert_into', | ||
'$values' | ||
]; | ||
const command_order = command_order_array.reduce((acc, val, i) => { | ||
acc[val] = i; | ||
return acc; | ||
}, {}); | ||
/* | ||
@@ -99,5 +105,3 @@ | ||
const string_arg = args[1].toString(); | ||
const search_value = string_arg | ||
.replace(/^\'/, '') | ||
.replace(/\'$/, ''); // get rid of quotes if they were put there by escape() | ||
const search_value = string_arg.replace(/^\'/, '').replace(/\'$/, ''); // get rid of quotes if they were put there by escape() | ||
return `${args[0]}${helpers_1.last(path) === '$not' ? ' NOT' : ''} LIKE '%${search_value}%'`; | ||
@@ -120,7 +124,5 @@ }, | ||
$values: (values) => `${values.map(inner_values => `(${inner_values.join(', ')})`).join(', ')}`, | ||
$update: (table_name) => `${table_name}`, | ||
$set: (...items) => `${items | ||
.map((column, value) => `${column} = ${value}`) | ||
.join(', ')}`, | ||
$delete_from: (table_name) => `DELETE FROM ${table_name}` | ||
$update: table_name => `${table_name}`, | ||
$set: (...items) => `${items.map((column, value) => `${column} = ${value}`).join(', ')}`, | ||
$delete_from: table_name => `DELETE FROM ${table_name}` | ||
}; | ||
@@ -143,7 +145,9 @@ /* | ||
const has_filter = value.$where || value.$having; | ||
const child_paths = Object.keys(value).map(child_key => { | ||
const child_paths = Object.keys(value) | ||
.map(child_key => { | ||
if (exports.is_subquery(value[child_key])) { | ||
return [...path, child_key]; | ||
} | ||
}).filter(el => el !== undefined); | ||
}) | ||
.filter(el => el !== undefined); | ||
if (child_paths.length === 0) { | ||
@@ -154,3 +158,3 @@ return; // subquery with nothing else nested on | ||
// entities directly under the root need to ge after because all entitiesneed at least one ancestor which is already queried | ||
// so we can search for those ancestor ids. This ensures that at least the root will have already been searched. | ||
// so we can search for those ancestor ids. This ensures that at least the root will have already been searched. | ||
const is_root_child = path.length === 1; | ||
@@ -228,4 +232,3 @@ // if this has a $where, or its the root/root child, then all the child paths go to a new tier. Otherwise, the child paths are appended on to the last tier | ||
const entity_name = helpers_1.last(subquery_path); | ||
const $select = Object.keys(subquery) | ||
.flatMap(key => { | ||
const $select = Object.keys(subquery).flatMap(key => { | ||
var _a; | ||
@@ -268,3 +271,4 @@ if (schema_helpers_1.is_reserved_keyword(key)) { | ||
const ancestor_rows = previous_results | ||
.filter(previous_result => previous_result[0].toString() === ancestor_path.toString()).map(previous_result => previous_result[1])[0]; | ||
.filter(previous_result => previous_result[0].toString() === ancestor_path.toString()) | ||
.map(previous_result => previous_result[1])[0]; | ||
const path_to_ancestor = subquery_path.slice(nesting_ancestor_index, Infinity).reverse(); | ||
@@ -359,7 +363,10 @@ const ancestor_where_clause = get_ancestor_where_clause(ancestor_rows, path_to_ancestor, orma_schema); | ||
return { | ||
$in: [edge.from_field, { | ||
$in: [ | ||
edge.from_field, | ||
{ | ||
$select: [edge.to_field], | ||
$from: edge.to_entity, | ||
[is_having ? '$having' : '$where']: acc | ||
}] | ||
} | ||
] | ||
}; | ||
@@ -412,5 +419,8 @@ }, subquery); | ||
const ancestor_query = exports.convert_any_path_macro({ | ||
$any: [any_path, { | ||
$any: [ | ||
any_path, | ||
{ | ||
$in: [last_edge_to_ancestor.from_field, ancestor_linking_key_values] | ||
}] | ||
} | ||
] | ||
}, path_to_ancestor[0], false, orma_schema); | ||
@@ -496,3 +506,3 @@ return ancestor_query; | ||
// type entity_schema<entity extends keyof schema, schema> = | ||
// // keyof schema[entity] extends keyof schema ? | ||
// // keyof schema[entity] extends keyof schema ? | ||
// { $comment?: string } | ||
@@ -502,4 +512,4 @@ // & { [field: string]: field_schema<entity, schema> } | ||
// type field_schema<parent extends keyof schema, schema> = { | ||
// references?: | ||
// { [entity in keyof schema]?: | ||
// references?: | ||
// { [entity in keyof schema]?: | ||
// {} | ||
@@ -562,2 +572,2 @@ // // boolean | ||
*/ | ||
*/ |
@@ -14,2 +14,3 @@ "use strict"; | ||
const is_subquery_resolver = typeof val === 'object' && query_1.is_subquery(val); | ||
const is_clauses_resolver = '?'; | ||
if (is_boolean_resolver) { | ||
@@ -16,0 +17,0 @@ const error = validate_field_exists(val, path, schema, query); |
{ | ||
"name": "orma", | ||
"version": "1.0.35", | ||
"version": "1.0.36", | ||
"description": "A declarative relational syncronous orm", | ||
@@ -5,0 +5,0 @@ "main": "build/index.js", |
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
225855
5482