From 0026d7ace3a32cc38a24dd601fb4a4ea3bcda8fa Mon Sep 17 00:00:00 2001 From: Mason Payne Date: Wed, 20 Jan 2021 19:02:31 -0700 Subject: [PATCH] refactor mapper-creator to its own file --- src/views/helpers.ts | 14 ++ src/views/mapper-creator.ts | 288 ++++++++++++++++++++++++++++++++++ src/views/views-creator.ts | 298 +----------------------------------- 3 files changed, 304 insertions(+), 296 deletions(-) create mode 100644 src/views/helpers.ts create mode 100644 src/views/mapper-creator.ts diff --git a/src/views/helpers.ts b/src/views/helpers.ts new file mode 100644 index 0000000..0a3989f --- /dev/null +++ b/src/views/helpers.ts @@ -0,0 +1,14 @@ +function uppercaseFirstLetter(input: string) +{ + return input.charAt(0).toUpperCase() + input.slice(1); +} + +function lowercaseFirstLetter(input: string) +{ + return input.charAt(0).toLowerCase() + input.slice(1); +} + +export { + uppercaseFirstLetter, + lowercaseFirstLetter +} \ No newline at end of file diff --git a/src/views/mapper-creator.ts b/src/views/mapper-creator.ts new file mode 100644 index 0000000..7c7123a --- /dev/null +++ b/src/views/mapper-creator.ts @@ -0,0 +1,288 @@ +import {ColumnRef, EndpointDef, Filter, JoinDef, Order} from "../systemGenService"; +import pluralize from "pluralize"; +import {uppercaseFirstLetter, lowercaseFirstLetter} from "./helpers"; + +function createMapperFunc(view: EndpointDef): string { + let func: string = ''; + if (view.type === 'list' || view.type === 'count') { + func = buildGetList(view); + } else if (view.type === 'item') { + func = buildGetItem(view); + } else if (view.type === 'update') { + func = buildUpdateFunc(view); + } else if (view.type === 'create') { + func = buildCreateFunc(view); + } else if (view.type === 'delete') { + func = buildDeleteItem(view); + } + return func; +} + +function buildDeleteItem(view: EndpointDef): string { + let func: string = ''; + let funcName = buildFunctionName(view); + let tables: string = `${view.table}`; + let filtersObj = buildFilters(view); + let filters: string = filtersObj.filters; + let requiredFilterValues: string = filtersObj.requiredFilterValues; + let optionalFilterParts = filtersObj.optionalFiltersCode; + let query: string = `DELETE FROM ${tables}${filters}`; + let funcParams = 'params: {[key: string]: string}'; + + func = ` + public ${funcName}(${funcParams}) { + + let query: string = '${query}'; + let queryValues: string[] = [${requiredFilterValues}]; + + // optional params? + ${optionalFilterParts} + return super.runQuery(query, [...queryValues]); + } + `; + + return func; +} + +function buildGetItem(view: EndpointDef): string { + let func: string = ''; + let funcName = buildFunctionName(view); + let columns: string = `${view.component}.${view.component}_id, ${view.columns.map(c => `${c.table}.${c.name}`).join(', ')}`; + let tables: string = view.join?.length ? buildJoin(view) : `${view.table}`; + let filtersObj = buildFilters(view); + let filters: string = filtersObj.filters; + let requiredFilterValues: string = filtersObj.requiredFilterValues; + let optionalFilterParts = filtersObj.optionalFiltersCode; + let query: string = `SELECT ${columns} FROM ${tables}${filters} LIMIT 1`; + let funcParams = 'params: {[key: string]: string}'; + + func = ` + public ${funcName}(${funcParams}) { + + let query: string = '${query}'; + let queryValues: string[] = [${requiredFilterValues}]; + + // optional params? + ${optionalFilterParts} + return super.runQuery(query, [...queryValues]); + } +`; + + return func; +} + +function buildCreateFunc(view: EndpointDef): string { + let func: string = ''; + let query: string = `INSERT INTO ${view.table} SET `; + func = getCreateOrUpdateFunc(query, view); + + return func; +} + +function buildUpdateFunc(view: EndpointDef): string { + let func: string = ''; + let query: string = `UPDATE ${view.table} SET `; + func = getCreateOrUpdateFunc(query, view); + + return func; +} + +function getCreateOrUpdateFunc(query: string, view: EndpointDef): string { + let func: string = ''; + let funcName = buildFunctionName(view); + let requiredQueryValues: string = ''; + let optionalValuesCode: string = ''; + for (let i in view.columns) { + let c: ColumnRef = view.columns[i]; + if (c.required) { + if (!query.endsWith('SET ')) { + query = query + `, `; + } + query = query + `${c.table}.${c.name} = ?`; + if (requiredQueryValues.length) { + requiredQueryValues = requiredQueryValues + `, `; + } + requiredQueryValues = requiredQueryValues + `params.${c.param}`; + } else { + optionalValuesCode = optionalValuesCode + ` + if (params.${c.param}) { + query = query + ', ${c.table}.${c.name} = ?'; + queryValues.push(params.${c.param}); + } +`; + } + } + + func = ` + public ${funcName}(params: {[key: string]: string}) { + + let query: string = '${query}'; + let queryValues: string[] = [${requiredQueryValues}]; + + // optional params? + ${optionalValuesCode} + return super.runQuery(query, [...queryValues]); + } +`; + + return func; +} + +function buildGetList(view: EndpointDef): string { + // TODO: optionally allow a raw query definition with predefined params + // This would be so much simpler and easy if it were just the queries wanted + let func: string = ''; + let funcName: string = ''; + let columns: string = view.type === 'count' ? `count(*)` : `${view.component}.${view.component}_id, ${view.columns.map(c => `${c.table}.${c.name}`).join(', ')}`; + let query: string = ''; + let tables: string = view.join?.length ? buildJoin(view) : `${view.table}`; + let filters: string = ''; + funcName = buildFunctionName(view); + + let requiredFilterStrings = []; + let requiredQueryValues = ''; + let optionalFilterParts = ''; + if (view.filters) { + for (let i in view.filters) { + let f: Filter = view.filters[i]; + if (f.required) { + requiredFilterStrings.push(`${f.column.table}.${f.column.name} ${f.comparison} ?`); // e.g. 'table.id = ?' + if (requiredQueryValues.length) { + requiredQueryValues = requiredQueryValues + `, `; + } + requiredQueryValues = requiredQueryValues + `params.${f.param}`; + } else { + /* e.g. + if (eventLog.app) { + query = query + ', app = ?'; + queryValues.push(eventLog.app); + } + */ + optionalFilterParts = optionalFilterParts + ` + if (params.${f.param}) { + query = query + ' AND ${f.column.table}.${f.column.name} ${f.comparison} ?'; + queryValues.push(params.${f.param}); + }`; + } + } + filters = ` WHERE ${requiredFilterStrings.join(' AND ')}`; + } + + query = `SELECT ${columns} FROM ${tables}${filters}`; + let orderByCode = ''; + if (view.orderBy) { + orderByCode = ` + query = query + '${buildOrderBy(view)}'; +`; + } + let funcParams = 'params: {[key: string]: string}, offset: number, limit: number'; + let limitOrderCode = `query = query + ' LIMIT ?, ?'; + queryValues.push(offset.toString(10)); + queryValues.push(limit.toString(10)); + ${orderByCode}`; + if (view.type === 'count') { + funcParams = 'params: {[key: string]: string}'; + limitOrderCode = ``; + } + + func = ` + public ${funcName}(${funcParams}) { + + let query: string = '${query}'; + let queryValues: string[] = [${requiredQueryValues}]; + + // optional params? + ${optionalFilterParts} + ${limitOrderCode} + return super.runQuery(query, [...queryValues]); + } +`; + return func; +} + +function buildFilters(view: EndpointDef): {filters: string, requiredFilterValues: string, optionalFiltersCode: string} { + let filtersObj: {filters: string, requiredFilterValues: string, optionalFiltersCode: string} = { + filters: '', + requiredFilterValues: '', + optionalFiltersCode: '' + }; + + let filters: string = ''; + let requiredFilterStrings = []; + let requiredQueryValues = ''; + let optionalFilterParts = ''; + if (view.filters) { + for (let i in view.filters) { + let f: Filter = view.filters[i]; + if (f.required) { + requiredFilterStrings.push(`${f.column.table}.${f.column.name} ${f.comparison} ?`); // e.g. 'table.id = ?' + if (requiredQueryValues.length) { + requiredQueryValues = requiredQueryValues + `, `; + } + requiredQueryValues = requiredQueryValues + `params.${f.param}`; + } else { + /* e.g. + if (eventLog.app) { + query = query + ', app = ?'; + queryValues.push(eventLog.app); + } + */ + optionalFilterParts = optionalFilterParts + ` + if (params.${f.param}) { + query = query + ' AND ${f.column.table}.${f.column.name} ${f.comparison} ?'; + queryValues.push(params.${f.param}); + }`; + } + } + filters = ` WHERE ${requiredFilterStrings.join(' AND ')}`; + } + + filtersObj.filters = filters; + filtersObj.requiredFilterValues = requiredQueryValues; + filtersObj.optionalFiltersCode = optionalFilterParts; + return filtersObj; +} + +function buildJoin(view: EndpointDef): string { + if (view.join?.length) { + let join = `${view.table}`; + for (let i in view.join) { + let j: JoinDef = view.join[i]; + join = join + ` JOIN ${j.table} ON ${j.on.left.table}.${j.on.left.name} = ${j.on.right.table}.${j.on.right.name}`; + } + return join; + } + return ''; +} + +function buildOrderBy(view: EndpointDef): string { + let orderBy: string = ''; + if (view.orderBy?.length) { + orderBy = orderBy + ' ORDER BY '; + for (let i in view.orderBy) { + let order: Order = view.orderBy[i]; + if (parseInt(i) !== 0) { + orderBy = orderBy + ', '; + } + orderBy = orderBy + `${order.column.table}.${order.column.name} ${order.direction}`; + } + } + return orderBy; +} + +function buildFunctionName(view: EndpointDef): string { + let selector: {[type: string]: (view: EndpointDef) => string} = { + 'list': (view: EndpointDef) => `get${pluralize(uppercaseFirstLetter(view.component))}` + (view.type === 'count' ? 'Count' : ''), + 'count': (view: EndpointDef) => `get${pluralize(uppercaseFirstLetter(view.component))}` + (view.type === 'count' ? 'Count' : ''), + 'item': (view: EndpointDef) => `get${uppercaseFirstLetter(view.component)}`, + 'update': (view: EndpointDef) => `update${uppercaseFirstLetter(view.component)}`, + 'create': (view: EndpointDef) => `create${uppercaseFirstLetter(view.component)}`, + 'delete': (view: EndpointDef) => `delete${uppercaseFirstLetter(view.component)}`, + 'search': (view: EndpointDef) => `search${uppercaseFirstLetter(view.component)}`, + }; + return selector[view.type](view); +} + +export { + createMapperFunc +} \ No newline at end of file diff --git a/src/views/views-creator.ts b/src/views/views-creator.ts index 5825421..36a8506 100644 --- a/src/views/views-creator.ts +++ b/src/views/views-creator.ts @@ -1,15 +1,12 @@ import { - ColumnRef, ComponentDef, EndpointDef, - Filter, - JoinDef, - Order, SystemDef, } from '../systemGenService'; import * as path from 'path'; import * as fs from 'fs'; -import pluralize from 'pluralize'; +import {createMapperFunc} from "./mapper-creator"; +import {uppercaseFirstLetter, lowercaseFirstLetter} from "./helpers"; const ncp = require('ncp').ncp; @@ -101,295 +98,4 @@ function insertMapperCode(view: EndpointDef, outDir: string): Promise { fs.writeFileSync(fileLocation, newMapperFile, 'utf8'); resolve(); }); -} - -function createMapperFunc(view: EndpointDef): string { - let func: string = ''; - if (view.type === 'list' || view.type === 'count') { - func = buildGetList(view); - } else if (view.type === 'item') { - func = buildGetItem(view); - } else if (view.type === 'update') { - func = buildUpdateFunc(view); - } else if (view.type === 'create') { - func = buildCreateFunc(view); - } else if (view.type === 'delete') { - func = buildDeleteItem(view); - } - return func; -} - -function buildDeleteItem(view: EndpointDef): string { - let func: string = ''; - let funcName = buildFunctionName(view); - let tables: string = `${view.table}`; - let filtersObj = buildFilters(view); - let filters: string = filtersObj.filters; - let requiredFilterValues: string = filtersObj.requiredFilterValues; - let optionalFilterParts = filtersObj.optionalFiltersCode; - let query: string = `DELETE FROM ${tables}${filters}`; - let funcParams = 'params: {[key: string]: string}'; - - func = ` - public ${funcName}(${funcParams}) { - - let query: string = '${query}'; - let queryValues: string[] = [${requiredFilterValues}]; - - // optional params? - ${optionalFilterParts} - return super.runQuery(query, [...queryValues]); - } - `; - - return func; -} - -function buildGetItem(view: EndpointDef): string { - let func: string = ''; - let funcName = buildFunctionName(view); - let columns: string = `${view.component}.${view.component}_id, ${view.columns.map(c => `${c.table}.${c.name}`).join(', ')}`; - let tables: string = view.join?.length ? buildJoin(view) : `${view.table}`; - let filtersObj = buildFilters(view); - let filters: string = filtersObj.filters; - let requiredFilterValues: string = filtersObj.requiredFilterValues; - let optionalFilterParts = filtersObj.optionalFiltersCode; - let query: string = `SELECT ${columns} FROM ${tables}${filters} LIMIT 1`; - let funcParams = 'params: {[key: string]: string}'; - - func = ` - public ${funcName}(${funcParams}) { - - let query: string = '${query}'; - let queryValues: string[] = [${requiredFilterValues}]; - - // optional params? - ${optionalFilterParts} - return super.runQuery(query, [...queryValues]); - } -`; - - return func; -} - -function buildCreateFunc(view: EndpointDef): string { - let func: string = ''; - let query: string = `INSERT INTO ${view.table} SET `; - func = getCreateOrUpdateFunc(query, view); - - return func; -} - -function buildUpdateFunc(view: EndpointDef): string { - let func: string = ''; - let query: string = `UPDATE ${view.table} SET `; - func = getCreateOrUpdateFunc(query, view); - - return func; -} - -function getCreateOrUpdateFunc(query: string, view: EndpointDef): string { - let func: string = ''; - let funcName = buildFunctionName(view); - let requiredQueryValues: string = ''; - let optionalValuesCode: string = ''; - for (let i in view.columns) { - let c: ColumnRef = view.columns[i]; - if (c.required) { - if (!query.endsWith('SET ')) { - query = query + `, `; - } - query = query + `${c.table}.${c.name} = ?`; - if (requiredQueryValues.length) { - requiredQueryValues = requiredQueryValues + `, `; - } - requiredQueryValues = requiredQueryValues + `params.${c.param}`; - } else { - optionalValuesCode = optionalValuesCode + ` - if (params.${c.param}) { - query = query + ', ${c.table}.${c.name} = ?'; - queryValues.push(params.${c.param}); - } -`; - } - } - - func = ` - public ${funcName}(params: {[key: string]: string}) { - - let query: string = '${query}'; - let queryValues: string[] = [${requiredQueryValues}]; - - // optional params? - ${optionalValuesCode} - return super.runQuery(query, [...queryValues]); - } -`; - - return func; -} - -function buildGetList(view: EndpointDef): string { - // TODO: optionally allow a raw query definition with predefined params - // This would be so much simpler and easy if it were just the queries wanted - let func: string = ''; - let funcName: string = ''; - let columns: string = view.type === 'count' ? `count(*)` : `${view.component}.${view.component}_id, ${view.columns.map(c => `${c.table}.${c.name}`).join(', ')}`; - let query: string = ''; - let tables: string = view.join?.length ? buildJoin(view) : `${view.table}`; - let filters: string = ''; - funcName = buildFunctionName(view); - - let requiredFilterStrings = []; - let requiredQueryValues = ''; - let optionalFilterParts = ''; - if (view.filters) { - for (let i in view.filters) { - let f: Filter = view.filters[i]; - if (f.required) { - requiredFilterStrings.push(`${f.column.table}.${f.column.name} ${f.comparison} ?`); // e.g. 'table.id = ?' - if (requiredQueryValues.length) { - requiredQueryValues = requiredQueryValues + `, `; - } - requiredQueryValues = requiredQueryValues + `params.${f.param}`; - } else { - /* e.g. - if (eventLog.app) { - query = query + ', app = ?'; - queryValues.push(eventLog.app); - } - */ - optionalFilterParts = optionalFilterParts + ` - if (params.${f.param}) { - query = query + ' AND ${f.column.table}.${f.column.name} ${f.comparison} ?'; - queryValues.push(params.${f.param}); - }`; - } - } - filters = ` WHERE ${requiredFilterStrings.join(' AND ')}`; - } - - query = `SELECT ${columns} FROM ${tables}${filters}`; - let orderByCode = ''; - if (view.orderBy) { - orderByCode = ` - query = query + '${buildOrderBy(view)}'; -`; - } - let funcParams = 'params: {[key: string]: string}, offset: number, limit: number'; - let limitOrderCode = `query = query + ' LIMIT ?, ?'; - queryValues.push(offset.toString(10)); - queryValues.push(limit.toString(10)); - ${orderByCode}`; - if (view.type === 'count') { - funcParams = 'params: {[key: string]: string}'; - limitOrderCode = ``; - } - - func = ` - public ${funcName}(${funcParams}) { - - let query: string = '${query}'; - let queryValues: string[] = [${requiredQueryValues}]; - - // optional params? - ${optionalFilterParts} - ${limitOrderCode} - return super.runQuery(query, [...queryValues]); - } -`; - return func; -} - -function buildFilters(view: EndpointDef): {filters: string, requiredFilterValues: string, optionalFiltersCode: string} { - let filtersObj: {filters: string, requiredFilterValues: string, optionalFiltersCode: string} = { - filters: '', - requiredFilterValues: '', - optionalFiltersCode: '' - }; - - let filters: string = ''; - let requiredFilterStrings = []; - let requiredQueryValues = ''; - let optionalFilterParts = ''; - if (view.filters) { - for (let i in view.filters) { - let f: Filter = view.filters[i]; - if (f.required) { - requiredFilterStrings.push(`${f.column.table}.${f.column.name} ${f.comparison} ?`); // e.g. 'table.id = ?' - if (requiredQueryValues.length) { - requiredQueryValues = requiredQueryValues + `, `; - } - requiredQueryValues = requiredQueryValues + `params.${f.param}`; - } else { - /* e.g. - if (eventLog.app) { - query = query + ', app = ?'; - queryValues.push(eventLog.app); - } - */ - optionalFilterParts = optionalFilterParts + ` - if (params.${f.param}) { - query = query + ' AND ${f.column.table}.${f.column.name} ${f.comparison} ?'; - queryValues.push(params.${f.param}); - }`; - } - } - filters = ` WHERE ${requiredFilterStrings.join(' AND ')}`; - } - - filtersObj.filters = filters; - filtersObj.requiredFilterValues = requiredQueryValues; - filtersObj.optionalFiltersCode = optionalFilterParts; - return filtersObj; -} - -function buildJoin(view: EndpointDef): string { - if (view.join?.length) { - let join = `${view.table}`; - for (let i in view.join) { - let j: JoinDef = view.join[i]; - join = join + ` JOIN ${j.table} ON ${j.on.left.table}.${j.on.left.name} = ${j.on.right.table}.${j.on.right.name}`; - } - return join; - } - return ''; -} - -function buildOrderBy(view: EndpointDef): string { - let orderBy: string = ''; - if (view.orderBy?.length) { - orderBy = orderBy + ' ORDER BY '; - for (let i in view.orderBy) { - let order: Order = view.orderBy[i]; - if (parseInt(i) !== 0) { - orderBy = orderBy + ', '; - } - orderBy = orderBy + `${order.column.table}.${order.column.name} ${order.direction}`; - } - } - return orderBy; -} - -function uppercaseFirstLetter(input: string) -{ - return input.charAt(0).toUpperCase() + input.slice(1); -} - -function lowercaseFirstLetter(input: string) -{ - return input.charAt(0).toLowerCase() + input.slice(1); -} - -function buildFunctionName(view: EndpointDef): string { - let selector: {[type: string]: (view: EndpointDef) => string} = { - 'list': (view: EndpointDef) => `get${pluralize(uppercaseFirstLetter(view.component))}` + (view.type === 'count' ? 'Count' : ''), - 'count': (view: EndpointDef) => `get${pluralize(uppercaseFirstLetter(view.component))}` + (view.type === 'count' ? 'Count' : ''), - 'item': (view: EndpointDef) => `get${uppercaseFirstLetter(view.component)}`, - 'update': (view: EndpointDef) => `update${uppercaseFirstLetter(view.component)}`, - 'create': (view: EndpointDef) => `create${uppercaseFirstLetter(view.component)}`, - 'delete': (view: EndpointDef) => `delete${uppercaseFirstLetter(view.component)}`, - 'search': (view: EndpointDef) => `search${uppercaseFirstLetter(view.component)}`, - }; - return selector[view.type](view); } \ No newline at end of file